From 14ccb3c7f87385cfed7ea6c7a9888d153926853a Mon Sep 17 00:00:00 2001 From: Max Tyson <98maxt98@gmail.com> Date: Sat, 1 Nov 2025 16:58:10 +1300 Subject: [PATCH 01/12] DOXY Structs: typedef and packed & other missed functions --- docs/CODE_OF_CONDUCT.md | 2 +- docs/Notes.md | 8 +- docs/Styles/.clang-format | 72 +++++++- docs/Styles/Coding Style.md | 6 +- docs/Styles/Interface Style.md | 4 +- docs/doxy/Doxyfile | 4 +- kernel/include/common/macros.h | 22 +++ kernel/include/common/time.h | 10 +- kernel/include/drivers/clock/clock.h | 7 +- .../include/drivers/ethernet/amd_am79c973.h | 165 ++++++++++-------- kernel/include/drivers/ethernet/ethernet.h | 1 + kernel/include/drivers/ethernet/intel_i217.h | 53 ++++-- kernel/include/drivers/peripherals/keyboard.h | 42 +++-- kernel/include/filesystem/filesystem.h | 138 +++++++-------- kernel/include/filesystem/format/ext2.h | 42 +++-- kernel/include/filesystem/format/fat32.h | 37 ++-- kernel/include/filesystem/partition/msdos.h | 15 +- kernel/include/gui/widget.h | 23 ++- kernel/include/hardwarecommunication/acpi.h | 29 ++- kernel/include/hardwarecommunication/apic.h | 51 ++++-- .../hardwarecommunication/interrupts.h | 19 +- kernel/include/memory/physical.h | 42 +++-- kernel/include/memory/virtual.h | 26 ++- kernel/include/net/arp.h | 7 +- kernel/include/net/ethernetframe.h | 16 +- kernel/include/net/icmp.h | 9 +- kernel/include/net/ipv4.h | 13 +- kernel/include/net/tcp.h | 20 ++- kernel/include/net/udp.h | 9 +- kernel/include/processes/elf.h | 15 ++ kernel/include/processes/process.h | 15 +- kernel/include/processes/resource.h | 4 +- kernel/include/runtime/cplusplus.h | 25 ++- kernel/include/runtime/ubsan.h | 51 ++++++ kernel/include/system/cpu.h | 46 +++-- kernel/include/system/gdt.h | 10 +- kernel/include/system/syscalls.h | 7 +- kernel/src/drivers/clock/clock.cpp | 6 +- kernel/src/drivers/console/serial.cpp | 2 +- kernel/src/drivers/ethernet/amd_am79c973.cpp | 2 +- kernel/src/drivers/ethernet/intel_i217.cpp | 6 - kernel/src/kernel.cpp | 3 + kernel/src/memory/physical.cpp | 8 +- kernel/src/runtime/cplusplus.cpp | 12 +- toolchain/pre_process/symbols.sh | 14 +- toolchain/pre_process/version.sh | 79 +++++++-- 46 files changed, 830 insertions(+), 367 deletions(-) create mode 100644 kernel/include/common/macros.h diff --git a/docs/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md index 5429b311..5b995fe9 100644 --- a/docs/CODE_OF_CONDUCT.md +++ b/docs/CODE_OF_CONDUCT.md @@ -38,7 +38,7 @@ The following behaviors are considered harassment and are unacceptable within ou * Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability. * Inappropriate photography or recording. * Inappropriate physical contact. You should have someone's consent before touching them. - * Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances. + * Unwelcome sexual attention. This includes, sexualised comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances. * Deliberate intimidation, stalking or following (online or in person). * Advocating for, or encouraging, any of the above behavior. * Sustained disruption of community events, including talks and presentations. diff --git a/docs/Notes.md b/docs/Notes.md index ff994afc..794a8308 100644 --- a/docs/Notes.md +++ b/docs/Notes.md @@ -63,7 +63,7 @@ This relates to "port.cpp", directly used by "interrupts.cpp, mouse.cpp, keyboar outb(portNumber, data) outb(0x20, 0x1) //Example using PIC (port 32) and the data 1 ``` -- To initialize the PIC ICWs (Initialization Control Words) must be sent +- To initialise the PIC ICWs (Initialization Control Words) must be sent ### Interrupts This relates to "interrupts.cpp, interruptstubs.s", which are extended by "keyboard.cpp, mouse.cpp". @@ -364,16 +364,16 @@ See also [List of syscalls](https://x64.syscall.sh/) ### Driver am79c971 See also [OSDev - PCNET](https://wiki.osdev.org/AMD_PCNET), [LowLevel - PCNET](http://www.lowlevel.eu/wiki/AMD_PCnet), [Logical and Physical Adresses](https://www.geeksforgeeks.org/logical-and-physical-address-in-operating-system/) [AMD_AM79C973](https://www.amd.com/system/files/TechDocs/20550.pdf) -- To get networking capability in the OS a driver for the virtualized network chip (am79c971) has to be written +- To get networking capability in the OS a driver for the virtualised network chip (am79c971) has to be written - This device is a complicated one to write a driver for. However, it will follow the same implementation as the other drivers: a class derived from driver, a class derived from interrupt handler (interrupt number and port number can be gotten from PCI) -- The device takes a lot of code to initialize (similar to loads for setting VGA graphics mode). +- The device takes a lot of code to initialise (similar to loads for setting VGA graphics mode). - The networking device can have multiple send and receive buffers and for every m_buffer there needs to be an instance of a struct (which mainly has a pointer to that m_buffer) - A problem with this though is that this is one of those devices that use some bits in the address for other purposes meaning it needs to be a multiple of 16 (similar to bar) - So the m_buffer will be 2KB but then an additional 15 bytes are added on and then 4 bytes are removed. This allows for the multiple of 16 to be found ### Handler See also [Wikipedia - Ethernet Frame](https://en.wikipedia.org/wiki/Ethernet_frame) -- The driver written for the am79c971 can be utilized to receive and send data, however for the device to be useful a protocol handler has to be written. +- The driver written for the am79c971 can be utilised to receive and send data, however for the device to be useful a protocol handler has to be written. - This protocol handler will look at the incoming data and decide what protocol should be used to interpret the data. - The data that is received by the am79c971 will be call raw data - The raw data is structured like this (Encoded in big endian): diff --git a/docs/Styles/.clang-format b/docs/Styles/.clang-format index 2d90114e..67533a75 100644 --- a/docs/Styles/.clang-format +++ b/docs/Styles/.clang-format @@ -1,8 +1,66 @@ +# Generated from CLion C/C++ Code Style settings BasedOnStyle: LLVM -IndentWidth: 2 -ContinuationIndentWidth: 2 -BreakConstructorInitializers: AfterColon -ConstructorInitializerIndentWidth: 2 -ConstructorInitializerAllOnOneLineOrOnePerLine: false -AllowShortFunctionsOnASingleLine: None -ColumnLimit: 0 \ No newline at end of file +AccessModifierOffset: 0 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: None +AlignOperands: Align +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Always +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Always +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterReturnType: None +AlwaysBreakTemplateDeclarations: No +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: true +BreakBeforeBinaryOperators: None +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +ColumnLimit: 0 +CompactNamespaces: false +ContinuationIndentWidth: 8 +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 4 +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: All +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PointerAlignment: Left +ReflowComments: false +SpaceAfterCStyleCast: true +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 0 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: ForIndentation diff --git a/docs/Styles/Coding Style.md b/docs/Styles/Coding Style.md index 8260ddb5..893ba2d7 100644 --- a/docs/Styles/Coding Style.md +++ b/docs/Styles/Coding Style.md @@ -2,13 +2,15 @@ # MaxOS C++ coding style +TODO: order import alphabetically (libc then project headers last), must typedef structs + This document describes the coding style used for C++ code in the Max Operating System project. All new code should conform to this style. ### Names A combination of CamelCase, snake\_case, and SCREAMING\_CASE: -- Use CamelCase (Capitalize the m_first_memory_chunk letter, including all letters in an acronym) in a class, struct, or namespace name +- Use CamelCase (Capitalise the m_first_memory_chunk letter, including all letters in an acronym) in a class, struct, or namespace name - Use snake\_case (all lowercase, with underscores separating words) for variable and function names - Use SCREAMING\_CASE for constants (both global and static member variables) @@ -145,7 +147,7 @@ Prefer `const` to `#define`. Prefer inline functions to macros. ### Other Punctuation -Constructors for C++ classes should initialize their members using C++ initializer syntax. Each member (and superclass) should be indented on a separate line, with the colon or comma preceding the member on that line. Prefer initialization at member definition whenever possible. +Constructors for C++ classes should initialise their members using C++ initialiser syntax. Each member (and superclass) should be indented on a separate line, with the colon or comma preceding the member on that line. Prefer initialization at member definition whenever possible. ###### Right: diff --git a/docs/Styles/Interface Style.md b/docs/Styles/Interface Style.md index 1bdc7284..f894a00e 100644 --- a/docs/Styles/Interface Style.md +++ b/docs/Styles/Interface Style.md @@ -9,7 +9,7 @@ MaxOS employs two capitalization styles: ### Book m_title capitalization -In this style, we capitalize the m_first_memory_chunk letter of the m_first_memory_chunk and last word, +In this style, we capitalise the m_first_memory_chunk letter of the m_first_memory_chunk and last word, as well as all words in between, *except* articles (a, an, the); the seven coordinating conjunctions (for, and, nor, but, or, yet, so); and prepositions with up to four letters (at, by, for, with, into, ...) @@ -34,7 +34,7 @@ and prepositions with up to four letters (at, by, for, with, into, ...) ### Sentence-style capitalization This style follows basic English sentence capitalization. -We capitalize the m_first_memory_chunk letter of the m_first_memory_chunk word, along with the m_first_memory_chunk letter +We capitalise the m_first_memory_chunk letter of the m_first_memory_chunk word, along with the m_first_memory_chunk letter of proper names, weekdays, etc. #### Examples: diff --git a/docs/doxy/Doxyfile b/docs/doxy/Doxyfile index 22bacb80..4b567f8a 100644 --- a/docs/doxy/Doxyfile +++ b/docs/doxy/Doxyfile @@ -1,6 +1,6 @@ DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = "Max OS" -PROJECT_NUMBER = 0.1 +PROJECT_NUMBER = 0.3 PROJECT_LOGO = ../Screenshots/Logo.png OUTPUT_DIRECTORY = . CREATE_SUBDIRS = NO @@ -94,7 +94,7 @@ WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_IF_INCOMPLETE_DOC = YES WARN_NO_PARAMDOC = YES -WARN_AS_ERROR = NO #Go thru docs again when can be bothered +WARN_AS_ERROR = YES WARN_FORMAT = "$file:$line: $text" WARN_LINE_FORMAT = "at line $line of file $file" INPUT = ../../kernel diff --git a/kernel/include/common/macros.h b/kernel/include/common/macros.h new file mode 100644 index 00000000..d1cf3839 --- /dev/null +++ b/kernel/include/common/macros.h @@ -0,0 +1,22 @@ +// +// Created by 98max on 1/11/2025. +// + +#ifndef MAXOS_COMMON_MACROS_H +#define MAXOS_COMMON_MACROS_H + +namespace MaxOS{ + + #ifdef DOXYGEN + /// Ensure no padding added to the struct + #define PACKED + #else + /// Ensure no padding added to the struct + #define PACKED __attribute__((packed)) + #endif + +} + + + +#endif //MAXOS_COMMON_MACROS_H diff --git a/kernel/include/common/time.h b/kernel/include/common/time.h index 57679ee1..92c9db8a 100644 --- a/kernel/include/common/time.h +++ b/kernel/include/common/time.h @@ -18,6 +18,9 @@ namespace MaxOS{ /** * @struct Time * @brief Stores the year, month, day, hour, minute and second of a time. + * + * @typedef time_t + * @brief Alias for Time struct */ typedef struct Time{ @@ -39,6 +42,7 @@ namespace MaxOS{ } time_t; + /// List of month names indexed by month number - 1 static const char* Months[] = { "January", "February", @@ -54,6 +58,7 @@ namespace MaxOS{ "December" }; + /// List of day names starting from Sunday ending on Saturday static const char* Days[] = { "Sunday", "Monday", @@ -64,6 +69,7 @@ namespace MaxOS{ "Saturday" }; + /// Number of days in each month indexed by month number - 1 constexpr uint8_t DAYS_IN_MONTH[] = { 31, // January 28, // February @@ -79,8 +85,8 @@ namespace MaxOS{ 31 // December }; - constexpr uint16_t DAYS_PER_YEAR = 365; - constexpr uint16_t DAYS_PER_LEAP_YEAR = 366; + constexpr uint16_t DAYS_PER_YEAR = 365; ///< Number of days in a non-leap year + constexpr uint16_t DAYS_PER_LEAP_YEAR = 366; ///< Number of days in a leap year /** * @brief Converts a time to an epoch diff --git a/kernel/include/drivers/clock/clock.h b/kernel/include/drivers/clock/clock.h index 9aca511f..896ec22f 100644 --- a/kernel/include/drivers/clock/clock.h +++ b/kernel/include/drivers/clock/clock.h @@ -71,12 +71,17 @@ namespace MaxOS { /** * @struct PITCommand * @brief The command byte to send to the PIT, specifies the channel, access mode, operating mode and BCD mode + * + * @typedef pit_command_t + * @brief Alias for PITCommand struct */ typedef struct PITCommand { + uint8_t bcd_mode: 1; ///< 0 = binary, 1 = BCD uint8_t operating_mode: 3; ///< What mode the PIT should operate in uint8_t access_mode: 2; ///< How the data is accessed uint8_t channel: 2; ///< Which channel to configure + } pit_command_t; @@ -162,7 +167,7 @@ namespace MaxOS { string device_name() final; static Clock* active_clock(); - common::Time get_time(); + common::time_t get_time(); }; } diff --git a/kernel/include/drivers/ethernet/amd_am79c973.h b/kernel/include/drivers/ethernet/amd_am79c973.h index 80b4e910..4b89c340 100644 --- a/kernel/include/drivers/ethernet/amd_am79c973.h +++ b/kernel/include/drivers/ethernet/amd_am79c973.h @@ -10,107 +10,122 @@ #define MAXOS_DRIVERS_ETHERNET_AMD_AM79C973_H #include +#include #include #include #include #include +namespace MaxOS { -namespace MaxOS{ + namespace drivers { + + namespace ethernet { + + /** + * @struct InitializationBlock + * @brief The initialization block for the AMD AM79C973 Ethernet Controller + * + * @typedef initialisation_block_t + * @brief Alias for InitializationBlock struct + */ + typedef struct PACKED InitializationBlock { - namespace drivers{ + uint16_t mode; ///< The operation mode + unsigned reserved1: 4; ///< Unused, must be zero + unsigned numSendBuffers: 4; ///< How many buffers are used for sending + unsigned reserved2: 4; ///< Unused, must be zero + unsigned numRecvBuffers: 4; ///< How many buffers are used for receiving + uint64_t physicalAddress: 48; ///< The physical (MAC) address of the device (Not 64 bits but will be treated like it is) + uint16_t reserved3; ///< Unused, must be zero + uint64_t logicalAddress; ///< The logical address filter for the device to use when deciding whether to accept a packet (0 = no filtering) + uint32_t recvBufferDescrAddress; ///< Physical address of the first receive buffer descriptor + uint32_t sendBufferDescrAddress; ///< Physical address of the first send buffer descriptor - namespace ethernet{ + } + initialisation_block_t; + /** + * @struct BufferDescriptor + * @brief Defines the layout of a buffer descriptor for the AMD AM79C973 Ethernet Controller + * + * @typedef buffer_descriptor_t + * @brief Alias for BufferDescriptor struct + */ + typedef struct PACKED BufferDescriptor { - /** - * @class AMD_AM79C973 - * @brief Driver for the AMD AM79C973 Ethernet Controller - */ - class AMD_AM79C973 : public EthernetDriver, public hardwarecommunication::InterruptHandler{ + uint64_t address; ///< Physical address of the buffer + uint32_t flags; ///< Flags for the buffer + uint32_t flags2; ///< Additional flags for the buffer (@todo enum this) + uint32_t avail; ///< Indicates whether the buffer is available to be used - struct InitializationBlock{ + } + buffer_descriptor_t; - uint16_t mode; - unsigned reserved1 : 4; - unsigned numSendBuffers : 4; - unsigned reserved2 : 4; - unsigned numRecvBuffers : 4; - uint64_t physicalAddress : 48; //Not 64 bits but will be treated like it is - uint16_t reserved3; - uint64_t logicalAddress; - uint32_t recvBufferDescrAddress; - uint32_t sendBufferDescrAddress; + /** + * @class AMD_AM79C973 + * @brief Driver for the AMD AM79C973 Ethernet Controller + */ + class AMD_AM79C973 : public EthernetDriver, public hardwarecommunication::InterruptHandler { + private: - } __attribute__((packed)); + //Reading the media access control address (MAC address) + hardwarecommunication::Port16Bit MACAddress0Port; + hardwarecommunication::Port16Bit MACAddress2Port; + hardwarecommunication::Port16Bit MACAddress4Port; - struct BufferDescriptor{ + //Register ports + hardwarecommunication::Port16Bit registerDataPort; + hardwarecommunication::Port16Bit registerAddressPort; + hardwarecommunication::Port16Bit busControlRegisterDataPort; - uint64_t address; - uint32_t flags; - uint32_t flags2; - uint32_t avail; + hardwarecommunication::Port16Bit resetPort; - } __attribute__((packed)); + //The main purpose of the initialization block it to hold a pointer to the array of BufferDescriptors, which hold the pointers to the buffers + initialisation_block_t initBlock { }; - //Reading the media access control address (MAC address) - hardwarecommunication::Port16Bit MACAddress0Port; - hardwarecommunication::Port16Bit MACAddress2Port; - hardwarecommunication::Port16Bit MACAddress4Port; + buffer_descriptor_t* sendBufferDescr; //Descriptor entry + uint8_t sendBuffers[2 * 1024 + 15][8] { }; //8 Send Buffers, 2KB + 15 bytes + uint8_t currentSendBuffer; //Which buffers are active - //Register ports - hardwarecommunication::Port16Bit registerDataPort; - hardwarecommunication::Port16Bit registerAddressPort; - hardwarecommunication::Port16Bit busControlRegisterDataPort; + buffer_descriptor_t* recvBufferDescr; //Descriptor entry + uint8_t recvBuffers[2 * 1024 + 15][8] { }; //8 Send Buffers, 2KB + 15 bytes + uint8_t currentRecvBuffer; //Which buffers are active - hardwarecommunication::Port16Bit resetPort; + //Ethernet Driver functions + MediaAccessControlAddress ownMAC; //MAC address of the device + volatile bool active; //Is the device active + volatile bool initDone; //Is the device initialised - //The main purpose of the initialization block it to hold a pointer to the array of BufferDescriptors, which hold the pointers to the buffers - InitializationBlock initBlock{}; + void FetchDataReceived(); //Fetches the data from the buffer + void FetchDataSent(); //Fetches the data from the buffer + public: + AMD_AM79C973(hardwarecommunication::PeripheralComponentInterconnectDeviceDescriptor* device_descriptor); + ~AMD_AM79C973(); - BufferDescriptor* sendBufferDescr; //Descriptor entry - uint8_t sendBuffers[2*1024+15][8]{}; //8 Send Buffers, 2KB + 15 bytes - uint8_t currentSendBuffer; //Which buffers are active + // Override driver default methods + uint32_t reset() final; + void activate() final; + void deactivate() final; - BufferDescriptor* recvBufferDescr; //Descriptor entry - uint8_t recvBuffers[2*1024+15][8]{}; //8 Send Buffers, 2KB + 15 bytes - uint8_t currentRecvBuffer; //Which buffers are active + // Naming + string vendor_name() final; + string device_name() final; - //Ethernet Driver functions - MediaAccessControlAddress ownMAC; //MAC address of the device - volatile bool active; //Is the device active - volatile bool initDone; //Is the device initialised - - void FetchDataReceived(); //Fetches the data from the buffer - void FetchDataSent(); //Fetches the data from the buffer - - public: - AMD_AM79C973(hardwarecommunication::PeripheralComponentInterconnectDeviceDescriptor* device_descriptor); - ~AMD_AM79C973(); - - //Override driver default methods - uint32_t reset() final; - void activate() final; - void deactivate() final; - - // Naming - string vendor_name() final; - string device_name() final; - - //Override Interrupt default methods - void handle_interrupt() final; - - //Ethernet Driver functions - void DoSend(uint8_t* buffer, uint32_t size) final; - uint64_t GetMediaAccessControlAddress() final; - }; - - - } - } + //Override Interrupt default methods + void handle_interrupt() final; + + //Ethernet Driver functions + void DoSend(uint8_t* buffer, uint32_t size) final; + uint64_t GetMediaAccessControlAddress() final; + }; + + + } + } } diff --git a/kernel/include/drivers/ethernet/ethernet.h b/kernel/include/drivers/ethernet/ethernet.h index d38ef6a3..1d991b9f 100644 --- a/kernel/include/drivers/ethernet/ethernet.h +++ b/kernel/include/drivers/ethernet/ethernet.h @@ -20,6 +20,7 @@ namespace MaxOS{ namespace ethernet { + /// Used to make MAC addresses more readable @todo make a MacAddress class and use mac_t typedef uint64_t MediaAccessControlAddress; /** diff --git a/kernel/include/drivers/ethernet/intel_i217.h b/kernel/include/drivers/ethernet/intel_i217.h index 16041e92..911e2e5b 100644 --- a/kernel/include/drivers/ethernet/intel_i217.h +++ b/kernel/include/drivers/ethernet/intel_i217.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -25,6 +26,39 @@ namespace MaxOS{ namespace ethernet{ + /** + * @struct ReceiveDescriptor + * @brief The receive descriptor for the Intel I217 Ethernet Controller + * + * @typedef receive_descriptor_t + * @brief Alias for ReceiveDescriptor struct + */ + typedef struct PACKED ReceiveDescriptor { + uint64_t bufferAddress; ///< The address of the receive buffer + uint16_t length; ///< The length of the received frame + uint16_t checksum; ///< The checksum of the received frame + uint8_t status; ///< The status of the received frame + uint8_t errors; ///< Any errors that occurred + uint16_t special; ///< Special + } receive_descriptor_t; + + /** + * @struct SendDescriptor + * @brief The send descriptor for the Intel I217 Ethernet Controller + * + * @typedef send_descriptor_t + * @brief Alias for SendDescriptor struct + */ + typedef struct PACKED SendDescriptor { + uint64_t bufferAddress; ///< The address of the send buffer + uint16_t length; ///< The length of the send frame + uint8_t cso; ///< The checksum offset + uint8_t cmd; ///< The command + uint8_t status; ///< The status + uint8_t css; ///< The checksum start + uint16_t special; ///< Special + } send_descriptor_t; + /** * @class IntelI217 @@ -32,25 +66,6 @@ namespace MaxOS{ */ class IntelI217 : public EthernetDriver, public hardwarecommunication::InterruptHandler { - struct receiveDescriptor { - uint64_t bufferAddress; // The address of the receive buffer - uint16_t length; // The length of the received frame - uint16_t checksum; // The checksum of the received frame - uint8_t status; // The status of the received frame - uint8_t errors; // Any errors that occurred - uint16_t special; // Special - } __attribute__((packed)); - - struct sendDescriptor { - uint64_t bufferAddress; // The address of the send buffer - uint16_t length; // The length of the send frame - uint8_t cso; // The checksum offset - uint8_t cmd; // The command - uint8_t status; // The status - uint8_t css; // The checksum start - uint16_t special; // Special - } __attribute__((packed)); - uint8_t bar_type = { 0 }; uint16_t portBase = { 0 }; uint64_t memBase = { 0 }; diff --git a/kernel/include/drivers/peripherals/keyboard.h b/kernel/include/drivers/peripherals/keyboard.h index 64cfe92a..def2e33d 100644 --- a/kernel/include/drivers/peripherals/keyboard.h +++ b/kernel/include/drivers/peripherals/keyboard.h @@ -25,12 +25,20 @@ namespace MaxOS { namespace peripherals { + /** + * @enum ScanCodeType + * @brief The type of scan code being sent by the keyboard + */ enum class ScanCodeType : int { REGULAR, - EXTENDED, + EXTENDED,237 EXTENDED_BUFFER }; + /** + * @enum KeyCode + * @brief A mapping of key codes to their values + */ enum class KeyCode : uint16_t { // Alphabet @@ -213,20 +221,24 @@ namespace MaxOS { ~KeyboardState(); // Left and Right - bool left_shift = false; ///< Is the left shift key pressed - bool right_shift = false; ///< Is the right shift key pressed - bool left_control = false; ///< Is the left control key pressed - bool right_control = false; ///< Is the right control key pressed - bool left_alt = false; ///< Is the left alt key pressed - bool right_alt = false; ///< Is the right alt key pressed + bool left_shift = false; ///< Is the left shift key pressed + bool right_shift = false; ///< Is the right shift key pressed + bool left_control = false; ///< Is the left control key pressed + bool right_control = false; ///< Is the right control key pressed + bool left_alt = false; ///< Is the left alt key pressed + bool right_alt = false; ///< Is the right alt key pressed // Other Stuff - bool caps_lock = false; ///< Is caps lock enabled - bool number_pad_lock = false; ///< Is number pad lock enabled - bool scroll_lock = false; ///< Is scroll lock enabled + bool caps_lock = false; ///< Is caps lock enabled + bool number_pad_lock = false; ///< Is number pad lock enabled + bool scroll_lock = false; ///< Is scroll lock enabled }; - enum KeyboardEvents { + /** + * @enum KeyboardEvents + * @brief The events that can be triggered by the Keyboard Driver + */ + enum class KeyboardEvents {f KEYDOWN, KEYUP }; @@ -279,11 +291,11 @@ namespace MaxOS { class KeyboardInterpreter : public common::InputStreamEventHandler, public common::EventManager { protected: - KeyboardState m_keyboard_state; ///< The current state of what special keys are pressed on the keyboard + KeyboardState m_keyboard_state; ///< The current state of what special keys are pressed on the keyboard - bool m_next_is_first_extended_code = false; ///< If true, the next code should be interpreted as an extended code (set when receiving 0xE0) - uint8_t m_extended_scan_code_bytes = 0; ///< How many bytes are left to read for the current extended scan code - uint16_t m_extended_code_buffer = 0; ///< The storage for scan codes that take more than one byte + bool m_next_is_first_extended_code = false; ///< If true, the next code should be interpreted as an extended code (set when receiving 0xE0) + uint8_t m_extended_scan_code_bytes = 0; ///< How many bytes are left to read for the current extended scan code + uint16_t m_extended_code_buffer = 0; ///< The storage for scan codes that take more than one byte public: KeyboardInterpreter(); diff --git a/kernel/include/filesystem/filesystem.h b/kernel/include/filesystem/filesystem.h index 31b1c762..6aa44f49 100644 --- a/kernel/include/filesystem/filesystem.h +++ b/kernel/include/filesystem/filesystem.h @@ -17,102 +17,98 @@ #include #include -namespace MaxOS{ +namespace MaxOS { - namespace filesystem{ + namespace filesystem { - // Easier to read - typedef uint32_t lba_t; - typedef syscore::filesystem::SeekType SeekType; - /** - * @class File - * @brief Handles file operations and information - */ - class File - { + typedef uint32_t lba_t; ///< Logical Block Addressing type + typedef syscore::filesystem::SeekType SeekType; ///< Seek type for file operations - protected: - uint32_t m_offset; ///< The current offset in the file - string m_name; ///< The name of the file - size_t m_size; ///< The size of the file + /** + * @class File + * @brief Handles file operations and information + */ + class File { - public: - File(); - virtual ~File(); + protected: + uint32_t m_offset; ///< The current offset in the file + string m_name; ///< The name of the file + size_t m_size; ///< The size of the file - virtual void write(const common::buffer_t* data, size_t size); - virtual void read(common::buffer_t* data, size_t size); - virtual void flush(); + public: + File(); + virtual ~File(); - void seek(SeekType seek_type, size_t offset); - uint32_t position(); + virtual void write(const common::buffer_t* data, size_t size); + virtual void read(common::buffer_t* data, size_t size); + virtual void flush(); - size_t size(); - string name(); - }; + void seek(SeekType seek_type, size_t offset); + uint32_t position(); + size_t size(); + string name(); + }; - /** - * @class Directory - * @brief Handles a group of files (directory) - */ - class Directory - { - protected: - common::Vector m_files; ///< The files in this directory - common::Vector m_subdirectories; ///< The subdirectories in this directory + /** + * @class Directory + * @brief Handles a group of files (directory) + */ + class Directory { + protected: + common::Vector m_files; ///< The files in this directory + common::Vector m_subdirectories; ///< The subdirectories in this directory - string m_name; ///< The name of this directory + string m_name; ///< The name of this directory - public: - Directory(); - virtual ~Directory(); + public: + Directory(); + virtual ~Directory(); - virtual void read_from_disk(); + virtual void read_from_disk(); - common::Vector files(); - common::Vector subdirectories(); + common::Vector files(); + common::Vector subdirectories(); - File* open_file(const string& name); - Directory* open_subdirectory(const string& name); + File* open_file(const string &name); + Directory* open_subdirectory(const string &name); - virtual File* create_file(const string& name); - virtual void remove_file(const string& name); + virtual File* create_file(const string &name); + virtual void remove_file(const string &name); - void rename_file(File* file, const string& new_name); - virtual void rename_file(const string& old_name, const string& new_name); + void rename_file(File* file, const string &new_name); + virtual void rename_file(const string &old_name, const string &new_name); - void rename_subdirectory(Directory* directory, const string& new_name); - virtual void rename_subdirectory(const string& old_name, const string& new_name); + void rename_subdirectory(Directory* directory, const string &new_name); + virtual void rename_subdirectory(const string &old_name, const string &new_name); - virtual Directory* create_subdirectory(const string& name); - virtual void remove_subdirectory(const string& name); + virtual Directory* create_subdirectory(const string &name); + virtual void remove_subdirectory(const string &name); - string name(); - size_t size(); - }; + string name(); + size_t size(); + }; - /** - * @class FileSystem - * @brief Handles the disk operations and file system information - */ - class FileSystem - { - protected: - Directory* m_root_directory; ///< The fist directory in the file system (not be confused with the system root) + /** + * @class FileSystem + * @brief Handles the disk operations and file system information + */ + class FileSystem { + protected: + Directory* m_root_directory; ///< The fist directory in the file system (not be confused with the system root) - public: - FileSystem(); - virtual ~FileSystem(); + public: + FileSystem(); + virtual ~FileSystem(); - Directory* root_directory(); - Directory* get_directory(const string& path); + Directory* root_directory(); + Directory* get_directory(const string &path); - bool exists(const string& path); - }; + bool exists(const string &path); + }; - } + } } diff --git a/kernel/include/filesystem/format/ext2.h b/kernel/include/filesystem/format/ext2.h index 35c13f22..831128f1 100644 --- a/kernel/include/filesystem/format/ext2.h +++ b/kernel/include/filesystem/format/ext2.h @@ -9,12 +9,13 @@ #ifndef MAXOS_FILESYSTEM_EXT2_H #define MAXOS_FILESYSTEM_EXT2_H -#include -#include #include -#include #include +#include +#include #include +#include +#include namespace MaxOS { namespace filesystem { @@ -24,8 +25,11 @@ namespace MaxOS { /** * @struct SuperBlock * @brief The metadata of the ext2 filesystem. Found at an offset of 1024 bytes from the start of the partition. + * + * @typedef superblock_t + * @brief Alias for SuperBlock struct */ - typedef struct SuperBlock { + typedef struct PACKED SuperBlock { uint32_t total_inodes; ///< Total number of inodes uint32_t total_blocks; ///< Total number of blocks uint32_t reserved_blocks; ///< Number of reserved blocks for superuser @@ -72,7 +76,7 @@ namespace MaxOS { uint32_t orphan_inodes_start; ///< The start of the list of inodes without a directory entry that need to be deleted uint8_t free[276]; ///< Reserved for future expansion - } __attribute__((packed)) superblock_t; + } superblock_t; /** * @enum FileSystemState @@ -145,9 +149,12 @@ namespace MaxOS { * @struct BlockGroupDescriptor * @brief The metadata for a block group in ext2 * + * @typedef block_group_descriptor_t + * @brief Alias for BlockGroupDescriptor struct + * * @todo Support updating directory_count when creating/deleting directories */ - typedef struct BlockGroupDescriptor { + typedef struct PACKED BlockGroupDescriptor { uint32_t block_usage_bitmap; ///< The block address of the block usage bitmap uint32_t block_inode_bitmap; ///< The block address of the inode usage bitmap uint32_t inode_table_address; ///< The starting block address of the inode table @@ -156,13 +163,16 @@ namespace MaxOS { uint16_t directory_count; ///< How many directories are in this block group uint8_t free[14]; ///< Reserved for future expansion - } __attribute__((packed)) block_group_descriptor_t; + } block_group_descriptor_t; /** * @struct Inode * @brief The metadata for a file or directory in ext2 + * + * @typedef inode_t + * @brief Alias for Inode struct */ - typedef struct Inode { + typedef struct PACKED Inode { union { uint16_t type_permissions; ///< The type and permissions of the inode struct { @@ -189,7 +199,7 @@ namespace MaxOS { uint32_t extended_attribute; ///< File extended attribute block (Access Control List) uint32_t size_upper; ///< The upper 32 bits of the size of the file in bytes (for files larger than 4GB). If this is a directory, this is the Directory Access Control List. uint32_t os_2[3]; ///< Second OS specific value (see InodeOS2Linux, ...) - } __attribute__((packed)) inode_t; + } inode_t; /** * @enum InodeType @@ -258,28 +268,34 @@ namespace MaxOS { * @struct InodeOS2Linux * @brief The OS specific data for Linux created ext2 inodes * + * @typedef linux_os_2_t + * @brief Alias for InodeOS2Linux struct + * * @todo HURD, MASIX */ - typedef struct InodeOS2Linux { + typedef struct PACKED InodeOS2Linux { uint8_t fragment; ///< The fragment number uint8_t fragment_size; ///< How many 1024 byte fragments are in the file uint16_t high_type_permissions; ///< The high bits of the type & permissions uint16_t high_user_id; ///< The high bits of the user ID uint16_t high_group_id; ///< The high bits of the group ID uint32_t author_id; ///< The user who created the inode (0xFFFFFFFF if use UID/GID fields) - } __attribute__((packed)) linux_os_2_t; + } linux_os_2_t; /** * @struct DirectoryEntry * @brief An entry in a directory that points to a file or subdirectory (the name follows this struct) + * + * @typedef directory_entry_t + * @brief Alias for DirectoryEntry struct */ - typedef struct DirectoryEntry { + typedef struct PACKED DirectoryEntry { uint32_t inode; ///< The inode number this entry points to (0 = unused) uint16_t size; ///< The total size of this entry (including name) uint8_t name_length; ///< The length of the name uint8_t type; ///< The type of the entry (see EntryType) (only if the high bit of the superblock's optional_features is set) // Rest are name chars - } __attribute__((packed)) directory_entry_t; + } directory_entry_t; /** * @enum EntryType diff --git a/kernel/include/filesystem/format/fat32.h b/kernel/include/filesystem/format/fat32.h index d3fb8325..aef84795 100644 --- a/kernel/include/filesystem/format/fat32.h +++ b/kernel/include/filesystem/format/fat32.h @@ -13,19 +13,23 @@ #ifndef MAXOS_FILESYSTEM_FAT32_H #define MAXOS_FILESYSTEM_FAT32_H +#include +#include #include #include -#include namespace MaxOS { namespace filesystem { namespace format { /** - * @struct BiosParameterBlock32 - * @brief Stores information about the FAT32 filesystem - */ - typedef struct BiosParameterBlock32 { + * @struct BiosParameterBlock32 + * @brief Stores information about the FAT32 filesystem + * + * @typedef bpb32_t + * @brief Alias for BiosParameterBlock32 struct + */ + typedef struct PACKED BiosParameterBlock32 { uint8_t jump[3]; ///< Jump instruction to boot code uint8_t OEM_name[8]; ///< OEM Name in ASCII @@ -56,13 +60,16 @@ namespace MaxOS { uint8_t volume_label[11]; ///< Volume label in ASCII (spaces padded) uint8_t file_system_type[8]; ///< System type in ASCII (not null-terminated) - } __attribute__((packed)) bpb32_t; + } bpb32_t; /** * @struct FSInfo * @brief Stores extra information about the FAT32 filesystem + * + * @typedef fs_info_t + * @brief Alias for FSInfo struct */ - typedef struct FSInfo { + typedef struct PACKED FSInfo { uint32_t lead_signature; ///< FSInfo lead signature (0x41615252) uint8_t reserved1[480]; ///< Reserved (should be zero) uint32_t structure_signature; ///< FSInfo structure signature (0x61417272) @@ -70,13 +77,16 @@ namespace MaxOS { uint32_t next_free_cluster; ///< Cluster number of the next free cluster (or 0xFFFFFFFF if unknown, start searching from cluster 2) uint8_t reserved2[12]; ///< Reserved (should be zero) uint32_t trail_signature; ///< FSInfo trail signature (0xAA550000) - } __attribute__((packed)) fs_info_t; + } fs_info_t; /** * @struct DirectoryEntry * @brief Stores information about a file or directory + * + * @typedef dir_entry_t + * @brief Alias for DirectoryEntry struct */ - typedef struct DirectoryEntry { + typedef struct PACKED DirectoryEntry { uint8_t name[8]; ///< File name uint8_t extension[3]; ///< File extension @@ -97,7 +107,7 @@ namespace MaxOS { uint32_t size; ///< File size in bytes - } __attribute__((packed)) dir_entry_t; + } dir_entry_t; /** * @enum DirectoryEntryAttributes @@ -126,8 +136,11 @@ namespace MaxOS { /** * @struct LongFileNameEntry * @brief Directory entry for a long file name + * + * @typedef long_file_name_entry_t + * @brief Alias for LongFileNameEntry struct */ - typedef struct LongFileNameEntry { + typedef struct PACKED LongFileNameEntry { uint8_t order; ///< Index of this entry in the sequence of LFN entries uint16_t name1[5]; ///< First 5 characters of the long file name uint8_t attributes; ///< Attributes (always 0x0F for LFN entries) @@ -137,7 +150,7 @@ namespace MaxOS { uint16_t zero; ///< Must be zero uint16_t name3[2]; ///< Last 2 characters of the long file name - } __attribute__((packed)) long_file_name_entry_t; + } long_file_name_entry_t; /** * @enum ClusterState diff --git a/kernel/include/filesystem/partition/msdos.h b/kernel/include/filesystem/partition/msdos.h index 6165a885..7eb5c36c 100644 --- a/kernel/include/filesystem/partition/msdos.h +++ b/kernel/include/filesystem/partition/msdos.h @@ -21,7 +21,6 @@ namespace MaxOS { namespace partition { - /// Credit: http://www.osdever.net/documents/pdf/partitiontypes.pdf enum class PartitionType { EMPTY, // 0x00 @@ -302,8 +301,11 @@ namespace MaxOS { /** * @struct PartitionTableEntry * @brief Stores information about a partition + * + * @typedef partition_table_entry_t + * @brief Alias for PartitionTableEntry struct */ - struct PartitionTableEntry { + typedef struct PACKED PartitionTableEntry { uint8_t bootable; ///< Is this partition bootable? (0x80 = bootable, 0x00 = not bootable) @@ -320,13 +322,16 @@ namespace MaxOS { uint32_t start_LBA; ///< The starting LBA of the partition uint32_t length; ///< The length of the partition in sectors - } __attribute__((packed)); + } partition_table_entry_t; /** * @struct MasterBootRecord * @brief Stores information about the master boot record + * + * @typedef master_boot_record_t + * @brief Alias for MasterBootRecord struct */ - struct MasterBootRecord { + typedef struct PACKED MasterBootRecord { uint8_t bootloader[440]; ///< The assembly bytes that make up the bootloader software uint32_t disk_signature; ///< Unique disk signature (optional) @@ -336,7 +341,7 @@ namespace MaxOS { uint16_t magic; ///< The magic number that identifies this as a valid MBR (0xAA55) - } __attribute__((packed)); + } master_boot_record_t; /** diff --git a/kernel/include/gui/widget.h b/kernel/include/gui/widget.h index 87bbe515..9d4656bb 100644 --- a/kernel/include/gui/widget.h +++ b/kernel/include/gui/widget.h @@ -135,23 +135,20 @@ namespace MaxOS{ }; - typedef WidgetMoverResizer<1, 1, 0, 0> WidgetMover; + typedef WidgetMoverResizer<1, 1, 0, 0> WidgetMover; ///< A widget mover that moves the widget without resizing it - typedef WidgetMoverResizer<0, 1, 0, -1> WidgetMoverResizerTop; - typedef WidgetMoverResizer<0, 0, 0, 1> WidgetMoverResizerBottom; - typedef WidgetMoverResizer<1, 0, -1, 0> WidgetMoverResizerLeft; - typedef WidgetMoverResizer<0, 0, 1, 0> WidgetMoverResizerRight; + typedef WidgetMoverResizer<0, 1, 0, -1> WidgetMoverResizerTop; ///< A widget mover and resizer that resizes the top edge of the widget + typedef WidgetMoverResizer<0, 0, 0, 1> WidgetMoverResizerBottom; ///< A widget mover andresizer that resizes the bottom edge of the widget + typedef WidgetMoverResizer<1, 0, -1, 0> WidgetMoverResizerLeft; ///< A widget mover and resizer that resizes the left edge of the widget + typedef WidgetMoverResizer<0, 0, 1, 0> WidgetMoverResizerRight; ///< A widget mover and resizer that resizes the right edge of the widget - typedef WidgetMoverResizer<1, 1, -1, -1> WidgetMoverResizerTopLeft; - typedef WidgetMoverResizer<0, 1, 1, -1> WidgetMoverResizerTopRight; - typedef WidgetMoverResizer<1, 0, -1, 1> WidgetMoverResizerBottomLeft; - typedef WidgetMoverResizer<0, 0, 1, 1> WidgetMoverResizerBottomRight; + typedef WidgetMoverResizer<1, 1, -1, -1> WidgetMoverResizerTopLeft; ///< A widget mover and resizer that resizes the top-left corner of the widget + typedef WidgetMoverResizer<0, 1, 1, -1> WidgetMoverResizerTopRight; ///< A widget mover and resizer that resizes the top-right corner of the widget + typedef WidgetMoverResizer<1, 0, -1, 1> WidgetMoverResizerBottomLeft; ///< A widget mover and resizer that resizes the bottom-left corner of the widget + typedef WidgetMoverResizer<0, 0, 1, 1> WidgetMoverResizerBottomRight; ///< A widget mover and resizer that resizes the bottom-right corner of the widget - - ///________________________________Tempaltes________________________________/// + ////@TODO move this to the cpp file /** - - * @details WidgetMoverResizer is a template class that allows you to move and resize a widget * * @tparam Left The left edge of the widget diff --git a/kernel/include/hardwarecommunication/acpi.h b/kernel/include/hardwarecommunication/acpi.h index aa7beb77..542be048 100644 --- a/kernel/include/hardwarecommunication/acpi.h +++ b/kernel/include/hardwarecommunication/acpi.h @@ -22,33 +22,42 @@ namespace MaxOS { /** * @struct RSDPDescriptor - * @brief Root System Description Pointer (RSDP) structure for ACPI 1. Ide + * @brief Root System Description Pointer (RSDP) structure for ACPI 1. + * + * @typedef rsdp_descriptor_t + * @brief Alias for RSDPDescriptor struct */ - typedef struct RSDPDescriptor { + typedef struct PACKED RSDPDescriptor { char signature[8]; ///< Indicates a valid RSDP structure if it contains "RSD PTR " (null-terminated) uint8_t checksum; ///< This byte added to all bytes in the table must equal zero for the table to be valid char OEMID[6]; ///< A string supplied by the OEM to identify the OEM uint8_t revision; ///< The version of the ACPI specification that is supported (higher means more features and is backwards compatible) uint32_t rsdt_address; ///< The physical address of the RSDT (@deprecated in ACPI 2 and above) - } __attribute__ ((packed)) rsdp_descriptor_t; + } rsdp_descriptor_t; /** * @struct RSDPDescriptor2 * @brief Root System Description Pointer (RSDP) structure for ACPI 2 and above + * + * @typedef rsdp_descriptor2_t + * @brief Alias for RSDPDescriptor2 struct */ - typedef struct RSDPDescriptor2 { + typedef struct PACKED RSDPDescriptor2 { RSDPDescriptor version_1_info; ///< The ACPI 1 RSDP structure (see rsdp_descriptor_t) uint32_t length; ///< The total length of the RSDP structure (including the version 1 part) uint64_t xsdt_address; ///< The physical address of the XSDT uint8_t extended_checksum; ///< This byte added to all bytes in the table must equal zero for the table to be valid (including the version 1 part) uint8_t reserved[3]; ///< Reserved, must be zero - } __attribute__ ((packed)) rsdp_descriptor2_t; + } rsdp_descriptor2_t; /** * @struct ACPISDTHeader * @brief Common header for all ACPI System Description Tables (SDTs) + * + * @typedef acpi_sdt_header_t + * @brief Alias for ACPISDTHeader struct */ - typedef struct ACPISDTHeader { + typedef struct PACKED ACPISDTHeader { char signature[4]; ///< The signature that identifies the type of the table uint32_t length; ///< The size of the entire table, including the header, in bytes uint8_t revision; ///< The version of the ACPI specification that is supported (higher means more features and is backwards compatible) @@ -58,11 +67,14 @@ namespace MaxOS { uint32_t OEM_revision; ///< The revision number of the table as supplied by the OEM uint32_t creator_id; ///< A vendor ID of the utility that created the table uint32_t creator_revision; ///< The revision number of the utility that created the table - } __attribute__ ((packed)) acpi_sdt_header_t; + } acpi_sdt_header_t; /** * @struct RSDT * @brief Root System Description Table (RSDT) structure for ACPI 1. Contains the header and an array of pointers to other SDTs + * + * @typedef rsdt_t + * @brief Alias for RSDT struct */ typedef struct RSDT { ACPISDTHeader header; ///< The common header for all ACPI SDTs (see acpi_sdt_header_t) @@ -72,6 +84,9 @@ namespace MaxOS { /** * @struct XSDT * @brief Extended System Description Table (XSDT) structure for ACPI 2 and above. Contains the header and an array of pointers to other SDTs + * + * @typedef xsdt_t + * @brief Alias for XSDT struct */ typedef struct XSDT { ACPISDTHeader header; ///< The common header for all ACPI SDTs (see acpi_sdt_header_t) diff --git a/kernel/include/hardwarecommunication/apic.h b/kernel/include/hardwarecommunication/apic.h index dfe4371f..f9ee9e50 100644 --- a/kernel/include/hardwarecommunication/apic.h +++ b/kernel/include/hardwarecommunication/apic.h @@ -9,6 +9,7 @@ #ifndef MAXOS_HARDWARECOMMUNICATION_APIC_H #define MAXOS_HARDWARECOMMUNICATION_APIC_H +#include #include #include #include @@ -47,21 +48,27 @@ namespace MaxOS { * @struct MADT * @brief Multiple APIC Description Table (MADT) (ACPI 2 or higher). Provides information about the APICs in * the system. Following this header are multiple entries describing the APICs (see MADTEntry). + * + * @typedef madt_t + * @brief Alias for MADT struct */ - typedef struct MADT { + typedef struct PACKED MADT { ACPISDTHeader header; ///< Common ACPI SDT header uint32_t local_apic_address; ///< The physical address of the local APIC uint32_t flags; ///< Flags indicating the capabilities of the system (1 = Legacy PICs are present) - } __attribute__((packed)) madt_t; + } madt_t; /** * @struct MADTEntry * @brief An item in the MADT table + * + * @typedef madt_entry_t + * @brief Alias for MADTEntry struct */ - typedef struct MADTEntry { + typedef struct PACKED MADTEntry { uint8_t type; ///< The type of the MADT entry (see MADT_TYPE) uint8_t length; ///< How many bytes this entry takes up (including the type and length fields) - } __attribute__((packed)) madt_entry_t; + } madt_entry_t; /** * @enum MADT_TYPE @@ -81,31 +88,40 @@ namespace MaxOS { * @struct MADT_IO_APIC * @brief An entry in the MADT table describing an IO APIC * + * @typedef madt_io_apic_t + * @brief Alias for MADT_IO_APIC struct + * * @todo Rename for consistency */ - typedef struct MADT_IO_APIC { + typedef struct PACKED MADT_IO_APIC { uint8_t io_apic_id; ///< The ID of the IO APIC uint8_t reserved; ///< Reserved uint32_t io_apic_address; ///< The physical address of the IO APIC uint32_t global_system_interrupt_base; ///< The first GSI number that this IO APIC handles - } __attribute__((packed)) madt_io_apic_t; + } madt_io_apic_t; /** * @struct MADT_PROCESSOR_APIC * @brief An entry in the MADT table describing a processor local APIC + * + * @typedef madt_processor_apic_t + * @brief Alias for MADT_PROCESSOR_APIC struct */ - typedef struct MADT_PROCESSOR_APIC { + typedef struct PACKED MADT_PROCESSOR_APIC { uint8_t processor_id; ///< The ID for the core uint8_t apic_id; ///< The ID for the APIC that the core uses uint32_t flags; ///< Flags indicating the status of the core (bit 0 = core enabled, bit 1 = can be enabled) - } __attribute__((packed)) madt_processor_apic_t; + } madt_processor_apic_t; /** - * @struct RedirectionEntry + * @union RedirectionEntry * @brief An IO APIC redirection entry. Describes how an interrupt is routed. + * + * @typedef redirection_entry_t + * @brief Alias for RedirectionEntry union */ typedef union RedirectionEntry { - struct { + struct PACKED { uint64_t vector: 8; ///< The interrupt that will be triggered when this redirection entry is used uint64_t delivery_mode: 3; ///< How the interrupt will be delvied to the core(s) (see DeliveryMode) uint64_t destination_mode: 1; ///< How to interpret the destination field (0 = means its the core ID, 1 = means a bitmask of cores) @@ -116,7 +132,7 @@ namespace MaxOS { uint64_t mask: 1; ///< Whether the interrupt is disabled or not uint64_t reserved: 39; ///< Reserved bits (should be zero) uint64_t destination: 8; ///< The core(s) the interrupt should be sent to (interpreted based on destination_mode) - } __attribute__((packed)); ///< Packed because the bitfields should be one uint64_t together + }; ///< Packed because the bitfields should be one uint64_t together uint64_t raw; ///< The raw 64-bit value of the redirection entry } redirection_entry_t; @@ -139,8 +155,12 @@ namespace MaxOS { /** * @struct InterruptRedirect * @brief Defines how an interrupt input is redirected to a specific processor via the I/O APIC + * + * @typedef interrupt_redirect_t + * @brief Alias for InterruptRedirect struct */ typedef struct InterruptRedirect { + uint8_t type; ///< The type of redirect (should be 0 for normal interrupts) uint8_t index; ///< Where in the IO APIC redirection table this redirect should be placed uint8_t interrupt; ///< The interrupt number to trigger when this redirect is used @@ -153,13 +173,18 @@ namespace MaxOS { /** * @struct Override * @brief Specifies how a specific interrupt source is mapped to a global system interrupt + * + * @typedef override_t + * @brief Alias for Override struct */ - typedef struct Override { + typedef struct PACKED Override { + uint8_t bus; ///< Identifies the hardware bus the interrupt comes from (0 = ISA, 1 = PCI) uint8_t source; ///< The interrupt source number on the specified bus uint32_t global_system_interrupt; ///< The global system interrupt that the source is mapped to uint16_t flags; ///< Flags describing the polarity and trigger mode of the interrupt source (see MADT override flags) - } __attribute__((packed)) override_t; + + } override_t; /** * @class IOAPIC diff --git a/kernel/include/hardwarecommunication/interrupts.h b/kernel/include/hardwarecommunication/interrupts.h index 6768ce6a..95d0c56d 100644 --- a/kernel/include/hardwarecommunication/interrupts.h +++ b/kernel/include/hardwarecommunication/interrupts.h @@ -22,7 +22,6 @@ namespace MaxOS { namespace hardwarecommunication { - class InterruptManager; /** @@ -45,17 +44,24 @@ namespace MaxOS { /** * @struct IDTR * @brief A struct that holds the Interrupt Descriptor Table Register (IDTR) + * + * @typedef idtr_t + * @brief Alias for IDTR struct */ - typedef struct IDTR { + typedef struct PACKED IDTR { uint16_t limit; ///< The size of the IDT uint64_t base; ///< The start address of the IDT - } __attribute__((packed)) idtr_t; + } idtr_t; - /** + /** * @struct InterruptDescriptor * @brief An entry in the Interrupt Descriptor Table (IDT) + * + * @typedef interrupt_descriptor_t + * @brief Alias for InterruptDescriptor struct */ - typedef struct InterruptDescriptor{ + typedef struct PACKED InterruptDescriptor{ + uint16_t address_low_bits; ///< The low bits of the handler function address uint16_t segment_selector; ///< The code segment selector in the GDT to use when this interrupt fires uint8_t ist; ///< The offset into the Interrupt Stack Table (0 if not used) (see TSS) @@ -63,7 +69,8 @@ namespace MaxOS { uint16_t address_mid_bits; ///< The middle bits of the handler function address uint32_t address_high_bits; ///< The high bits of the handler function address uint32_t reserved; ///< Reserved, must be zero - } __attribute__((packed)) interrupt_descriptor_t; + + } interrupt_descriptor_t; constexpr uint16_t HARDWARE_INTERRUPT_OFFSET = 0x20; ///< The offset in the IDT where interrupts from hardware start constexpr uint16_t MAX_INTERRUPT_HANDLERS = 256; ///< The maximum number of interrupt handlers diff --git a/kernel/include/memory/physical.h b/kernel/include/memory/physical.h index 72f1f6bf..1aeceeb2 100644 --- a/kernel/include/memory/physical.h +++ b/kernel/include/memory/physical.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -19,23 +20,25 @@ namespace MaxOS { namespace memory { - #define ENTRIES_TO_ADDRESS(pml4, pdpr, pd, pt)((pml4 << 39) | (pdpr << 30) | (pd << 21) | (pt << 12)) - #define PMLX_GET_INDEX(ADDR, LEVEL) (((uint64_t)ADDR & ((uint64_t)0x1ff << (12 + LEVEL * 9))) >> (12 + LEVEL * 9)) + #define ENTRIES_TO_ADDRESS(pml4, pdpr, pd, pt)((pml4 << 39) | (pdpr << 30) | (pd << 21) | (pt << 12)) ///< Convert page map level indices to a virtual address + #define PMLX_GET_INDEX(ADDR, LEVEL) (((uint64_t)ADDR & ((uint64_t)0x1ff << (12 + LEVEL * 9))) >> (12 + LEVEL * 9)) ///< Get the index for a given page map level from a virtual address - #define PML4_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 3) - #define PML3_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 2) - #define PML2_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 1) - #define PML1_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 0) + #define PML4_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 3) ///< Get the PML4 index from a virtual address + #define PML3_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 2) ///< Get the PDPT index from a virtual address + #define PML2_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 1) ///< Get the PDP index from a virtual address + #define PML1_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 0) ///< Get the PT index from a virtual address - // Useful for readability - typedef void virtual_address_t; - typedef void physical_address_t; + typedef void virtual_address_t; ///< A type representing a virtual address (used for readability) + typedef void physical_address_t; ///< A type representing a physical address (used for readability) /** * @enum PageFlags * @brief Flags for page table entries * - * @todo: fix. this is stupid. Leave as enum not enum class for bitwise operations + * @typedef page_flags_t + * @brief Alias for PageFlags enum + * + * @todo: fix. this is stupid: Leave as enum not enum class for bitwise operations */ typedef enum PageFlags { NONE = 0, ///< No flags @@ -54,8 +57,12 @@ namespace MaxOS { /** * @struct PageTableEntry * @brief Struct for a page table entry + * + * @typedef pte_t + * @brief Alias for PageTableEntry struct */ - typedef struct PageTableEntry { + typedef struct PACKED PageTableEntry { + bool present: 1; ///< *copydoc PageFlags::PRESENT bool write: 1; ///< *copydoc PageFlags::WRITE bool user: 1; ///< *copydoc PageFlags::USER @@ -67,16 +74,21 @@ namespace MaxOS { bool global: 1; ///< *copydoc PageFlags::GLOBAL uint8_t available: 3; ///< Extra metadata bytes available for OS use uint64_t physical_address: 52; ///< The address the page represents in memory - } __attribute__((packed)) pte_t; + + } pte_t; /** * @struct PageMapLevel * @brief Struct for a page map level (PML4, PDPT, PD, PT) + * + * @typedef pml_t + * @brief Alias for PageMapLevel struct */ - typedef struct PageMapLevel { + typedef struct PACKED PageMapLevel { + pte_t entries[512]; ///< The entries in this page map level. If it is a PT then these are page table entries, otherwise they are pointers to the next level. Indexed by the relevant bits in the virtual address. - } __attribute__((packed)) pml_t; + } pml_t; constexpr uint64_t PAGE_SIZE = 0x1000; ///< The size of a page (4KB) constexpr uint8_t ROW_BITS = 64; ///< The number of bits in the bitmap row @@ -114,7 +126,7 @@ namespace MaxOS { uint64_t* m_pml4_root_address; pte_t* m_pml4_root; - bool m_initialized; + bool m_initialised; bool m_nx_allowed; common::Spinlock m_lock; diff --git a/kernel/include/memory/virtual.h b/kernel/include/memory/virtual.h index 577ddcf2..98489ddb 100644 --- a/kernel/include/memory/virtual.h +++ b/kernel/include/memory/virtual.h @@ -22,10 +22,14 @@ namespace MaxOS { * @enum VirtualFlags * @brief Flags for chunks used in virtual memory allocation * + * @typedef virtual_flags_t + * @brief Alias for VirtualFlags enum + * * @see PageFlags * @note 0 - (1 << 8) are reserved for the page flags */ typedef enum VirtualFlags { + RESERVE = (1 << 9), ///< Reserve the memory but do not map any physical memory to it SHARED = (1 << 10), ///< The memory is shared between multiple processes @@ -35,9 +39,13 @@ namespace MaxOS { * @struct VirtualMemoryChunk * @brief A container for a region of virtual memory that has been allocated by the Virtual Memory Manager * + * @typedef virtual_memory_chunk_t + * @brief Alias for VirtualMemoryChunk struct + * * @see VirtualFlags */ typedef struct VirtualMemoryChunk { + uintptr_t start_address; ///< The first virtual address that this chunk covers size_t size; ///< The size of the chunk's memory region in bytes size_t flags; ///< The flags for the memory (see VirtualFlags) @@ -47,26 +55,37 @@ namespace MaxOS { /** * @struct FreeChunk * @brief A chunk of memory that has been freed and is available for allocation. A node in a linked list. + * + * @typedef free_chunk_t + * @brief Alias for FreeChunk struct */ typedef struct FreeChunk { + uintptr_t start_address; ///< *copydoc VirtualMemoryChunk::start_address size_t size; ///< *copydoc VirtualMemoryChunk::size struct FreeChunk* next; ///< Pointer to the next free chunk in the list (not sequential in memory) + } free_chunk_t; - static const size_t CHUNKS_PER_PAGE = PAGE_SIZE / sizeof(virtual_memory_chunk_t) - 1; ///< Number of chunks per virtual memory region (limited to fit in one page) + static const size_t CHUNKS_PER_PAGE = PAGE_SIZE / sizeof(virtual_memory_chunk_t) - + 1; ///< Number of chunks per virtual memory region (limited to fit in one page) static const size_t VMM_RESERVED = 0x138000000; ///< The starting address for the VMM to start allocating from when in higher half (otherwise can cause conflicts with kernel space) /** * @struct VirtualMemoryRegion * @brief A region of virtual memory containing multiple chunks (should fit in one page). * + * @typedef virtual_memory_region_t + * @brief Alias for VirtualMemoryRegion struct + * * @note This stores the metadata for the chunks, not the actual memory they represent. (ie chunks are not slices of this region) */ - typedef struct VirtualMemoryRegion { + typedef struct PACKED VirtualMemoryRegion { + virtual_memory_chunk_t chunks[CHUNKS_PER_PAGE]; ///< The metadata for the chunks in this region struct VirtualMemoryRegion* next; ///< Pointer to the next region in the list - } __attribute__((packed)) virtual_memory_region_t; + + } virtual_memory_region_t; /** * @class VirtualMemoryManager @@ -92,7 +111,6 @@ namespace MaxOS { void new_region(); void fill_up_to_address(uintptr_t address, size_t flags, bool mark_used); - public: VirtualMemoryManager(); ~VirtualMemoryManager(); diff --git a/kernel/include/net/arp.h b/kernel/include/net/arp.h index c8282e11..c4e71b9a 100644 --- a/kernel/include/net/arp.h +++ b/kernel/include/net/arp.h @@ -20,8 +20,11 @@ namespace MaxOS { /** * @struct ARPMessage * @brief An ARP message + * + * @typedef arp_message_t + * @brief Alias for ARPMessage struct */ - struct ARPMessage { + typedef struct PACKED ARPMessage { uint16_t hardwareType; ///< The type of device that sent the ARP message (1 = Ethernet) uint16_t protocol; ///< The protocol being used (0x0800 = IPv4) @@ -36,7 +39,7 @@ namespace MaxOS { uint32_t dstIP; ///< The IP address of the target - }__attribute__((packed)); + } arp_message_t; /** * @class AddressResolutionProtocol diff --git a/kernel/include/net/ethernetframe.h b/kernel/include/net/ethernetframe.h index 7476b5e9..e6c36937 100644 --- a/kernel/include/net/ethernetframe.h +++ b/kernel/include/net/ethernetframe.h @@ -23,23 +23,31 @@ namespace MaxOS { /** * @struct EthernetFrameHeader * @brief Structure the raw data. This is the header of an Ethernet Frame + * + * @typedef ethernet_frame_header_t + * @brief Alias for EthernetFrameHeader struct */ - struct EthernetFrameHeader { + typedef struct PACKED EthernetFrameHeader { uint64_t destinationMAC: 48; ///< The mac address of the target (Big Endian) uint64_t sourceMAC: 48; ///< The mac address of the sender (Big Endian) uint16_t type; ///< The type (Big Endian) 0x0800 = IPv4, 0x0806 = ARP, 0x86DD = IPv6 - }__attribute__ ((packed)); + } ethernet_frame_header_t; /** * @struct EthernetFrameFooter * @brief Structure the raw data. This is the footer of an Ethernet Frame + * + * @typedef ethernet_frame_footer_t + * @brief Alias for EthernetFrameFooter struct */ - struct EthernetFrameFooter { + typedef struct PACKED EthernetFrameFooter { + uint32_t checksum; ///< Checksum of the payload - }__attribute__ ((packed)); + + } ethernet_frame_footer_t; class EthernetFrameHandler; diff --git a/kernel/include/net/icmp.h b/kernel/include/net/icmp.h index 44cbac2b..9e60e804 100644 --- a/kernel/include/net/icmp.h +++ b/kernel/include/net/icmp.h @@ -21,14 +21,19 @@ namespace MaxOS { /** * @struct ICMPHeader * @brief The header of an ICMP packet + * + * @typedef icmp_header_t + * @brief Alias for ICMPHeader struct */ - struct ICMPHeader { + typedef struct PACKED ICMPHeader { + uint8_t type; ///< The type of ICMP message uint8_t code; ///< The code of the ICMP message uint16_t checksum; ///< Checksum to verify integrity uint32_t data; ///< Payload data (Varies by type and code) - }__attribute__((packed)); + + } icmp_header_t; /** * @class InternetControlMessageProtocol diff --git a/kernel/include/net/ipv4.h b/kernel/include/net/ipv4.h index 278bbef4..9a6caad2 100644 --- a/kernel/include/net/ipv4.h +++ b/kernel/include/net/ipv4.h @@ -16,14 +16,18 @@ namespace MaxOS { namespace net { - typedef uint32_t InternetProtocolAddress; - typedef uint32_t SubnetMask; + typedef uint32_t InternetProtocolAddress; ///< An IPv4 address @todo: Make IPv4Address class and do ip_t + typedef uint32_t SubnetMask; ///< A subnet mask @todo: Make SubnetMask class and do subnetmask_t /** * @struct IPV4Header * @brief The header of an IPv4 packet + * + * @typedef ipv4_header_t + * @brief Alias for IPV4Header struct */ - struct IPV4Header { + typedef struct PACKED IPV4Header { + uint8_t headerLength: 4; ///< The length of the header in 32-bit words (min 5, max 15) uint8_t version: 4; ///< The version of the IP protocol (4 for IPv4) uint8_t typeOfService; ///< The type of service (low delay, high throughput, high reliability, etc. @todo: enum @@ -38,7 +42,8 @@ namespace MaxOS { uint32_t sourceIP; ///< The IP of the sender uint32_t destinationIP; ///< The IP of the receiver - } __attribute__((packed)); + + } ipv4_header_t; class InternetProtocolHandler; diff --git a/kernel/include/net/tcp.h b/kernel/include/net/tcp.h index 396d3b7b..5dc13015 100644 --- a/kernel/include/net/tcp.h +++ b/kernel/include/net/tcp.h @@ -17,7 +17,7 @@ namespace MaxOS { namespace net { - typedef uint16_t TransmissionControlProtocolPort; + typedef uint16_t TransmissionControlProtocolPort; ///< TCP port @todo: Make TCPPort class and do tcp_port_t /** * @enum TCPSocketState @@ -59,8 +59,12 @@ namespace MaxOS { /** * @struct TCPHeader * @brief The header of a TCP packet + * + * @typedef tcp_header_t + * @brief Alias for TCPHeader struct */ - struct TCPHeader { + typedef struct PACKED TCPHeader { + uint16_t srcPort; ///< The port of the sender uint16_t dstPort; ///< The port of the receiver uint32_t sequenceNumber; ///< Where this packet's data fits in the overall order of the data stream @@ -75,7 +79,8 @@ namespace MaxOS { uint16_t urgentPtr; ///< Where in the data the urgent data *ends* (if the URG flag is set) uint32_t options; ///< The options for the TCP packet (MSS, Window Scale, SACK Permitted) @todo: make this a struct - } __attribute__((packed)); + + } tcp_header_t; /** * @struct TCPPseudoHeader @@ -83,13 +88,18 @@ namespace MaxOS { * * @details The pseudo header is used to calculate the checksum of the TCP header. It is a copy of the IP * header, but with the protocol field set to 6 (TCP) and the length field set to the length of the TCP header. + * + * @typedef tcp_pseudo_header_t + * @brief Alias for TCPPseudoHeader struct */ - struct TCPPseudoHeader { + typedef struct PACKED TCPPseudoHeader { + uint32_t srcIP; ///< The IP address of the sender uint32_t dstIP; ///< The IP address of the receiver uint16_t protocol; ///< The protocol (set to 6 for TCP) uint16_t totalLength; ///< The total length of the TCP header and data - } __attribute__((packed)); + + } tcp_pseudo_header_t; // Forward declarations diff --git a/kernel/include/net/udp.h b/kernel/include/net/udp.h index 3c9e56c3..d93f6bec 100644 --- a/kernel/include/net/udp.h +++ b/kernel/include/net/udp.h @@ -21,15 +21,18 @@ namespace MaxOS { /** * @struct UDPHeader * @brief The header of a UDP packet + * + * @typedef udp_header_t + * @brief Alias for UDPHeader struct */ - struct UDPHeader { + typedef struct PACKED UDPHeader { uint16_t sourcePort; ///< The port of the sender uint16_t destinationPort; ///< The port of the receiver uint16_t length; ///< The length of the UDP header and data uint16_t checksum; ///< The checksum of the header and data - } __attribute__((packed)); + } udp_header_t; /** * @enum UDPEvents @@ -43,7 +46,7 @@ namespace MaxOS { class UDPSocket; class UserDatagramProtocolHandler; - typedef uint16_t UserDatagramProtocolPort; + typedef uint16_t UserDatagramProtocolPort; ///< UDP port @todo: Make UDPPort class and do udp_port_t (or generic port that can be used for TCP and UDP) /** * @class UDPDataReceivedEvent diff --git a/kernel/include/processes/elf.h b/kernel/include/processes/elf.h index e2054e90..58dfb374 100644 --- a/kernel/include/processes/elf.h +++ b/kernel/include/processes/elf.h @@ -103,8 +103,12 @@ namespace MaxOS { /** * @struct ELFHeader64 * @brief The header of a 64-bit ELF file + * + * @typedef elf_64_header_t + * @brief Alias for ELFHeader64 struct */ typedef struct ELFHeader64 { + unsigned char identification[16]; ///< Identifies the file as an ELF file and contains metadata about the file (class, data encoding, version, OS ABI, etc.) uint16_t type; ///< The type of the ELF file (see ELFType) uint16_t machine; ///< The target architecture of the ELF file (see ELFMachine) @@ -119,6 +123,7 @@ namespace MaxOS { uint16_t section_header_size; ///< The size of each entry in the section header table uint16_t section_header_count; ///< The number of entries in the section header table uint16_t section_header_string_table_index; ///< Where the section header string table is located (index into the section header table) + } elf_64_header_t; /** @@ -150,8 +155,12 @@ namespace MaxOS { /** * @struct ELFProgramHeader64 * @brief The header for the program segments in a 64-bit ELF file + * + * @typedef elf_64_program_header_t + * @brief Alias for ELFProgramHeader64 struct */ typedef struct ELFProgramHeader64 { + uint32_t type; ///< The type of the program header (see ELFProgramType) uint32_t flags; ///< The flags of the program header (see ELFProgramFlags) uint64_t offset; ///< The offset in the file where the segment is located @@ -160,6 +169,7 @@ namespace MaxOS { uint64_t file_size; ///< The size of the segment in the file uint64_t memory_size; ///< The size of the segment in memory (should be >= file_size) uint64_t align; ///< The required alignment of the segment in memory (normally 2^n) + } elf_64_program_header_t; /** @@ -181,8 +191,12 @@ namespace MaxOS { /** * @struct ELFSectionHeader64 * @brief The header for the sections in a 64-bit ELF file + * + * @typedef elf_64_section_header_t + * @brief Alias for ELFSectionHeader64 struct */ typedef struct ELFSectionHeader64 { + uint32_t name_index; ///< The index into the section header string table where the name of this section is located uint32_t type; ///< The type of the section (see ELFSectionType) uint64_t sh_flags; ///< The flags of the section (see ELFSectionFlags) @@ -193,6 +207,7 @@ namespace MaxOS { uint32_t info; ///< Extra information (meaning depends on section type) uint64_t address_alignment; ///< The required alignment of the section in memory (normally 2^n) uint64_t entry_size; ///< The size of each entry in the section if it contains a table of fixed-size entries + } elf_64_section_header_t; /** diff --git a/kernel/include/processes/process.h b/kernel/include/processes/process.h index 622584da..20d1864f 100644 --- a/kernel/include/processes/process.h +++ b/kernel/include/processes/process.h @@ -20,12 +20,19 @@ #include #include - namespace MaxOS { namespace processes { - + class Process; + + /** + * @enum ThreadState + * @brief The different operational states a thread can be in + * + * @typedef thread_state_t + * @brief Alias for ThreadState enum + */ typedef enum class ThreadState{ NEW, RUNNING, @@ -35,9 +42,7 @@ namespace MaxOS STOPPED } thread_state_t; - - // Forward declaration - class Process; + /// The size of the stack for each thread (4KB) constexpr size_t STACK_SIZE = 0x10000; /** diff --git a/kernel/include/processes/resource.h b/kernel/include/processes/resource.h index f47dfa8f..34fc0b5e 100644 --- a/kernel/include/processes/resource.h +++ b/kernel/include/processes/resource.h @@ -19,8 +19,8 @@ namespace MaxOS { namespace processes { - typedef ::syscore::ResourceType resource_type_t; - typedef ::syscore::ResourceErrorBase resource_error_base_t; + typedef ::syscore::ResourceType resource_type_t; ///< Alias to make the libsyscore ResourceType accessible here + typedef ::syscore::ResourceErrorBase resource_error_base_t; ///< Alias to make the libsyscore ResourceErrorBase accessible here /** * @class Resource diff --git a/kernel/include/runtime/cplusplus.h b/kernel/include/runtime/cplusplus.h index bd424d04..48bea211 100644 --- a/kernel/include/runtime/cplusplus.h +++ b/kernel/include/runtime/cplusplus.h @@ -16,8 +16,8 @@ namespace MaxOS { namespace runtime { - typedef void (* constructor)(); - typedef unsigned uarch_t; + typedef void (* constructor)(); ///< A pointer to a constructor function + typedef unsigned uarch_t; ///< An unsigned architecture specific type extern "C" { @@ -31,13 +31,30 @@ namespace MaxOS { void* dso_handle; ///< The DSO handle (not used) }; + /** + * @brief Register a function to be called at program exit + * + * @param f The function to call + * @param objptr The object pointer to pass to the function + * @param dso The DSO handle (not used) + * @return int 0 on success, non-zero on failure + */ int __cxa_atexit(void (* f)(void*), void* objptr, void* dso); + + /** + * @brief Finalise all global objects by calling their destructors + * + * @param f The DSO handle to finalise (nullptr for all) + */ void __cxa_finalize(void* f); - // Stack Gaurd + /// The stack canary value used to detect stack buffer overflows (@todo make random at runtime) uintptr_t __stack_chk_guard = 0x595e9fbd94fda766; - void __stack_chk_fail(void); + /** + * @brief Called when a stack buffer overflow is detected + */ + void __stack_chk_fail(void); } } } diff --git a/kernel/include/runtime/ubsan.h b/kernel/include/runtime/ubsan.h index 485f6a3d..6e1bceca 100644 --- a/kernel/include/runtime/ubsan.h +++ b/kernel/include/runtime/ubsan.h @@ -14,103 +14,154 @@ namespace MaxOS { namespace runtime { + /// Check if a value is aligned to the given alignment #define ubsan_aligned(value, alignment) !(value & (alignment - 1)) /** * @struct SourceLocation * @brief The location in the source code where the undefined behaviour occurred + * + * @typedef source_location_t + * @brief Alias for SourceLocation struct */ typedef struct SourceLocation { + const char* file; ///< The name of the source file uint32_t line; ///< The line number in the source file uint32_t column; ///< The column number in the source file + } source_location_t; /** * @struct TypeDescriptor * @brief Describes a type in the program + * + * @typedef type_descriptor_t + * @brief Alias for TypeDescriptor struct */ typedef struct TypeDescriptor { + uint16_t kind; ///< The kind of type (e.g., struct, class, union) uint16_t info; ///< Additional type information char name[]; ///< The name of the type + } type_descriptor_t; /** * @struct TypeMismatchInfo * @brief Information about a type mismatch error + * + * @typedef type_mismatch_info_t + * @brief Alias for TypeMismatchInfo struct */ typedef struct TypeMismatchInfo { + source_location_t location; ///< The location of the type mismatch type_descriptor_t* type; ///< The type that was expected uintptr_t alignment; ///< The required alignment uint8_t type_check_kind; ///< The kind of type check that failed + } type_mismatch_info_t; /** * @struct TypeMismatchInfoV1 * @brief Information about a type mismatch error (version 1) + * + * @typedef type_mismatch_info_v1_t + * @brief Alias for TypeMismatchInfoV1 struct */ typedef struct TypeMismatchInfoV1 { + source_location_t location; ///< The location of the type mismatch type_descriptor_t* type; ///< The type that was expected unsigned char log_alignment; ///< The log2 of the required alignment unsigned char type_check_kind; ///< The kind of type check that failed + } type_mismatch_info_v1_t; /** * @struct OverflowInfo * @brief Information about an overflow error + * + * @typedef overflow_info_t + * @brief Alias for OverflowInfo struct */ typedef struct OverflowInfo { + source_location_t location; ///< The location of the overflow type_descriptor_t* base_type; ///< The base type of the operation + } overflow_info_t; /** * @struct ShiftOutOfBoundsInfo * @brief Information about a shift out of bounds error + * + * @typedef shift_out_of_bounds_info_t + * @brief Alias for ShiftOutOfBoundsInfo struct */ typedef struct ShiftOutOfBoundsInfo { + source_location_t location; ///< The location of the shift out of bounds type_descriptor_t* left_type; ///< The type of the left operand type_descriptor_t* right_type; ///< The type of the right operand + } shift_out_of_bounds_info_t; /** * @struct OutOfBoundsInfo * @brief Information about an out of bounds error + * + * @typedef out_of_bounds_info_t + * @brief Alias for OutOfBoundsInfo struct */ typedef struct OutOfBoundsInfo { + source_location_t location; ///< The location of the out of bounds access type_descriptor_t* array_type; ///< The type of the array type_descriptor_t* index_type; ///< The type of the index + } out_of_bounds_info_t; /** * @struct LocationOnlyInfo * @brief Information that an error that only has a location + * + * @typedef location_only_info_t + * @brief Alias for LocationOnlyInfo struct */ typedef struct LocationOnlyInfo { + source_location_t location; ///< The location of the error + } location_only_info_t; /** * @struct InvaildValueInfo * @brief Information about an invalid value error + * + * @typedef invalid_value_info_t + * @brief Alias for InvaildValueInfo struct */ typedef struct InvaildValueInfo { + source_location_t location; ///< The location of the invalid value type_descriptor_t* type; ///< The type of the invalid value + } invalid_value_info_t; /** * @struct VLABoundNotPositiveInfo * @brief Information about a VLA bound not positive error + * + * @typedef vla_bound_not_positive_info_t + * @brief Alias for VLABoundNotPositiveInfo struct */ typedef struct VLABoundNotPositiveInfo { + source_location_t location; ///< The location of the VLA bound not positive type_descriptor_t* type; ///< The type of the VLA bound + } vla_bound_not_positive_info_t; /// List of type check errors diff --git a/kernel/include/system/cpu.h b/kernel/include/system/cpu.h index 2f51ae2e..0333d5f1 100644 --- a/kernel/include/system/cpu.h +++ b/kernel/include/system/cpu.h @@ -28,8 +28,15 @@ namespace MaxOS { namespace system { - /// The state of the CPU when an interrupt occurs (must align with the interrupt handler assembly code) - typedef struct { + /** + * @struct CPUStatus + * @brief Structure representing the CPU state during an interrupt + * + * @typedef cpu_status_t + * @brief Alias for CPUStatus struct + */ + typedef struct PACKED CPUStatus { + uint64_t r15; ///< Register r15 uint64_t r14; ///< Register r14 uint64_t r13; ///< Register r13 @@ -54,10 +61,18 @@ namespace MaxOS { uint64_t rflags; ///< Flags register uint64_t rsp; ///< Stack pointer uint64_t ss; ///< Stack segment - } __attribute__((__packed__)) cpu_status_t; - /// Task State Segment (TSS) structure for x86_64 - typedef struct TaskStateSegment { + } cpu_status_t; + + /** + * @struct TaskStateSegment + * @brief Structure representing the Task State Segment (TSS) + * + * @typedef tss_t + * @brief Alias for TaskStateSegment struct + */ + typedef struct PACKED TaskStateSegment { + uint32_t reserved0; ///< Unused, must be zero uint64_t rsp0; ///< Stack pointer for ring 0 uint64_t rsp1; ///< Stack pointer for ring 1 @@ -74,7 +89,8 @@ namespace MaxOS { uint64_t reserved3; ///< Unused, must be zero uint16_t reserved4; ///< Unused, must be zero uint16_t io_bitmap_offset; ///< Offset to the I/O bitmap - }__attribute__((__packed__)) tss_t; + + } tss_t; /** * @enum CPU_FEATURE_ECX @@ -158,23 +174,33 @@ namespace MaxOS { /** * @struct StackFrame * @brief A snapshot of the a frame in the call stack + * + * @typedef stack_frame_t + * @brief Alias for StackFrame struct */ - typedef struct StackFrame { + typedef struct PACKED StackFrame { + StackFrame* next; ///< Pointer to the next stack frame (up the call stack) uintptr_t rip; ///< The instruction pointer at this frame - }__attribute__((__packed__)) stack_frame_t; + + } stack_frame_t; /** * @struct CoreBootInfo * @brief Information needed when booting a core + * + * @typedef core_boot_info_t + * @brief Alias for CoreBootInfo struct */ - typedef struct CoreBootInfo { + typedef struct PACKED CoreBootInfo { + uint64_t stack; ///< The stack pointer for the core uint64_t p4_table; ///< The physical address of the P4 page table uint8_t id; ///< The ID of the core bool activated; ///< Whether the core has been activated void* gdt_64_base; ///< The base of the 64-bit GDT - }__attribute__((__packed__)) core_boot_info_t; + + } core_boot_info_t; /// The size of the stack allocated for booting a core (should align with the startup assembly code for the kernel) constexpr size_t BOOT_STACK_SIZE = 16384; diff --git a/kernel/include/system/gdt.h b/kernel/include/system/gdt.h index 9402fb04..d1ebb7cb 100644 --- a/kernel/include/system/gdt.h +++ b/kernel/include/system/gdt.h @@ -10,6 +10,7 @@ #define MAX_OS_SYSTEM_GDT_H #include +#include #include namespace MaxOS { @@ -34,11 +35,16 @@ namespace MaxOS { /** * @struct GDTRegister * @brief How the CPU stores the GDT + * + * @typedef gdtr_t + * @brief Alias for GDTRegister struct */ - typedef struct GDTRegister { + typedef struct PACKED GDTRegister { + uint16_t size; ///< The size of the GDT uint64_t address; ///< The address of the GDT - } __attribute__((packed)) gdtr_t; + + } gdtr_t; /** * @class GlobalDescriptorTable diff --git a/kernel/include/system/syscalls.h b/kernel/include/system/syscalls.h index c6fc4b61..e0b1b298 100644 --- a/kernel/include/system/syscalls.h +++ b/kernel/include/system/syscalls.h @@ -29,8 +29,12 @@ namespace MaxOS { /** * @struct SyscallArguments * @brief The arguments passed to a syscall (simplified representation of values in registers) + * + * @typedef syscall_args_t + * @brief Alias for SyscallArguments struct */ typedef struct SyscallArguments { + uint64_t arg0; ///< First argument (in rdi) uint64_t arg1; ///< Second argument (in rsi) uint64_t arg2; ///< Third argument (in rdx) @@ -39,6 +43,7 @@ namespace MaxOS { uint64_t arg5; ///< Sixth argument (in r9) uint64_t return_value; ///< The return value of the syscall (in rax) cpu_status_t* return_state; ///< The CPU state to return to after the syscall + } syscall_args_t; /// @todo Could use a class based response but a single class might want multiple handlers e.g. fs @@ -79,9 +84,7 @@ namespace MaxOS { static syscall_args_t* syscall_thread_sleep(syscall_args_t* args); static syscall_args_t* syscall_thread_close(syscall_args_t* args); }; - } - } #endif //MAXOS_SYSTEM_SYSCALLS_H diff --git a/kernel/src/drivers/clock/clock.cpp b/kernel/src/drivers/clock/clock.cpp index add9654b..25f7bdbc 100644 --- a/kernel/src/drivers/clock/clock.cpp +++ b/kernel/src/drivers/clock/clock.cpp @@ -179,14 +179,14 @@ void Clock::setup_apic_clock(hardwarecommunication::LocalAPIC* local_apic) const * * @return The current time in a Time struct format */ -common::Time Clock::get_time() { +common::time_t Clock::get_time() { // Wait for the clock to be ready while (read_hardware_clock(0xA) & 0x80) asm volatile("nop"); // Read the time from the clock - Time time{}; + time_t time{}; time.year = binary_representation(read_hardware_clock(0x9)) + 2000; time.month = binary_representation(read_hardware_clock(0x8)); time.day = binary_representation(read_hardware_clock(0x7)); @@ -210,7 +210,7 @@ Clock *Clock::active_clock() { } /** - * @brief Constructor for the PIT class. Registers a handler for interrupt 0x22 and initializes ports + * @brief Constructor for the PIT class. Registers a handler for interrupt 0x22 and initialises ports * @param apic The APIC controller for the BSP core */ PIT::PIT(AdvancedProgrammableInterruptController *apic) diff --git a/kernel/src/drivers/console/serial.cpp b/kernel/src/drivers/console/serial.cpp index 5ec944b7..e1363737 100644 --- a/kernel/src/drivers/console/serial.cpp +++ b/kernel/src/drivers/console/serial.cpp @@ -12,7 +12,7 @@ using namespace MaxOS; using namespace MaxOS::drivers; /** - * @brief Constructs a new Serial Console object and initializes the serial port + * @brief Constructs a new Serial Console object and initialises the serial port * @param logger The logger which will use this serial console as a log writer */ SerialConsole::SerialConsole(Logger* logger) diff --git a/kernel/src/drivers/ethernet/amd_am79c973.cpp b/kernel/src/drivers/ethernet/amd_am79c973.cpp index 98cde7a2..2b27da78 100644 --- a/kernel/src/drivers/ethernet/amd_am79c973.cpp +++ b/kernel/src/drivers/ethernet/amd_am79c973.cpp @@ -36,7 +36,7 @@ AMD_AM79C973::AMD_AM79C973(PeripheralComponentInterconnectDeviceDescriptor *dev) currentSendBuffer = 0; currentRecvBuffer = 0; - //Not active or initialized + //Not active or initialised active = false; initDone = false; diff --git a/kernel/src/drivers/ethernet/intel_i217.cpp b/kernel/src/drivers/ethernet/intel_i217.cpp index ba74ee76..5100a08f 100644 --- a/kernel/src/drivers/ethernet/intel_i217.cpp +++ b/kernel/src/drivers/ethernet/intel_i217.cpp @@ -22,13 +22,7 @@ using namespace memory; /// See OSDEV wiki for the credit for this driver // Buffer Sizes -#define buffer256 (3 << 16) -#define buffer512 (2 << 16) -#define buffer1024 (1 << 16) -#define buffer2048 (0 << 16) -#define buffer4096 ((3 << 16) | (1 << 25)) #define buffer8192 ((2 << 16) | (1 << 25)) -#define buffer16384 ((1 << 16) | (1 << 25)) ///__DRIVER___ diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp index c2fbb91e..50f663f5 100644 --- a/kernel/src/kernel.cpp +++ b/kernel/src/kernel.cpp @@ -122,6 +122,9 @@ extern "C" [[noreturn]] void kernel_main(unsigned long addr, unsigned long magic } /** + * @todo Proper file formatting + * @todo Full doxygen comments + * @todo Kernel configuration (debug/release) * @todo Clean up warnings * @todo Test suite of common functions & other statics (paths) * @todo Thread storage (when clib) diff --git a/kernel/src/memory/physical.cpp b/kernel/src/memory/physical.cpp index bed7de6b..ad434e56 100644 --- a/kernel/src/memory/physical.cpp +++ b/kernel/src/memory/physical.cpp @@ -73,7 +73,7 @@ PhysicalMemoryManager::PhysicalMemoryManager(Multiboot* multiboot) reserve_kernel_regions(multiboot); // Initialisation Done - m_initialized = true; + m_initialised = true; Logger::DEBUG() << "Memory used at start: " << (int) (memory_used() / 1024 / 1024) << "mb \n"; } @@ -191,7 +191,7 @@ void* PhysicalMemoryManager::allocate_frame() { // If not initialised, cant use the bitmap or higher half mapped physical memory so use leftover kernel memory already // mapped in loader.s - if (!m_initialized) { + if (!m_initialised) { // Use frames at the start of the mmap free void* address = (void*)m_mmap->addr + (m_setup_frames * PAGE_SIZE); @@ -391,7 +391,7 @@ pml_t* PhysicalMemoryManager::get_or_create_table(pml_t* table, size_t index, si } /** - * @brief Creates a page table entry when the higher half is not initialized + * @brief Creates a page table entry when the higher half is not initialised * * @param parent_table The parent table to create the entry in * @param table_index The index of the table to create @@ -444,7 +444,7 @@ pte_t* PhysicalMemoryManager::get_entry(virtual_address_t* virtual_address, pml_ pml_t* pt_table = nullptr; // If it is before initialization then cant rely on the direct map - if (!m_initialized) { + if (!m_initialised) { pdpr_table = get_and_create_table(pml4_table, pml4_index, get_higher_half_table(pml4_index)); pd_table = get_and_create_table(pdpr_table, pdpr_index, get_higher_half_table(pdpr_index, pml4_index)); pt_table = get_and_create_table(pd_table, pd_index, get_higher_half_table(pd_index, pdpr_index, pml4_index)); diff --git a/kernel/src/runtime/cplusplus.cpp b/kernel/src/runtime/cplusplus.cpp index d9eb7c9e..80af8143 100644 --- a/kernel/src/runtime/cplusplus.cpp +++ b/kernel/src/runtime/cplusplus.cpp @@ -15,17 +15,27 @@ using namespace MaxOS::runtime; // Define static constructors (DSO = Dynamic Shared Object) extern "C" void* __dso_handle = nullptr; -// Pure virtual function call +/** + * @brief Called when a virtual function is called on an object with no implementation + */ extern "C" void __cxa_pure_virtual() { ASSERT(false, "Pure virtual function call failed"); } +/** + * @brief Called when stack smashing is detected + */ extern "C" void __stack_chk_fail(void) { ASSERT(false, "Stack Smashed"); } + extern "C" constructor start_ctors; extern "C" constructor end_ctors; + +/** + * @brief Calls all global constructors + */ extern "C" void call_constructors() { // Loop through and initialise all the global constructors for (constructor* i = &start_ctors; i != &end_ctors; i++) diff --git a/toolchain/pre_process/symbols.sh b/toolchain/pre_process/symbols.sh index f22c2c69..c8c79ceb 100755 --- a/toolchain/pre_process/symbols.sh +++ b/toolchain/pre_process/symbols.sh @@ -75,15 +75,19 @@ namespace MaxOS{ namespace common{ - /** - * @struct KernelSymbol - * @brief Holds the address and name of a kernel symbol - */ + /** + * @struct KernelSymbol + * @brief Holds the address and name of a kernel symbol + * + * @typedef kernel_sym_t + * @brief alias for KernelSymbol + */ typedef struct KernelSymbol { uintptr_t address; ///< The address of the symbol (loaded address) const char* name; ///< The stripped name of the symbol (including namespaces) } kernel_sym_t; + /// Holds a list of address/name pairs for kernel symbols const kernel_sym_t kernel_symbols[] = { EOF if [ ! -s "$RAW" ]; then @@ -134,6 +138,8 @@ fi # Write the footer cat >> "$OUT" < .buildCount @@ -12,12 +11,13 @@ fi # Increment the buildCount by 1 new_value=$(($(cat .buildCount) + 1)) echo "$new_value" > .buildCount +msg "New build count: $new_value" msg "Writing version header" # Version data MAJOR_VERSION="0" MINOR_VERSION="3" -VERSION_NAME="Development Version" +VERSION_NAME="Kernel Focus" BUILD_NUMBER=$(cat .buildCount) BUILD_YEAR="$(date +'%-Y')" BUILD_MONTH="$(date +'%-m')" @@ -25,6 +25,7 @@ BUILD_DAY="$(date +'%-d')" BUILD_HOUR="$(date +'%-H')" BUILD_MINUTE="$(date +'%-M')" BUILD_SECOND="$(date +'%-S')" +BUILD_TYPE="Debug" #/release GIT_REVISION="$(git rev-parse --short HEAD)" GIT_BRANCH="$(git rev-parse --abbrev-ref HEAD)" GIT_COMMIT="$(git rev-list --count HEAD)" @@ -40,6 +41,50 @@ fi # Write the version header cat > "${OUTPUT_FILE}" << EOF +/** + * @file version.h + * @brief Defines version information for MaxOS + * + * @date 2025-11-1 + * @author Max Tyson + */ +#ifndef MAX_OS_COMMON_VERSION_H +#define MAX_OS_COMMON_VERSION_H + + +#include +#include +#include + +namespace MaxOS { + + namespace common { + + /** + * @typedef vstring + * @brief A type alias for a const char* string + */ + typedef const char* vstring; + + const uint8_t MAJOR_VERSION = ${MAJOR_VERSION}; ///< The official release version + const uint8_t MINOR_VERSION = ${MINOR_VERSION}; ///< The significant feature update version + const vstring VERSION_STRING = "${MAJOR_VERSION}.${MINOR_VERSION}"; ///< A c style string representing the MAJOR.MINOR version + const vstring VERSION_NAME = "${VERSION_NAME}"; ///< The human readable version name + const int BUILD_NUMBER = ${BUILD_NUMBER}; ///< How many times the code has been built on this device + const time_t BUILD_DATE = {${BUILD_YEAR}, ${BUILD_MONTH}, ${BUILD_DAY}, ${BUILD_HOUR}, ${BUILD_MINUTE}, ${BUILD_SECOND}}; ///< The build date and time + const vstring BUILD_TYPE = "${BUILD_TYPE}"; ///< The build type (Debug/Release) + const vstring GIT_REVISION = "${GIT_REVISION}"; ///< The git revision hash + const vstring GIT_BRANCH = "${GIT_BRANCH}"; ///< The name of the git branch that was built + const int GIT_COMMIT = ${GIT_COMMIT}; ///< The commit number in the git repository that this build was made from + const vstring GIT_AUTHOR = "${GIT_AUTHOR}"; ///< Who authored the build of this version + + } + +} + +#endif //MAX_OS_VERSION_H + + /** * @file version.h * @brief Defines version information for MaxOS @@ -60,22 +105,30 @@ namespace MaxOS{ namespace common { + /** + * @typedef vstring + * @brief A type alias for a const char* string + */ typedef const char* vstring; - const uint8_t MAJOR_VERSION = ${MAJOR_VERSION}; - const uint8_t MINOR_VERSION = ${MINOR_VERSION}; - const vstring VERSION_STRING = "${MAJOR_VERSION}.${MINOR_VERSION}"; - const vstring VERSION_NAME = "${VERSION_NAME}"; - const int BUILD_NUMBER = ${BUILD_NUMBER}; - const Time BUILD_DATE = {${BUILD_YEAR}, ${BUILD_MONTH}, ${BUILD_DAY}, ${BUILD_HOUR}, ${BUILD_MINUTE}, ${BUILD_SECOND}}; - const vstring GIT_REVISION = "${GIT_REVISION}"; - const vstring GIT_BRANCH = "${GIT_BRANCH}"; - const int GIT_COMMIT = ${GIT_COMMIT}; - const vstring GIT_AUTHOR = "${GIT_AUTHOR}"; + const uint8_t MAJOR_VERSION = ${MAJOR_VERSION}; + const uint8_t MINOR_VERSION = ${MINOR_VERSION}; + const vstring VERSION_STRING = "${MAJOR_VERSION}.${MINOR_VERSION}"; + const vstring VERSION_NAME = "${VERSION_NAME}"; + const int BUILD_NUMBER = ${BUILD_NUMBER}; + const Time BUILD_DATE = {${BUILD_YEAR}, ${BUILD_MONTH}, ${BUILD_DAY}, ${BUILD_HOUR}, ${BUILD_MINUTE}, ${BUILD_SECOND}}; + const vstring GIT_REVISION = "${GIT_REVISION}"; + const vstring GIT_BRANCH = "${GIT_BRANCH}"; + const int GIT_COMMIT = ${GIT_COMMIT}; + const vstring GIT_AUTHOR = "${GIT_AUTHOR}"; } } #endif //MAX_OS_VERSION_H -EOF \ No newline at end of file +EOF + +# Copy the version to the doxygen file (replace PROJECT_NUMBER = x.x with the VERSION_STRING value) +sed -i.bak "s/PROJECT_NUMBER = .*/PROJECT_NUMBER = ${MAJOR_VERSION}.${MINOR_VERSION}/" "${SCRIPTDIR}/../../docs/doxy/Doxyfile" +rm "${SCRIPTDIR}/../../docs/Doxyfile.bak" \ No newline at end of file From bc6b4f893cf0b7cb96003b731efa3017e9ac84c1 Mon Sep 17 00:00:00 2001 From: Max Tyson <98maxt98@gmail.com> Date: Sun, 2 Nov 2025 20:25:28 +1300 Subject: [PATCH 02/12] Doxy happy --- kernel/include/common/buffer.h | 14 +- kernel/include/common/eventHandler.h | 12 +- kernel/include/common/graphicsContext.h | 98 +-- kernel/include/common/logger.h | 157 ++-- kernel/include/common/macros.h | 11 + kernel/include/common/string.h | 128 +-- kernel/include/common/vector.h | 819 +++++++++--------- kernel/include/drivers/disk/ide.h | 2 +- .../include/drivers/ethernet/amd_am79c973.h | 2 +- kernel/include/drivers/ethernet/intel_i217.h | 172 ++-- kernel/include/drivers/peripherals/keyboard.h | 4 +- kernel/include/drivers/peripherals/mouse.h | 168 ++-- kernel/include/filesystem/format/fat32.h | 12 +- .../hardwarecommunication/interrupts.h | 6 +- kernel/include/hardwarecommunication/pci.h | 180 ++-- kernel/include/processes/process.h | 2 +- kernel/include/processes/resource.h | 8 +- kernel/include/system/cpu.h | 1 + kernel/src/asm/interrupts.s | 12 +- kernel/src/common/buffer.cpp | 3 + kernel/src/common/graphicsContext.cpp | 4 + kernel/src/common/logger.cpp | 8 +- kernel/src/common/outputStream.cpp | 3 + kernel/src/common/string.cpp | 176 ++-- kernel/src/drivers/console/console.cpp | 4 +- kernel/src/drivers/console/vesaboot.cpp | 2 + kernel/src/drivers/disk/ide.cpp | 6 +- kernel/src/drivers/driver.cpp | 25 +- kernel/src/drivers/ethernet/amd_am79c973.cpp | 8 +- kernel/src/drivers/ethernet/ethernet.cpp | 20 +- kernel/src/drivers/ethernet/intel_i217.cpp | 24 +- .../src/drivers/ethernet/rawdatahandler.cpp | 4 +- kernel/src/drivers/peripherals/keyboard.cpp | 9 + kernel/src/drivers/peripherals/mouse.cpp | 3 + kernel/src/drivers/video/vga.cpp | 7 + kernel/src/filesystem/filesystem.cpp | 8 +- kernel/src/filesystem/format/ext2.cpp | 6 +- kernel/src/filesystem/vfs.cpp | 9 + kernel/src/gui/widget.cpp | 4 +- kernel/src/gui/widgets/button.cpp | 1 + kernel/src/gui/window.cpp | 1 + kernel/src/hardwarecommunication/apic.cpp | 6 + .../src/hardwarecommunication/interrupts.cpp | 10 +- kernel/src/hardwarecommunication/pci.cpp | 33 +- kernel/src/memory/memorymanagement.cpp | 3 + kernel/src/memory/physical.cpp | 18 +- kernel/src/memory/virtual.cpp | 16 +- kernel/src/net/ethernetframe.cpp | 1 + kernel/src/net/ipv4.cpp | 19 +- kernel/src/net/tcp.cpp | 61 +- kernel/src/net/udp.cpp | 8 +- kernel/src/processes/elf.cpp | 2 + kernel/src/processes/ipc.cpp | 3 + kernel/src/processes/process.cpp | 7 + kernel/src/processes/resource.cpp | 14 +- kernel/src/processes/scheduler.cpp | 7 +- kernel/src/runtime/cplusplus.cpp | 8 +- kernel/src/runtime/ubsan.cpp | 72 ++ kernel/src/system/cpu.cpp | 11 +- kernel/src/system/gdt.cpp | 3 + kernel/src/system/syscalls.cpp | 4 +- 61 files changed, 1417 insertions(+), 1032 deletions(-) diff --git a/kernel/include/common/buffer.h b/kernel/include/common/buffer.h index 1164dfba..8533301d 100644 --- a/kernel/include/common/buffer.h +++ b/kernel/include/common/buffer.h @@ -14,23 +14,23 @@ #include #include -namespace MaxOS{ +namespace MaxOS { - namespace common{ + namespace common { /** * @class Buffer * @brief Wrapper class for a region of bytes in memor in an attempt to add some memory safety. Automatically * allocates the size specified and frees it once done, adds boundary to I/O. */ - class Buffer{ + class Buffer { private: - uint8_t* m_bytes = nullptr; - size_t m_capacity; - bool m_dont_delete = false; + uint8_t* m_bytes = nullptr; + size_t m_capacity; + bool m_dont_delete = false; - size_t m_offset = 0; + size_t m_offset = 0; public: Buffer(size_t size, bool update_offset = true); diff --git a/kernel/include/common/eventHandler.h b/kernel/include/common/eventHandler.h index 1f16df7f..7d061e2e 100644 --- a/kernel/include/common/eventHandler.h +++ b/kernel/include/common/eventHandler.h @@ -79,8 +79,14 @@ namespace MaxOS{ Vector*> raise_event(Event* event); }; - - /// ___________________________ Template Implementation ___________________________ + ///@todo move to a c++ files + + /** + * @brief Constructs a new Event object + * + * @tparam EventType The type of event + * @param type The type of the event + */ template Event::Event(EventType type) { this->type = type; } @@ -98,6 +104,8 @@ namespace MaxOS{ * * @tparam EventType The type of event * @param event The event that was raised + * + * @return The event after it has been handled */ template Event* EventHandler::on_event(Event* event) { return event; diff --git a/kernel/include/common/graphicsContext.h b/kernel/include/common/graphicsContext.h index 3841ac9a..6c1b5df5 100644 --- a/kernel/include/common/graphicsContext.h +++ b/kernel/include/common/graphicsContext.h @@ -14,74 +14,74 @@ namespace MaxOS { - namespace common { + namespace common { - /** - * @class GraphicsContext - * @brief Draws pixels to the screen, and handles drawing lines, rectangles and circles - */ - class GraphicsContext { + /** + * @class GraphicsContext + * @brief Draws pixels to the screen, and handles drawing lines, rectangles and circles + */ + class GraphicsContext { - protected: - bool mirror_y_axis { false }; ///< Should the y axis be mirrored (0,0 is top left if false, bottom left if true) + protected: + bool mirror_y_axis { false }; ///< Should the y axis be mirrored (0,0 is top left if false, bottom left if true) - int32_t m_width { 0 }; ///< The width of the screen in pixels - int32_t m_height { 0 }; ///< The height of the screen in pixels - uint32_t m_color_depth { 0 }; ///< The color depth of the screen in bits per pixel + int32_t m_width { 0 }; ///< The width of the screen in pixels + int32_t m_height { 0 }; ///< The height of the screen in pixels + uint32_t m_color_depth { 0 }; ///< The color depth of the screen in bits per pixel - Colour m_colour_pallet[256]; ///< The colour pallet for 8 bit color depth @todo make const + Colour m_colour_pallet[256]; ///< The colour pallet for 8 bit color depth @todo make const - uint64_t* m_framebuffer_address { nullptr }; ///< The address of the framebuffer + uint64_t* m_framebuffer_address { nullptr }; ///< The address of the framebuffer - virtual void render_pixel(uint32_t x, uint32_t y, uint32_t colour); - virtual void render_pixel_8_bit(uint32_t x, uint32_t y, uint8_t colour); - virtual void render_pixel_16_bit(uint32_t x, uint32_t y, uint16_t colour); - virtual void render_pixel_24_bit(uint32_t x, uint32_t y, uint32_t colour); - virtual void render_pixel_32_bit(uint32_t x, uint32_t y, uint32_t colour); + virtual void render_pixel(uint32_t x, uint32_t y, uint32_t colour); + virtual void render_pixel_8_bit(uint32_t x, uint32_t y, uint8_t colour); + virtual void render_pixel_16_bit(uint32_t x, uint32_t y, uint16_t colour); + virtual void render_pixel_24_bit(uint32_t x, uint32_t y, uint32_t colour); + virtual void render_pixel_32_bit(uint32_t x, uint32_t y, uint32_t colour); - virtual uint32_t get_rendered_pixel(uint32_t x, uint32_t y); - virtual uint8_t get_rendered_pixel_8_bit(uint32_t x, uint32_t y); - virtual uint16_t get_rendered_pixel_16_bit(uint32_t x, uint32_t y); - virtual uint32_t get_rendered_pixel_24_bit(uint32_t x, uint32_t y); - virtual uint32_t get_rendered_pixel_32_bit(uint32_t x, uint32_t y); + virtual uint32_t get_rendered_pixel(uint32_t x, uint32_t y); + virtual uint8_t get_rendered_pixel_8_bit(uint32_t x, uint32_t y); + virtual uint16_t get_rendered_pixel_16_bit(uint32_t x, uint32_t y); + virtual uint32_t get_rendered_pixel_24_bit(uint32_t x, uint32_t y); + virtual uint32_t get_rendered_pixel_32_bit(uint32_t x, uint32_t y); - public: - GraphicsContext(); - ~GraphicsContext(); + public: + GraphicsContext(); + ~GraphicsContext(); - uint32_t colour_to_int(const Colour&); - Colour int_to_colour(uint32_t); + uint32_t colour_to_int(const Colour&); + Colour int_to_colour(uint32_t); - // Convert uint32_t to uint64s? - [[nodiscard]] uint32_t width() const; - uint32_t height() const; - uint32_t color_depth() const; + // Convert uint32_t to uint64s? + [[nodiscard]] uint32_t width() const; + uint32_t height() const; + uint32_t color_depth() const; - uint64_t* framebuffer_address(); + uint64_t* framebuffer_address(); - void put_pixel(int32_t x, int32_t y, const Colour& colour); - void putPixel(int32_t x, int32_t y, uint32_t colour); - Colour get_pixel(int32_t x, int32_t y); - void invert_pixel(int32_t x, int32_t y); + void put_pixel(int32_t x, int32_t y, const Colour& colour); + void putPixel(int32_t x, int32_t y, uint32_t colour); + Colour get_pixel(int32_t x, int32_t y); + void invert_pixel(int32_t x, int32_t y); - void draw_line(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const Colour& colour); - void drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colour); + void draw_line(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const Colour& colour); + void drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colour); - void draw_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const Colour& colour); - void draw_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colour); + void draw_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const Colour& colour); + void draw_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colour); - void fill_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const Colour& colour); - void fill_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colour); + void fill_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const Colour& colour); + void fill_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colour); - void draw_circle(int32_t x0, int32_t y0, int32_t radius, const Colour& colour); - void draw_circle(int32_t x0, int32_t y0, int32_t radius, uint32_t colour); + void draw_circle(int32_t x0, int32_t y0, int32_t radius, const Colour& colour); + void draw_circle(int32_t x0, int32_t y0, int32_t radius, uint32_t colour); - void fill_circle(int32_t x0, int32_t y0, int32_t radius, const Colour& colour); - void fillCircle(int32_t x0, int32_t y0, int32_t radius, uint32_t colour); + void fill_circle(int32_t x0, int32_t y0, int32_t radius, const Colour& colour); + void fillCircle(int32_t x0, int32_t y0, int32_t radius, uint32_t colour); - }; + }; - } + } } #endif //MaxOS_COMMON_GRAPHICSCONTEX_H diff --git a/kernel/include/common/logger.h b/kernel/include/common/logger.h index 0f9ee010..55c72378 100644 --- a/kernel/include/common/logger.h +++ b/kernel/include/common/logger.h @@ -13,85 +13,86 @@ #include #include +namespace MaxOS{ - /** - * @enum LogLevel - * @brief Priority levels for logging messages. Different levels may be used to filter messages based on their importance depending on build type. - */ - enum class LogLevel - { - WARNING, - ERROR, - HEADER, - INFO, - DEBUG, - }; - - - constexpr uint8_t MAX_LOG_WRITERS = 5; ///< The maximum number of log writers that can be added to the logger - constexpr LogLevel MAX_LOG_LEVEL = LogLevel::DEBUG; ///< The maximum log level for this build (messages above this level will not be logged) - - /** - * @class Logger - * @brief A class that handles logging messages to the console and files. - */ - class Logger : public MaxOS::common::OutputStream - { - private: - - // Cant use vector as this needs to be init before the heap - uint8_t m_log_writer_count = 0; - OutputStream* m_log_writers[MAX_LOG_WRITERS] = {nullptr, nullptr, nullptr, nullptr, nullptr}; - bool m_log_writers_enabled[MAX_LOG_WRITERS] = {false, false, false, false, false}; - - // Progress bar - static inline uint8_t s_progress_total = 100; - uint8_t m_progress_current = 0; - - static inline Logger* s_active_logger = nullptr; - - LogLevel m_log_level = LogLevel::INFO; - - public: - Logger(); - ~Logger(); - - void add_log_writer(OutputStream* log_writer); - void disable_log_writer(OutputStream* log_writer); - - void set_log_level(LogLevel log_level); - - void write_char(char c) final; - void printf(const char* format, ...); - - static void ASSERT(bool condition, const char* message, ...); - - static Logger* active_logger(); - - static Logger& Out(); - - static Logger HEADER(); - static Logger INFO(); - static Logger DEBUG(); - static Logger WARNING(); - static Logger ERROR(); - - using OutputStream::operator<<; - Logger& operator << (LogLevel log_level); - }; - - /** - * @brief If the specified condition is not met then the kernel will crash with the specified message. - * - * This macro wraps Logger::ASSERT and supports printf-style formatting with variadic arguments. - * - * @param condition The condition to check. - * @param format The format string (like printf). - * @param ... Additional arguments to format. - * - * @see Logger::ASSERT - */ - #define ASSERT(condition, format, ...) Logger::ASSERT(condition, format, ##__VA_ARGS__) +/** + * @enum LogLevel + * @brief Priority levels for logging messages. Different levels may be used to filter messages based on their importance depending on build type. + */ + enum class LogLevel { + WARNING, + ERROR, + HEADER, + INFO, + DEBUG, + }; + + + constexpr uint8_t MAX_LOG_WRITERS = 5; ///< The maximum number of log writers that can be added to the logger + constexpr LogLevel MAX_LOG_LEVEL = LogLevel::DEBUG; ///< The maximum log level for this build (messages above this level will not be logged) + +/** + * @class Logger + * @brief A class that handles logging messages to the console and files. + */ + class Logger : public MaxOS::common::OutputStream { + private: + + // Cant use vector as this needs to be init before the heap + uint8_t m_log_writer_count = 0; + OutputStream* m_log_writers[MAX_LOG_WRITERS] = { nullptr, nullptr, nullptr, nullptr, nullptr }; + bool m_log_writers_enabled[MAX_LOG_WRITERS] = { false, false, false, false, false }; + + // Progress bar + static inline uint8_t s_progress_total = 100; + uint8_t m_progress_current = 0; + + static inline Logger* s_active_logger = nullptr; + + LogLevel m_log_level = LogLevel::INFO; + + public: + Logger(); + ~Logger(); + + void add_log_writer(OutputStream* log_writer); + void disable_log_writer(OutputStream* log_writer); + + void set_log_level(LogLevel log_level); + + void write_char(char c) final; + void printf(const char* format, ...); + + static void ASSERT(bool condition, const char* message, ...); + + static Logger* active_logger(); + + static Logger &Out(); + + static Logger HEADER(); + static Logger INFO(); + static Logger DEBUG(); + static Logger WARNING(); + static Logger ERROR(); + + using OutputStream::operator<<; + Logger &operator<<(LogLevel log_level); + }; + + /** + * @brief If the specified condition is not met then the kernel will crash with the specified message. + * + * This macro wraps Logger::ASSERT and supports printf-style formatting with variadic arguments. + * + * @param condition The condition to check. + * @param format The format string (like printf). + * @param ... Additional arguments to format. + * + * @see Logger::ASSERT + */ + #define ASSERT(condition, format, ...) Logger::ASSERT(condition, format, ##__VA_ARGS__) + +} #endif // MAXOS_COMMON_LOGGER_H diff --git a/kernel/include/common/macros.h b/kernel/include/common/macros.h index d1cf3839..fad02a8b 100644 --- a/kernel/include/common/macros.h +++ b/kernel/include/common/macros.h @@ -15,6 +15,17 @@ namespace MaxOS{ #define PACKED __attribute__((packed)) #endif + #ifdef DOXYGEN + /// Align to page size (4096 bytes) + #define PAGE_ALIGNED + #else + /// Align to page size (4096 bytes) + #define PAGE_ALIGNED __attribute__((aligned(4096))) + #endif + + + + } diff --git a/kernel/include/common/string.h b/kernel/include/common/string.h index a8fbe3c2..00ffed65 100644 --- a/kernel/include/common/string.h +++ b/kernel/include/common/string.h @@ -19,75 +19,75 @@ namespace MaxOS { /// How many characters can be stored in the small string optimization array constexpr int MAX_STRING_SMALL_STORAGE = 0x99; - /** - * @class String - * @brief Dynamically sized string with various operations - */ - typedef class String { - private: - char* m_string = nullptr; - int m_length = 0; // Does not include the null terminator + /** + * @class String + * @brief Dynamically sized string with various operations + */ + typedef class String { + private: + char* m_string = nullptr; + int m_length = 0; // Does not include the null terminator - char m_small_string[MAX_STRING_SMALL_STORAGE] = {0}; - bool m_using_small = true; + char m_small_string[MAX_STRING_SMALL_STORAGE] = { 0 }; + bool m_using_small = true; - [[nodiscard]] static int lex_value(String const &other) ; - void allocate_self(); + [[nodiscard]] static int lex_value(String const &other); + void allocate_self(); - public: + public: - String(); - explicit String(char c); - String(char const* string); - String(uint8_t const* string, int length); - String(String const &other); - explicit String(int value); - explicit String(uint64_t value); - explicit String(float value); - explicit String(bool value); - ~String(); + String(); + explicit String(char c); + String(char const* string); + String(uint8_t const* string, int length); + String(String const &other); + explicit String(int value); + explicit String(uint64_t value); + explicit String(float value); + explicit String(bool value); + ~String(); - void copy(String const &other); + void copy(String const &other); - static String formatted(char const *format, ...); - static String formatted(char const *format, va_list parameters); + static String formatted(char const* format, ...); + static String formatted(char const* format, va_list parameters); - [[nodiscard]] int length(bool count_ansi = true) const; - char* c_str(); - const char* c_str() const; + [[nodiscard]] int length(bool count_ansi = true) const; + char* c_str(); + const char* c_str() const; - bool starts_with(String const &other); - [[nodiscard]] String substring(int start, int length) const; + bool starts_with(String const &other); + [[nodiscard]] String substring(int start, int length) const; - [[nodiscard]] common::Vector split(String const &delimiter) const; - [[nodiscard]] String strip(char strip_char = ' ') const; + [[nodiscard]] common::Vector split(String const &delimiter) const; + [[nodiscard]] String strip(char strip_char = ' ') const; - [[nodiscard]] String center(int width, char fill = ' ') const; + [[nodiscard]] String center(int width, char fill = ' ') const; - // Operator functions - [[nodiscard]] bool equals(String const &other) const; + // Operator functions + [[nodiscard]] bool equals(String const &other) const; - // Operators - String &operator = (String const &other); - String operator + (String const &other) const; - String &operator += (String const &other); + // Operators + String &operator=(String const &other); + String operator+(String const &other) const; + String &operator+=(String const &other); - String operator * (int times) const; + String operator*(int times) const; - bool operator == (String const &other) const; - bool operator != (String const &other) const; + bool operator==(String const &other) const; + bool operator!=(String const &other) const; - bool operator < (String const &other) const; - bool operator > (String const &other) const; + bool operator<(String const &other) const; + bool operator>(String const &other) const; - bool operator <= (String const &other) const; - bool operator >= (String const &other) const; + bool operator<=(String const &other) const; + bool operator>=(String const &other) const; - char& operator [] (int index); - char& operator [] (int index) const; + char &operator[](int index); + char &operator[](int index) const; - } string; ///< Typedef for String + } string; ///< Typedef for String /** * @class StringBuilder @@ -98,34 +98,34 @@ namespace MaxOS { class StringBuilder { public: String out; ///< The output string - operator String() const { return out; } ///< Convert to string + operator String() const { return out; } ///< Convert to string - StringBuilder& operator << (char const* str) { out += string(str); return *this; } ///< Append C-string - StringBuilder& operator << (String const &other) { out += other; return *this; } ///< Append String - StringBuilder& operator << (int value) { out += string(value); return *this; } ///< Append int - StringBuilder& operator << (uint64_t value) { out += string(value); return *this; } ///< Append hex - StringBuilder& operator << (float value) { out += string(value); return *this; } ///< Append decimal - StringBuilder& operator << (bool value) { out += string(value); return *this; } ///< Append bool + StringBuilder &operator<<(char const* str); + StringBuilder &operator<<(String const &other); + StringBuilder &operator<<(int value); + StringBuilder &operator<<(uint64_t value); + StringBuilder &operator<<(float value); + StringBuilder &operator<<(bool value); }; } // Convert functions int strlen(const char* str); -char* itoa(int base, int64_t number); +char* itoa(int base, int64_t number); char* htoa(uint64_t number); char* ftoa(float number); // Compare functions -bool strcmp(char const *str1, char const *str2); -bool strcmp(char const *str1, MaxOS::String const &str2); -bool strcmp(MaxOS::String const &str1, char const *str2); +bool strcmp(char const* str1, char const* str2); +bool strcmp(char const* str1, MaxOS::String const &str2); +bool strcmp(MaxOS::String const &str1, char const* str2); bool strcmp(MaxOS::String const &str1, MaxOS::String const &str2); // Compare limited functions -bool strncmp(char const *str1, char const *str2, int length); -bool strncmp(char const *str1, MaxOS::String const &str2, int length); -bool strncmp(MaxOS::String const &str1, char const *str2, int length); +bool strncmp(char const* str1, char const* str2, int length); +bool strncmp(char const* str1, MaxOS::String const &str2, int length); +bool strncmp(MaxOS::String const &str1, char const* str2, int length); bool strncmp(MaxOS::String const &str1, MaxOS::String const &str2, int length); #endif //MAXOS_STRING_H diff --git a/kernel/include/common/vector.h b/kernel/include/common/vector.h index 12e7f363..37928c6c 100644 --- a/kernel/include/common/vector.h +++ b/kernel/include/common/vector.h @@ -12,107 +12,105 @@ #include #include -namespace MaxOS{ - - namespace common{ - - /** - * @class VectorIterationHandler - * @brief Handles the iteration of a Vector providing read and end of stream functions - * - * @tparam Type Type of the Vector - */ - template class VectorIterationHandler - { - public: - VectorIterationHandler(); - ~VectorIterationHandler(); - - virtual void on_read(Type); - virtual void on_end_of_stream(); - }; - - /** - * @class Vector - * @brief Dynamically stores an array of elements - * - * @tparam Type Type of the Vector - */ - template class Vector - { - protected: - Type* m_elements; ///< The array of elements - uint32_t m_size { 0 }; ///< How many elements are currently stored - uint32_t m_capacity { 1 }; ///< How many elements can be stored without resizing - - public: - typedef Type* iterator; ///< The iterator type for the Vector - - Vector(); - Vector(int Size, Type element); - Vector(const Vector& other); - Vector(Vector&& other); - ~Vector(); - - Type& operator[](uint32_t index) const; - Vector& operator=(const Vector& other); - Vector& operator=(Vector&& other); - - [[nodiscard]] bool empty() const; - [[nodiscard]] uint32_t size() const; - - iterator begin() const; - iterator end() const; - iterator find(Type) const; - - iterator push_back(Type); - Type pop_back(); - - iterator push_front(Type); - Type pop_front(); - - void erase(Type); - void erase(typename Vector::iterator position); - void clear(); - - void reserve(size_t amount); - void increase_size(); - - void iterate(VectorIterationHandler*); - void Iterate(void callback(Type&)); - }; - - ///______________________________________Implementation__________________________________________________ - /** - * @brief Constructor for Vector - * - * @tparam Type Type of the Vector - */ - template Vector::Vector() { - - // Allocate space for the array - m_elements = new Type[m_capacity]; - - } - - /** - * @brief Constructor for Vector - * - * @tparam Type Type of the Vector - * @param size Size of the Vector - * @param element Element to fill the Vector with - */ - template Vector::Vector(int size, Type element) { - - // Allocate space for the array - m_elements = new Type[size]; - m_capacity = size > 0 ? size : 1; - m_size = 0; - - // Push all the elements to the Vector - for (int i = 0; i < size; ++i) - push_back(element); - } +namespace MaxOS { + + namespace common { + + /** + * @class VectorIterationHandler + * @brief Handles the iteration of a Vector providing read and end of stream functions + * + * @tparam Type Type of the Vector + */ + template class VectorIterationHandler { + public: + VectorIterationHandler(); + ~VectorIterationHandler(); + + virtual void on_read(Type); + virtual void on_end_of_stream(); + }; + + /** + * @class Vector + * @brief Dynamically stores an array of elements + * + * @tparam Type Type of the Vector + */ + template class Vector { + protected: + Type* m_elements; ///< The array of elements + uint32_t m_size { 0 }; ///< How many elements are currently stored + uint32_t m_capacity { 1 }; ///< How many elements can be stored without resizing + + public: + typedef Type* iterator; ///< The iterator type for the Vector + + Vector(); + Vector(int Size, Type element); + Vector(const Vector& other); + Vector(Vector&& other); + ~Vector(); + + Type& operator [](uint32_t index) const; + Vector& operator =(const Vector& other); + Vector& operator =(Vector&& other); + + [[nodiscard]] bool empty() const; + [[nodiscard]] uint32_t size() const; + + iterator begin() const; + iterator end() const; + iterator find(Type) const; + + iterator push_back(Type); + Type pop_back(); + + iterator push_front(Type); + Type pop_front(); + + void erase(Type); + void erase(typename Vector::iterator position); + void clear(); + + void reserve(size_t amount); + void increase_size(); + + void iterate(VectorIterationHandler*); + void Iterate(void callback(Type&)); + }; + + ///______________________________________Implementation__________________________________________________ + /** + * @brief Constructor for Vector + * + * @tparam Type Type of the Vector + */ + template Vector::Vector() { + + // Allocate space for the array + m_elements = new Type[m_capacity]; + + } + + /** + * @brief Constructor for Vector + * + * @tparam Type Type of the Vector + * @param size Size of the Vector + * @param element Element to fill the Vector with + */ + template Vector::Vector(int size, Type element) { + + // Allocate space for the array + m_elements = new Type[size]; + m_capacity = size > 0 ? size : 1; + m_size = 0; + + // Push all the elements to the Vector + for (int i = 0; i < size; ++i) + push_back(element); + } /** * @brief Copy constructor for Vector @@ -120,15 +118,14 @@ namespace MaxOS{ * @tparam Type The type of data to be stored * @param other The vector to copy from */ - template Vector::Vector(const Vector& other) - : m_size(other.m_size), - m_capacity(other.m_capacity) - { + template Vector::Vector(const Vector& other) + : m_size(other.m_size), + m_capacity(other.m_capacity) { // Copy each element into a new array - m_elements = new Type[m_capacity]; - for (uint32_t i = 0; i < m_size; ++i) - m_elements[i] = other.m_elements[i]; - } + m_elements = new Type[m_capacity]; + for (uint32_t i = 0; i < m_size; ++i) + m_elements[i] = other.m_elements[i]; + } /** * @brief Move constructor for Vector @@ -136,34 +133,38 @@ namespace MaxOS{ * @tparam Type The type of data to be stored * @param other The vector to copy from */ - template Vector::Vector(Vector &&other) + template Vector::Vector(Vector&& other) : m_elements(other.m_elements), - m_size(other.m_size), - m_capacity(other.m_capacity) - { + m_size(other.m_size), + m_capacity(other.m_capacity) { // Clear the other Vector other.m_elements = nullptr; other.m_size = 0; other.m_capacity = 0; - } + } - template Vector::~Vector() { + /** + * @brief Destructor for Vector, de-allocates the array + * + * @tparam Type Type data stored in the Vector + */ + template Vector::~Vector() { - // De-allocate the array - delete[] m_elements; + // De-allocate the array + delete[] m_elements; - } + } - /** - * @brief Increases the size of the Vector by doubling the capacity - * - * @tparam Type Type of the Vector - */ - template void Vector::increase_size() { - reserve(m_capacity * 2); - } + /** + * @brief Increases the size of the Vector by doubling the capacity + * + * @tparam Type Type of the Vector + */ + template void Vector::increase_size() { + reserve(m_capacity * 2); + } /** * @brief Reserves space in the Vector for a certain amount of elements @@ -171,45 +172,45 @@ namespace MaxOS{ * @tparam Type Type of the Vector * @param amount The amount of elements to reserve space for */ - template void Vector::reserve(size_t amount) { + template void Vector::reserve(size_t amount) { - // Increase the capacity of the Vector - if(m_capacity < amount) + // Increase the capacity of the Vector + if (m_capacity < amount) m_capacity = amount; - // Allocate more space for the array - Type* new_elements = new Type[amount]; + // Allocate more space for the array + Type* new_elements = new Type[amount]; - // Copy the elements to the new array - for (uint32_t i = 0; i < m_size; ++i) - new_elements[i] = m_elements[i]; + // Copy the elements to the new array + for (uint32_t i = 0; i < m_size; ++i) + new_elements[i] = m_elements[i]; - // De-allocate the old array - delete[] m_elements; + // De-allocate the old array + delete[] m_elements; - // Set the new array - m_elements = new_elements; - } + // Set the new array + m_elements = new_elements; + } - /** - * @brief Overloads the [] operator to return the element at the index - * - * @tparam Type Type of the Vector - * @param index The index of the element - * @return the element at the index or the end of the Vector if the index is out of bounds - */ - template Type &Vector::operator[](uint32_t index) const{ + /** + * @brief Overloads the [] operator to return the element at the index + * + * @tparam Type Type of the Vector + * @param index The index of the element + * @return the element at the index or the end of the Vector if the index is out of bounds + */ + template Type& Vector::operator [](uint32_t index) const { - // If the index is in the Vector - if (index < m_size) - return m_elements[index]; + // If the index is in the Vector + if (index < m_size) + return m_elements[index]; - // Return the last element of the Vector - return m_elements[m_size - 1]; + // Return the last element of the Vector + return m_elements[m_size - 1]; - } + } /** * @brief Assignment by copy, data is copied into a new buffer stored in this vector @@ -218,283 +219,283 @@ namespace MaxOS{ * @param other The vector to copy from * @return This vector, with the copied elements */ - template Vector& Vector::operator=(const Vector& other) { + template Vector& Vector::operator =(const Vector& other) { // Setting to itself? if (this == &other) return *this; // Create a new buffer to store the elements - delete[] m_elements; + delete[] m_elements; m_elements = new Type[other.m_capacity]; // Copy data - m_size = other.m_size; - m_capacity = other.m_capacity; - for (uint32_t i = 0; i < m_size; ++i) - m_elements[i] = other.m_elements[i]; + m_size = other.m_size; + m_capacity = other.m_capacity; + for (uint32_t i = 0; i < m_size; ++i) + m_elements[i] = other.m_elements[i]; - return *this; - } + return *this; + } - /** + /** * @brief Assignment by move, data is moved into the buffer stored in this vector and the other vector is cleared * * @tparam Type Type of the Vector * @param other The vector to copy from * @return This vector, with the copied elements */ - template Vector& Vector::operator=(Vector&& other) noexcept { + template Vector& Vector::operator =(Vector&& other) noexcept { - // Moving to itself? - if (this == &other) - return *this; + // Moving to itself? + if (this == &other) + return *this; - // Move into this vector - delete[] m_elements; - m_elements = other.m_elements; - m_size = other.m_size; - m_capacity = other.m_capacity; + // Move into this vector + delete[] m_elements; + m_elements = other.m_elements; + m_size = other.m_size; + m_capacity = other.m_capacity; // Remove from other vector - other.m_elements = nullptr; - other.m_size = 0; - other.m_capacity = 0; - - return *this; - } - - /** - * @brief Returns the number of elements in the Vector - * - * @tparam Type Type of the Vector - * @return The size of the Vector - */ - template uint32_t Vector::size() const{ - return m_size; - } - - /** - * @brief Returns the first element of the Vector - * - * @tparam Type Type of the Vector - * @return The first element of the Vector - */ - template typename Vector::iterator Vector::begin() const{ - return &m_elements[0]; - } - - /** - * @brief Returns the last element of the Vector - * - * @tparam Type Type of the Vector - * @return The last element of the Vector - */ - template typename Vector::iterator Vector::end() const{ - return &m_elements[0] + m_size; - } - - /** - * @brief Finds an element in the Vector and returns the iterator of the element - * - * @tparam Type Type of the Vector - * @param element The element to find - * @return The iterator of the element or the end of the Vector if the element is not found - */ - template typename Vector::iterator Vector::find(Type element) const{ - - // Find the element - for (iterator i = begin(); i != end(); ++i) - if (*i == element) - return i; - - // The element must not be in the Vector - return end(); - } - - /** - * @brief Checks if the Vector is empty - * - * @tparam Type Type of the Vector - * @return True if the Vector is empty, false otherwise - */ - template bool Vector::empty() const{ - return begin() == end(); - } - - - /** - * @brief Adds an element to the end of the vector and returns the iterator of the element - * - * @tparam Type Type of the Vector - * @param element The element to add - * @return The iterator of the element, if the Vector is full it returns the end of the Vector - */ - template typename Vector::iterator Vector::push_back(Type element) { - - // Check if we need to allocate more space for the array - if(m_size == m_capacity) - increase_size(); - - // Add the element to the Vector and return the iterator of the element - m_elements[m_size++] = element; - return end() - 1; - } - - /** - * @brief Removes the last element from the Vector - * @tparam Type Type of the Vector - */ - template Type Vector::pop_back() { - - // Remove the last element from the Vector - if (m_size > 0) - --m_size; - - return m_elements[m_size]; - } - - /** - * @brief Adds an element to the front of the Vector and returns the iterator of the element - * - * @tparam Type Type of the Vector - * @param element The element to add - * @return The iterator of the element, if the Vector is full it returns the end of the Vector - */ - template typename Vector::iterator Vector::push_front(Type element) { - - // Check if we need to allocate more space for the array - if(m_size == m_capacity) - increase_size(); - - // Move all elements one index to the right - for (iterator i = end(); i > begin(); --i) - *i = *(i - 1); - - // Add the element to the front of the Vector - m_elements[0] = element; - ++m_size; - - // Return the iterator of the element - return begin(); - } - - /** - * @brief Removes the m_first_memory_chunk element from the Vector - * - * @tparam Type Type of the Vector - * @return The element that was removed, or a default constructed element if the Vector is empty - */ - template Type Vector::pop_front() { - - // Make sure the Vector is not empty - if (m_size == 0) - return Type(); + other.m_elements = nullptr; + other.m_size = 0; + other.m_capacity = 0; + + return *this; + } + + /** + * @brief Returns the number of elements in the Vector + * + * @tparam Type Type of the Vector + * @return The size of the Vector + */ + template uint32_t Vector::size() const { + return m_size; + } + + /** + * @brief Returns the first element of the Vector + * + * @tparam Type Type of the Vector + * @return The first element of the Vector + */ + template typename Vector::iterator Vector::begin() const { + return &m_elements[0]; + } + + /** + * @brief Returns the last element of the Vector + * + * @tparam Type Type of the Vector + * @return The last element of the Vector + */ + template typename Vector::iterator Vector::end() const { + return &m_elements[0] + m_size; + } + + /** + * @brief Finds an element in the Vector and returns the iterator of the element + * + * @tparam Type Type of the Vector + * @param element The element to find + * @return The iterator of the element or the end of the Vector if the element is not found + */ + template typename Vector::iterator Vector::find(Type element) const { + + // Find the element + for (iterator i = begin(); i != end(); ++i) + if (*i == element) + return i; + + // The element must not be in the Vector + return end(); + } + + /** + * @brief Checks if the Vector is empty + * + * @tparam Type Type of the Vector + * @return True if the Vector is empty, false otherwise + */ + template bool Vector::empty() const { + return begin() == end(); + } + + + /** + * @brief Adds an element to the end of the vector and returns the iterator of the element + * + * @tparam Type Type of the Vector + * @param element The element to add + * @return The iterator of the element, if the Vector is full it returns the end of the Vector + */ + template typename Vector::iterator Vector::push_back(Type element) { + + // Check if we need to allocate more space for the array + if (m_size == m_capacity) + increase_size(); + + // Add the element to the Vector and return the iterator of the element + m_elements[m_size++] = element; + return end() - 1; + } + + /** + * @brief Removes the last element from the Vector + * @tparam Type Type of the Vector + * + * @return The element that was removed + */ + template Type Vector::pop_back() { + + // Remove the last element from the Vector + if (m_size > 0) + --m_size; + + return m_elements[m_size]; + } + + /** + * @brief Adds an element to the front of the Vector and returns the iterator of the element + * + * @tparam Type Type of the Vector + * @param element The element to add + * @return The iterator of the element, if the Vector is full it returns the end of the Vector + */ + template typename Vector::iterator Vector::push_front(Type element) { + + // Check if we need to allocate more space for the array + if (m_size == m_capacity) + increase_size(); + + // Move all elements one index to the right + for (iterator i = end(); i > begin(); --i) + *i = *(i - 1); + + // Add the element to the front of the Vector + m_elements[0] = element; + ++m_size; + + // Return the iterator of the element + return begin(); + } + + /** + * @brief Removes the m_first_memory_chunk element from the Vector + * + * @tparam Type Type of the Vector + * @return The element that was removed, or a default constructed element if the Vector is empty + */ + template Type Vector::pop_front() { + + // Make sure the Vector is not empty + if (m_size == 0) + return Type(); // Store the element to return Type element = m_elements[0]; - // Move all elements one index to the left - for (uint32_t i = 0; i < m_size - 1; ++i) - m_elements[i] = m_elements[i + 1]; - - // Decrease the size of the Vector - --m_size; - return element; - } - - /** - * @brief Removes all elements from the Vector that are equal to the element - * - * @tparam Type Type of the Vector - * @param element The element to remove - */ - template void Vector::erase(Type element) { - - // Search for the element - int hits = 0; - for (iterator i = begin(); i != end(); ++i) - { - // If it is the element we are looking for - if (*i == element) - { - ++hits; - } else { - - // If there are hits move the element to the left - if (hits > 0) - *(i - hits) = *i; - } - - } - - // Decrease the size of the Vector - m_size -= hits; - } - - /** - * @brief Removes the element at the m_position - * - * @tparam Type The type of the Vector - * @param position The m_position of the element to remove - */ - template void Vector::erase(typename Vector::iterator position) { - - // If the m_position is not in the Vector - if (position < begin() || position >= end()) - return; - - // Move all elements one index to the left - for (++position; position != end(); ++position) - *(position - 1) = *position; - - // Decrease the size of the Vector - --m_size; - } - - /** - * @brief Removes all elements from the Vector - * - * @tparam Type Type of the Vector - */ - template void Vector::clear() { - m_size = 0; - } - - /** - * @brief Iterates over the Vector and calls the OnRead function of the handler for each element - * - * @tparam Type Type of the Vector - * @param vector_iteration_handler The handler - */ - template void Vector::iterate(VectorIterationHandler *vector_iteration_handler) { - - // Call the OnRead function of the handler for each element - for(auto& element : m_elements) - vector_iteration_handler->on_read(element); - - // Call the OnEndOfStream function of the handler - vector_iteration_handler->on_end_of_stream(); - } - - - /** - * @brief Iterates over the Vector and calls the callback function for each element - * - * @tparam Type Type of the Vector - * @param callback The callback function - */ - template void Vector::Iterate(void callback(Type &)) { - - // Call the callback function for each element - for(auto& element : m_elements) - callback(element); - } - - template VectorIterationHandler::VectorIterationHandler() = default; - - template VectorIterationHandler::~VectorIterationHandler() = default; + // Move all elements one index to the left + for (uint32_t i = 0; i < m_size - 1; ++i) + m_elements[i] = m_elements[i + 1]; + + // Decrease the size of the Vector + --m_size; + return element; + } + + /** + * @brief Removes all elements from the Vector that are equal to the element + * + * @tparam Type Type of the Vector + * @param element The element to remove + */ + template void Vector::erase(Type element) { + + // Search for the element + int hits = 0; + for (iterator i = begin(); i != end(); ++i) { + // If it is the element we are looking for + if (*i == element) { + ++hits; + } else { + + // If there are hits move the element to the left + if (hits > 0) + *(i - hits) = *i; + } + + } + + // Decrease the size of the Vector + m_size -= hits; + } + + /** + * @brief Removes the element at the m_position + * + * @tparam Type The type of the Vector + * @param position The m_position of the element to remove + */ + template void Vector::erase(typename Vector::iterator position) { + + // If the m_position is not in the Vector + if (position < begin() || position >= end()) + return; + + // Move all elements one index to the left + for (++position; position != end(); ++position) + *(position - 1) = *position; + + // Decrease the size of the Vector + --m_size; + } + + /** + * @brief Removes all elements from the Vector + * + * @tparam Type Type of the Vector + */ + template void Vector::clear() { + m_size = 0; + } + + /** + * @brief Iterates over the Vector and calls the OnRead function of the handler for each element + * + * @tparam Type Type of the Vector + * @param vector_iteration_handler The handler + */ + template void Vector::iterate(VectorIterationHandler* vector_iteration_handler) { + + // Call the OnRead function of the handler for each element + for (auto& element : m_elements) + vector_iteration_handler->on_read(element); + + // Call the OnEndOfStream function of the handler + vector_iteration_handler->on_end_of_stream(); + } + + + /** + * @brief Iterates over the Vector and calls the callback function for each element + * + * @tparam Type Type of the Vector + * @param callback The callback function + */ + template void Vector::Iterate(void callback(Type&)) { + + // Call the callback function for each element + for (auto& element : m_elements) + callback(element); + } + + template VectorIterationHandler::VectorIterationHandler() = default; + + template VectorIterationHandler::~VectorIterationHandler() = default; /** @@ -502,19 +503,19 @@ namespace MaxOS{ * * @tparam Type Type of the values stored in the Vector */ - template void VectorIterationHandler::on_end_of_stream() { + template void VectorIterationHandler::on_end_of_stream() { - } + } /** * @brief Called when an element is read from the Vector (overridden by subclasses, no default behavior) * * @tparam Type Type of the values stored in the Vector */ - template void VectorIterationHandler::on_read(Type) { + template void VectorIterationHandler::on_read(Type) { - } - } + } + } } diff --git a/kernel/include/drivers/disk/ide.h b/kernel/include/drivers/disk/ide.h index 440b5393..2364d9ff 100644 --- a/kernel/include/drivers/disk/ide.h +++ b/kernel/include/drivers/disk/ide.h @@ -31,7 +31,7 @@ namespace MaxOS { common::Map devices; public: - IntegratedDriveElectronicsController(hardwarecommunication::PeripheralComponentInterconnectDeviceDescriptor* device_descriptor); + IntegratedDriveElectronicsController(hardwarecommunication::PCIDeviceDescriptor* device_descriptor); ~IntegratedDriveElectronicsController(); void initialise() final; diff --git a/kernel/include/drivers/ethernet/amd_am79c973.h b/kernel/include/drivers/ethernet/amd_am79c973.h index 4b89c340..586269e1 100644 --- a/kernel/include/drivers/ethernet/amd_am79c973.h +++ b/kernel/include/drivers/ethernet/amd_am79c973.h @@ -103,7 +103,7 @@ namespace MaxOS { void FetchDataSent(); //Fetches the data from the buffer public: - AMD_AM79C973(hardwarecommunication::PeripheralComponentInterconnectDeviceDescriptor* device_descriptor); + AMD_AM79C973(hardwarecommunication::PCIDeviceDescriptor* dev); ~AMD_AM79C973(); // Override driver default methods diff --git a/kernel/include/drivers/ethernet/intel_i217.h b/kernel/include/drivers/ethernet/intel_i217.h index 911e2e5b..61adc625 100644 --- a/kernel/include/drivers/ethernet/intel_i217.h +++ b/kernel/include/drivers/ethernet/intel_i217.h @@ -20,11 +20,11 @@ #include #include -namespace MaxOS{ +namespace MaxOS { - namespace drivers { + namespace drivers { - namespace ethernet{ + namespace ethernet { /** * @struct ReceiveDescriptor @@ -33,14 +33,14 @@ namespace MaxOS{ * @typedef receive_descriptor_t * @brief Alias for ReceiveDescriptor struct */ - typedef struct PACKED ReceiveDescriptor { - uint64_t bufferAddress; ///< The address of the receive buffer - uint16_t length; ///< The length of the received frame - uint16_t checksum; ///< The checksum of the received frame - uint8_t status; ///< The status of the received frame - uint8_t errors; ///< Any errors that occurred - uint16_t special; ///< Special - } receive_descriptor_t; + typedef struct PACKED ReceiveDescriptor { + uint64_t bufferAddress; ///< The address of the receive buffer + uint16_t length; ///< The length of the received frame + uint16_t checksum; ///< The checksum of the received frame + uint8_t status; ///< The status of the received frame + uint8_t errors; ///< Any errors that occurred + uint16_t special; ///< Special + } receive_descriptor_t; /** * @struct SendDescriptor @@ -49,110 +49,110 @@ namespace MaxOS{ * @typedef send_descriptor_t * @brief Alias for SendDescriptor struct */ - typedef struct PACKED SendDescriptor { - uint64_t bufferAddress; ///< The address of the send buffer - uint16_t length; ///< The length of the send frame - uint8_t cso; ///< The checksum offset - uint8_t cmd; ///< The command - uint8_t status; ///< The status - uint8_t css; ///< The checksum start - uint16_t special; ///< Special - } send_descriptor_t; + typedef struct PACKED SendDescriptor { + uint64_t bufferAddress; ///< The address of the send buffer + uint16_t length; ///< The length of the send frame + uint8_t cso; ///< The checksum offset + uint8_t cmd; ///< The command + uint8_t status; ///< The status + uint8_t css; ///< The checksum start + uint16_t special; ///< Special + } send_descriptor_t; - /** - * @class IntelI217 - * @brief Driver for the Intel I217 Ethernet Controller - */ - class IntelI217 : public EthernetDriver, public hardwarecommunication::InterruptHandler { + /** + * @class IntelI217 + * @brief Driver for the Intel I217 Ethernet Controller + */ + class IntelI217 : public EthernetDriver, public hardwarecommunication::InterruptHandler { - uint8_t bar_type = { 0 }; - uint16_t portBase = { 0 }; - uint64_t memBase = { 0 }; - uint8_t macAddress[6] = { 0 }; + uint8_t bar_type = { 0 }; + uint16_t portBase = { 0 }; + uint64_t memBase = { 0 }; + uint8_t macAddress[6] = { 0 }; - //Registers Addresses (Main Registers) - uint16_t controlRegister; // The control register - uint16_t statusRegister; // The status register - uint16_t epromRegister; // The address of the eeprom register - uint16_t controlExtRegister; // The control extension register - uint16_t interruptMaskRegister; // The interrupt mask register + //Registers Addresses (Main Registers) + uint16_t controlRegister; // The control register + uint16_t statusRegister; // The status register + uint16_t epromRegister; // The address of the eeprom register + uint16_t controlExtRegister; // The control extension register + uint16_t interruptMaskRegister; // The interrupt mask register - //Registers Addresses (Receive Registers) - uint16_t receiveControlRegister; // The receive control register - uint16_t receiveDescriptorLowRegister; // The receive descriptor low register - uint16_t receiveDescriptorHighRegister; // The receive descriptor high register - uint16_t receiveDescriptorLengthRegister;// The receive descriptor length register - uint16_t receiveDescriptorHeadRegister; // The receive descriptor head register - uint16_t receiveDescriptorTailRegister; // The receive descriptor tail register + //Registers Addresses (Receive Registers) + uint16_t receiveControlRegister; // The receive control register + uint16_t receiveDescriptorLowRegister; // The receive descriptor low register + uint16_t receiveDescriptorHighRegister; // The receive descriptor high register + uint16_t receiveDescriptorLengthRegister;// The receive descriptor length register + uint16_t receiveDescriptorHeadRegister; // The receive descriptor head register + uint16_t receiveDescriptorTailRegister; // The receive descriptor tail register - //Registers Addresses (Send Registers) - uint16_t sendControlRegister; // The send control register - uint16_t sendDescriptorLowRegister; // The send descriptor low register - uint16_t sendDescriptorHighRegister; // The send descriptor high register - uint16_t sendDescriptorLengthRegister; // The send descriptor length register - uint16_t sendDescriptorHeadRegister; // The send descriptor head register - uint16_t sendDescriptorTailRegister; // The send descriptor tail register + //Registers Addresses (Send Registers) + uint16_t sendControlRegister; // The send control register + uint16_t sendDescriptorLowRegister; // The send descriptor low register + uint16_t sendDescriptorHighRegister; // The send descriptor high register + uint16_t sendDescriptorLengthRegister; // The send descriptor length register + uint16_t sendDescriptorHeadRegister; // The send descriptor head register + uint16_t sendDescriptorTailRegister; // The send descriptor tail register - //Buffers - struct receiveDescriptor *receiveDsrctrs[32]; // The receive descriptors - uint16_t currentReceiveBuffer; // The current receive buffer + //Buffers + receive_descriptor_t* receiveDsrctrs[32]; // The receive descriptors + uint16_t currentReceiveBuffer; // The current receive buffer - struct sendDescriptor *sendDsrctrs[8]; // The send descriptors - uint16_t currentSendBuffer; // The current send buffer + send_descriptor_t * sendDsrctrs[8]; // The send descriptors + uint16_t currentSendBuffer; // The current send buffer - // write Commands and read results From NICs either using MemIO or IO Ports - void Write(uint16_t address, uint32_t data) const; - uint32_t Read(uint16_t address) const; + // write Commands and read results From NICs either using MemIO or IO Ports + void Write(uint16_t address, uint32_t data) const; + uint32_t Read(uint16_t address) const; - //EPROM (Device Memory) - bool epromPresent; // Whether the EPROM is present - bool detectEEProm(); // Return true if EEProm exist, else it returns false and set the error_exists data member - uint32_t eepromRead( uint8_t addr); // read 4 bytes from a specific EEProm Address + //EPROM (Device Memory) + bool epromPresent; // Whether the EPROM is present + bool detectEEProm(); // Return true if EEProm exist, else it returns false and set the error_exists data member + uint32_t eepromRead(uint8_t addr); // read 4 bytes from a specific EEProm Address - bool readMACAddress(); // read MAC Address + bool readMACAddress(); // read MAC Address - void receiveInit(); // Initialise receive descriptors buffers - void sendInit(); // Initialise transmit descriptors buffers + void receiveInit(); // Initialise receive descriptors buffers + void sendInit(); // Initialise transmit descriptors buffers - //Ethernet Driver functions - MediaAccessControlAddress ownMAC; //MAC address of the device - volatile bool active; //Is the device active - volatile bool initDone; //Is the device initialised + //Ethernet Driver functions + MediaAccessControlAddress ownMAC; //MAC address of the device + volatile bool active; //Is the device active + volatile bool initDone; //Is the device initialised - void FetchDataReceived(); //Fetches the data from the buffer + void FetchDataReceived(); //Fetches the data from the buffer - public: + public: - IntelI217(hardwarecommunication::PeripheralComponentInterconnectDeviceDescriptor* deviceDescriptor); - ~IntelI217(); // Default Destructor + IntelI217(hardwarecommunication::PCIDeviceDescriptor* deviceDescriptor); + ~IntelI217(); // Default Destructor - //Override driver default methods - uint32_t reset() final; - void activate() final; - void deactivate() final; + //Override driver default methods + uint32_t reset() final; + void activate() final; + void deactivate() final; - //Override Interrupt default methods - void handle_interrupt() final; + //Override Interrupt default methods + void handle_interrupt() final; - //Ethernet Driver functions - string vendor_name() final; - string device_name() final; + //Ethernet Driver functions + string vendor_name() final; + string device_name() final; - void DoSend(uint8_t* buffer, uint32_t size) final; - uint64_t GetMediaAccessControlAddress() final; - }; + void DoSend(uint8_t* buffer, uint32_t size) final; + uint64_t GetMediaAccessControlAddress() final; + }; - } - } + } + } } diff --git a/kernel/include/drivers/peripherals/keyboard.h b/kernel/include/drivers/peripherals/keyboard.h index def2e33d..dca10bde 100644 --- a/kernel/include/drivers/peripherals/keyboard.h +++ b/kernel/include/drivers/peripherals/keyboard.h @@ -31,7 +31,7 @@ namespace MaxOS { */ enum class ScanCodeType : int { REGULAR, - EXTENDED,237 + EXTENDED, EXTENDED_BUFFER }; @@ -238,7 +238,7 @@ namespace MaxOS { * @enum KeyboardEvents * @brief The events that can be triggered by the Keyboard Driver */ - enum class KeyboardEvents {f + enum class KeyboardEvents { KEYDOWN, KEYUP }; diff --git a/kernel/include/drivers/peripherals/mouse.h b/kernel/include/drivers/peripherals/mouse.h index 2b188699..ab49bf5e 100644 --- a/kernel/include/drivers/peripherals/mouse.h +++ b/kernel/include/drivers/peripherals/mouse.h @@ -19,94 +19,96 @@ #include namespace MaxOS { - namespace drivers { - namespace peripherals { + namespace drivers { + namespace peripherals { /** * @enum MouseEvents * @brief The different types of mouse events that can be triggered */ - enum class MouseEvents{ - MOVE, - DOWN, - UP - }; - - /** - * @class MouseMoveEvent - * @brief Event that is triggered when the mouse moves, holds the x and y coordinates - */ - class MouseMoveEvent : public common::Event{ - public: - int8_t x; ///< The x coordinate of the mouse - int8_t y; ///< The y coordinate of the mouse - MouseMoveEvent(int8_t x, int8_t y); - ~MouseMoveEvent(); - }; - - /** - * @class MouseDownEvent - * @brief Event that is triggered when a mouse button is pressed, holds the button that was pressed - */ - class MouseDownEvent : public common::Event{ - public: - uint8_t button; ///< The button that was pressed - MouseDownEvent(uint8_t); - ~MouseDownEvent(); - }; - - /** - * @class MouseUpEvent - * @brief Event that is triggered when a mouse button is released, holds the button that was released - */ - class MouseUpEvent : public common::Event{ - public: - uint8_t button; ///< The button that was released - MouseUpEvent(uint8_t); - ~MouseUpEvent(); - }; - - /** - * @class MouseEventHandler - * @brief Handles events that are triggered by the mouse driver - */ - class MouseEventHandler : public common::EventHandler{ - - public: - MouseEventHandler(); - ~MouseEventHandler(); - - common::Event* - on_event(common::Event*) override; - - virtual void on_mouse_down_event(uint8_t button); - virtual void on_mouse_up_event(uint8_t button); - virtual void on_mouse_move_event(int8_t x, int8_t y); - }; - - /** - * @class MouseDriver - * @brief Driver for the PS/2 mouse, manages the mouse and triggers events when the mouse moves or a button is pressed - */ - class MouseDriver : public hardwarecommunication::InterruptHandler, public Driver, public common::EventManager{ - hardwarecommunication::Port8Bit data_port; - hardwarecommunication::Port8Bit command_port; - - void handle_interrupt() final; - - uint8_t m_buffer[3] = {}; - uint8_t m_offset = 0; - uint8_t m_buttons = 0; - - public: - MouseDriver(); - ~MouseDriver(); - - void activate() final; - string device_name() final; - }; - } - } + enum class MouseEvents { + MOVE, + DOWN, + UP + }; + + /** + * @class MouseMoveEvent + * @brief Event that is triggered when the mouse moves, holds the x and y coordinates + */ + class MouseMoveEvent : public common::Event { + public: + int8_t x; ///< The x coordinate of the mouse + int8_t y; ///< The y coordinate of the mouse + MouseMoveEvent(int8_t x, int8_t y); + ~MouseMoveEvent(); + }; + + /** + * @class MouseDownEvent + * @brief Event that is triggered when a mouse button is pressed, holds the button that was pressed + */ + class MouseDownEvent : public common::Event { + public: + uint8_t button; ///< The button that was pressed + MouseDownEvent(uint8_t); + ~MouseDownEvent(); + }; + + /** + * @class MouseUpEvent + * @brief Event that is triggered when a mouse button is released, holds the button that was released + */ + class MouseUpEvent : public common::Event { + public: + uint8_t button; ///< The button that was released + MouseUpEvent(uint8_t); + ~MouseUpEvent(); + }; + + /** + * @class MouseEventHandler + * @brief Handles events that are triggered by the mouse driver + */ + class MouseEventHandler : public common::EventHandler { + + public: + MouseEventHandler(); + ~MouseEventHandler(); + + common::Event* + on_event(common::Event*) override; + + virtual void on_mouse_down_event(uint8_t button); + virtual void on_mouse_up_event(uint8_t button); + virtual void on_mouse_move_event(int8_t x, int8_t y); + }; + + /** + * @class MouseDriver + * @brief Driver for the PS/2 mouse, manages the mouse and triggers events when the mouse moves or a button is pressed + */ + class MouseDriver : public hardwarecommunication::InterruptHandler, public Driver, public common::EventManager { + + private: + hardwarecommunication::Port8Bit data_port; + hardwarecommunication::Port8Bit command_port; + + void handle_interrupt() final; + + uint8_t m_buffer[3] = { }; + uint8_t m_offset = 0; + uint8_t m_buttons = 0; + + public: + MouseDriver(); + ~MouseDriver(); + + void activate() final; + string device_name() final; + }; + } + } } diff --git a/kernel/include/filesystem/format/fat32.h b/kernel/include/filesystem/format/fat32.h index aef84795..9e52b297 100644 --- a/kernel/include/filesystem/format/fat32.h +++ b/kernel/include/filesystem/format/fat32.h @@ -222,7 +222,11 @@ namespace MaxOS { void read(common::buffer_t* data, size_t amount) final; void flush() final; - uint32_t first_cluster() const { return m_first_cluster; } ///< Get the first cluster of the file + /** + * @brief Get the first cluster of the directory + * @return The first cluster of the directory + */ + [[nodiscard]] uint32_t first_cluster() const { return m_first_cluster; } }; /** @@ -269,7 +273,11 @@ namespace MaxOS { Directory* create_subdirectory(const string &name) final; void remove_subdirectory(const string &name) final; - [[nodiscard]] lba_t first_cluster() const { return m_first_cluster; } ///< Get the first cluster of the directory + /** + * @brief Get the first cluster of the directory + * @return The first cluster of the directory + */ + [[nodiscard]] lba_t first_cluster() const { return m_first_cluster; } }; /** diff --git a/kernel/include/hardwarecommunication/interrupts.h b/kernel/include/hardwarecommunication/interrupts.h index 95d0c56d..54b97478 100644 --- a/kernel/include/hardwarecommunication/interrupts.h +++ b/kernel/include/hardwarecommunication/interrupts.h @@ -174,7 +174,11 @@ namespace MaxOS { void activate(); void deactivate(); - static void ForceInterruptReturn(system::cpu_status_t* state); ///< Force the CPU to return from an interrupt (see interrupts.s) + /** + * @brief Force the CPU to return from an interrupt (see interrupts.s) + * @param state the state to return to + */ + static void ForceInterruptReturn(system::cpu_status_t* state); }; } diff --git a/kernel/include/hardwarecommunication/pci.h b/kernel/include/hardwarecommunication/pci.h index 0b6aac10..bd25e368 100644 --- a/kernel/include/hardwarecommunication/pci.h +++ b/kernel/include/hardwarecommunication/pci.h @@ -17,100 +17,98 @@ #include #include -namespace MaxOS -{ - namespace hardwarecommunication - { +namespace MaxOS { + namespace hardwarecommunication { + /** - * @enum BaseAddressRegisterType + * @enum BARType * @brief Determines whether the PCI device communicates via IO ports or memory. */ - enum class BaseAddressRegisterType{ - MemoryMapped, - InputOutput - }; - - /** - * @class BaseAddressRegister - * @brief Used to store the base address register - * - * @todo Should be a struct - */ - class BaseAddressRegister{ - public: - bool pre_fetchable; ///< Reading from this address wont change the state of the device and data can be cached by the CPU - uint8_t* address; ///< The address of the device (IO port or memory address, can be 32 or 64 bit) - uint32_t size; ///< @todo Document Size of the address space - BaseAddressRegisterType type; ///< Where to access the device - - }; - - - /** - * @class PeripheralComponentInterconnectDeviceDescriptor - * @brief Stores information about a PCI device - * - * @todo Should be a struct aswell - */ - class PeripheralComponentInterconnectDeviceDescriptor { - public: - bool has_port_base = false; ///< Whether the device has an IO port base address - uint32_t port_base = 0; ///< The IO port base address - - bool has_memory_base = false; ///< Whether the device has a memory base address - uint32_t memory_base = 0; ///< The memory base address - - uint32_t interrupt = 0; ///< The interrupt number the device uses to communicate with the CPU - - uint16_t bus = 0; ///< The PCI bus the device is connected to - uint16_t device = 0; ///< The device number on the PCI bus - uint16_t function = 0; ///< The function number of the device - - uint16_t vendor_id = 0; ///< The company's that made the device unique identifier - uint16_t device_id = 0; ///< The device's unique identifier - - uint8_t class_id = 0; ///< The class type of the device - uint8_t subclass_id = 0; ///< The subclass type of the device - uint8_t interface_id = 0; ///< The interface type of the device - - uint8_t revision = 0; ///< The device version number - - PeripheralComponentInterconnectDeviceDescriptor(); - ~PeripheralComponentInterconnectDeviceDescriptor(); - - string get_type() const; - }; - - - /** - * @class PeripheralComponentInterconnectController - * @brief Handles the selecting and loading of drivers for PCI devices - */ - class PeripheralComponentInterconnectController : public drivers::DriverSelector - { - private: - // Ports - Port32Bit m_data_port; - Port32Bit m_command_port; - - // I/O - uint32_t read(uint16_t bus, uint16_t device, uint16_t function, uint32_t register_offset); - void write(uint16_t bus, uint16_t device, uint16_t function, uint32_t register_offset, uint32_t value); - - // Device - PeripheralComponentInterconnectDeviceDescriptor get_device_descriptor(uint16_t bus, uint16_t device, uint16_t function); - BaseAddressRegister get_base_address_register(uint16_t bus, uint16_t device, uint16_t function, uint16_t bar); - bool device_has_functions(uint16_t bus, uint16_t device); - - public: - PeripheralComponentInterconnectController(); - ~PeripheralComponentInterconnectController(); - - void select_drivers(drivers::DriverSelectorEventHandler* handler) override; - static drivers::Driver* get_driver(PeripheralComponentInterconnectDeviceDescriptor dev); - static void list_known_device(const PeripheralComponentInterconnectDeviceDescriptor& dev); - }; - } + enum class BARType { + MemoryMapped, + InputOutput + }; + + /** + * @class BaseAddressRegister + * @brief Used to store the Base Address Register (BAR) of a PCI device + * + * @todo Should be a struct + */ + class BaseAddressRegister { + public: + bool pre_fetchable; ///< Reading from this address wont change the state of the device and data can be cached by the CPU + uint8_t* address; ///< The address of the device (IO port or memory address, can be 32 or 64 bit) + uint32_t size; ///< @todo Document Size of the address space + BARType type; ///< Where to access the device + + }; + + + /** + * @class PCIDeviceDescriptor + * @brief Stores information about a PCI device + * + * @todo Should be a struct aswell + */ + class PCIDeviceDescriptor { + public: + bool has_port_base = false; ///< Whether the device has an IO port base address + uint32_t port_base = 0; ///< The IO port base address + + bool has_memory_base = false; ///< Whether the device has a memory base address + uint32_t memory_base = 0; ///< The memory base address + + uint32_t interrupt = 0; ///< The interrupt number the device uses to communicate with the CPU + + uint16_t bus = 0; ///< The PCI bus the device is connected to + uint16_t device = 0; ///< The device number on the PCI bus + uint16_t function = 0; ///< The function number of the device + + uint16_t vendor_id = 0; ///< The company's that made the device unique identifier + uint16_t device_id = 0; ///< The device's unique identifier + + uint8_t class_id = 0; ///< The class type of the device + uint8_t subclass_id = 0; ///< The subclass type of the device + uint8_t interface_id = 0; ///< The interface type of the device + + uint8_t revision = 0; ///< The device version number + + PCIDeviceDescriptor(); + ~PCIDeviceDescriptor(); + + string get_type() const; + }; + + + /** + * @class PCIController + * @brief Handles the selecting and loading of drivers for PCI devices + */ + class PCIController : public drivers::DriverSelector { + private: + // Ports + Port32Bit m_data_port; + Port32Bit m_command_port; + + // I/O + uint32_t read(uint16_t bus, uint16_t device, uint16_t function, uint32_t register_offset); + void write(uint16_t bus, uint16_t device, uint16_t function, uint32_t register_offset, uint32_t value); + + // Device + PCIDeviceDescriptor get_device_descriptor(uint16_t bus, uint16_t device, uint16_t function); + BaseAddressRegister get_base_address_register(uint16_t bus, uint16_t device, uint16_t function, uint16_t bar); + bool device_has_functions(uint16_t bus, uint16_t device); + + public: + PCIController(); + ~PCIController(); + + void select_drivers(drivers::DriverSelectorEventHandler* handler) override; + static drivers::Driver* get_driver(PCIDeviceDescriptor dev); + static void list_known_device(const PCIDeviceDescriptor& dev); + }; + } } #endif //MAX_OS_HARDWARECOMMUNICATION_PCI_H diff --git a/kernel/include/processes/process.h b/kernel/include/processes/process.h index 20d1864f..0e6522fa 100644 --- a/kernel/include/processes/process.h +++ b/kernel/include/processes/process.h @@ -73,7 +73,7 @@ namespace MaxOS size_t ticks; ///< The number of ticks the thread has run for size_t wakeup_time; ///< The time at which the thread should wake up (if sleeping) - [[nodiscard]] uintptr_t tss_pointer() const { return m_tss_stack_pointer; } ///< Gets the stack pointer to use for the TSS when switching to this thread + [[nodiscard]] uintptr_t tss_pointer() const { return m_tss_stack_pointer; } ///< Gets the stack pointer to use for the TSS when switching to this thread @return tss void save_sse_state(); void restore_sse_state(); diff --git a/kernel/include/processes/resource.h b/kernel/include/processes/resource.h index 34fc0b5e..f1c3fe6d 100644 --- a/kernel/include/processes/resource.h +++ b/kernel/include/processes/resource.h @@ -84,7 +84,13 @@ namespace MaxOS { explicit ResourceRegistry(resource_type_t type); ~ResourceRegistry() = default; - /// Creates a resource of the specific type + /** + * @brief Create a new resource of the specific type + * + * @param name The name of the resource + * @param flags The flags to open the resource with + * @return The created resource, or nullptr on failure + */ Resource* create_resource(const string &name, size_t flags) override { auto resource = new Type(name, flags, type()); diff --git a/kernel/include/system/cpu.h b/kernel/include/system/cpu.h index 0333d5f1..6e6a7375 100644 --- a/kernel/include/system/cpu.h +++ b/kernel/include/system/cpu.h @@ -34,6 +34,7 @@ namespace MaxOS { * * @typedef cpu_status_t * @brief Alias for CPUStatus struct + * */ typedef struct PACKED CPUStatus { diff --git a/kernel/src/asm/interrupts.s b/kernel/src/asm/interrupts.s index b20054fb..ab390b24 100644 --- a/kernel/src/asm/interrupts.s +++ b/kernel/src/asm/interrupts.s @@ -10,7 +10,7 @@ ; */ [bits 64] -[extern _ZN5MaxOS21hardwarecommunication16InterruptManager15HandleInterruptEPNS_6system12cpu_status_tE] +[extern _ZN5MaxOS21hardwarecommunication16InterruptManager15HandleInterruptEPNS_6system9CPUStatusE] %macro HandleException 1 [global _ZN5MaxOS21hardwarecommunication16InterruptManager19HandleException%1Ev] @@ -21,7 +21,7 @@ _ZN5MaxOS21hardwarecommunication16InterruptManager19HandleException%1Ev: save_context ; Now we can save the general purpose registers mov rdi, rsp ; Let's set the current stack pointer as a parameter of the interrupts_handler cld ; Clear the direction flag - call _ZN5MaxOS21hardwarecommunication16InterruptManager15HandleInterruptEPNS_6system12cpu_status_tE ; Now we call the interrupt handler + call _ZN5MaxOS21hardwarecommunication16InterruptManager15HandleInterruptEPNS_6system9CPUStatusE ; Now we call the interrupt handler mov rsp, rax ; use the returned context restore_context ; We served the interrupt let's restore the previous context add rsp, 16 ; We can discard the interrupt number and the error code @@ -37,7 +37,7 @@ _ZN5MaxOS21hardwarecommunication16InterruptManager26HandleInterruptRequest%1Ev: save_context ; Now we can save the general purpose registers mov rdi, rsp ; Let's set the current stack pointer as a parameter of the interrupts_handler cld ; Clear the direction flag - call _ZN5MaxOS21hardwarecommunication16InterruptManager15HandleInterruptEPNS_6system12cpu_status_tE ; Now we call the interrupt handler + call _ZN5MaxOS21hardwarecommunication16InterruptManager15HandleInterruptEPNS_6system9CPUStatusE ; Now we call the interrupt handler mov rsp, rax ; use the returned context restore_context ; We served the interrupt let's restore the previous context add rsp, 16 ; We can discard the interrupt number and the error code @@ -51,7 +51,7 @@ _ZN5MaxOS21hardwarecommunication16InterruptManager24HandleInterruptError%1Ev: save_context mov rdi, rsp cld - call _ZN5MaxOS21hardwarecommunication16InterruptManager15HandleInterruptEPNS_6system12cpu_status_tE + call _ZN5MaxOS21hardwarecommunication16InterruptManager15HandleInterruptEPNS_6system9CPUStatusE mov rsp, rax ; use the returned context restore_context add rsp, 16 @@ -59,8 +59,8 @@ _ZN5MaxOS21hardwarecommunication16InterruptManager24HandleInterruptError%1Ev: %endmacro -[global _ZN5MaxOS21hardwarecommunication16InterruptManager20ForceInterruptReturnEPNS_6system12cpu_status_tE] -_ZN5MaxOS21hardwarecommunication16InterruptManager20ForceInterruptReturnEPNS_6system12cpu_status_tE: +[global _ZN5MaxOS21hardwarecommunication16InterruptManager20ForceInterruptReturnEPNS_6system9CPUStatusE] +_ZN5MaxOS21hardwarecommunication16InterruptManager20ForceInterruptReturnEPNS_6system9CPUStatusE: mov rsp, rdi ; use the returned context restore_context diff --git a/kernel/src/common/buffer.cpp b/kernel/src/common/buffer.cpp index d8d945d0..0f0cba4f 100644 --- a/kernel/src/common/buffer.cpp +++ b/kernel/src/common/buffer.cpp @@ -160,6 +160,7 @@ void Buffer::write(size_t offset, uint8_t byte) { /** * @brief Safely reads a byte from the buffer at the current offset * + * @return The read byte */ uint8_t Buffer::read() { set_offset(m_offset + 1); @@ -170,6 +171,8 @@ uint8_t Buffer::read() { * @brief Safely reads a byte from the buffer at the specified offset * * @param offset The offset into the buffer storage array + * + * @return The read byte */ uint8_t Buffer::read(size_t offset) { diff --git a/kernel/src/common/graphicsContext.cpp b/kernel/src/common/graphicsContext.cpp index edc349b1..dbd3571c 100644 --- a/kernel/src/common/graphicsContext.cpp +++ b/kernel/src/common/graphicsContext.cpp @@ -10,6 +10,10 @@ using namespace MaxOS::common; + +/** + * @brief Constructs a GraphicsContext object and initializes the color palette + */ GraphicsContext::GraphicsContext() { diff --git a/kernel/src/common/logger.cpp b/kernel/src/common/logger.cpp index 3c908549..8a6092a7 100644 --- a/kernel/src/common/logger.cpp +++ b/kernel/src/common/logger.cpp @@ -19,6 +19,9 @@ using namespace MaxOS::drivers::console; using namespace MaxOS::processes; using namespace MaxOS::system; +/** + * @brief Constructs a Logger object and sets it as the active logger + */ Logger::Logger() : m_log_writers() { @@ -31,10 +34,7 @@ Logger::Logger() } -Logger::~Logger() { - - -} +Logger::~Logger() = default; /** * @brief Adds an output stream to the logger diff --git a/kernel/src/common/outputStream.cpp b/kernel/src/common/outputStream.cpp index 6ef00a4f..5ea43630 100644 --- a/kernel/src/common/outputStream.cpp +++ b/kernel/src/common/outputStream.cpp @@ -11,6 +11,9 @@ using namespace MaxOS; using namespace MaxOS::common; +/** + * @brief Constructs an OutputStream object that uses strings as the underlying data type + */ OutputStream::OutputStream() : GenericOutputStream::GenericOutputStream() { diff --git a/kernel/src/common/string.cpp b/kernel/src/common/string.cpp index 322f6b7f..c15a6774 100644 --- a/kernel/src/common/string.cpp +++ b/kernel/src/common/string.cpp @@ -43,7 +43,7 @@ String::String(char c) { * @brief Constructs a String from a pointer to an array of chars * @param string An array of chars, must be null terminated and of length less than 10,000 */ -String::String(char const *string) { +String::String(char const* string) { // Get the length of the string, prevent longer than 10000 because this should mean something's gone wrong m_length = 0; @@ -56,7 +56,7 @@ String::String(char const *string) { m_string[i] = string[i]; // If the length is more than 10,000 Replace the end with a warning incase future use actually requires that - const char *warning = "MAXOS: String length exceeded 10000 - might be a bug"; + const char* warning = "MAXOS: String length exceeded 10000 - might be a bug"; if (m_length > 10000) for (int i = 0; i < 52; i++) m_string[m_length - 52 + i] = warning[i]; @@ -70,7 +70,7 @@ String::String(char const *string) { * @param string The string bytes * @param length How large the string byte buffer is */ -String::String(uint8_t const *string, int length) { +String::String(uint8_t const* string, int length) { // Allocate memory for the string (and null terminator) m_length = length; allocate_self(); @@ -91,7 +91,7 @@ String::String(uint8_t const *string, int length) { String::String(int value) { // Convert to a string - const char *str = itoa(10, value); + const char* str = itoa(10, value); m_length = strlen(str); // Create space to store @@ -112,7 +112,7 @@ String::String(int value) { String::String(uint64_t value) { // Convert to a string - const char *str = htoa(value); + const char* str = htoa(value); m_length = strlen(str); // Create space to store @@ -131,7 +131,7 @@ String::String(uint64_t value) { String::String(float value) { // Convert to a string - const char *str = ftoa(value); + const char* str = ftoa(value); m_length = strlen(str); // Create space to store @@ -150,7 +150,7 @@ String::String(float value) { */ String::String(bool value) { - if(value) + if (value) *this = string("true"); else *this = string("false"); @@ -162,11 +162,13 @@ String::String(bool value) { * * @param other String to copy from */ -String::String(String const &other) { +String::String(String const& other) { copy(other); } - +/** + * @brief Destructor for the string, cleans up memory if needed + */ String::~String() { // Free the memory @@ -180,7 +182,7 @@ String::~String() { * * @param other The other string */ -void String::copy(String const &other) { +void String::copy(String const& other) { // Allocate memory for the string (and null terminator) m_length = other.length(); @@ -201,7 +203,7 @@ void String::copy(String const &other) { * @param string The string * @return The sum of the ascii values of the characters in the string */ -int String::lex_value(String const &string) { +int String::lex_value(String const& string) { // Sum the ascii values of the characters in the string int sum = 0; @@ -232,7 +234,7 @@ void String::allocate_self() { * @param other The string for this one to be updated to * @return String The string */ -String &String::operator=(String const &other) { +String& String::operator =(String const& other) { // Self assignment check if (this == &other) @@ -248,7 +250,7 @@ String &String::operator=(String const &other) { * * @return The char* string */ -char *String::c_str() { +char* String::c_str() { return m_string; } @@ -258,7 +260,7 @@ char *String::c_str() { * * @return The string as an array of characters */ -const char *String::c_str() const { +const char* String::c_str() const { return m_string; } @@ -269,7 +271,7 @@ const char *String::c_str() const { * @param other The other string * @return True if the string starts with the other string, false otherwise */ -bool String::starts_with(String const &other) { +bool String::starts_with(String const& other) { // Must at least be able to fit the other string if (m_length < other.length()) @@ -295,11 +297,11 @@ String String::substring(int start, int length) const { // Ensure the start is within bounds if (start < 0 || start >= m_length) - return {}; + return { }; // Ensure the length is within bounds if (length < 0 || start + length > m_length) - return {}; + return { }; // Allocate memory for the substring (and null terminator) String substring; @@ -322,7 +324,7 @@ String String::substring(int start, int length) const { * @param delimiter What to split the string by * @return A vector of strings that were split by the delimiter */ -common::Vector String::split(String const &delimiter) const { +common::Vector String::split(String const& delimiter) const { common::Vector strings; // Go through the string and split it by the delimiter @@ -337,7 +339,7 @@ common::Vector String::split(String const &delimiter) const { break; } - if(!matches) + if (!matches) continue; // Add the splice of the string @@ -389,7 +391,7 @@ int String::length(bool count_ansi) const { * @param other The other string * @return True if the strings are equal, false otherwise */ -bool String::equals(String const &other) const { +bool String::equals(String const& other) const { // Check if the lengths are equal if (m_length != other.length()) @@ -411,7 +413,7 @@ bool String::equals(String const &other) const { * @param other The other string * @return True if the strings are equal, false otherwise */ -bool String::operator == (String const &other) const { +bool String::operator ==(String const& other) const { // Check if the strings are equal return equals(other); @@ -423,7 +425,7 @@ bool String::operator == (String const &other) const { * @param other The other string * @return True if the strings are not equal, false otherwise */ -bool String::operator != (String const &other) const { +bool String::operator !=(String const& other) const { // Self assignment check if (*this == other) @@ -438,7 +440,7 @@ bool String::operator != (String const &other) const { * @param other The other string * @return True if the string is less than the other, false otherwise */ -bool String::operator < (String const &other) const { +bool String::operator <(String const& other) const { return lex_value(*this) < lex_value(other); @@ -450,7 +452,7 @@ bool String::operator < (String const &other) const { * @param other The other string * @return True if the string is greater than the other, false otherwise */ -bool String::operator > (String const &other) const { +bool String::operator >(String const& other) const { return lex_value(*this) > lex_value(other); @@ -462,7 +464,7 @@ bool String::operator > (String const &other) const { * @param other The other string * @return True if the string is less than or equal to the other, false otherwise */ -bool String::operator <= (String const &other) const { +bool String::operator <=(String const& other) const { return lex_value(*this) <= lex_value(other); @@ -474,7 +476,7 @@ bool String::operator <= (String const &other) const { * @param other The other string * @return True if the string is greater than or equal to the other, false otherwise */ -bool String::operator >= (String const &other) const { +bool String::operator >=(String const& other) const { return lex_value(*this) >= lex_value(other); @@ -486,7 +488,7 @@ bool String::operator >= (String const &other) const { * @param other The other string * @return The concatenated string */ -String String::operator + (String const &other) const { +String String::operator +(String const& other) const { // The concatenated string String concatenated; @@ -514,7 +516,7 @@ String String::operator + (String const &other) const { * @param other The other string * @return The concatenated string */ -String &String::operator+=(String const &other) { +String& String::operator +=(String const& other) { // Add the other string to this string String concatenated = *this + other; @@ -529,7 +531,7 @@ String &String::operator+=(String const &other) { * @param index The index of the character * @return The character at the specified index */ -char &String::operator[](int index) { +char& String::operator [](int index) { return m_string[index]; } @@ -540,7 +542,7 @@ char &String::operator[](int index) { * @param index The index of the character * @return The character at the specified index */ -char &String::operator[](int index) const { +char& String::operator [](int index) const { return m_string[index]; } @@ -550,7 +552,7 @@ char &String::operator[](int index) const { * @param times The number of times to repeat the string * @return The string repeated a number of times */ -String String::operator*(int times) const { +String String::operator *(int times) const { // The repeated string String repeated; @@ -665,7 +667,7 @@ String String::formatted(char const* format, va_list parameters) { // If it is not a %, print the character if (*format != '%') { - out += (string)(char)(*format); + out += (string) (char) (*format); continue; } @@ -675,19 +677,19 @@ String String::formatted(char const* format, va_list parameters) { case 'd': { // Print a decimal int number = va_arg (parameters, int); - out += (string)(number); + out += (string) (number); break; } case 'x': { // Print a hex uint64_t number = va_arg (parameters, uint64_t); - out += (string)(number); + out += (string) (number); break; } case 's': { // Print a string - char *str = va_arg (parameters, char*); - out += (string)(str); + char* str = va_arg (parameters, char*); + out += (string) (str); break; } } @@ -703,7 +705,7 @@ String String::formatted(char const* format, va_list parameters) { * @param str The string to get the length of * @return The length of the string */ -int strlen(const char *str) { +int strlen(const char* str) { int len = 0; for (; str[len] != '\0'; len++); return len; @@ -717,10 +719,10 @@ int strlen(const char *str) { * * @return The converted string */ -char *itoa(int base, int64_t number) { +char* itoa(int base, int64_t number) { // If there is no buffer use a default buffer - static char buffer[50] = {0}; + static char buffer[50] = { 0 }; int i = 49; bool isNegative = number < 0; @@ -748,9 +750,9 @@ char *itoa(int base, int64_t number) { * @param number The number to convert * @return The converted string */ -char *htoa(uint64_t number) { +char* htoa(uint64_t number) { // If there is no buffer use a default buffer - static char buffer[50] = {0}; + static char buffer[50] = { 0 }; int i = 49; if (number == 0) { @@ -770,10 +772,10 @@ char *htoa(uint64_t number) { * @param number The number to convert * @return The converted string */ -char *ftoa(float number) { +char* ftoa(float number) { static char buffer[50]; - char *ptr = buffer; + char* ptr = buffer; // Handle negative numbers. if (number < 0) { @@ -786,7 +788,7 @@ char *ftoa(float number) { float fraction = number - (float) intPart; // Convert integer part to string using itoa. - char *intStr = itoa(10, intPart); + char* intStr = itoa(10, intPart); while (*intStr) { *ptr++ = *intStr++; } @@ -808,12 +810,12 @@ char *ftoa(float number) { // Convert the fractional part to string. char fracBuffer[50]; - char *fracStr = itoa(10, fracInt); + char* fracStr = itoa(10, fracInt); // Ensure we have leading zeros if the fractional part doesn't produce enough digits. // Calculate length of the converted fractional string. int len = 0; - for (char *p = fracStr; *p; p++) { + for (char* p = fracStr; *p; p++) { len++; } for (int i = 0; i < precision - len; i++) { @@ -838,7 +840,7 @@ char *ftoa(float number) { * @param str2 The second string * @return True if the strings are equal, false otherwise */ -bool strcmp(char const *str1, char const *str2) { +bool strcmp(char const* str1, char const* str2) { // Check if the strings are equal for (int i = 0; str1[i] != '\0' || str2[i] != '\0'; i++) @@ -857,7 +859,7 @@ bool strcmp(char const *str1, char const *str2) { * @param str2 The second string * @return True if the strings are equal, false otherwise */ -bool strcmp(char const *str1, String const &str2) { +bool strcmp(char const* str1, String const& str2) { // Use the other strcmp function return strcmp(str1, str2.c_str()); @@ -871,7 +873,7 @@ bool strcmp(char const *str1, String const &str2) { * @param str2 The second string * @return True if the strings are equal, false otherwise */ -bool strcmp(String const &str1, char const *str2) { +bool strcmp(String const& str1, char const* str2) { // Use the other strcmp function return strcmp(str1.c_str(), str2); @@ -884,7 +886,7 @@ bool strcmp(String const &str1, char const *str2) { * @param str2 The second string * @return True if the strings are equal, false otherwise */ -bool strcmp(String const &str1, String const &str2) { +bool strcmp(String const& str1, String const& str2) { // Use the other strcmp function return strcmp(str1.c_str(), str2.c_str()); @@ -899,7 +901,7 @@ bool strcmp(String const &str1, String const &str2) { * @param length The length of the string to compare * @return True if the strings are equal, false otherwise */ -bool strncmp(char const *str1, char const *str2, int length) { +bool strncmp(char const* str1, char const* str2, int length) { // Check if the strings are equal for (int i = 0; i < length; i++) @@ -919,7 +921,7 @@ bool strncmp(char const *str1, char const *str2, int length) { * @param length The length of the string to compare * @return True if the strings are equal, false otherwise */ -bool strncmp(char const *str1, String const &str2, int length) { +bool strncmp(char const* str1, String const& str2, int length) { // Use the other strncmp function return strncmp(str1, str2.c_str(), length); @@ -934,7 +936,7 @@ bool strncmp(char const *str1, String const &str2, int length) { * @param length The length of the string to compare * @return True if the strings are equal, false otherwise */ -bool strncmp(String const &str1, char const *str2, int length) { +bool strncmp(String const& str1, char const* str2, int length) { // Use the other strncmp function return strncmp(str1.c_str(), str2, length); @@ -949,8 +951,74 @@ bool strncmp(String const &str1, char const *str2, int length) { * @param length The length of the string to compare * @return True if the strings are equal, false otherwise */ -bool strncmp(String const &str1, String const &str2, int length) { +bool strncmp(String const& str1, String const& str2, int length) { // Use the other strncmp function return strncmp(str1.c_str(), str2.c_str(), length); } + +/** + * @brief Append C-string to the StringBuilder + * + * @param str The C-string to append + * @return The StringBuilder reference + */ +StringBuilder& StringBuilder::operator <<(char const* str) { + out += string(str); + return *this; +} + +/** + * @brief Append String to the StringBuilder + * + * @param other The String to append + * @return The StringBuilder reference + */ +StringBuilder& StringBuilder::operator <<(String const& other) { + out += other; + return *this; +} + +/** + * @brief Append int to the StringBuilder + * + * @param value The int value to append + * @return The StringBuilder reference + */ +StringBuilder& StringBuilder::operator <<(int value) { + out += string(value); + return *this; +} + +/** + * @brief Append a hex to the StringBuilder + * + * @param value The hex value to append + * @return The StringBuilder reference + */ +StringBuilder& StringBuilder::operator <<(uint64_t value) { + out += string(value); + return *this; +} + +/** + * @brief Append decimal to the StringBuilder + * + * @param value The decimal value to append + * @return The StringBuilder reference + */ +StringBuilder& StringBuilder::operator <<(float value) { + out += string(value); + return *this; +} + +/** + * @brief Append bool to the StringBuilder + * + * @param value The bool value to append + * @return The StringBuilder reference + */ +StringBuilder& StringBuilder::operator <<(bool value) { + out += string(value); + return *this; +} \ No newline at end of file diff --git a/kernel/src/drivers/console/console.cpp b/kernel/src/drivers/console/console.cpp index 54af1fcd..00099a15 100644 --- a/kernel/src/drivers/console/console.cpp +++ b/kernel/src/drivers/console/console.cpp @@ -428,9 +428,7 @@ ConsoleStream::ConsoleStream(Console *console) } -ConsoleStream::~ConsoleStream() { - -} +ConsoleStream::~ConsoleStream() = default; /** * @brief write a character to the console stream diff --git a/kernel/src/drivers/console/vesaboot.cpp b/kernel/src/drivers/console/vesaboot.cpp index 95e157d0..f255cfb1 100644 --- a/kernel/src/drivers/console/vesaboot.cpp +++ b/kernel/src/drivers/console/vesaboot.cpp @@ -245,6 +245,8 @@ ConsoleColour VESABootConsole::get_background_color(uint16_t x, uint16_t y) { /** * @brief Prints the logo to the center of the screen + * + * @param is_panic Whether to print the kernel panic logo or the normal logo */ void VESABootConsole::print_logo(bool is_panic) { diff --git a/kernel/src/drivers/disk/ide.cpp b/kernel/src/drivers/disk/ide.cpp index 7bfa3f2b..760814d8 100644 --- a/kernel/src/drivers/disk/ide.cpp +++ b/kernel/src/drivers/disk/ide.cpp @@ -22,7 +22,7 @@ using namespace MaxOS::filesystem::partition; * @param device_descriptor The PCI device descriptor for this controller * @todo Use the device descriptor to get the port base and add the devices dynamically */ -IntegratedDriveElectronicsController::IntegratedDriveElectronicsController(PeripheralComponentInterconnectDeviceDescriptor* device_descriptor) +IntegratedDriveElectronicsController::IntegratedDriveElectronicsController(PCIDeviceDescriptor* device_descriptor) { // Primary auto primary_maser = new AdvancedTechnologyAttachment(0x1F0, true); @@ -89,6 +89,8 @@ void IntegratedDriveElectronicsController::activate() { /** * @brief Get the vendor name + * + * @return The vendor name */ string IntegratedDriveElectronicsController::vendor_name() { return "Intel"; @@ -96,6 +98,8 @@ string IntegratedDriveElectronicsController::vendor_name() { /** * @brief Get the device name + * + * @return The device name */ string IntegratedDriveElectronicsController::device_name() { return "PIIX4"; diff --git a/kernel/src/drivers/driver.cpp b/kernel/src/drivers/driver.cpp index 0f45cc0a..d59e11ea 100644 --- a/kernel/src/drivers/driver.cpp +++ b/kernel/src/drivers/driver.cpp @@ -20,14 +20,14 @@ Driver::Driver() = default; Driver::~Driver() = default; /** - * @brief activate the driver + * @brief Activate the driver */ void Driver::activate() { } /** - * @brief deactivate the driver + * @brief Deactivate the driver */ void Driver::deactivate() { @@ -84,19 +84,26 @@ DriverSelector::DriverSelector() = default; DriverSelector::~DriverSelector() = default; /** - * @brief Select the drivers + * @brief Select the drivers available on the system + * + * @param handler The event handler to notify when a driver is selected */ -void DriverSelector::select_drivers(DriverSelectorEventHandler *) { +void DriverSelector::select_drivers(DriverSelectorEventHandler* handler) { } - +/** + * @brief Constructs the Driver Manager, adding any default driver selectors + */ DriverManager::DriverManager() { Logger::INFO() << "Setting up Driver Manager \n"; - add_driver_selector(new PeripheralComponentInterconnectController); + add_driver_selector(new PCIController); // add_driver_selector(new UniversalSerialBusController); } +/** + * @brief Destructor for the Driver Manager, removes all drivers and driver selectors + */ DriverManager::~DriverManager() { // Remove any drivers that are still attached @@ -132,6 +139,8 @@ void DriverManager::remove_driver(Driver *driver) { /** * @brief When a driver is selected add it to the manager + * + * @param driver The driver that was selected */ void DriverManager::on_driver_selected(Driver *driver) { add_driver(driver); @@ -139,6 +148,8 @@ void DriverManager::on_driver_selected(Driver *driver) { /** * @brief Add a driver selector to the manager + * + * @param driver_selector The driver selector to add */ void DriverManager::add_driver_selector(DriverSelector *driver_selector) { @@ -148,6 +159,8 @@ void DriverManager::add_driver_selector(DriverSelector *driver_selector) { /** * @brief Remove a driver selector from the manager + * + * @param driver_selector The driver selector to remove */ void DriverManager::remove_driver_selector(DriverSelector *driver_selector) { diff --git a/kernel/src/drivers/ethernet/amd_am79c973.cpp b/kernel/src/drivers/ethernet/amd_am79c973.cpp index 2b27da78..8db674a9 100644 --- a/kernel/src/drivers/ethernet/amd_am79c973.cpp +++ b/kernel/src/drivers/ethernet/amd_am79c973.cpp @@ -19,7 +19,11 @@ using namespace MaxOS::hardwarecommunication; /// All the old (this) networking code poorly written and not used, this will be moved to userspace in the future /// but is kept here as a reference for now. -AMD_AM79C973::AMD_AM79C973(PeripheralComponentInterconnectDeviceDescriptor *dev) +/** + * @brief Constructs a new AMD_AM79C973 Ethernet driver, reads the MAC address and sets up the initialisation block and buffer descriptors + * @param dev The PCI device descriptor for this device + */ +AMD_AM79C973::AMD_AM79C973(PCIDeviceDescriptor *dev) : InterruptHandler(0x20 + dev -> interrupt), MACAddress0Port(dev ->port_base), MACAddress2Port(dev ->port_base + 0x02), @@ -40,6 +44,8 @@ AMD_AM79C973::AMD_AM79C973(PeripheralComponentInterconnectDeviceDescriptor *dev) active = false; initDone = false; + ///@todo move all this to initilise() + // Get the MAC addresses (split up in little endian order) uint64_t MAC0 = MACAddress0Port.read() % 256; uint64_t MAC1 = MACAddress0Port.read() / 256; diff --git a/kernel/src/drivers/ethernet/ethernet.cpp b/kernel/src/drivers/ethernet/ethernet.cpp index 7fc5a1dd..36404e40 100644 --- a/kernel/src/drivers/ethernet/ethernet.cpp +++ b/kernel/src/drivers/ethernet/ethernet.cpp @@ -21,22 +21,31 @@ EthernetDriverEventHandler::~EthernetDriverEventHandler() = default; /** * @brief Handle data received event + * + * @param buffer The buffer to handle + * @param size The size of the buffer * @return True if the data should be sent back, false otherwise */ -bool EthernetDriverEventHandler::DataReceived(uint8_t*, uint32_t) { +bool EthernetDriverEventHandler::DataReceived(uint8_t* buffer, uint32_t size) { return false; } /** * @brief Handle before send event + * + * @param buffer The buffer to handle + * @param size The size of the buffer */ -void EthernetDriverEventHandler::BeforeSend(uint8_t*, uint32_t) { +void EthernetDriverEventHandler::BeforeSend(uint8_t* buffer, uint32_t size) { } /** * @brief Handle data sent event + * + * @param buffer The buffer to handle + * @param size The size of the buffer */ -void EthernetDriverEventHandler::DataSent(uint8_t*, uint32_t) { +void EthernetDriverEventHandler::DataSent(uint8_t* buffer, uint32_t size) { } /** @@ -97,8 +106,11 @@ void EthernetDriver::Send(uint8_t* buffer, uint32_t size) { /** * @brief (Device Side) Send the data + * + * @param buffer The buffer to handle + * @param size The size of the buffer */ -void EthernetDriver::DoSend(uint8_t*, uint32_t) { +void EthernetDriver::DoSend(uint8_t* buffer, uint32_t size) { } /** diff --git a/kernel/src/drivers/ethernet/intel_i217.cpp b/kernel/src/drivers/ethernet/intel_i217.cpp index 5100a08f..7651d96d 100644 --- a/kernel/src/drivers/ethernet/intel_i217.cpp +++ b/kernel/src/drivers/ethernet/intel_i217.cpp @@ -24,9 +24,13 @@ using namespace memory; // Buffer Sizes #define buffer8192 ((2 << 16) | (1 << 25)) -///__DRIVER___ -IntelI217::IntelI217(PeripheralComponentInterconnectDeviceDescriptor *deviceDescriptor) +/** + * @brief Constructs a new Intel I217 Ethernet driver. Gets the MAC address and clears the receive descriptor array + * + * @param deviceDescriptor The PCI device descriptor for this device + */ +IntelI217::IntelI217(PCIDeviceDescriptor *deviceDescriptor) : InterruptHandler(0x20 + deviceDescriptor->interrupt) { @@ -198,13 +202,13 @@ bool IntelI217::readMACAddress() { void IntelI217::receiveInit() { uint8_t * ptr; //A pointer to the memory - struct receiveDescriptor *descs; //A pointer to the receive descriptors - ptr = (uint8_t *)(MemoryManager::kmalloc(sizeof(struct receiveDescriptor)*32 + 16)); //Allocate memory for the receive descriptors - descs = (struct receiveDescriptor *)ptr; //Set the pointer to the receive descriptors + receive_descriptor_t*descs; //A pointer to the receive descriptors + ptr = (uint8_t *)(MemoryManager::kmalloc(sizeof(receive_descriptor_t)*32 + 16)); //Allocate memory for the receive descriptors + descs = (receive_descriptor_t*)ptr; //Set the pointer to the receive descriptors for(int i = 0; i < 32; i++) { - receiveDsrctrs[i] = (struct receiveDescriptor *)((uint8_t *)descs + i*16); + receiveDsrctrs[i] = (receive_descriptor_t*)((uint8_t *)descs + i*16); receiveDsrctrs[i] -> bufferAddress = (uint64_t)(uint8_t *)(MemoryManager::kmalloc(8192 + 16)); receiveDsrctrs[i] -> status = 0; } @@ -242,14 +246,14 @@ void IntelI217::receiveInit() { void IntelI217::sendInit() { uint8_t * ptr; //A pointer to the memory - struct sendDescriptor *descs; //A pointer to the send descriptors - ptr = (uint8_t *)(MemoryManager::kmalloc(sizeof(struct sendDescriptor)*8 + 16)); //Allocate memory for the send descriptors - descs = (struct sendDescriptor *)ptr; //Set the pointer to the send descriptors + send_descriptor_t* descs; //A pointer to the send descriptors + ptr = (uint8_t *)(MemoryManager::kmalloc(sizeof(send_descriptor_t)*8 + 16)); //Allocate memory for the send descriptors + descs = (send_descriptor_t*)ptr; //Set the pointer to the send descriptors for(int i = 0; i < 8; i++) { - sendDsrctrs[i] = (struct sendDescriptor *)((uint8_t*)descs + i*16); + sendDsrctrs[i] = (send_descriptor_t*)((uint8_t*)descs + i*16); sendDsrctrs[i] -> bufferAddress = 0; sendDsrctrs[i] -> cmd = 0; sendDsrctrs[i] -> status = (1 << 0); // Descriptor Done diff --git a/kernel/src/drivers/ethernet/rawdatahandler.cpp b/kernel/src/drivers/ethernet/rawdatahandler.cpp index 34f7eead..228b4c17 100644 --- a/kernel/src/drivers/ethernet/rawdatahandler.cpp +++ b/kernel/src/drivers/ethernet/rawdatahandler.cpp @@ -19,9 +19,11 @@ RawDataHandler::~RawDataHandler() = default; /** * @brief Handles raw data received from the Ethernet driver * + * @param data Pointer to the raw data + * @param size Size of the raw data in bytes * @return True if the data was handled, false otherwise */ -bool RawDataHandler::HandleRawData(uint8_t*, uint32_t) +bool RawDataHandler::HandleRawData(uint8_t* data, uint32_t size) { return false; } \ No newline at end of file diff --git a/kernel/src/drivers/peripherals/keyboard.cpp b/kernel/src/drivers/peripherals/keyboard.cpp index 74b77d20..a99e60f4 100644 --- a/kernel/src/drivers/peripherals/keyboard.cpp +++ b/kernel/src/drivers/peripherals/keyboard.cpp @@ -61,6 +61,9 @@ Event *KeyboardEventHandler::on_event(Event *eve return event; } +/** + * @brief Construct a new Keyboard Driver object, registering it as an interrupt handler for interrupt 0x21 + */ KeyboardDriver::KeyboardDriver() : InterruptHandler(0x21, 0x1, 0x12), m_data_port(0x60), @@ -119,6 +122,9 @@ KeyboardState::KeyboardState() = default; KeyboardState::~KeyboardState() = default; +/** + * @brief Construct a new Keyboard Interpreter object + */ KeyboardInterpreter::KeyboardInterpreter() : InputStreamEventHandler() { @@ -144,6 +150,9 @@ void KeyboardInterpreter::on_key_read(bool released, const KeyboardState &state, } +/** + * @brief Construct a new Keyboard Interpreter for the EN_US layout + */ KeyboardInterpreterEN_US::KeyboardInterpreterEN_US() : KeyboardInterpreter() { diff --git a/kernel/src/drivers/peripherals/mouse.cpp b/kernel/src/drivers/peripherals/mouse.cpp index fa11d541..01a00374 100644 --- a/kernel/src/drivers/peripherals/mouse.cpp +++ b/kernel/src/drivers/peripherals/mouse.cpp @@ -73,6 +73,9 @@ void MouseEventHandler::on_mouse_move_event(int8_t, int8_t) { MouseEventHandler::~MouseEventHandler() = default; +/** + * @brief Constructs a new MouseDriver object and registers it as an interrupt handler for interrupt 0x2C + */ MouseDriver::MouseDriver() : InterruptHandler(0x2C, 0xC, 0x28), data_port(0x60), diff --git a/kernel/src/drivers/video/vga.cpp b/kernel/src/drivers/video/vga.cpp index 00aeea24..cabe5b2f 100644 --- a/kernel/src/drivers/video/vga.cpp +++ b/kernel/src/drivers/video/vga.cpp @@ -15,6 +15,10 @@ using namespace MaxOS::drivers; using namespace MaxOS::drivers::video; using namespace MaxOS::hardwarecommunication; + +/** + * @brief Constructs a new Video Graphics Array (VGA) driver object, initializing the necessary I/O ports for VGA register access. + */ VideoGraphicsArray::VideoGraphicsArray() : m_misc_port(0x3C2), m_crtc_index_port(0x3D4), @@ -86,6 +90,9 @@ void VideoGraphicsArray::write_registers(uint8_t *registers) { /** * @brief Checks if the specified resolution is supported. * + * @param width The width of the resolution. + * @param height The height of the resolution. + * @param colour_depth The byte depth of the resolution. * @return True if the specified resolution is supported, otherwise false. */ bool VideoGraphicsArray::supports_mode(uint32_t width, uint32_t height, uint32_t colour_depth) { diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index 5236b497..a5bbc047 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -94,6 +94,9 @@ size_t File::size() { Directory::Directory() = default; +/** + * @brief Destructor for Directory, frees all files and subdirectories + */ Directory::~Directory() { // Free the files @@ -276,12 +279,15 @@ void Directory::rename_subdirectory(string const &old_name, string const &new_na FileSystem::FileSystem() = default; +/** + * @brief Destructor for FileSystem, frees the root directory (Which in turn frees all files and subdirectories) + */ FileSystem::~FileSystem() { // Free the root directory delete m_root_directory; -}; +} /** * @brief Get the directory at "/" diff --git a/kernel/src/filesystem/format/ext2.cpp b/kernel/src/filesystem/format/ext2.cpp index 290c6a89..2bf76676 100644 --- a/kernel/src/filesystem/format/ext2.cpp +++ b/kernel/src/filesystem/format/ext2.cpp @@ -142,6 +142,7 @@ void Ext2Volume::read_block(uint32_t block_num, buffer_t *buffer) const { * @brief Read an inode from the filesystem * * @param inode_num The inode index + * @return The inode read */ inode_t Ext2Volume::read_inode(uint32_t inode_num) const { @@ -1172,6 +1173,9 @@ Ext2FileSystem::Ext2FileSystem(Disk *disk, uint32_t partition_offset) } +/** + * @brief Destroy the Ext2 File System object and free the root directory + */ Ext2FileSystem::~Ext2FileSystem() { delete m_root_directory; -}; \ No newline at end of file +} \ No newline at end of file diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 84ceea84..0c1ebb3c 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -13,6 +13,11 @@ using namespace MaxOS; using namespace MaxOS::filesystem; using namespace MaxOS::common; +/** + * @brief Construct a new Virtual File System object and set it as the current file system + * + * @note Only call once + */ VirtualFileSystem::VirtualFileSystem() { // Set the current file system to this instance @@ -20,6 +25,9 @@ VirtualFileSystem::VirtualFileSystem() { } +/** + * @brief Destroy the Virtual File System object and unmount all filesystems + */ VirtualFileSystem::~VirtualFileSystem() { // Remove all mounted filesystems @@ -435,6 +443,7 @@ File* VirtualFileSystem::create_file(const string &path) { * * @param parent The directory where the file should be created * @param name The name of the file to create + * @return The created file or null pointer if it could not be created */ File* VirtualFileSystem::create_file(Directory* parent, string const &name) { return parent->create_file(name); diff --git a/kernel/src/gui/widget.cpp b/kernel/src/gui/widget.cpp index 87539c6e..0920ce47 100644 --- a/kernel/src/gui/widget.cpp +++ b/kernel/src/gui/widget.cpp @@ -13,6 +13,9 @@ using namespace MaxOS::gui; using namespace MaxOS::drivers; using namespace MaxOS::drivers::peripherals; +/** + * @brief Construct a new Widget object + */ Widget::Widget() : KeyboardEventHandler() { @@ -34,7 +37,6 @@ Widget::Widget(int32_t left, int32_t top, uint32_t width, uint32_t height) } - Widget::~Widget() = default; /** diff --git a/kernel/src/gui/widgets/button.cpp b/kernel/src/gui/widgets/button.cpp index 3cd8d4eb..88119fcc 100644 --- a/kernel/src/gui/widgets/button.cpp +++ b/kernel/src/gui/widgets/button.cpp @@ -23,6 +23,7 @@ ButtonEventHandler::~ButtonEventHandler() = default; * @brief Handles the button events * * @param event The event to handle + * @return The handled event */ Event* ButtonEventHandler::on_event(Event* event) { diff --git a/kernel/src/gui/window.cpp b/kernel/src/gui/window.cpp index 4fa0df95..5d131ce1 100644 --- a/kernel/src/gui/window.cpp +++ b/kernel/src/gui/window.cpp @@ -98,6 +98,7 @@ Window::~Window() = default; * @param mouse_x The x coordinate of the mouse. * @param mouse_y The y coordinate of the mouse. * @param button The button that is pressed. + * @return The MouseEventHandler of the widget that will handle the event, nullptr otherwise. */ MouseEventHandler* Window::on_mouse_button_pressed(uint32_t mouse_x, uint32_t mouse_y, uint8_t button) { diff --git a/kernel/src/hardwarecommunication/apic.cpp b/kernel/src/hardwarecommunication/apic.cpp index 8d710133..779e55f8 100644 --- a/kernel/src/hardwarecommunication/apic.cpp +++ b/kernel/src/hardwarecommunication/apic.cpp @@ -15,6 +15,9 @@ using namespace MaxOS::hardwarecommunication; using namespace MaxOS::system; using namespace MaxOS::memory; +/** + * @brief Construct a new Local APIC object and map the APIC base address to the higher half if needed as well as enabling the APIC + */ LocalAPIC::LocalAPIC() { // Get the APIC base address @@ -433,6 +436,9 @@ AdvancedProgrammableInterruptController::AdvancedProgrammableInterruptController m_io_apic = new IOAPIC(acpi); } +/** + * @brief Destroy the Advanced Programmable Interrupt Controller object and frees the Local APIC and IO APIC + */ AdvancedProgrammableInterruptController::~AdvancedProgrammableInterruptController() { // Free the memory diff --git a/kernel/src/hardwarecommunication/interrupts.cpp b/kernel/src/hardwarecommunication/interrupts.cpp index 3e9a2f37..0fb978f6 100644 --- a/kernel/src/hardwarecommunication/interrupts.cpp +++ b/kernel/src/hardwarecommunication/interrupts.cpp @@ -49,7 +49,9 @@ InterruptHandler::InterruptHandler(uint8_t interrupt_number, int64_t redirect, u io_apic->set_redirect(&temp); } - +/** + * @brief Destroys the interrupt handler and unregisters it from the interrupt manager + */ InterruptHandler::~InterruptHandler() { // Get the interrupt manager @@ -82,6 +84,9 @@ system::cpu_status_t* InterruptHandler::handle_interrupt(system::cpu_status_t* s return status; } +/** + * @brief Constructs the Interrupt Manager and sets up the interrupt descriptor table (does not activate interrupts) + */ InterruptManager::InterruptManager() { Logger::INFO() << "Setting up Interrupt Manager\n"; @@ -144,6 +149,9 @@ InterruptManager::InterruptManager() { load_current(); } +/** + * @brief Destroys the Interrupt Manager and deactivates interrupts + */ InterruptManager::~InterruptManager() { deactivate(); } diff --git a/kernel/src/hardwarecommunication/pci.cpp b/kernel/src/hardwarecommunication/pci.cpp index 865e5326..f358aa82 100644 --- a/kernel/src/hardwarecommunication/pci.cpp +++ b/kernel/src/hardwarecommunication/pci.cpp @@ -23,9 +23,9 @@ using namespace MaxOS::drivers::ethernet; using namespace MaxOS::drivers::video; using namespace MaxOS::drivers::disk; -PeripheralComponentInterconnectDeviceDescriptor::PeripheralComponentInterconnectDeviceDescriptor() = default; +PCIDeviceDescriptor::PCIDeviceDescriptor() = default; -PeripheralComponentInterconnectDeviceDescriptor::~PeripheralComponentInterconnectDeviceDescriptor() = default; +PCIDeviceDescriptor::~PCIDeviceDescriptor() = default; /** * @brief Get the type of the device @@ -34,7 +34,7 @@ PeripheralComponentInterconnectDeviceDescriptor::~PeripheralComponentInterconnec * * @return Type of the device as a string (or Unknown if the type is not known) */ -string PeripheralComponentInterconnectDeviceDescriptor::get_type() const { +string PCIDeviceDescriptor::get_type() const { switch (class_id) { case 0x00: @@ -93,7 +93,10 @@ string PeripheralComponentInterconnectDeviceDescriptor::get_type() const { return "Unknown"; } -PeripheralComponentInterconnectController::PeripheralComponentInterconnectController() +/** + * @brief Construct a new PCI Controller object + */ +PCIController::PCIController() : m_data_port(0xCFC), m_command_port(0xCF8) { @@ -101,7 +104,7 @@ PeripheralComponentInterconnectController::PeripheralComponentInterconnectContro } -PeripheralComponentInterconnectController::~PeripheralComponentInterconnectController() = default; +PCIController::~PCIController() = default; /** * @brief read data from the PCI Controller @@ -112,7 +115,7 @@ PeripheralComponentInterconnectController::~PeripheralComponentInterconnectContr * @param register_offset Register offset * @return data from the PCI Controller */ -uint32_t PeripheralComponentInterconnectController::read(uint16_t bus, uint16_t device, uint16_t function, +uint32_t PCIController::read(uint16_t bus, uint16_t device, uint16_t function, uint32_t register_offset) { // Calculate the id @@ -138,7 +141,7 @@ uint32_t PeripheralComponentInterconnectController::read(uint16_t bus, uint16_t * @param register_offset Register offset * @param value Value to write */ -void PeripheralComponentInterconnectController::write(uint16_t bus, uint16_t device, uint16_t function, +void PCIController::write(uint16_t bus, uint16_t device, uint16_t function, uint32_t register_offset, uint32_t value) { // Calculate the id @@ -160,7 +163,7 @@ void PeripheralComponentInterconnectController::write(uint16_t bus, uint16_t dev * @param device Device number * @return true if the device has a function */ -bool PeripheralComponentInterconnectController::device_has_functions(uint16_t bus, uint16_t device) { +bool PCIController::device_has_functions(uint16_t bus, uint16_t device) { return read(bus, device, 0, 0x0E) & (1 << 7); } @@ -170,7 +173,7 @@ bool PeripheralComponentInterconnectController::device_has_functions(uint16_t bu * * @param handler device driver event manager */ -void PeripheralComponentInterconnectController::select_drivers(DriverSelectorEventHandler* handler) { +void PCIController::select_drivers(DriverSelectorEventHandler* handler) { for (int bus = 0; bus < 8; ++bus) { for (int device = 0; device < 32; ++device) { @@ -180,7 +183,7 @@ void PeripheralComponentInterconnectController::select_drivers(DriverSelectorEve for (int function = 0; function < numFunctions; ++function) { // Get the device descriptor, if the vendor id is 0x0000 or 0xFFFF, the device is not present/ready - PeripheralComponentInterconnectDeviceDescriptor deviceDescriptor = get_device_descriptor(bus, device, + PCIDeviceDescriptor deviceDescriptor = get_device_descriptor(bus, device, function); if (deviceDescriptor.vendor_id == 0x0000 || deviceDescriptor.vendor_id == 0x0001 || deviceDescriptor.vendor_id == 0xFFFF) @@ -218,9 +221,9 @@ void PeripheralComponentInterconnectController::select_drivers(DriverSelectorEve * @param function Function number * @return Device descriptor */ -PeripheralComponentInterconnectDeviceDescriptor PeripheralComponentInterconnectController::get_device_descriptor(uint16_t bus, uint16_t device, uint16_t function) { +PCIDeviceDescriptor PCIController::get_device_descriptor(uint16_t bus, uint16_t device, uint16_t function) { - PeripheralComponentInterconnectDeviceDescriptor result; + PCIDeviceDescriptor result; result.bus = bus; result.device = device; @@ -245,7 +248,7 @@ PeripheralComponentInterconnectDeviceDescriptor PeripheralComponentInterconnectC * @param dev Device descriptor * @return Driver for the device, null pointer if there is no driver */ -Driver* PeripheralComponentInterconnectController::get_driver(PeripheralComponentInterconnectDeviceDescriptor dev) { +Driver* PCIController::get_driver(PCIDeviceDescriptor dev) { switch (dev.vendor_id) { case 0x1022: //AMD @@ -304,7 +307,7 @@ Driver* PeripheralComponentInterconnectController::get_driver(PeripheralComponen * * @param dev The device to print */ -void PeripheralComponentInterconnectController::list_known_device( const PeripheralComponentInterconnectDeviceDescriptor& dev) { +void PCIController::list_known_device( const PCIDeviceDescriptor& dev) { switch (dev.vendor_id) { case 0x1022: { @@ -432,7 +435,7 @@ void PeripheralComponentInterconnectController::list_known_device( const Periphe * @param barNum base address register number * @return base address register */ -BaseAddressRegister PeripheralComponentInterconnectController::get_base_address_register(uint16_t bus, uint16_t device, uint16_t function, uint16_t bar) { +BaseAddressRegister PCIController::get_base_address_register(uint16_t bus, uint16_t device, uint16_t function, uint16_t bar) { BaseAddressRegister result{}; diff --git a/kernel/src/memory/memorymanagement.cpp b/kernel/src/memory/memorymanagement.cpp index 1db76fad..1e0b0654 100644 --- a/kernel/src/memory/memorymanagement.cpp +++ b/kernel/src/memory/memorymanagement.cpp @@ -44,6 +44,9 @@ MemoryManager::MemoryManager(VirtualMemoryManager* vmm) } +/** + * @brief Destroy the Memory Manager object, frees the VMM if not the kernel memory manager + */ MemoryManager::~MemoryManager() { // Free the VMM (if this is not the kernel memory manager) diff --git a/kernel/src/memory/physical.cpp b/kernel/src/memory/physical.cpp index ad434e56..19e69dc8 100644 --- a/kernel/src/memory/physical.cpp +++ b/kernel/src/memory/physical.cpp @@ -14,15 +14,15 @@ using namespace MaxOS::memory; using namespace MaxOS::system; using namespace MaxOS::common; -volatile extern __attribute__((aligned(4096))) unsigned char p4_table[]; -volatile extern __attribute__((aligned(4096))) unsigned char p3_table[]; -volatile extern __attribute__((aligned(4096))) unsigned char p3_table_hh[]; -volatile extern __attribute__((aligned(4096))) unsigned char p2_table[]; -volatile extern __attribute__((aligned(4096))) unsigned char p1_table[]; - -extern uint64_t _kernel_end; -extern uint64_t _kernel_size; -extern uint64_t _kernel_physical_end; +volatile extern PAGE_ALIGNED unsigned char p4_table[]; ///< The PML4 table setup in loader.s +volatile extern PAGE_ALIGNED unsigned char p3_table[]; ///< The PDPT table setup in loader.s +volatile extern PAGE_ALIGNED unsigned char p3_table_hh[]; ///< The PDPT table for higher half direct map setup in loader.s +volatile extern PAGE_ALIGNED unsigned char p2_table[]; ///< The PD table setup in loader.s +volatile extern PAGE_ALIGNED unsigned char p1_table[]; ///< The PT table setup in loader.s + +extern uint64_t _kernel_end; ///< The virtual address of where the kernel ends +extern uint64_t _kernel_size; ///< The length of the memory region used by the kernel code +extern uint64_t _kernel_physical_end; ///< The physical address where the kernel ends /** * @brief Constructs a PhysicalMemoryManager. Unmaps the lower kernel and sets up the bitmap for physical memory management. Reserves the kernel and the multiboot regions. diff --git a/kernel/src/memory/virtual.cpp b/kernel/src/memory/virtual.cpp index e38eb9a2..6567d041 100644 --- a/kernel/src/memory/virtual.cpp +++ b/kernel/src/memory/virtual.cpp @@ -14,6 +14,11 @@ using namespace MaxOS::memory; using namespace MaxOS::common; using namespace MaxOS::processes; +/** + * @brief Construct a new Virtual Memory Manager object and set up the initial page tables (kernel mapped into the hh) + * + * @note Should only be called once per memory manager (kernel and each process) + */ VirtualMemoryManager::VirtualMemoryManager() { // Set the kernel flag @@ -70,6 +75,9 @@ VirtualMemoryManager::VirtualMemoryManager() { } +/** + * @brief Destroy the Virtual Memory Manager object and free all used pages + */ VirtualMemoryManager::~VirtualMemoryManager() { // Free all the frames used by the VMM @@ -85,22 +93,18 @@ VirtualMemoryManager::~VirtualMemoryManager() { if (i == m_current_chunk && region == m_current_region) break; - // Loop through the pages + // Free each page in the chunk size_t pages = PhysicalMemoryManager::size_to_frames(region->chunks[i].size); for (size_t j = 0; j < pages; j++) { - // Get the frame + // Convert the virtual address to a physical address and free it physical_address_t* frame = PhysicalMemoryManager::s_current_manager->get_physical_address((virtual_address_t*) region->chunks[i].start_address + (j * PAGE_SIZE), m_pml4_root_address); - - // Free the frame PhysicalMemoryManager::s_current_manager->free_frame(frame); } } - // Move to the next region region = region->next; - } } diff --git a/kernel/src/net/ethernetframe.cpp b/kernel/src/net/ethernetframe.cpp index 99b43847..d3cc0906 100644 --- a/kernel/src/net/ethernetframe.cpp +++ b/kernel/src/net/ethernetframe.cpp @@ -98,6 +98,7 @@ drivers::ethernet::MediaAccessControlAddress EthernetFrameHandler::getMAC() { * * @param buffer the buffer with the received data * @param size the size of the received data + * @return True if the data is to be sent back, false otherwise * * @todo Future debugging me: the override is not being called in derived classes */ diff --git a/kernel/src/net/ipv4.cpp b/kernel/src/net/ipv4.cpp index a112abdb..ec99a3db 100644 --- a/kernel/src/net/ipv4.cpp +++ b/kernel/src/net/ipv4.cpp @@ -15,10 +15,10 @@ using namespace MaxOS::memory; using namespace MaxOS::drivers; using namespace MaxOS::drivers::ethernet; - - -///__RESOLVER__/// - +/** + * @brief Construct a new IPV4 Address Resolver object and register it with the Internet Protocol Handler + * @param internetProtocolHandler The Internet Protocol Handler to register with + */ IPV4AddressResolver::IPV4AddressResolver(InternetProtocolHandler *internetProtocolHandler) { @@ -33,9 +33,10 @@ IPV4AddressResolver::~IPV4AddressResolver() = default; /** * @brief Resolves an IP address to a MAC address. (Default, returns broadcast address, override for use) * + * @param address The IP address to turn into a MAC address. * @return The MAC address. */ -MediaAccessControlAddress IPV4AddressResolver::Resolve(InternetProtocolAddress) { +MediaAccessControlAddress IPV4AddressResolver::Resolve(InternetProtocolAddress address) { return 0xFFFFFFFFFFFF; } @@ -49,8 +50,12 @@ void IPV4AddressResolver::Store(InternetProtocolAddress, MediaAccessControlAddre } - -///__Payload Handler__/// +/** + * @brief Construct a new IPV4 Payload Handler object and register it with the Internet Protocol Handler + * + * @param internetProtocolHandler The Internet Protocol Handler to register with + * @param protocol The IP protocol to handle + */ IPV4PayloadHandler::IPV4PayloadHandler(InternetProtocolHandler* internetProtocolHandler, uint8_t protocol) { // Store vars diff --git a/kernel/src/net/tcp.cpp b/kernel/src/net/tcp.cpp index 5e10f914..4bab91a1 100644 --- a/kernel/src/net/tcp.cpp +++ b/kernel/src/net/tcp.cpp @@ -21,22 +21,41 @@ TCPPayloadHandler::TCPPayloadHandler() = default; TCPPayloadHandler::~TCPPayloadHandler()= default; -/// Revisit and document -void TCPPayloadHandler::handleTransmissionControlProtocolPayload(TCPSocket*, uint8_t*, uint16_t) { +/** + * @brief Handle TCP data received on the socket + * + * @param socket The socket the data was received on + * @param data The data received + * @param size The size of the data in bytes + */ +void TCPPayloadHandler::handleTransmissionControlProtocolPayload(TCPSocket* socket, uint8_t* data, uint16_t size) { } -/// Revisit and document -void TCPPayloadHandler::Connected(TCPSocket*) { +/** + * @brief Handle a new TCP connection on the socket + * + * @param socket The socket that was connected + */ +void TCPPayloadHandler::Connected(TCPSocket* socket) { } -/// Revisit and document -void TCPPayloadHandler::Disconnected(TCPSocket*) { +/** + * @brief Handle a TCP disconnection on the socket + * + * @param socket The socket that was disconnected + */ +void TCPPayloadHandler::Disconnected(TCPSocket* socket) { } -/// Revisit and document +/** + * @brief Handle an event occurring on the TCP payload handler + * + * @param event The event to handle + * @return The handled event + */ Event* TCPPayloadHandler::on_event(Event* event) { switch (event->type) { @@ -56,8 +75,11 @@ Event* TCPPayloadHandler::on_event(EventtransmissionControlProtocolHandler = transmissionControlProtocolHandler; @@ -143,7 +165,12 @@ TransmissionControlProtocolHandler::TransmissionControlProtocolHandler(MaxOS::ne TransmissionControlProtocolHandler::~TransmissionControlProtocolHandler() = default; -//Shorthand for BE +/** + * @brief Convert a 32-bit integer to big-endian format + * + * @param x The 32-bit integer to convert + * @return The big-endian formatted integer + */ uint32_t bigEndian32(uint32_t x) { return ((x & 0xFF000000) >> 24) | ((x & 0x00FF0000) >> 8) @@ -151,6 +178,12 @@ uint32_t bigEndian32(uint32_t x) { | ((x & 0x000000FF) << 24); } +/** + * @brief Convert a 16-bit integer to big-endian format + * + * @param x The 16-bit integer to convert + * @return The big-endian formatted integer + */ uint32_t bigEndian16(uint16_t x) { return ((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8); @@ -548,8 +581,14 @@ void TransmissionControlProtocolHandler::Bind(TCPSocket* socket, TCPPayloadHandl } -/// ___ EVENTS ___ /// +/** + * @brief Construct a new Data Received Event object + * + * @param socket The socket that received the data + * @param data The data that was received + * @param size The size of the data + */ DataReceivedEvent::DataReceivedEvent(TCPSocket* socket, uint8_t* data, uint16_t size) : Event(TCPPayloadHandlerEvents::DATA_RECEIVED) { this->socket = socket; diff --git a/kernel/src/net/udp.cpp b/kernel/src/net/udp.cpp index 100de4b3..7c76ac68 100644 --- a/kernel/src/net/udp.cpp +++ b/kernel/src/net/udp.cpp @@ -309,7 +309,13 @@ void UserDatagramProtocolHandler::Bind(UDPSocket *socket, UDPPayloadHandler *UDP } -/// ___ Events ___ /// +/** + * @brief Construct a new UDP Data Received Event object + * + * @param socket The socket that received the data + * @param data The data received + * @param size The size of the data received + */ UDPDataReceivedEvent::UDPDataReceivedEvent(UDPSocket *socket, uint8_t *data, uint16_t size) : Event(UDPEvents::DATA_RECEIVED) { diff --git a/kernel/src/processes/elf.cpp b/kernel/src/processes/elf.cpp index 0c007616..d00623ff 100644 --- a/kernel/src/processes/elf.cpp +++ b/kernel/src/processes/elf.cpp @@ -93,6 +93,8 @@ elf_64_section_header_t* ELF64::get_section_header(size_t index) const { /** * @brief Checks if the elf file is valid for MaxOS runtime * + * @return True if the elf file is valid, false otherwise + * * @todo Add support for maxOS ABI */ bool ELF64::is_valid() const { diff --git a/kernel/src/processes/ipc.cpp b/kernel/src/processes/ipc.cpp index 557b999f..7d8e8840 100644 --- a/kernel/src/processes/ipc.cpp +++ b/kernel/src/processes/ipc.cpp @@ -115,6 +115,9 @@ SharedMessageEndpoint::SharedMessageEndpoint(const string& name, size_t size, re } +/** + * @brief Destroys the shared message endpoint and frees all messages + */ SharedMessageEndpoint::~SharedMessageEndpoint() { // Free the messages diff --git a/kernel/src/processes/process.cpp b/kernel/src/processes/process.cpp index a16553c4..5644b785 100644 --- a/kernel/src/processes/process.cpp +++ b/kernel/src/processes/process.cpp @@ -17,6 +17,11 @@ using namespace MaxOS::common; /** * @brief Constructor for the Thread class + * + * @param _entry_point The address of the function to start executing + * @param args The arguments to pass to the function + * @param arg_amount The number of arguments + * @param parent The proccess that owns this thread (started it) */ Thread::Thread(void (* _entry_point)(void*), void* args, int arg_amount, Process* parent) { @@ -305,6 +310,8 @@ void Process::set_pid(uint64_t pid) { /** * @brief Gets the threads of the process + * + * @return The threads of the process */ Vector Process::threads() { diff --git a/kernel/src/processes/resource.cpp b/kernel/src/processes/resource.cpp index 0d50f43b..eddb745b 100644 --- a/kernel/src/processes/resource.cpp +++ b/kernel/src/processes/resource.cpp @@ -101,6 +101,9 @@ BaseResourceRegistry::BaseResourceRegistry(resource_type_t type) GlobalResourceRegistry::add_registry(type, this); } +/** + * @brief Destructor for BaseResourceRegistry, removes it from the global list + */ BaseResourceRegistry::~BaseResourceRegistry(){ GlobalResourceRegistry::remove_registry(this); @@ -188,11 +191,17 @@ Resource* BaseResourceRegistry::create_resource(string const& name, size_t flags return nullptr; } +/** + * @brief Constructs a new GlobalResourceRegistry and sets it as the current global registry + */ GlobalResourceRegistry::GlobalResourceRegistry() { s_current = this; } +/** + * @brief Destructor for GlobalResourceRegistry, unsets it as the current global registry if it is + */ GlobalResourceRegistry::~GlobalResourceRegistry() { if(s_current == this) s_current = nullptr; @@ -246,6 +255,9 @@ void GlobalResourceRegistry::remove_registry(BaseResourceRegistry* registry) { ResourceManager::ResourceManager() = default; +/** + * @brief Destructor for ResourceManager, closes all open resources + */ ResourceManager::~ResourceManager(){ // Collect all resources (as closing will break iteration) @@ -257,7 +269,7 @@ ResourceManager::~ResourceManager(){ for (auto h : handles) close_resource(h, 0); -}; +} /** * @brief Get the resources currently open diff --git a/kernel/src/processes/scheduler.cpp b/kernel/src/processes/scheduler.cpp index a21fd80e..3acff77b 100644 --- a/kernel/src/processes/scheduler.cpp +++ b/kernel/src/processes/scheduler.cpp @@ -74,13 +74,16 @@ system::cpu_status_t* GlobalScheduler::handle_interrupt(system::cpu_status_t* st * @brief Pass execution to the next thread * * @param current where to resume this thread to + * @return The cpu state of the next thread to run */ system::cpu_status_t* GlobalScheduler::yield(cpu_status_t* current) { current_thread()->execution_state = *current; return core_scheduler()->yield(); } - +/** + * @brief Destroys the global scheduler and frees the per core schedulers + */ GlobalScheduler::~GlobalScheduler(){ // No longer the global instance @@ -546,6 +549,8 @@ uint64_t Scheduler::ticks() const { /** * @brief Pass execution to the next thread + * + * @return The cpu state of the next thread to run */ cpu_status_t* Scheduler::yield() { diff --git a/kernel/src/runtime/cplusplus.cpp b/kernel/src/runtime/cplusplus.cpp index 80af8143..cb5b020f 100644 --- a/kernel/src/runtime/cplusplus.cpp +++ b/kernel/src/runtime/cplusplus.cpp @@ -12,7 +12,7 @@ using namespace MaxOS; using namespace MaxOS::runtime; -// Define static constructors (DSO = Dynamic Shared Object) +/// Define static constructors (DSO = Dynamic Shared Object) extern "C" void* __dso_handle = nullptr; /** @@ -30,14 +30,14 @@ extern "C" void __stack_chk_fail(void) ASSERT(false, "Stack Smashed"); } -extern "C" constructor start_ctors; -extern "C" constructor end_ctors; +extern "C" constructor start_ctors; ///< Pointer to the start of the constructors section +extern "C" constructor end_ctors; ///< Pointer to the end of the constructors section /** * @brief Calls all global constructors */ extern "C" void call_constructors() { - // Loop through and initialise all the global constructors + // Loop through and initialise all the global constructorsu for (constructor* i = &start_ctors; i != &end_ctors; i++) (*i)(); } diff --git a/kernel/src/runtime/ubsan.cpp b/kernel/src/runtime/ubsan.cpp index 658cebe1..b7403d38 100644 --- a/kernel/src/runtime/ubsan.cpp +++ b/kernel/src/runtime/ubsan.cpp @@ -66,80 +66,152 @@ void UBSanHandler::print_type_mismatch_v1(type_mismatch_info_v1_t* info, uintptr handle(info->location, msg.c_str()); } +/** + * @brief Triggered when memory is accessed with an unexpected type + * + * @param info The mismatch between the two types + * @param ptr The pointer to where the type mismatch occurred + */ extern "C" void __ubsan_handle_type_mismatch(type_mismatch_info_t* info, uintptr_t ptr) { UBSanHandler::print_type_mismatch(info, ptr); } +/** + * @brief Triggered when memory is accessed with an unexpected type (UBSan v1 - includes more metadata) + * + * @param info The mismatch between the two types + * @param ptr The pointer to where the type mismatch occurred + */ extern "C" void __ubsan_handle_type_mismatch_v1(type_mismatch_info_v1_t* info, uintptr_t ptr) { UBSanHandler::print_type_mismatch_v1(info, ptr); } +/** + * @brief Triggered when adding/subbing to a memory address is outside the expected bounds + * + * @param info The overflow information + */ extern "C" void __ubsan_handle_pointer_overflow(overflow_info_t* info) { UBSanHandler::handle(info->location, "Pointer overflow"); } +/** + * @brief Triggered when subtracting below the minimum value for the type + * + * @param info The location and type of the overflow + */ extern "C" void __ubsan_handle_sub_overflow(overflow_info_t* info) { UBSanHandler::handle(info->location, "Subtraction overflow"); } +/** + * @brief Triggered when shifting beyond the capacity of the type + * + * @param info The shift out of bounds information + */ extern "C" void __ubsan_handle_shift_out_of_bounds(shift_out_of_bounds_info_t* info) { UBSanHandler::handle(info->location, "Shift out of bounds"); } +/** + * @brief Triggered when accessing an array at an index larger than its size (or negative) + * + * @param info The location and type of the out of bounds access + */ extern "C" void __ubsan_handle_out_of_bounds(out_of_bounds_info_t* info) { UBSanHandler::handle(info->location, "Array out of bounds"); } +/** + * @brief Triggered when adding beyond the maximum value for the type + * + * @param info The location and type of the overflow + */ extern "C" void __ubsan_handle_add_overflow(overflow_info_t* info) { UBSanHandler::handle(info->location, "Addition overflow"); } +/** + * @brief Triggered when dividing or taking the remainder results in an overflow (eg dividing INT_MIN by -1) + * + * @param info The location and type of the overflow + */ extern "C" void __ubsan_handle_divrem_overflow(overflow_info_t* info) { UBSanHandler::handle(info->location, "Division overflow"); } +/** + * @brief Triggered when negating (taking -x) when there is no corresponding positive/negative value + * + * @param info The location and type of the overflow + */ extern "C" void __ubsan_handle_negate_overflow(overflow_info_t* info) { UBSanHandler::handle(info->location, "Negation overflow"); } +/** + * @brief Triggered when reaching code that should be unreachable + * + * @param info The location of the unreachable code + */ extern "C" void __ubsan_handle_builtin_unreachable(location_only_info_t* info) { UBSanHandler::handle(info->location, "Unreachable code"); } +/** + * @brief Triggered when multiplying beyond the maximum value for the type + * + * @param info The location and type of the overflow + */ extern "C" void __ubsan_handle_mul_overflow(overflow_info_t* info) { UBSanHandler::handle(info->location, "Multiplication overflow"); } +/** + * @brief Triggered when loading a value that is invalid for its type (eg corrupted or uninitialised) + * + * @param info The location and type of the invalid value + */ extern "C" void __ubsan_handle_load_invalid_value(invalid_value_info_t* info) { UBSanHandler::handle(info->location, "Load of invalid value"); } +/** + * @brief Triggered when a function that is expected to return a value does not + * + * @param info The location of the missing return + */ extern "C" void __ubsan_handle_missing_return(location_only_info_t* info) { UBSanHandler::handle(info->location, "Missing return"); } +/** + * @brief Triggered when a variable length array (VLA) is declared with a non-positive bound + * + * @param info The location and type of the VLA bound + */ extern "C" void __ubsan_handle_vla_bound_not_positive(vla_bound_not_positive_info_t* info) { UBSanHandler::handle(info->location, "VLA bound not positive"); diff --git a/kernel/src/system/cpu.cpp b/kernel/src/system/cpu.cpp index 49a78026..749e27a8 100644 --- a/kernel/src/system/cpu.cpp +++ b/kernel/src/system/cpu.cpp @@ -23,11 +23,11 @@ using namespace MaxOS::hardwarecommunication; using namespace MaxOS::processes; using namespace MaxOS::memory; -extern uint64_t stack[]; -volatile extern __attribute__((aligned(4096))) unsigned char p4_table[]; +extern uint64_t stack[]; ///< The stack setup for the core in loader.s +volatile extern PAGE_ALIGNED unsigned char p4_table[]; ///< The PML4 table setup in loader.s -extern "C" void core_start(); -extern "C" uint8_t core_boot_info[]; +extern "C" void core_start(); ///< The entry point for the core startup assembly code +extern "C" uint8_t core_boot_info[]; ///< The info passed between the bsp c++ and booting core assembly code /** * @brief Constructs a new Core object from the MADT entry @@ -245,6 +245,9 @@ void Core::init() { /** * @brief Constructor for the CPU class + * + * @param gdt The global descriptor table + * @param multiboot The multiboot information struct */ CPU::CPU(GlobalDescriptorTable* gdt, Multiboot* multiboot) : acpi(multiboot), diff --git a/kernel/src/system/gdt.cpp b/kernel/src/system/gdt.cpp index 3f13af4e..79d0fa2c 100644 --- a/kernel/src/system/gdt.cpp +++ b/kernel/src/system/gdt.cpp @@ -12,6 +12,9 @@ using namespace MaxOS; using namespace MaxOS::system; +/** + * @brief Construct a new Global Descriptor Table object and set up the GDT entries and load it into the CPU, reloading segment registers + */ GlobalDescriptorTable::GlobalDescriptorTable() { diff --git a/kernel/src/system/syscalls.cpp b/kernel/src/system/syscalls.cpp index 016df2b1..31f68e58 100644 --- a/kernel/src/system/syscalls.cpp +++ b/kernel/src/system/syscalls.cpp @@ -17,7 +17,9 @@ using namespace MaxOS::system; using namespace MaxOS::processes; using namespace MaxOS::memory; - +/** + * @brief Construct a new Syscall Manager object and register the syscall handlers. Registers to interrupt 0x80 + */ SyscallManager::SyscallManager() : InterruptHandler(0x80) { From a95209d113869344b484260b5309ab41bf616131 Mon Sep 17 00:00:00 2001 From: Max Tyson <98maxt98@gmail.com> Date: Sun, 9 Nov 2025 17:38:39 +1300 Subject: [PATCH 03/12] Debug/Release Version Support --- .github/workflows/max-os.yml | 6 +- .idea/inspectionProfiles/Project_Default.xml | 1 - CMakeLists.txt | 5 - filesystem/boot/grub/grub.cfg | 2 +- kernel/CMakeLists.txt | 4 +- kernel/include/common/logger.h | 4 + kernel/include/common/macros.h | 3 - kernel/include/common/string.h | 2 - kernel/src/common/graphicsContext.cpp | 9 +- kernel/src/common/logger.cpp | 2 +- kernel/src/common/string.cpp | 109 ++----------------- kernel/src/drivers/console/vesaboot.cpp | 2 +- kernel/src/hardwarecommunication/pci.cpp | 4 +- kernel/src/kernel.cpp | 5 +- kernel/src/system/cpu.cpp | 2 +- kernel/src/system/syscalls.cpp | 7 +- toolchain/pre_process/version.sh | 6 +- toolchain/run_qemu.sh | 2 +- 18 files changed, 43 insertions(+), 132 deletions(-) diff --git a/.github/workflows/max-os.yml b/.github/workflows/max-os.yml index 1bd34891..5a3e02d4 100644 --- a/.github/workflows/max-os.yml +++ b/.github/workflows/max-os.yml @@ -45,9 +45,9 @@ jobs: cd toolchain/pre_process ./version.sh --force cd ../../ - mkdir -p cmake-build - cd cmake-build - cmake .. -DCMAKE_TOOLCHAIN_FILE=toolchain/CMakeToolchain.txt + mkdir -p cmake-release + cd cmake-release + cmake .. -DCMAKE_TOOLCHAIN_FILE=toolchain/CMakeToolchain.txt -DCMAKE_BUILD_TYPE=Release make install - name: Upload binary diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 01227ec0..e526a298 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,7 +2,6 @@ + diff --git a/docs/Syscalls.md b/docs/Syscalls.md index e07ad26c..fa63b019 100644 --- a/docs/Syscalls.md +++ b/docs/Syscalls.md @@ -23,8 +23,8 @@ This is helpful for updating syscall table (I don't know if that will even happe | 4 | resource_create | Create a resource | ResourceType type | char* name | size_t flags | | | | int success (1 = success, 0 = failed) | | 5 | resource_open | Open a resource | ResourceType type | char* name | size_t flags | | | | uint64_t handle (0 if failed) | | 6 | resource_close | Close a resource | uint64_t handle | size_t flags | | | | | | -| 7 | resource_write | Write to a resource | uint64_t handle | void* buffer | size_t size | size_t flags | | | size_t bytes written (0 if failed) | -| 8 | resource_read | Read from a resource | uint64_t handle | void* buffer | size_t size | size_t flags | | | size_t bytes read (0 if failed) | +| 7 | resource_write | write to a resource | uint64_t handle | void* buffer | size_t size | size_t flags | | | size_t bytes written (0 if failed) | +| 8 | resource_read | read from a resource | uint64_t handle | void* buffer | size_t size | size_t flags | | | size_t bytes read (0 if failed) | | 9 | thread_yield | Yield the current thread | | | | | | | | | 10 | thread_sleep | Put the current thread to sleep | uint64_t time (ms) | | | | | | | | 11 | thread_exit | Exit the current thread | | | | | | | | \ No newline at end of file diff --git a/kernel/include/common/buffer.h b/kernel/include/common/buffer.h index 8533301d..fdca4b81 100644 --- a/kernel/include/common/buffer.h +++ b/kernel/include/common/buffer.h @@ -9,69 +9,67 @@ #ifndef MAXOS_COMMON_BUFFER_H #define MAXOS_COMMON_BUFFER_H -#include -#include +#include +#include #include #include -namespace MaxOS { - namespace common { +namespace MaxOS::common { - /** - * @class Buffer - * @brief Wrapper class for a region of bytes in memor in an attempt to add some memory safety. Automatically - * allocates the size specified and frees it once done, adds boundary to I/O. - */ - class Buffer { + /** + * @class Buffer + * @brief Wrapper class for a region of bytes in memor in an attempt to add some memory safety. Automatically + * allocates the size specified and frees it once done, adds boundary to I/O. + */ + class Buffer { - private: - uint8_t* m_bytes = nullptr; - size_t m_capacity; - bool m_dont_delete = false; + private: + uint8_t* m_bytes = nullptr; + size_t m_capacity; + bool m_dont_delete = false; - size_t m_offset = 0; + size_t m_offset = 0; - public: - Buffer(size_t size, bool update_offset = true); - Buffer(void* source, size_t size, bool update_offset = true); - ~Buffer(); + public: + explicit Buffer(size_t size, bool update_offset = true); + Buffer(void* source, size_t size, bool update_offset = true); + ~Buffer(); - [[nodiscard]] uint8_t* raw() const; + [[nodiscard]] uint8_t* raw() const; - void clear(); - void full(uint8_t byte, size_t offset = 0, size_t amount = 0); + void clear(); + void full(uint8_t byte, size_t offset = 0, size_t amount = 0); - bool update_offset = true; ///< Should operations write/read/copy update the offset in the buffer? - void set_offset(size_t offset); + bool update_offset = true; ///< Should operations write/read/copy update the offset in the buffer? + void set_offset(size_t offset); - [[nodiscard]] size_t capacity() const; - void resize(size_t size); + [[nodiscard]] size_t capacity() const; + void resize(size_t size); - void write(uint8_t byte); - void write(size_t offset, uint8_t byte); - uint8_t read(); - uint8_t read(size_t offset); + void write(uint8_t byte); + void write(size_t offset, uint8_t byte); + uint8_t read(); + uint8_t read(size_t offset); - void copy_from(const Buffer* buffer); - void copy_from(const Buffer* buffer, size_t length); - void copy_from(const Buffer* buffer, size_t length, size_t offset); - void copy_from(const Buffer* buffer, size_t length, size_t offset, size_t offset_other); - void copy_from(const void* source, size_t length); - void copy_from(const void* source, size_t length, size_t offset); + void copy_from(const Buffer* buffer); + void copy_from(const Buffer* buffer, size_t length); + void copy_from(const Buffer* buffer, size_t length, size_t offset); + void copy_from(const Buffer* buffer, size_t length, size_t offset, size_t offset_other); + void copy_from(const void* source, size_t length); + void copy_from(const void* source, size_t length, size_t offset); - void copy_to(Buffer* buffer); - void copy_to(Buffer* buffer, size_t length); - void copy_to(Buffer* buffer, size_t length, size_t offset); - void copy_to(Buffer* buffer, size_t length, size_t offset, size_t offset_other); - void copy_to(void* destination, size_t length); - void copy_to(void* destination, size_t length, size_t offset); - }; + void copy_to(Buffer* buffer); + void copy_to(Buffer* buffer, size_t length); + void copy_to(Buffer* buffer, size_t length, size_t offset); + void copy_to(Buffer* buffer, size_t length, size_t offset, size_t offset_other); + void copy_to(void* destination, size_t length); + void copy_to(void* destination, size_t length, size_t offset); + }; - typedef Buffer buffer_t; ///< Typedef for Buffer class - - } + typedef Buffer buffer_t; ///< Typedef for Buffer class } + #endif //MAXOS_COMMON_BUFFER_H diff --git a/kernel/include/common/colour.h b/kernel/include/common/colour.h index 09faaefd..7e4c0a9d 100644 --- a/kernel/include/common/colour.h +++ b/kernel/include/common/colour.h @@ -10,112 +10,110 @@ #define MAXOS_COMMON_COLOUR_H #include -#include - -namespace MaxOS { - - namespace common { - - /// ANSI Colour Codes - const char* const ANSI_COLOURS[] = { - "\033[0;30m", // FG Black - "\033[0;31m", // FG Red - "\033[0;32m", // FG Green - "\033[0;33m", // FG Yellow - "\033[0;34m", // FG Blue - "\033[0;35m", // FG Magenta - "\033[0;36m", // FG Cyan - "\033[0;37m", // FG White - "\033[0;40m", // BG Black - "\033[0;41m", // BG Red - "\033[0;42m", // BG Green - "\033[0;43m", // BG Yellow - "\033[0;44m", // BG Blue - "\033[0;45m", // BG Magenta - "\033[0;46m", // BG Cyan - "\033[0;47m", // BG White - "\033[0m" // Reset - }; - - /** - * @enum ANSIColour - * @brief Enumeration of ANSI colour codes for foreground and background colours - */ - enum ANSIColour { - FG_Black, - FG_Red, - FG_Green, - FG_Yellow, - FG_Blue, - FG_Magenta, - FG_Cyan, - FG_White, - BG_Black, - BG_Red, - BG_Green, - BG_Yellow, - BG_Blue, - BG_Magenta, - BG_Cyan, - BG_White, - Reset, - }; - - /** - * @enum ConsoleColour - * @brief Enumeration of console colour codes - */ - enum class ConsoleColour { - Uninitialised = 0xFF, - Black = 0x00, - Blue = 0x01, - Green = 0x02, - Cyan = 0x03, - Red = 0x04, - Magenta = 0x05, - Brown = 0x06, - LightGrey = 0x07, - DarkGrey = 0x08, - LightBlue = 0x09, - LightGreen = 0x0A, - LightCyan = 0x0B, - LightRed = 0x0C, - LightMagenta = 0x0D, - Yellow = 0x0E, - White = 0x0F - }; - - /** - * @class Colour - * @brief Stores the red, green, blue and alpha values of a colour. Can be parsed from a hex string, an ANSI string or a ConsoleColour - */ - class Colour { - private: - void parse_hex_string(string hex_string); - void parse_ansi_string(string ansi_string); - - void parse_console_colour(ConsoleColour colour); - - public: - uint8_t red { 0 }; ///< The amount of red 0-255 - uint8_t green { 0 }; ///< The amount of green 0-255 - uint8_t blue { 0 }; ///< The amount of blue 0-255 - uint8_t alpha { 0 }; ///< The amount of alpha 0-255 (0 is visible, 255 is invisible) todo: confirm - - - Colour(); - Colour(ConsoleColour colour); - Colour(string string); - Colour(uint8_t red, uint8_t green, uint8_t blue); - Colour(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha); - - ~Colour(); - - [[nodiscard]] ConsoleColour to_console_colour() const; - }; - - } +#include + + +namespace MaxOS::common { + + /// ANSI Colour Codes + const char* const ANSI_COLOURS[] = { + "\033[0;30m", // FG Black + "\033[0;31m", // FG Red + "\033[0;32m", // FG Green + "\033[0;33m", // FG Yellow + "\033[0;34m", // FG Blue + "\033[0;35m", // FG Magenta + "\033[0;36m", // FG Cyan + "\033[0;37m", // FG White + "\033[0;40m", // BG Black + "\033[0;41m", // BG Red + "\033[0;42m", // BG Green + "\033[0;43m", // BG Yellow + "\033[0;44m", // BG Blue + "\033[0;45m", // BG Magenta + "\033[0;46m", // BG Cyan + "\033[0;47m", // BG White + "\033[0m" // Reset + }; + + /** + * @enum ANSIColour + * @brief Enumeration of ANSI colour codes for foreground and background colours + */ + enum ANSIColour { + FG_Black, + FG_Red, + FG_Green, + FG_Yellow, + FG_Blue, + FG_Magenta, + FG_Cyan, + FG_White, + BG_Black, + BG_Red, + BG_Green, + BG_Yellow, + BG_Blue, + BG_Magenta, + BG_Cyan, + BG_White, + Reset, + }; + + /** + * @enum ConsoleColour + * @brief Enumeration of console colour codes + */ + enum class ConsoleColour { + Uninitialised = 0xFF, + Black = 0x00, + Blue = 0x01, + Green = 0x02, + Cyan = 0x03, + Red = 0x04, + Magenta = 0x05, + Brown = 0x06, + LightGrey = 0x07, + DarkGrey = 0x08, + LightBlue = 0x09, + LightGreen = 0x0A, + LightCyan = 0x0B, + LightRed = 0x0C, + LightMagenta = 0x0D, + Yellow = 0x0E, + White = 0x0F + }; + + /** + * @class Colour + * @brief Stores the red, green, blue and alpha values of a colour. Can be parsed from a hex string, an ANSI string or a ConsoleColour + */ + class Colour { + private: + void parse_hex_string(string hex_string); + void parse_ansi_string(string ansi_string); + + void parse_console_colour(ConsoleColour colour); + + public: + uint8_t red { 0 }; ///< The amount of red 0-255 + uint8_t green { 0 }; ///< The amount of green 0-255 + uint8_t blue { 0 }; ///< The amount of blue 0-255 + uint8_t alpha { 0 }; ///< The amount of alpha 0-255 (0 is visible, 255 is invisible) todo: confirm + + + Colour(); + explicit Colour(ConsoleColour colour); + explicit Colour(string string); + Colour(uint8_t red, uint8_t green, uint8_t blue); + Colour(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha); + + ~Colour(); + + [[nodiscard]] ConsoleColour to_console_colour() const; + }; } + #endif //MAXOS_COMMON_COLOUR_H diff --git a/kernel/include/common/coordinates.h b/kernel/include/common/coordinates.h index ef5f1af3..bc990624 100644 --- a/kernel/include/common/coordinates.h +++ b/kernel/include/common/coordinates.h @@ -9,21 +9,19 @@ #ifndef MAXOS_COMMON_COORDINATES_H #define MAXOS_COMMON_COORDINATES_H -#include +#include #include -namespace MaxOS{ - namespace common{ +namespace MaxOS::common { - /** - * @typedef Coordinates - * @brief A type representing 2D coordinates as a pair of int32_t - */ - typedef Pair Coordinates; - - } + /** + * @typedef Coordinates + * @brief A type representing 2D coordinates as a pair of int32_t + */ + typedef Pair Coordinates; } + #endif //MAXOS_COMMON_COORDINATES_H diff --git a/kernel/include/common/eventHandler.h b/kernel/include/common/eventHandler.h index 7d061e2e..f9f64bc3 100644 --- a/kernel/include/common/eventHandler.h +++ b/kernel/include/common/eventHandler.h @@ -12,163 +12,159 @@ #ifndef MAXOS_COMMON_EVENTHANDLER_H #define MAXOS_COMMON_EVENTHANDLER_H -#include +#include #include -namespace MaxOS{ - - namespace common{ - - - /** - * @class Event - * @brief Used to store information about an event, has a type and a return value - * - * @tparam EventType The type of event - * @todo deprecate, things that should fire events should have their own event firer class and things that connect to it, dont have a class per event - * @todo events should be made on stack and passed as references not pointers for better perf - * @deprecated Will Remove Soon - */ - template class Event - { - public: - Event(EventType type); - ~Event(); - - EventType type; ///< @deprecated WRS - - union { - uint8_t* bufferValue; ///< @deprecated WRS - uint32_t intValue; ///< @deprecated WRS - bool boolValue; ///< @deprecated WRS - } return_value; ///< @deprecated WRS - }; - - /** - * @class EventHandler - * @brief Used to handle an event - * - * @tparam EventType The type of event - */ - template class EventHandler - { - public: - EventHandler(); - ~EventHandler(); - virtual Event* on_event(Event* event); - }; - - /** - * @class EventManager - * @brief Manages the m_handlers for a type of event, raises events and calls the m_handlers - * - * @deprecated Will Remove Soon - * - * @tparam EventType The type of event - */ - template class EventManager - { - protected: - Vector*> m_handlers; ///< @deprecated WRS - - public: - EventManager(); - ~EventManager(); - void connect_event_handler(EventHandler* handler); - void disconnect_event_handler(EventHandler* handler); - Vector*> raise_event(Event* event); - }; - - ///@todo move to a c++ files - - /** - * @brief Constructs a new Event object - * - * @tparam EventType The type of event - * @param type The type of the event - */ - template Event::Event(EventType type) { - this->type = type; - } - - - template Event::~Event() = default; - - template EventHandler::EventHandler() = default; - - - template EventHandler::~EventHandler() = default; - - /** - * @brief This function is called when an event is raised - * - * @tparam EventType The type of event - * @param event The event that was raised - * - * @return The event after it has been handled - */ - template Event* EventHandler::on_event(Event* event) { - return event; - } - - template EventManager::EventManager() = default; - - template EventManager::~EventManager() = default; - - - /** - * @brief Connect an event handler to the event manager if it is not already connected - * - * @tparam EventType The type of event - * @param handler The event handler to connect - */ - template void EventManager::connect_event_handler(EventHandler* handler) { - // If the handler is already connected, return - if(m_handlers.find(handler) != m_handlers.end()) { - return; - } - - m_handlers.push_back(handler); - - } - - /** - * @brief Disconnect an event handler from the event manager if it is connected - * - * @tparam EventType The type of event - * @param handler The event handler to disconnect - */ - template void EventManager::disconnect_event_handler(EventHandler* handler) { - // If the handler is not connected, return - if(m_handlers.find(handler) == m_handlers.end()) { - return; - } - - m_handlers.erase(handler); - } - - /** - * @brief Calls the on_event function of all the event m_handlers connected to the event manager and returns a list of the results - * - * @tparam EventType The type of event - * @param event The event to raise - * @return A list of the results of the event m_handlers - */ - template Vector*> EventManager::raise_event(Event* event) { - - - // Store a list of the results of the event handlers - Vector*> results; - for(auto& handler : m_handlers) { - results.push_back(handler->on_event(event)); - } - - // Free the memory used by the event - delete event; - - return results; - } - } + +namespace MaxOS::common { + + + /** + * @class Event + * @brief Used to store information about an event, has a type and a return value + * + * @tparam EventType The type of event + * @todo deprecate, things that should fire events should have their own event firer class and things that connect to it, dont have a class per event + * @todo events should be made on stack and passed as references not pointers for better perf + * @deprecated Will Remove Soon + */ + template class Event { + public: + explicit Event(EventType type); + ~Event(); + + EventType type; ///< @deprecated WRS + + union { + uint8_t* buffer_value; ///< @deprecated WRS + uint32_t int_value; ///< @deprecated WRS + bool bool_value; ///< @deprecated WRS + } return_value; ///< @deprecated WRS + }; + + /** + * @class EventHandler + * @brief Used to handle an event + * + * @tparam EventType The type of event + */ + template class EventHandler { + public: + EventHandler(); + ~EventHandler() = default; + virtual Event* on_event(Event* event); + }; + + /** + * @class EventManager + * @brief Manages the m_handlers for a type of event, raises events and calls the m_handlers + * + * @deprecated Will Remove Soon + * + * @tparam EventType The type of event + */ + template class EventManager { + protected: + Vector*> m_handlers; ///< @deprecated WRS + + public: + EventManager(); + ~EventManager(); + void connect_event_handler(EventHandler* handler); + void disconnect_event_handler(EventHandler* handler); + Vector*> raise_event(Event* event); + }; + + ///@todo move to a c++ files + + /** + * @brief Constructs a new Event object + * + * @tparam EventType The type of event + * @param type The type of the event + */ + template Event::Event(EventType type) { + this->type = type; + } + + + template Event::~Event() = default; + + template EventHandler::EventHandler() = default; + + + + + /** + * @brief This function is called when an event is raised + * + * @tparam EventType The type of event + * @param event The event that was raised + * + * @return The event after it has been handled + */ + template Event* EventHandler::on_event(Event* event) { + return event; + } + + template EventManager::EventManager() = default; + + template EventManager::~EventManager() = default; + + + /** + * @brief connect an event handler to the event manager if it is not already connected + * + * @tparam EventType The type of event + * @param handler The event handler to connect + */ + template void EventManager::connect_event_handler(EventHandler* handler) { + // If the handler is already connected, return + if (m_handlers.find(handler) != m_handlers.end()) { + return; + } + + m_handlers.push_back(handler); + + } + + /** + * @brief disconnect an event handler from the event manager if it is connected + * + * @tparam EventType The type of event + * @param handler The event handler to disconnect + */ + template void EventManager::disconnect_event_handler(EventHandler* handler) { + // If the handler is not connected, return + if (m_handlers.find(handler) == m_handlers.end()) { + return; + } + + m_handlers.erase(handler); + } + + /** + * @brief Calls the on_event function of all the event m_handlers connected to the event manager and returns a list of the results + * + * @tparam EventType The type of event + * @param event The event to raise + * @return A list of the results of the event m_handlers + */ + template Vector*> EventManager::raise_event(Event* event) { + + + // Store a list of the results of the event handlers + Vector*> results; + for (auto& handler : m_handlers) { + results.push_back(handler->on_event(event)); + } + + // Free the memory used by the event + delete event; + + return results; + } } + #endif //MAXOS_COMMON_EVENTHANDLER_H diff --git a/kernel/include/common/graphicsContext.h b/kernel/include/common/graphicsContext.h index 6c1b5df5..752fbff2 100644 --- a/kernel/include/common/graphicsContext.h +++ b/kernel/include/common/graphicsContext.h @@ -9,79 +9,79 @@ #ifndef MaxOS_COMMON_GRAPHICSCONTEX_H #define MaxOS_COMMON_GRAPHICSCONTEX_H -#include +#include #include -namespace MaxOS { - namespace common { +namespace MaxOS::common { - /** - * @class GraphicsContext - * @brief Draws pixels to the screen, and handles drawing lines, rectangles and circles - */ - class GraphicsContext { + /** + * @class GraphicsContext + * @brief Draws pixels to the screen, and handles drawing lines, rectangles and circles + */ + class GraphicsContext { - protected: - bool mirror_y_axis { false }; ///< Should the y axis be mirrored (0,0 is top left if false, bottom left if true) + protected: + bool mirror_y_axis { + false }; ///< Should the y axis be mirrored (0,0 is top left if false, bottom left if true) - int32_t m_width { 0 }; ///< The width of the screen in pixels - int32_t m_height { 0 }; ///< The height of the screen in pixels - uint32_t m_color_depth { 0 }; ///< The color depth of the screen in bits per pixel + uint32_t m_width { 0 }; ///< The width of the screen in pixels + uint32_t m_height { 0 }; ///< The height of the screen in pixels + uint32_t m_color_depth { 0 }; ///< The color depth of the screen in bits per pixel - Colour m_colour_pallet[256]; ///< The colour pallet for 8 bit color depth @todo make const + Colour m_colour_pallet[256]; ///< The colour pallet for 8 bit color depth @todo make const - uint64_t* m_framebuffer_address { nullptr }; ///< The address of the framebuffer + uint64_t* m_framebuffer_address { nullptr }; ///< The address of the framebuffer - virtual void render_pixel(uint32_t x, uint32_t y, uint32_t colour); - virtual void render_pixel_8_bit(uint32_t x, uint32_t y, uint8_t colour); - virtual void render_pixel_16_bit(uint32_t x, uint32_t y, uint16_t colour); - virtual void render_pixel_24_bit(uint32_t x, uint32_t y, uint32_t colour); - virtual void render_pixel_32_bit(uint32_t x, uint32_t y, uint32_t colour); + virtual void render_pixel(uint32_t x, uint32_t y, uint32_t colour); + virtual void render_pixel_8_bit(uint32_t x, uint32_t y, uint8_t colour); + virtual void render_pixel_16_bit(uint32_t x, uint32_t y, uint16_t colour); + virtual void render_pixel_24_bit(uint32_t x, uint32_t y, uint32_t colour); + virtual void render_pixel_32_bit(uint32_t x, uint32_t y, uint32_t colour); - virtual uint32_t get_rendered_pixel(uint32_t x, uint32_t y); - virtual uint8_t get_rendered_pixel_8_bit(uint32_t x, uint32_t y); - virtual uint16_t get_rendered_pixel_16_bit(uint32_t x, uint32_t y); - virtual uint32_t get_rendered_pixel_24_bit(uint32_t x, uint32_t y); - virtual uint32_t get_rendered_pixel_32_bit(uint32_t x, uint32_t y); + virtual uint32_t get_rendered_pixel(uint32_t x, uint32_t y); + virtual uint8_t get_rendered_pixel_8_bit(uint32_t x, uint32_t y); + virtual uint16_t get_rendered_pixel_16_bit(uint32_t x, uint32_t y); + virtual uint32_t get_rendered_pixel_24_bit(uint32_t x, uint32_t y); + virtual uint32_t get_rendered_pixel_32_bit(uint32_t x, uint32_t y); - public: - GraphicsContext(); - ~GraphicsContext(); + public: + GraphicsContext(); + ~GraphicsContext(); - uint32_t colour_to_int(const Colour&); - Colour int_to_colour(uint32_t); + uint32_t colour_to_int(const Colour&); + Colour int_to_colour(uint32_t); - // Convert uint32_t to uint64s? - [[nodiscard]] uint32_t width() const; - uint32_t height() const; - uint32_t color_depth() const; + // Convert uint32_t to uint64s? + [[nodiscard]] uint32_t width() const; + [[nodiscard]] uint32_t height() const; + [[nodiscard]] uint32_t color_depth() const; - uint64_t* framebuffer_address(); + uint64_t* framebuffer_address(); - void put_pixel(int32_t x, int32_t y, const Colour& colour); - void putPixel(int32_t x, int32_t y, uint32_t colour); - Colour get_pixel(int32_t x, int32_t y); - void invert_pixel(int32_t x, int32_t y); + void put_pixel(uint32_t x, uint32_t y, const Colour& colour); + void put_pixel(uint32_t x, uint32_t y, uint32_t colour); + Colour get_pixel(uint32_t x, uint32_t y); + void invert_pixel(uint32_t x, uint32_t y); - void draw_line(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const Colour& colour); - void drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colour); + void draw_line(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, const Colour& colour); + void draw_line(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t colour); - void draw_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const Colour& colour); - void draw_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colour); + void draw_rectangle(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, const Colour& colour); + void draw_rectangle(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t colour); - void fill_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const Colour& colour); - void fill_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colour); + void fill_rectangle(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, const Colour& colour); + void fill_rectangle(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t colour); - void draw_circle(int32_t x0, int32_t y0, int32_t radius, const Colour& colour); - void draw_circle(int32_t x0, int32_t y0, int32_t radius, uint32_t colour); + void draw_circle(uint32_t x0, uint32_t y0, uint32_t radius, const Colour& colour); + void draw_circle(uint32_t x0, uint32_t y0, uint32_t radius, uint32_t colour); - void fill_circle(int32_t x0, int32_t y0, int32_t radius, const Colour& colour); - void fillCircle(int32_t x0, int32_t y0, int32_t radius, uint32_t colour); + void fill_circle(uint32_t x0, uint32_t y0, uint32_t radius, const Colour& colour); + void fill_circle(uint32_t x0, uint32_t y0, uint32_t radius, uint32_t colour); - }; + }; - } } + #endif //MaxOS_COMMON_GRAPHICSCONTEX_H diff --git a/kernel/include/common/inputStream.h b/kernel/include/common/inputStream.h index e847f156..185c1097 100644 --- a/kernel/include/common/inputStream.h +++ b/kernel/include/common/inputStream.h @@ -11,433 +11,421 @@ #ifndef MAXOS_COMMON_INPUTSTREAM_H #define MAXOS_COMMON_INPUTSTREAM_H -#include +#include #include #include -namespace MaxOS{ - - namespace common{ - - // Forward declaration - template class GenericInputStream; - - /** - * @class InputStreamEventHandler - * @brief Handles read and end of stream events from a set of streams - * - * @tparam Type The type of data the stream is handling - */ - template class InputStreamEventHandler - { - friend class GenericInputStream; - - protected: - common::Vector*> m_generic_input_streams; ///< List of streams being observed by this handler - public: - InputStreamEventHandler(); - ~InputStreamEventHandler(); - - virtual void on_stream_read(Type); - virtual void on_end_of_stream(GenericInputStream*); - }; - - /** - * @class InputStreamProcessor - * @brief Converts one stream data type into another - * - * @tparam Type - * @tparam ProcessorType - */ - template class InputStreamProcessor : public InputStreamEventHandler, public GenericInputStream - { - public: - InputStreamProcessor(); - InputStreamProcessor(InputStreamEventHandler* generic_stream_event_handler); - ~InputStreamProcessor(); - - void on_end_of_stream(GenericInputStream* stream) override; - }; - - - /** - * @class InputStreamSocket - * @brief Passes read events on to the handlers - * - * @tparam Type The type of data the stream is handling - */ - template class InputStreamSocket : public InputStreamProcessor - { - public: - InputStreamSocket(); - InputStreamSocket(InputStreamEventHandler*); - ~InputStreamSocket(); - - void on_stream_read(Type) override; - }; - - /** - * @class InputStreamBuffer - * @brief Buffers data from a stream and fires an event when a certain element is read - * - * @tparam Type The type of data the stream is handling - */ - template class InputStreamBuffer : protected InputStreamProcessor - { - protected: - Type m_buffer[10240]; ///< The buffer to store data in - int m_offset { 0 }; ///< The current position in the buffer - Type m_event_fire_element; ///< The element that will cause the buffer to flush and fire an event - Type m_termination_element; ///< The element that will cause the buffer to flush and end the stream - - public: - InputStreamBuffer(Type event_fire_element, Type termination_element); - ~InputStreamBuffer(); - - void on_stream_read(Type) override; - void on_end_of_stream(GenericInputStream*) override; - void flush(); - }; - - /** - * @class GenericInputStream - * @brief Manages the connection of a stream to handlers - * - * @tparam Type The type of data the stream is handling - */ - template class GenericInputStream{ - - protected: - common::Vector*> m_input_stream_event_handlers; ///< List of streams being observed by this handler - - public: - GenericInputStream(); - GenericInputStream(InputStreamEventHandler*); - ~GenericInputStream(); - - void connect_input_stream_event_handler(InputStreamEventHandler*); - void disconnect_input_stream_event_handler(InputStreamEventHandler*); - - }; - - /** - * @brief The ">>" operator is used to read data from a stream, it takes a stream to read from and an event handler to handle the data - * - * @tparam Type The type of data the stream is handling - * @param source The stream to read from - * @param inputStreamEventHandler The event handler to handle the data - */ - template void operator >> (GenericInputStream& source, InputStreamEventHandler& inputStreamEventHandler); - - /** - * @brief The ">>" operator is used to read data from a stream, it takes a stream to read from and an InputStreamProcessor to process the data - * - * @tparam Type The type of data the stream is handling - * @tparam ProcessorType The type of data to convert the data into via the processor - * @param source The stream to read from - * @param processor The processor to process the data - * @return The processed stream - */ - template GenericInputStream& operator >> (GenericInputStream& source, InputStreamProcessor& processor); - - /** - * @class InputStream - * @brief A stream that handles strings - */ - class InputStream : public GenericInputStream - { - public: - InputStream(InputStreamEventHandler*); - }; - - - ///_______________________________________________TEMPLATES_________________________________________________________________/// - - /** - * @brief Creates a new InputStreamProcessor - * - * @tparam Type the type of data the stream is handling - */ - template InputStreamEventHandler::InputStreamEventHandler() = default; - - /** - * @brief Destroys the InputStreamProcessor and disconnects it from all streams - * - * @tparam Type the type of data the stream is handling - */ - template InputStreamEventHandler::~InputStreamEventHandler() { - - // Disconnect the handler from all streams - while(!m_generic_input_streams.empty()) - (*m_generic_input_streams.begin()) -> disconnect_input_stream_event_handler(this); - - } - - /** - * @brief Called when data is read from a stream (overridden by subclasses) - * - * @tparam Type the type of data the stream is handling - */ - template void InputStreamEventHandler::on_stream_read(Type) { - - } - - /** - * @brief Called when a stream has finished. Removes the stream from the array of streams - * - * @tparam Type The type of data the stream is handling - * @param stream The stream that has finished - */ - template void InputStreamEventHandler::on_end_of_stream(GenericInputStream *stream) { - - // Remove the stream - m_generic_input_streams.erase(stream); - } - - - /** - * @brief Creates a new InputStreamProcessor - * - * @tparam Type The type of data the stream is handling - * @tparam ProcessorType The type of data to convert the data into via the processor - */ - template InputStreamProcessor::InputStreamProcessor() - : InputStreamEventHandler(), - GenericInputStream() - { - - } - - /** - * @brief Creates a new InputStreamProcessor - * - * @tparam Type The type of data the stream is handling - * @tparam ProcessorType The type of data to convert the data into via the processor - * @param generic_stream_event_handler The event handler to handle the data - */ - template InputStreamProcessor::InputStreamProcessor(InputStreamEventHandler *generic_stream_event_handler) - : InputStreamEventHandler(), - GenericInputStream(generic_stream_event_handler) - { - - } - - /** - * @brief Destroys the InputStreamProcessor - * - * @tparam Type The type of data the stream is handling - * @tparam ProcessorType The type of data to convert the data into via the processor - */ - template InputStreamProcessor::~InputStreamProcessor() = default; - - /** - * @brief Called when a stream has finished. Passes the event on to the handlers and then removes the stream from the array of streams - * - * @tparam Type The type of data the stream is handling - * @tparam ProcessorType The type of data to convert the data into via the processor - * @param stream The stream that has finished - */ - template void InputStreamProcessor::on_end_of_stream(GenericInputStream* stream) { - - // Pass the end of stream event on to the handlers - for(auto& event_handler : this -> m_input_stream_event_handlers) - event_handler -> on_end_of_stream(this); - - // Remove the stream - InputStreamEventHandler::on_end_of_stream(stream); - - } - - /** - * @brief Creates a new InputStreamSocket - * - * @tparam Type The type of data the stream is handling - */ - template InputStreamSocket::InputStreamSocket() = default; - - /** - * @brief Creates a new InputStreamSocket and connects it to the handler - * - * @tparam Type The type of data the stream is handling (and the sockets processor type) - * @param processor_handler The handler to pass to InputStreamProcessor - */ - template InputStreamSocket::InputStreamSocket(InputStreamEventHandler *processor_handler) - : InputStreamProcessor(processor_handler) - { - - } - - /** - * @brief Destroys the InputStreamSocket - * - * @tparam Type The type of data the stream is handling - */ - template InputStreamSocket::~InputStreamSocket() = default; - - /** - * @brief Called when data is read from a stream. Passes the event on to the internetProtocolHandlers - * - * @tparam Type The type of data the stream is handling - * @param read_element The element that was read from the stream - */ - template void InputStreamSocket::on_stream_read(Type read_element) { - - // Pass the read event on to the handlers - for(auto& event_handler : this -> m_input_stream_event_handlers) - event_handler -> on_stream_read(read_element); - - } - - /** - * @brief Creates a new InputStreamBuffer - * - * @tparam Type The type of data the stream is handling - * @param event_fire_element The element to fire the event on - * @param termination_element The element that signifies the end of the part of the stream to be buffered (e.g a newline) - */ - template InputStreamBuffer::InputStreamBuffer(Type event_fire_element, Type termination_element) - : m_event_fire_element(event_fire_element), - m_termination_element(termination_element) - { - - } - - /** - * @brief Destroys the InputStreamBuffer - * - * @tparam Type The type of data the stream is handling - */ - template InputStreamBuffer::~InputStreamBuffer() = default; - - /** - * @brief Called when data is read from a stream. Adds the data to the buffer and checks if the event should be fired - * - * @tparam Type - * @param read_element - */ - template void InputStreamBuffer::on_stream_read(Type read_element) { - - // flush the buffer if the event fire element is read - if(read_element == m_event_fire_element){ - flush(); - return; - } - - // Ensure the buffer is not full - if(m_offset >= 10238){ - flush(); - } - - // Add the element - m_buffer[m_offset++] = read_element; - - } - - /** - * @brief Called when a stream has finished. Flushes the buffer if there is any data in it - * - * @tparam Type The type of data the stream is handling - * @param stream The stream that has finished - */ - template void InputStreamBuffer::on_end_of_stream(GenericInputStream *stream) { - - // flush the buffer if there is any data in it - if(m_offset > 0) - flush(); - - // Pass the event on to the handlers and remove the stream - InputStreamProcessor::on_end_of_stream(stream); - } - - /** - * @brief Flushes the buffer by adding the termination element and firing an on read event (NOTE: The buffer is not cleared after this just overwritten) - * - * @tparam Type The type of data the stream is handling - */ - template void InputStreamBuffer::flush() { - - // Ensure the buffer is not empty - if(m_offset == 0) - return; - - // Add the termination element to the buffer - m_buffer[m_offset] = m_termination_element; - - // Fire the on read event - InputStreamProcessor::on_stream_read(m_buffer); - - // Reset the offset - m_offset = 0; - - } - - /** - * @brief Creates a new GenericInputStream - * - * @tparam Type The type of data the stream is handling - */ - template GenericInputStream::GenericInputStream() = default; - - /** - * @brief Creates a new GenericInputStream and connects it to the handler - * - * @tparam Type The type of data the stream is handling - * @param input_stream_event_handler The handler to handle the data - */ - template GenericInputStream::GenericInputStream(InputStreamEventHandler *input_stream_event_handler) { - - // Connect the handler - connect_input_stream_event_handler(input_stream_event_handler); - } - - /** - * @brief Destroys the GenericInputStream and disconnects all handlers - * - * @tparam Type The type of data the stream is handling - */ - template GenericInputStream::~GenericInputStream() { - - // Disconnect all handlers - while (!m_input_stream_event_handlers.empty()) - disconnect_input_stream_event_handler(*(m_input_stream_event_handlers.begin())); - } - - /** - * @brief Adds a inputStreamEventHandler to the list of internetProtocolHandlers - * @tparam Type The type of data the stream is handling - * @param input_stream_event_handler The inputStreamEventHandler to add - */ - template void GenericInputStream::connect_input_stream_event_handler(InputStreamEventHandler *input_stream_event_handler) { - - // Don't add the handler if it is already connected - if(m_input_stream_event_handlers.find(input_stream_event_handler) != m_input_stream_event_handlers.end()) - return; - - // Add the handler - m_input_stream_event_handlers.push_back(input_stream_event_handler); - - } - - /** - * @brief Removes a handler from the list of handlers - * - * @tparam Type The type of data the stream is handling - * @param input_stream_event_handler The handler to remove - */ - template void GenericInputStream::disconnect_input_stream_event_handler(InputStreamEventHandler *input_stream_event_handler) { - - // Don't remove the handler if it is not connected - if(m_input_stream_event_handlers.find(input_stream_event_handler) == m_input_stream_event_handlers.end()) - return; - - // Remove the handler - m_input_stream_event_handlers.erase(input_stream_event_handler); - - // Fire the end of stream event - input_stream_event_handler->on_end_of_stream(this); - - } - } +namespace MaxOS::common { + + // Forward declaration + template class GenericInputStream; + + /** + * @class InputStreamEventHandler + * @brief Handles read and end of stream events from a set of streams + * + * @tparam Type The type of data the stream is handling + */ + template class InputStreamEventHandler { + friend class GenericInputStream; + + protected: + common::Vector*> m_generic_input_streams; ///< List of streams being observed by this handler + public: + InputStreamEventHandler(); + ~InputStreamEventHandler(); + + virtual void on_stream_read(Type); + virtual void on_end_of_stream(GenericInputStream*); + }; + + /** + * @class InputStreamProcessor + * @brief Converts one stream data type into another + * + * @tparam Type + * @tparam ProcessorType + */ + template class InputStreamProcessor : public InputStreamEventHandler, public GenericInputStream { + public: + InputStreamProcessor(); + explicit InputStreamProcessor(InputStreamEventHandler* generic_stream_event_handler); + ~InputStreamProcessor(); + + void on_end_of_stream(GenericInputStream* stream) override; + }; + + + /** + * @class InputStreamSocket + * @brief Passes read events on to the handlers + * + * @tparam Type The type of data the stream is handling + */ + template class InputStreamSocket : public InputStreamProcessor { + public: + InputStreamSocket(); + explicit InputStreamSocket(InputStreamEventHandler*); + ~InputStreamSocket(); + + void on_stream_read(Type) override; + }; + + /** + * @class InputStreamBuffer + * @brief Buffers data from a stream and fires an event when a certain element is read + * + * @tparam Type The type of data the stream is handling + */ + template class InputStreamBuffer : protected InputStreamProcessor { + protected: + Type m_buffer[10240]; ///< The buffer to store data in + int m_offset { 0 }; ///< The current position in the buffer + Type m_event_fire_element; ///< The element that will cause the buffer to flush and fire an event + Type m_termination_element; ///< The element that will cause the buffer to flush and end the stream + + public: + InputStreamBuffer(Type event_fire_element, Type termination_element); + ~InputStreamBuffer(); + + void on_stream_read(Type) override; + void on_end_of_stream(GenericInputStream*) override; + void flush(); + }; + + /** + * @class GenericInputStream + * @brief Manages the connection of a stream to handlers + * + * @tparam Type The type of data the stream is handling + */ + template class GenericInputStream { + + protected: + common::Vector*> m_input_stream_event_handlers; ///< List of streams being observed by this handler + + public: + GenericInputStream(); + explicit GenericInputStream(InputStreamEventHandler*); + ~GenericInputStream(); + + void connect_input_stream_event_handler(InputStreamEventHandler*); + void disconnect_input_stream_event_handler(InputStreamEventHandler*); + + }; + + /** + * @brief The ">>" operator is used to read data from a stream, it takes a stream to read from and an event handler to handle the data + * + * @tparam Type The type of data the stream is handling + * @param source The stream to read from + * @param input_stream_event_handler The event handler to handle the data + */ + template void operator >>(GenericInputStream& source, InputStreamEventHandler& input_stream_event_handler); + + /** + * @brief The ">>" operator is used to read data from a stream, it takes a stream to read from and an InputStreamProcessor to process the data + * + * @tparam Type The type of data the stream is handling + * @tparam ProcessorType The type of data to convert the data into via the processor + * @param source The stream to read from + * @param processor The processor to process the data + * @return The processed stream + */ + template GenericInputStream& operator >>(GenericInputStream& source, InputStreamProcessor& processor); + + /** + * @class InputStream + * @brief A stream that handles strings + */ + class InputStream : public GenericInputStream { + public: + explicit InputStream(InputStreamEventHandler*); + }; + + + ///_______________________________________________TEMPLATES_________________________________________________________________/// + + /** + * @brief Creates a new InputStreamProcessor + * + * @tparam Type the type of data the stream is handling + */ + template InputStreamEventHandler::InputStreamEventHandler() = default; + + /** + * @brief Destroys the InputStreamProcessor and disconnects it from all streams + * + * @tparam Type the type of data the stream is handling + */ + template InputStreamEventHandler::~InputStreamEventHandler() { + + // Disconnect the handler from all streams + while(!m_generic_input_streams.empty()) + (*m_generic_input_streams.begin())->disconnect_input_stream_event_handler(this); + + } + + /** + * @brief Called when data is read from a stream (overridden by subclasses) + * + * @tparam Type the type of data the stream is handling + */ + template void InputStreamEventHandler::on_stream_read(Type) { + + } + + /** + * @brief Called when a stream has finished. Removes the stream from the array of streams + * + * @tparam Type The type of data the stream is handling + * @param stream The stream that has finished + */ + template void InputStreamEventHandler::on_end_of_stream(GenericInputStream* stream) { + + // Remove the stream + m_generic_input_streams.erase(stream); + } + + + /** + * @brief Creates a new InputStreamProcessor + * + * @tparam Type The type of data the stream is handling + * @tparam ProcessorType The type of data to convert the data into via the processor + */ + template InputStreamProcessor::InputStreamProcessor() + : InputStreamEventHandler(), + GenericInputStream() { + + } + + /** + * @brief Creates a new InputStreamProcessor + * + * @tparam Type The type of data the stream is handling + * @tparam ProcessorType The type of data to convert the data into via the processor + * @param generic_stream_event_handler The event handler to handle the data + */ + template InputStreamProcessor::InputStreamProcessor(InputStreamEventHandler* generic_stream_event_handler) + : InputStreamEventHandler(), + GenericInputStream(generic_stream_event_handler) { + + } + + /** + * @brief Destroys the InputStreamProcessor + * + * @tparam Type The type of data the stream is handling + * @tparam ProcessorType The type of data to convert the data into via the processor + */ + template InputStreamProcessor::~InputStreamProcessor() = default; + + /** + * @brief Called when a stream has finished. Passes the event on to the handlers and then removes the stream from the array of streams + * + * @tparam Type The type of data the stream is handling + * @tparam ProcessorType The type of data to convert the data into via the processor + * @param stream The stream that has finished + */ + template void InputStreamProcessor::on_end_of_stream(GenericInputStream* stream) { + + // Pass the end of stream event on to the handlers + for(auto& event_handler : this->m_input_stream_event_handlers) + event_handler->on_end_of_stream(this); + + // Remove the stream + InputStreamEventHandler::on_end_of_stream(stream); + + } + + /** + * @brief Creates a new InputStreamSocket + * + * @tparam Type The type of data the stream is handling + */ + template InputStreamSocket::InputStreamSocket() = default; + + /** + * @brief Creates a new InputStreamSocket and connects it to the handler + * + * @tparam Type The type of data the stream is handling (and the sockets processor type) + * @param processor_handler The handler to pass to InputStreamProcessor + */ + template InputStreamSocket::InputStreamSocket(InputStreamEventHandler* processor_handler) + : InputStreamProcessor(processor_handler) { + + } + + /** + * @brief Destroys the InputStreamSocket + * + * @tparam Type The type of data the stream is handling + */ + template InputStreamSocket::~InputStreamSocket() = default; + + /** + * @brief Called when data is read from a stream. Passes the event on to the internetProtocolHandlers + * + * @tparam Type The type of data the stream is handling + * @param read_element The element that was read from the stream + */ + template void InputStreamSocket::on_stream_read(Type read_element) { + + // Pass the read event on to the handlers + for(auto& event_handler : this->m_input_stream_event_handlers) + event_handler->on_stream_read(read_element); + + } + + /** + * @brief Creates a new InputStreamBuffer + * + * @tparam Type The type of data the stream is handling + * @param event_fire_element The element to fire the event on + * @param termination_element The element that signifies the end of the part of the stream to be buffered (e.g a newline) + */ + template InputStreamBuffer::InputStreamBuffer(Type event_fire_element, Type termination_element) + : m_event_fire_element(event_fire_element), + m_termination_element(termination_element) { + + } + + /** + * @brief Destroys the InputStreamBuffer + * + * @tparam Type The type of data the stream is handling + */ + template InputStreamBuffer::~InputStreamBuffer() = default; + + /** + * @brief Called when data is read from a stream. Adds the data to the buffer and checks if the event should be fired + * + * @tparam Type + * @param read_element + */ + template void InputStreamBuffer::on_stream_read(Type read_element) { + + // flush the buffer if the event fire element is read + if(read_element == m_event_fire_element) { + flush(); + return; + } + + // Ensure the buffer is not full + if(m_offset >= 10238) { + flush(); + } + + // Add the element + m_buffer[m_offset++] = read_element; + + } + + /** + * @brief Called when a stream has finished. Flushes the buffer if there is any data in it + * + * @tparam Type The type of data the stream is handling + * @param stream The stream that has finished + */ + template void InputStreamBuffer::on_end_of_stream(GenericInputStream* stream) { + + // flush the buffer if there is any data in it + if(m_offset > 0) + flush(); + + // Pass the event on to the handlers and remove the stream + InputStreamProcessor::on_end_of_stream(stream); + } + + /** + * @brief Flushes the buffer by adding the termination element and firing an on read event (NOTE: The buffer is not cleared after this just overwritten) + * + * @tparam Type The type of data the stream is handling + */ + template void InputStreamBuffer::flush() { + + // Ensure the buffer is not empty + if(m_offset == 0) + return; + + // Add the termination element to the buffer + m_buffer[m_offset] = m_termination_element; + + // Fire the on read event + InputStreamProcessor::on_stream_read(m_buffer); + + // Reset the offset + m_offset = 0; + + } + + /** + * @brief Creates a new GenericInputStream + * + * @tparam Type The type of data the stream is handling + */ + template GenericInputStream::GenericInputStream() = default; + + /** + * @brief Creates a new GenericInputStream and connects it to the handler + * + * @tparam Type The type of data the stream is handling + * @param input_stream_event_handler The handler to handle the data + */ + template GenericInputStream::GenericInputStream(InputStreamEventHandler* input_stream_event_handler) { + + // Connect the handler + connect_input_stream_event_handler(input_stream_event_handler); + } + + /** + * @brief Destroys the GenericInputStream and disconnects all handlers + * + * @tparam Type The type of data the stream is handling + */ + template GenericInputStream::~GenericInputStream() { + + // Disconnect all handlers + while(!m_input_stream_event_handlers.empty()) + disconnect_input_stream_event_handler(*(m_input_stream_event_handlers.begin())); + } + + /** + * @brief Adds a inputStreamEventHandler to the list of internetProtocolHandlers + * @tparam Type The type of data the stream is handling + * @param input_stream_event_handler The inputStreamEventHandler to add + */ + template void GenericInputStream::connect_input_stream_event_handler(InputStreamEventHandler* input_stream_event_handler) { + + // Don't add the handler if it is already connected + if(m_input_stream_event_handlers.find(input_stream_event_handler) != m_input_stream_event_handlers.end()) + return; + + // Add the handler + m_input_stream_event_handlers.push_back(input_stream_event_handler); + + } + + /** + * @brief Removes a handler from the list of handlers + * + * @tparam Type The type of data the stream is handling + * @param input_stream_event_handler The handler to remove + */ + template void GenericInputStream::disconnect_input_stream_event_handler(InputStreamEventHandler* input_stream_event_handler) { + + // Don't remove the handler if it is not connected + if(m_input_stream_event_handlers.find(input_stream_event_handler) == m_input_stream_event_handlers.end()) + return; + + // Remove the handler + m_input_stream_event_handlers.erase(input_stream_event_handler); + + // Fire the end of stream event + input_stream_event_handler->on_end_of_stream(this); + + } } #endif //MAXOS_COMMON_INPUTSTREAM_H diff --git a/kernel/include/common/map.h b/kernel/include/common/map.h index 5da1f7c9..4803a54c 100644 --- a/kernel/include/common/map.h +++ b/kernel/include/common/map.h @@ -12,350 +12,346 @@ #include #include -namespace MaxOS{ - namespace common{ - - /** - * @class MapIterationHandler - * @brief Handles iteration of a map - * - * @tparam Key The key type - * @tparam Value The value type - */ - template class MapIterationHandler - { - public: - MapIterationHandler(); - ~MapIterationHandler(); - - virtual void on_read(Key, Value); - virtual void on_end_of_stream(); - }; - - /** - * @class Map - * @brief A list of key-value pairs - * - * @tparam Key The key type - * @tparam Value The value type - */ - template class Map - { - protected: - Vector> m_elements; ///< The internal storage of the map, a vector of key-value pairs - - public: - typedef typename Vector>::iterator iterator; ///< The iterator type for the map - - Map(); - ~Map(); - - Value& operator[](Key); - - bool empty(); - int size(); - - iterator begin(); - iterator end(); - iterator find(Key); - - iterator push_back(Key, Value); - Pair pop_back(); - - iterator push_front(Key, Value); - Pair pop_front(); - - void insert(Key, Value); - - void erase(Key); - void erase(iterator position); - void clear(); - - void reserve(size_t amount); - void increase_size(); - - void iterate(MapIterationHandler* handler); - void iterate(void (*callback)(Key &, Value &)); - - }; - - /// ______________ TEMPLATE IMPLEMENTATION ______________ - template MapIterationHandler::MapIterationHandler() = default; - - template MapIterationHandler::~MapIterationHandler() = default; - - /** - * @brief Called when the end of the stream is reached - * - * @tparam Key The key type - * @tparam Value The value type - */ - template void MapIterationHandler::on_end_of_stream() { - - } - - /** - * @brief Called when a key-value pair is read - * - * @tparam Key The key type - * @tparam Value The value type - */ - template void MapIterationHandler::on_read(Key, Value) { - - } - - template Map::Map() = default; - - template Map::~Map() = default; - - /** - * @brief Overloads the [] operator to return the value of the key - * - * @tparam Key The key type - * @tparam Value The value type - * @param key The key to search for - * @return The value of the key - */ - template Value &Map::operator[](Key key) { - - // Return the value of the key (second item in the pair) - return find(key) -> second; - } - - /** - * @brief Returns the beginning of the map - * - * @tparam Key The key type - * @tparam Value The value type - * @return The m_first_memory_chunk element in the map - */ - template typename Map::iterator Map::begin() { - return m_elements.begin(); - } - - /** - * @brief Returns the end of the map - * - * @tparam Key The key type - * @tparam Value The value type - * @return The last element in the map - */ - template typename Map::iterator Map::end() { - return m_elements.end(); - } - - /** - * @brief Finds an element in the map based on the key - * - * @tparam Key The key type - * @tparam Value The value type - * @param element The key to search for - * @return The iterator of the element, or the end iterator if not found - */ - template typename Map::iterator Map::find(Key element) { - - // Search for the element - for (iterator it = begin(); it != end(); it++) - if (it -> first == element) - return it; - - // Item not found - return end(); - - } - - /** - * @brief Adds a new key-value pair to the end of the map - * - * @tparam Key The key type - * @tparam Value The value type - * @param key The key - * @param value The value - * @return The iterator of the new element - */ - template Map::iterator Map::push_back(Key key, Value value) { - return m_elements.push_back(Pair(key, value)); - } - - /** - * @brief Removes the last key-value pair from the map and returns it - * - * @tparam Key The key type - * @tparam Value The value type - * @return - */ - template Pair Map::pop_back() { - return m_elements.pop_back(); - } - - /** - * @brief Adds a new key-value pair to the front of the map - * - * @tparam Key The key type - * @tparam Value The value type - * @param key The key - * @param value The value - * @return - */ - template Map::iterator Map::push_front(Key key, Value value) { - return m_elements.push_front({key, value}); - } - - /** - * @brief Removes the first key-value pair from the map and returns it - * - * @tparam Key The key type - * @tparam Value The value type - * @return The removed key-value pair - */ - template Pair Map::pop_front() { - return m_elements.pop_front(); - } - - /** - * @brief Returns whether the map is empty - * - * @tparam Key The key type - * @tparam Value The value type - * @return Whether the map is empty - */ - template bool Map::empty() { - return m_elements.empty(); - } - - /** - * @brief The number of elements in the map - * - * @return The number of elements in the Map - */ - template int Map::size() - { - // Return the size of the vector - return m_elements.size(); - - } - - /** - * @brief Removes all elements from the map - * - * @tparam Key The key type - * @tparam Value The value type - */ - template void Map::clear() { - m_elements.clear(); - } - - /** - * @brief Updates the value of an element, or adds a new element if it does not exist - * - * @tparam Key The key type - * @tparam Value The value type - * @param key The key of the new element - * @param value The value of the new element - */ - template void Map::insert(Key key, Value value) { - - // Find the element - iterator it = find(key); - - // If the element is found then update the value - if (it != end()) { - it -> second = value; - } else { - // Otherwise, add a new element - m_elements.push_back(Pair(key, value)); - } - } - - /** - * @brief Removes an element from the map - * - * @tparam Key The key type - * @tparam Value The value type - * @param key The key of the element to remove - */ - template void Map::erase(Key key) { - - // Find the element - iterator it = find(key); - - // If the element is found then remove it - if (it != end()) { - m_elements.erase(it); - } - - } - - /** - * @brief Removes an element from the map at the specified position - * - * @tparam Key The key type - * @tparam Value The value type - * @param position The iterator of the element to remove - */ - template void Map::erase(Map::iterator position) { - m_elements.erase(position); - - } - - /** - * @brief Reserves space in the map for a certain amount of elements to avoid reallocations - * - * @tparam Key The key type - * @tparam Value The value type - * @param amount The amount of elements to reserve space for - */ - template void Map::reserve(size_t amount) { - m_elements.reserve(amount); - } - - /** - * @brief Doubles the size of the map - * - * @tparam Key The key type - * @tparam Value The value type - */ - template void Map::increase_size() { - m_elements.increase_size(); - } - - /** - * @brief Iterates through the map and calls the handler - * - * @tparam Key The key type - * @tparam Value The value type - * @param handler The handler to call - */ - template void Map::iterate(MapIterationHandler *handler) { - - // Loop through the elements - for(auto& it : m_elements) { - - // Call the handler - handler->on_read(it.first, it.second); - } - - // Call the handler - handler->on_end_of_stream(); - - } - - /** - * @brief Iterates through the map and calls the callback - * - * @tparam Key The key type - * @tparam Value The value type - * @param callback The callback to call - */ - template void Map::iterate(void (*callback)(Key &, Value &)) { - - // Call the callback for each element - for(auto& it : m_elements) { - callback(it.first, it.second); - } - } - } +namespace MaxOS::common { + + /** + * @class MapIterationHandler + * @brief Handles iteration of a map + * + * @tparam Key The key type + * @tparam Value The value type + */ + template class MapIterationHandler { + public: + MapIterationHandler(); + ~MapIterationHandler() = default; + + virtual void on_read(Key, Value); + virtual void on_end_of_stream(); + }; + + /** + * @class Map + * @brief A list of key-value pairs + * + * @tparam Key The key type + * @tparam Value The value type + */ + template class Map { + protected: + Vector> m_elements; ///< The internal storage of the map, a vector of key-value pairs + + public: + typedef typename Vector>::iterator iterator; ///< The iterator type for the map + + Map(); + ~Map(); + + Value& operator [](Key); + + bool empty(); + int size(); + + iterator begin(); + iterator end(); + iterator find(Key); + + iterator push_back(Key, Value); + Pair pop_back(); + + iterator push_front(Key, Value); + Pair pop_front(); + + void insert(Key, Value); + + void erase(Key); + void erase(iterator position); + void clear(); + + void reserve(size_t amount); + void increase_size(); + + void iterate(MapIterationHandler* handler); + void iterate(void (* callback)(Key&, Value&)); + + }; + + /// ______________ TEMPLATE IMPLEMENTATION ______________ + template MapIterationHandler::MapIterationHandler() = default; + + + + /** + * @brief Called when the end of the stream is reached + * + * @tparam Key The key type + * @tparam Value The value type + */ + template void MapIterationHandler::on_end_of_stream() { + + } + + /** + * @brief Called when a key-value pair is read + * + * @tparam Key The key type + * @tparam Value The value type + */ + template void MapIterationHandler::on_read(Key, Value) { + + } + + template Map::Map() = default; + + template Map::~Map() = default; + + /** + * @brief Overloads the [] operator to return the value of the key + * + * @tparam Key The key type + * @tparam Value The value type + * @param key The key to search for + * @return The value of the key + */ + template Value& Map::operator [](Key key) { + + // Return the value of the key (second item in the pair) + return find(key)->second; + } + + /** + * @brief Returns the beginning of the map + * + * @tparam Key The key type + * @tparam Value The value type + * @return The m_first_memory_chunk element in the map + */ + template typename Map::iterator Map::begin() { + return m_elements.begin(); + } + + /** + * @brief Returns the end of the map + * + * @tparam Key The key type + * @tparam Value The value type + * @return The last element in the map + */ + template typename Map::iterator Map::end() { + return m_elements.end(); + } + + /** + * @brief Finds an element in the map based on the key + * + * @tparam Key The key type + * @tparam Value The value type + * @param element The key to search for + * @return The iterator of the element, or the end iterator if not found + */ + template typename Map::iterator Map::find(Key element) { + + // Search for the element + for(iterator it = begin(); it != end(); it++) + if(it->first == element) + return it; + + // Item not found + return end(); + + } + + /** + * @brief Adds a new key-value pair to the end of the map + * + * @tparam Key The key type + * @tparam Value The value type + * @param key The key + * @param value The value + * @return The iterator of the new element + */ + template Map::iterator Map::push_back(Key key, Value value) { + return m_elements.push_back(Pair(key, value)); + } + + /** + * @brief Removes the last key-value pair from the map and returns it + * + * @tparam Key The key type + * @tparam Value The value type + * @return + */ + template Pair Map::pop_back() { + return m_elements.pop_back(); + } + + /** + * @brief Adds a new key-value pair to the front of the map + * + * @tparam Key The key type + * @tparam Value The value type + * @param key The key + * @param value The value + * @return + */ + template Map::iterator Map::push_front(Key key, Value value) { + return m_elements.push_front({ key, value }); + } + + /** + * @brief Removes the first key-value pair from the map and returns it + * + * @tparam Key The key type + * @tparam Value The value type + * @return The removed key-value pair + */ + template Pair Map::pop_front() { + return m_elements.pop_front(); + } + + /** + * @brief Returns whether the map is empty + * + * @tparam Key The key type + * @tparam Value The value type + * @return Whether the map is empty + */ + template bool Map::empty() { + return m_elements.empty(); + } + + /** + * @brief The number of elements in the map + * + * @return The number of elements in the Map + */ + template int Map::size() { + // Return the size of the vector + return m_elements.size(); + + } + + /** + * @brief Removes all elements from the map + * + * @tparam Key The key type + * @tparam Value The value type + */ + template void Map::clear() { + m_elements.clear(); + } + + /** + * @brief Updates the value of an element, or adds a new element if it does not exist + * + * @tparam Key The key type + * @tparam Value The value type + * @param key The key of the new element + * @param value The value of the new element + */ + template void Map::insert(Key key, Value value) { + + // Find the element + iterator it = find(key); + + // If the element is found then update the value + if(it != end()) { + it->second = value; + } else { + // Otherwise, add a new element + m_elements.push_back(Pair(key, value)); + } + } + + /** + * @brief Removes an element from the map + * + * @tparam Key The key type + * @tparam Value The value type + * @param key The key of the element to remove + */ + template void Map::erase(Key key) { + + // Find the element + iterator it = find(key); + + // If the element is found then remove it + if(it != end()) { + m_elements.erase(it); + } + + } + + /** + * @brief Removes an element from the map at the specified position + * + * @tparam Key The key type + * @tparam Value The value type + * @param position The iterator of the element to remove + */ + template void Map::erase(Map::iterator position) { + m_elements.erase(position); + + } + + /** + * @brief Reserves space in the map for a certain amount of elements to avoid reallocations + * + * @tparam Key The key type + * @tparam Value The value type + * @param amount The amount of elements to reserve space for + */ + template void Map::reserve(size_t amount) { + m_elements.reserve(amount); + } + + /** + * @brief Doubles the size of the map + * + * @tparam Key The key type + * @tparam Value The value type + */ + template void Map::increase_size() { + m_elements.increase_size(); + } + + /** + * @brief Iterates through the map and calls the handler + * + * @tparam Key The key type + * @tparam Value The value type + * @param handler The handler to call + */ + template void Map::iterate(MapIterationHandler* handler) { + + // Loop through the elements + for(auto& it : m_elements) { + + // Call the handler + handler->on_read(it.first, it.second); + } + + // Call the handler + handler->on_end_of_stream(); + + } + + /** + * @brief Iterates through the map and calls the callback + * + * @tparam Key The key type + * @tparam Value The value type + * @param callback The callback to call + */ + template void Map::iterate(void (* callback)(Key&, Value&)) { + + // Call the callback for each element + for(auto& it : m_elements) { + callback(it.first, it.second); + } + } } + #endif //MAXOS_COMMON_MAP_H diff --git a/kernel/include/common/math.h b/kernel/include/common/math.h index 9f5cd0cd..0c497841 100644 --- a/kernel/include/common/math.h +++ b/kernel/include/common/math.h @@ -12,7 +12,7 @@ #include #include -namespace common{ +namespace common { // // uint64_t min(uint64_t val1, uint64_t val2); diff --git a/kernel/include/common/outputStream.h b/kernel/include/common/outputStream.h index 37bb6815..c4049116 100644 --- a/kernel/include/common/outputStream.h +++ b/kernel/include/common/outputStream.h @@ -9,152 +9,149 @@ #ifndef MAXOS_COMMON_OUTPUTSTREAM_H #define MAXOS_COMMON_OUTPUTSTREAM_H -#include +#include #include #include -namespace MaxOS{ - - namespace common{ - - /** - * @class GenericOutputStream - * @brief A stream that can be written to. - * - * @tparam Type The type of the elements that will be written to the stream. - */ - template class GenericOutputStream : public InputStreamProcessor - { - public: - GenericOutputStream(); - ~GenericOutputStream(); - - void on_stream_read(Type) override; - void on_end_of_stream(GenericInputStream*) override; - - virtual void write(Type); - virtual void close(); - - virtual GenericOutputStream& operator << (Type); - }; - - /** - * @class OutputStream - * @brief A stream that strings can be written to. - */ - class OutputStream : public GenericOutputStream - { - - public: - OutputStream(); - ~OutputStream(); - - virtual void line_feed(); - virtual void carriageReturn(); - virtual void clear(); - - void write(string string_to_write) override; - void write(const char* string_to_write); - virtual void write_char(char char_to_write); - virtual void write_int(int int_to_write); - virtual void write_hex(uint64_t hex_to_write); - - OutputStream& operator << (string string_to_write) override; - OutputStream& operator << (const char* string_to_write); - OutputStream& operator << (int int_to_write); - OutputStream& operator << (uint64_t hex_to_write); - OutputStream& operator << (char char_to_write); - }; - - - - ///__________________________________________Templates__________________________________________________/// - - /** - * @brief Constructor of the GenericOutputStream class. - * - * @tparam Type The type of the elements that will be written to the stream. - */ - template GenericOutputStream::GenericOutputStream() = default; - - /** - * @brief Destructor of the GenericOutputStream class. - * - * @tparam Type The type of the elements that will be written to the stream. - */ - template GenericOutputStream::~GenericOutputStream() = default; - - /** - * @brief Writes the date that was read from the input stream to the output stream. - * - * @tparam Type The type of the elements that will be written to the stream. - * @param read_element The element that was read from the stream. - */ - template void GenericOutputStream::on_stream_read(Type read_element) { - - // When something is read from the input stream, it is written to the output stream. - write(read_element); - - // Pass the element to any handlers - for(auto& input_stream_event_handler : this ->m_input_stream_event_handlers) - input_stream_event_handler->on_stream_read(read_element); - - - } - - /** - * @brief Close the stream and remove it from the list of streams when the end of the stream is reached. - * - * @tparam Type The type of the elements that will be written to the stream. - * @param stream The stream that reached the end. - */ - template void GenericOutputStream::on_end_of_stream(GenericInputStream *stream) { - - // Close the stream. - close(); - - // Pass the event to any handlers - for(auto& input_stream_event_handler : this ->m_input_stream_event_handlers) - input_stream_event_handler->on_end_of_stream(stream); - - // Remove the stream from the list of streams. - InputStreamProcessor::on_end_of_stream(stream); - - } - - /** - * @brief write an element to the stream. - * - * @tparam Type The type of the elements that will be written to the stream. - */ - template void GenericOutputStream::write(Type) { - - } - - /** - * @brief Close the stream. - * - * @tparam Type The type of the elements that will be written to the stream. - */ - template void GenericOutputStream::close() { - - } - - /** - * @brief Overload the << operator to write an element to the stream. - * - * @tparam Type The type of the elements that will be written to the stream. - * @param write_element The element that will be written to the stream. - * @return The stream - */ - template GenericOutputStream &GenericOutputStream::operator << (Type write_element) { - - // write the element to the stream. - write(write_element); - - // Return the stream. - return *this; - } - } + +namespace MaxOS::common { + + /** + * @class GenericOutputStream + * @brief A stream that can be written to. + * + * @tparam Type The type of the elements that will be written to the stream. + */ + template class GenericOutputStream : public InputStreamProcessor { + public: + GenericOutputStream(); + ~GenericOutputStream(); + + void on_stream_read(Type) override; + void on_end_of_stream(GenericInputStream*) override; + + virtual void write(Type); + virtual void close(); + + virtual GenericOutputStream& operator <<(Type); + }; + + /** + * @class OutputStream + * @brief A stream that strings can be written to. + */ + class OutputStream : public GenericOutputStream { + + public: + OutputStream(); + ~OutputStream(); + + virtual void line_feed(); + virtual void carriage_return(); + virtual void clear(); + + void write(string string_to_write) override; + void write(const char* string_to_write); + virtual void write_char(char char_to_write); + virtual void write_int(int int_to_write); + virtual void write_hex(uint64_t hex_to_write); + + OutputStream& operator <<(string string_to_write) override; + OutputStream& operator <<(const char* string_to_write); + OutputStream& operator <<(int int_to_write); + OutputStream& operator <<(uint64_t hex_to_write); + OutputStream& operator <<(char char_to_write); + }; + + + + ///__________________________________________Templates__________________________________________________/// + + /** + * @brief Constructor of the GenericOutputStream class. + * + * @tparam Type The type of the elements that will be written to the stream. + */ + template GenericOutputStream::GenericOutputStream() = default; + + /** + * @brief Destructor of the GenericOutputStream class. + * + * @tparam Type The type of the elements that will be written to the stream. + */ + template GenericOutputStream::~GenericOutputStream() = default; + + /** + * @brief Writes the date that was read from the input stream to the output stream. + * + * @tparam Type The type of the elements that will be written to the stream. + * @param read_element The element that was read from the stream. + */ + template void GenericOutputStream::on_stream_read(Type read_element) { + + // When something is read from the input stream, it is written to the output stream. + write(read_element); + + // Pass the element to any handlers + for(auto& input_stream_event_handler : this->m_input_stream_event_handlers) + input_stream_event_handler->on_stream_read(read_element); + + + } + + /** + * @brief Close the stream and remove it from the list of streams when the end of the stream is reached. + * + * @tparam Type The type of the elements that will be written to the stream. + * @param stream The stream that reached the end. + */ + template void GenericOutputStream::on_end_of_stream(GenericInputStream* stream) { + + // Close the stream. + close(); + + // Pass the event to any handlers + for(auto& input_stream_event_handler : this->m_input_stream_event_handlers) + input_stream_event_handler->on_end_of_stream(stream); + + // Remove the stream from the list of streams. + InputStreamProcessor::on_end_of_stream(stream); + + } + + /** + * @brief write an element to the stream. + * + * @tparam Type The type of the elements that will be written to the stream. + */ + template void GenericOutputStream::write(Type) { + + } + + /** + * @brief Close the stream. + * + * @tparam Type The type of the elements that will be written to the stream. + */ + template void GenericOutputStream::close() { + + } + + /** + * @brief Overload the << operator to write an element to the stream. + * + * @tparam Type The type of the elements that will be written to the stream. + * @param write_element The element that will be written to the stream. + * @return The stream + */ + template GenericOutputStream& GenericOutputStream::operator <<(Type write_element) { + + // write the element to the stream. + write(write_element); + + // Return the stream. + return *this; + } } + #endif //MAXOS_COMMON_OUTPUTSTREAM_H diff --git a/kernel/include/common/pair.h b/kernel/include/common/pair.h index 0ac5f342..f97a3c29 100644 --- a/kernel/include/common/pair.h +++ b/kernel/include/common/pair.h @@ -9,49 +9,47 @@ #ifndef MAXOS_PAIR_H #define MAXOS_PAIR_H -namespace MaxOS { - - namespace common { - - /** - * @class Pair - * @brief A pair of two objects - * - * @tparam First The type of the first object - * @tparam Second The type of the second object - */ - template class Pair { - - public: - First first; ///< The first object (often the key) - Second second; ///< The second object (often the value) - - Pair(); - Pair(First, Second); - ~Pair(); - }; - - ///_____________________________Implementation___________________________________________/// - template Pair::Pair() = default; - - /** - * @brief Creates a new pair - * - * @tparam First The type of the first object - * @tparam Second The type of the second object - * @param first The first object - * @param second The second object - */ - template Pair::Pair(First first, Second second) - : first(first), - second(second) - { - - } - - template Pair::~Pair() - = default; - } +namespace MaxOS::common { + + /** + * @class Pair + * @brief A pair of two objects + * + * @tparam First The type of the first object + * @tparam Second The type of the second object + */ + template class Pair { + + public: + First first; ///< The first object (often the key) + Second second; ///< The second object (often the value) + + Pair(); + Pair(First, Second); + ~Pair(); + }; + + ///_____________________________Implementation___________________________________________/// + template Pair::Pair() = default; + + /** + * @brief Creates a new pair + * + * @tparam First The type of the first object + * @tparam Second The type of the second object + * @param first The first object + * @param second The second object + */ + template Pair::Pair(First first, Second second) + : first(first), + second(second) { + + } + + template Pair::~Pair() + = default; } + + #endif //MAXOS_PAIR_H diff --git a/kernel/include/common/rectangle.h b/kernel/include/common/rectangle.h index 7aa1aaa1..e9e1e83f 100644 --- a/kernel/include/common/rectangle.h +++ b/kernel/include/common/rectangle.h @@ -11,242 +11,238 @@ #include -namespace MaxOS{ - - namespace common{ - - /** - * @class Rectangle - * @brief Stores the left, top, width and height of a rectangle - * - * @tparam Type The type of the rectangle (assumed to be numeric) - */ - template class Rectangle{ - public: - Type left { 0 }; ///< The left coordinate of the rectangle - Type top { 0 }; ///< The top coordinate of the rectangle - Type width { 0 }; ///< The width of the rectangle - Type height { 0 }; ///< The height of the rectangle - - Rectangle(); - Rectangle(Type left, Type top, Type width, Type height); - ~Rectangle(); - - bool intersects(const Rectangle&); - Rectangle intersection(const Rectangle&); - - Vector > subtract(const Rectangle&); - - bool contains(const Rectangle&); - bool contains(Type x, Type y); - }; - - ///_______________________________________________TEMPLATES_________________________________________________________________/// - - template Rectangle::Rectangle() = default; - - - /** - * @brief Creates a new rectangle, if width or height are negative, the left/top will be adjusted and the width/height made positive - * - * @tparam Type The type of the rectangle - * @param left The left coordinate - * @param top The top coordinate - * @param width The width of the rectangle - * @param height The height of the rectangle - */ - template Rectangle::Rectangle(Type left, Type top, Type width, Type height) - : left(left), - top(top), - width(width), - height(height) - { - - // If the width is negative, move the left and make the width positive - if(width < 0) - { - left += width; - width *= -1; - } - - // If the m_height is negative, move the top and make the height positive - if(height < 0) - { - top += height; - height *= -1; - } - - // Set the values - this->left = left; - this->top = top; - } - - template Rectangle::~Rectangle() = default; - - /** - * @details Checks if the rectangle intersects with another rectangle - * - * @tparam Type The type of the rectangle - * @param other The other rectangle - * @return True if the rectangles intersect, false otherwise - */ - template bool Rectangle::intersects(const Rectangle& other){ - // If the other rectangle is to the left of this rectangle - if(other.left + other.width <= left) - return false; - - // If the other rectangle is to the right of this rectangle - if(other.left >= left + width) - return false; - - // If the other rectangle is above this rectangle - if(other.top + other.height <= top) - return false; - - // If the other rectangle is below this rectangle - if(other.top >= top + height) - return false; - - // If none of the above conditions are true, then the rectangles intersect - return true; - } - - /** - * @details Returns a retangle that represents the intersection of this rectangle and another rectangle - * - * @tparam Type The type of the rectangle - * @param other The other rectangle - * @return The intersection of the two rectangles - */ - template Rectangle Rectangle::intersection(const Rectangle& other){ - // If the rectangles don't intersect, return an empty rectangle - if(!intersects(other)) - return Rectangle(); - - // Get the left and top of the intersection using the maximum of the two - Type left = this -> left > other.left ? this -> left : other.left; - Type top = this -> top > other.top ? this -> top : other.top; - - // Get the right and bottom of the intersection using the minimum of the two - Type right = this -> left + this -> width < other.left + other.width ? this -> left + this -> width : other.left + other.width; - Type bottom = this -> top + this -> height < other.top + other.height ? this -> top + this -> height : other.top + other.height; - - // Return the intersection - return Rectangle(left, top, right - left, bottom - top); - } - - /** - * @details Subtracts a rectangle from this rectangle - * - * @tparam Type The type of the rectangle - * @param other The rectangle to subtract - * @return A vector of rectangles that represent the subtraction - */ - template Vector > Rectangle::subtract(const Rectangle& other){ - - // Store the result rectangle - Vector > result; - - // Make sure the rectangles intersect - if(!intersects(other)) - { - result.push_back(*this); - return result; - } - - // Get the minimum and maximum values for the width and height - Type maxLeft = left > other.left ? left : other.left; - Type minRight = (left + width < other.left + other.width ? left + width : other.left + other.width); - Type minBottom = (top + height < other.top + other.height ? top+height : other.top + other.height); - - // Add the non-intersecting rectangles to the result - - // Add non-overlapping region above if current top is less than other top - if (top < other.top) - result.push_back(Rectangle(maxLeft, top, minRight - maxLeft, - other.top - top)); - - // Add non-overlapping region to the left if current left is less than other left - if (left < other.left) - result.push_back( - Rectangle(left, top, other.left - left, height)); - - // Add non-overlapping region to the right if current right is greater than other right - if (left + width > other.left + other.width) - result.push_back(Rectangle( - other.left + other.width, top, - (left + width) - (other.left + other.width) + 1, height)); - - // Add non-overlapping region below if current bottom is greater than other bottom - if (this->top + this->height > other.top + other.height) - result.push_back(Rectangle(maxLeft, minBottom, - minRight - maxLeft, - top + height - minBottom + 1)); - - return result; - } - - /** - * @details Checks if this rectangle contains another rectangle - * - * @tparam Type The type of the rectangle - * @param other The other rectangle - * @return True if this rectangle contains the other rectangle, false otherwise - */ - template bool Rectangle::contains(const Rectangle& other){ - - // If the other rectangle is to the left of this rectangle - if(other.left + other.width <= left) - return false; - - // If the other rectangle is to the right of this rectangle - if(other.left >= left + width) - return false; - - // If the other rectangle is above this rectangle - if(other.top + other.height <= top) - return false; - - // If the other rectangle is below this rectangle - if(other.top >= top + height) - return false; - - // If none of the above conditions are true, then the rectangles intersect - return true; - } - - - /** - * @details Checks if this rectangle contains a point - * - * @tparam Type The type of the rectangle - * @param x The x coordinate of the point - * @param y The y coordinate of the point - * @return True if this rectangle contains the point, false otherwise - */ - template bool Rectangle::contains(Type x, Type y){ - - // If the point is to the left of this rectangle - if(x < left) - return false; - - // If the point is to the right of this rectangle - if(x >= left + width) - return false; - - // If the point is above this rectangle - if(y < top) - return false; - - // If the point is below this rectangle - if(y >= top + height) - return false; - - // If none of the above conditions are true, then the point is inside the rectangle - return true; - - } - - } +namespace MaxOS::common { + + /** + * @class Rectangle + * @brief Stores the left, top, width and height of a rectangle + * + * @tparam Type The type of the rectangle (assumed to be numeric) + */ + template class Rectangle { + public: + Type left { 0 }; ///< The left coordinate of the rectangle + Type top { 0 }; ///< The top coordinate of the rectangle + Type width { 0 }; ///< The width of the rectangle + Type height { 0 }; ///< The height of the rectangle + + Rectangle(); + Rectangle(Type left, Type top, Type width, Type height); + ~Rectangle(); + + bool intersects(const Rectangle&); + Rectangle intersection(const Rectangle&); + + Vector> subtract(const Rectangle&); + + bool contains(const Rectangle&); + bool contains(Type x, Type y); + }; + + ///_______________________________________________TEMPLATES_________________________________________________________________/// + + template Rectangle::Rectangle() = default; + + + /** + * @brief Creates a new rectangle, if width or height are negative, the left/top will be adjusted and the width/height made positive + * + * @tparam Type The type of the rectangle + * @param left The left coordinate + * @param top The top coordinate + * @param width The width of the rectangle + * @param height The height of the rectangle + */ + template Rectangle::Rectangle(Type left, Type top, Type width, Type height) + : left(left), + top(top), + width(width), + height(height) { + + // If the width is negative, move the left and make the width positive + if(width < 0) { + left += width; + width *= -1; + } + + // If the m_height is negative, move the top and make the height positive + if(height < 0) { + top += height; + height *= -1; + } + + // Set the values + this->left = left; + this->top = top; + } + + template Rectangle::~Rectangle() = default; + + /** + * @details Checks if the rectangle intersects with another rectangle + * + * @tparam Type The type of the rectangle + * @param other The other rectangle + * @return True if the rectangles intersect, false otherwise + */ + template bool Rectangle::intersects(const Rectangle& other) { + // If the other rectangle is to the left of this rectangle + if(other.left + other.width <= left) + return false; + + // If the other rectangle is to the right of this rectangle + if(other.left >= left + width) + return false; + + // If the other rectangle is above this rectangle + if(other.top + other.height <= top) + return false; + + // If the other rectangle is below this rectangle + if(other.top >= top + height) + return false; + + // If none of the above conditions are true, then the rectangles intersect + return true; + } + + /** + * @details Returns a retangle that represents the intersection of this rectangle and another rectangle + * + * @tparam Type The type of the rectangle + * @param other The other rectangle + * @return The intersection of the two rectangles + */ + template Rectangle Rectangle::intersection(const Rectangle& other) { + // If the rectangles don't intersect, return an empty rectangle + if(!intersects(other)) + return Rectangle(); + + // Get the left and top of the intersection using the maximum of the two + Type i_left = this->left > other.left ? this->left : other.left; + Type i_top = this->top > other.top ? this->top : other.top; + + // Get the right and bottom of the intersection using the minimum of the two + Type right = this->left + this->width < other.left + other.width ? this->left + this->width : other.left + + other.width; + Type bottom = this->top + this->height < other.top + other.height ? this->top + this->height : other.top + + other.height; + + // Return the intersection + return Rectangle(i_left, i_top, right - left, bottom - top); + } + + /** + * @details Subtracts a rectangle from this rectangle + * + * @tparam Type The type of the rectangle + * @param other The rectangle to subtract + * @return A vector of rectangles that represent the subtraction + */ + template Vector> Rectangle::subtract(const Rectangle& other) { + + // Store the result rectangle + Vector> result; + + // Make sure the rectangles intersect + if(!intersects(other)) { + result.push_back(*this); + return result; + } + + // Get the minimum and maximum values for the width and height + Type max_left = left > other.left ? left : other.left; + Type min_right = (left + width < other.left + other.width ? left + width : other.left + other.width); + Type min_bottom = (top + height < other.top + other.height ? top + height : other.top + other.height); + + // Add the non-intersecting rectangles to the result + + // Add non-overlapping region above if current top is less than other top + if(top < other.top) + result.push_back(Rectangle(max_left, top, min_right - max_left, + other.top - top)); + + // Add non-overlapping region to the left if current left is less than other left + if(left < other.left) + result.push_back( + Rectangle(left, top, other.left - left, height)); + + // Add non-overlapping region to the right if current right is greater than other right + if(left + width > other.left + other.width) + result.push_back(Rectangle( + other.left + other.width, top, + (left + width) - (other.left + other.width) + 1, height)); + + // Add non-overlapping region below if current bottom is greater than other bottom + if(this->top + this->height > other.top + other.height) + result.push_back(Rectangle(max_left, min_bottom, + min_right - max_left, + top + height - min_bottom + 1)); + + return result; + } + + /** + * @details Checks if this rectangle contains another rectangle + * + * @tparam Type The type of the rectangle + * @param other The other rectangle + * @return True if this rectangle contains the other rectangle, false otherwise + */ + template bool Rectangle::contains(const Rectangle& other) { + + // If the other rectangle is to the left of this rectangle + if(other.left + other.width <= left) + return false; + + // If the other rectangle is to the right of this rectangle + if(other.left >= left + width) + return false; + + // If the other rectangle is above this rectangle + if(other.top + other.height <= top) + return false; + + // If the other rectangle is below this rectangle + if(other.top >= top + height) + return false; + + // If none of the above conditions are true, then the rectangles intersect + return true; + } + + + /** + * @details Checks if this rectangle contains a point + * + * @tparam Type The type of the rectangle + * @param x The x coordinate of the point + * @param y The y coordinate of the point + * @return True if this rectangle contains the point, false otherwise + */ + template bool Rectangle::contains(Type x, Type y) { + + // If the point is to the left of this rectangle + if(x < left) + return false; + + // If the point is to the right of this rectangle + if(x >= left + width) + return false; + + // If the point is above this rectangle + if(y < top) + return false; + + // If the point is below this rectangle + if(y >= top + height) + return false; + + // If none of the above conditions are true, then the point is inside the rectangle + return true; + + } + } + #endif //MAXOS_COMMON_RECTANGLE_H diff --git a/kernel/include/common/spinlock.h b/kernel/include/common/spinlock.h index ee5c5e5b..9d1a4a3e 100644 --- a/kernel/include/common/spinlock.h +++ b/kernel/include/common/spinlock.h @@ -11,68 +11,64 @@ #include -namespace MaxOS { - namespace common { +namespace MaxOS::common { - /** - * @class Spinlock - * @brief Enables a resource to be used by only one instance at a time through locking and unlocking - */ - class Spinlock { + /** + * @class Spinlock + * @brief Enables a resource to be used by only one instance at a time through locking and unlocking + */ + class Spinlock { - private: - bool m_locked = false; + private: + bool m_locked = false; - public: - Spinlock(); - ~Spinlock(); + public: + Spinlock(); + ~Spinlock(); - void lock(); - void unlock(); - [[nodiscard]] bool is_locked() const; + void lock(); + void unlock(); + [[nodiscard]] bool is_locked() const; - void acquire(); - void release(); - }; + void acquire(); + void release(); + }; + /// How many attempts to acquire the lock should fail before queueing + constexpr uint8_t BLOCKING_FAST_TRY_LIMIT = UINT8_MAX; - /// How many attempts to acquire the lock should fail before queueing - constexpr uint8_t BLOCKING_FAST_TRY_LIMIT = UINT8_MAX; + /** + * @class BlockingLock + * @brief Enables a resource to be used by only one instance at a time through a combination of spinning and queuing. When waiting enqueued, thread will sleep. + * + * @note Repeated API that could be made a class that isn't because lock types shouldn't be interchangeable + * @see Spinlock + */ + class BlockingLock { - /** - * @class BlockingLock - * @brief Enables a resource to be used by only one instance at a time through a combination of spinning and queuing. When waiting enqueued, thread will sleep. - * - * @note Repeated API that could be made a class that isn't because lock types shouldn't be interchangeable - * @see Spinlock - */ - class BlockingLock { + private: + bool m_locked = false; + Vector m_queue; - private: - bool m_locked = false; - Vector m_queue; + static bool must_spin(); - static bool must_spin(); + public: + BlockingLock(); + ~BlockingLock(); - public: - BlockingLock(); - ~BlockingLock(); + void lock(); + void unlock(); + [[nodiscard]] bool is_locked() const; - void lock(); - void unlock(); - [[nodiscard]] bool is_locked() const; + void acquire(); + void release(); - void acquire(); - void release(); + }; - }; - - - - } } + #endif // MAXOS_COMMON_SPINLOCK_H diff --git a/kernel/include/common/string.h b/kernel/include/common/string.h index 86a7e938..fdb788ea 100644 --- a/kernel/include/common/string.h +++ b/kernel/include/common/string.h @@ -9,7 +9,7 @@ #ifndef MAXOS_STRING_H #define MAXOS_STRING_H -#include +#include #include #include @@ -31,60 +31,60 @@ namespace MaxOS { char m_small_string[MAX_STRING_SMALL_STORAGE] = { 0 }; bool m_using_small = true; - [[nodiscard]] static int lex_value(String const &other); + [[nodiscard]] static int lex_value(String const& other); void allocate_self(); public: String(); - explicit String(char c); + String(char c); String(char const* string); String(uint8_t const* string, int length); - String(String const &other); - explicit String(int value); - explicit String(uint64_t value); - explicit String(bool value); + String(String const& other); + String(int value); + String(uint64_t value); + String(bool value); ~String(); - void copy(String const &other); + void copy(String const& other); static String formatted(char const* format, ...); static String formatted(char const* format, va_list parameters); [[nodiscard]] size_t length(bool count_ansi = true) const; - char* c_str(); - const char* c_str() const; + [[nodiscard]] char* c_str(); + [[nodiscard]] const char* c_str() const; - bool starts_with(String const &other); + bool starts_with(String const& other); [[nodiscard]] String substring(size_t start, size_t length) const; - [[nodiscard]] common::Vector split(String const &delimiter) const; + [[nodiscard]] common::Vector split(String const& delimiter) const; [[nodiscard]] String strip(char strip_char = ' ') const; [[nodiscard]] String center(size_t width, char fill = ' ') const; // Operator functions - [[nodiscard]] bool equals(String const &other) const; + [[nodiscard]] bool equals(String const& other) const; // Operators - String &operator=(String const &other); - String operator+(String const &other) const; - String &operator+=(String const &other); + String& operator =(String const& other); + String operator +(String const& other) const; + String& operator +=(String const& other); - String operator*(int times) const; + String operator *(int times) const; - bool operator==(String const &other) const; - bool operator!=(String const &other) const; + bool operator ==(String const& other) const; + bool operator !=(String const& other) const; - bool operator<(String const &other) const; - bool operator>(String const &other) const; + bool operator <(String const& other) const; + bool operator >(String const& other) const; - bool operator<=(String const &other) const; - bool operator>=(String const &other) const; + bool operator <=(String const& other) const; + bool operator >=(String const& other) const; - char &operator[](size_t index); - char &operator[](size_t index) const; + char& operator [](size_t index); + char& operator [](size_t index) const; } string; ///< Typedef for String @@ -97,13 +97,13 @@ namespace MaxOS { class StringBuilder { public: String out; ///< The output string - operator String() const { return out; } ///< Convert to string + operator String() const { return out; } ///< Convert to string - StringBuilder &operator<<(char const* str); - StringBuilder &operator<<(String const &other); - StringBuilder &operator<<(int value); - StringBuilder &operator<<(uint64_t value); - StringBuilder &operator<<(bool value); + StringBuilder& operator <<(char const* str); + StringBuilder& operator <<(String const& other); + StringBuilder& operator <<(int value); + StringBuilder& operator <<(uint64_t value); + StringBuilder& operator <<(bool value); }; } @@ -116,14 +116,14 @@ char* ftoa(float number); // Compare functions bool strcmp(char const* str1, char const* str2); -bool strcmp(char const* str1, MaxOS::String const &str2); -bool strcmp(MaxOS::String const &str1, char const* str2); -bool strcmp(MaxOS::String const &str1, MaxOS::String const &str2); +bool strcmp(char const* str1, MaxOS::String const& str2); +bool strcmp(MaxOS::String const& str1, char const* str2); +bool strcmp(MaxOS::String const& str1, MaxOS::String const& str2); // Compare limited functions bool strncmp(char const* str1, char const* str2, int length); -bool strncmp(char const* str1, MaxOS::String const &str2, int length); -bool strncmp(MaxOS::String const &str1, char const* str2, int length); -bool strncmp(MaxOS::String const &str1, MaxOS::String const &str2, int length); +bool strncmp(char const* str1, MaxOS::String const& str2, int length); +bool strncmp(MaxOS::String const& str1, char const* str2, int length); +bool strncmp(MaxOS::String const& str1, MaxOS::String const& str2, int length); #endif //MAXOS_STRING_H diff --git a/kernel/include/common/time.h b/kernel/include/common/time.h index 92c9db8a..a0a74257 100644 --- a/kernel/include/common/time.h +++ b/kernel/include/common/time.h @@ -9,123 +9,121 @@ #ifndef MAXOS_COMMON_TIME_H #define MAXOS_COMMON_TIME_H -#include - -namespace MaxOS{ - - namespace common{ - - /** - * @struct Time - * @brief Stores the year, month, day, hour, minute and second of a time. - * - * @typedef time_t - * @brief Alias for Time struct - */ - typedef struct Time{ - - uint16_t year; ///< The year - uint8_t month; ///< The month (1-12) - uint8_t day; ///< The day (1-31) - - uint8_t hour; ///< The hour (0-23) - uint8_t minute; ///< The minute (0-59) - uint8_t second; ///< The second (0-59) - - /** - * @brief Checks if the year is a leap year - * @return True if the year is a leap year, false otherwise - */ - [[nodiscard]] bool is_leap_year() const { - return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; - } - - } time_t; - - /// List of month names indexed by month number - 1 - static const char* Months[] = { - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December" - }; - - /// List of day names starting from Sunday ending on Saturday - static const char* Days[] = { - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday" - }; - - /// Number of days in each month indexed by month number - 1 - constexpr uint8_t DAYS_IN_MONTH[] = { - 31, // January - 28, // February - 31, // March - 30, // April - 31, // May - 30, // June - 31, // July - 31, // August - 30, // September - 31, // October - 30, // November - 31 // December - }; - - constexpr uint16_t DAYS_PER_YEAR = 365; ///< Number of days in a non-leap year - constexpr uint16_t DAYS_PER_LEAP_YEAR = 366; ///< Number of days in a leap year - - /** - * @brief Converts a time to an epoch - * - * @param time The time representation - * @return The epoch time - */ - static uint64_t time_to_epoch(Time time){ - uint64_t epoch = 0; - - // Add the number of years - for(uint16_t year = 1970; year < time.year; year++) - epoch += (time.is_leap_year() ? DAYS_PER_LEAP_YEAR : DAYS_PER_YEAR); - - - // Add the number of days in the current year - for(uint8_t month = 0; month < time.month - 1; month++) - epoch += DAYS_IN_MONTH[month]; - - // Add the number of days in the current month - epoch += time.day - 1; - - // Add the number of hours - epoch *= 24; - epoch += time.hour; - - // Add the number of minutes - epoch *= 60; - epoch += time.minute; - - // Add the number of seconds - epoch *= 60; - epoch += time.second; - - return epoch; - } - - } +#include + + +namespace MaxOS::common { + + /** + * @struct Time + * @brief Stores the year, month, day, hour, minute and second of a time. + * + * @typedef time_t + * @brief Alias for Time struct + */ + typedef struct Time { + + uint16_t year; ///< The year + uint8_t month; ///< The month (1-12) + uint8_t day; ///< The day (1-31) + + uint8_t hour; ///< The hour (0-23) + uint8_t minute; ///< The minute (0-59) + uint8_t second; ///< The second (0-59) + + /** + * @brief Checks if the year is a leap year + * @return True if the year is a leap year, false otherwise + */ + [[nodiscard]] bool is_leap_year() const { + return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; + } + + } time_t; + + /// List of month names indexed by month number - 1 + static const char* Months[] = { + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + }; + + /// List of day names starting from Sunday ending on Saturday + static const char* Days[] = { + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" + }; + + /// Number of days in each month indexed by month number - 1 + constexpr uint8_t DAYS_IN_MONTH[] = { + 31, // January + 28, // February + 31, // March + 30, // April + 31, // May + 30, // June + 31, // July + 31, // August + 30, // September + 31, // October + 30, // November + 31 // December + }; + + constexpr uint16_t DAYS_PER_YEAR = 365; ///< Number of days in a non-leap year + constexpr uint16_t DAYS_PER_LEAP_YEAR = 366; ///< Number of days in a leap year + + /** + * @brief Converts a time to an epoch + * + * @param time The time representation + * @return The epoch time + */ + static uint64_t time_to_epoch(Time time) { + uint64_t epoch = 0; + + // Add the number of years + for(uint16_t year = 1970; year < time.year; year++) + epoch += (time.is_leap_year() ? DAYS_PER_LEAP_YEAR : DAYS_PER_YEAR); + + + // Add the number of days in the current year + for(uint8_t month = 0; month < time.month - 1; month++) + epoch += DAYS_IN_MONTH[month]; + + // Add the number of days in the current month + epoch += time.day - 1; + + // Add the number of hours + epoch *= 24; + epoch += time.hour; + + // Add the number of minutes + epoch *= 60; + epoch += time.minute; + + // Add the number of seconds + epoch *= 60; + epoch += time.second; + + return epoch; + } } + #endif //MAXOS_COMMON_TIME_H diff --git a/kernel/include/common/vector.h b/kernel/include/common/vector.h index 37928c6c..dbf962c1 100644 --- a/kernel/include/common/vector.h +++ b/kernel/include/common/vector.h @@ -9,512 +9,510 @@ #ifndef MAXOS_COMMON_VECTOR_H #define MAXOS_COMMON_VECTOR_H -#include -#include - -namespace MaxOS { - - namespace common { - - /** - * @class VectorIterationHandler - * @brief Handles the iteration of a Vector providing read and end of stream functions - * - * @tparam Type Type of the Vector - */ - template class VectorIterationHandler { - public: - VectorIterationHandler(); - ~VectorIterationHandler(); - - virtual void on_read(Type); - virtual void on_end_of_stream(); - }; - - /** - * @class Vector - * @brief Dynamically stores an array of elements - * - * @tparam Type Type of the Vector - */ - template class Vector { - protected: - Type* m_elements; ///< The array of elements - uint32_t m_size { 0 }; ///< How many elements are currently stored - uint32_t m_capacity { 1 }; ///< How many elements can be stored without resizing - - public: - typedef Type* iterator; ///< The iterator type for the Vector - - Vector(); - Vector(int Size, Type element); - Vector(const Vector& other); - Vector(Vector&& other); - ~Vector(); - - Type& operator [](uint32_t index) const; - Vector& operator =(const Vector& other); - Vector& operator =(Vector&& other); - - [[nodiscard]] bool empty() const; - [[nodiscard]] uint32_t size() const; - - iterator begin() const; - iterator end() const; - iterator find(Type) const; - - iterator push_back(Type); - Type pop_back(); - - iterator push_front(Type); - Type pop_front(); - - void erase(Type); - void erase(typename Vector::iterator position); - void clear(); - - void reserve(size_t amount); - void increase_size(); - - void iterate(VectorIterationHandler*); - void Iterate(void callback(Type&)); - }; - - ///______________________________________Implementation__________________________________________________ - /** - * @brief Constructor for Vector - * - * @tparam Type Type of the Vector - */ - template Vector::Vector() { - - // Allocate space for the array - m_elements = new Type[m_capacity]; +#include +#include + + +namespace MaxOS::common { + + /** + * @class VectorIterationHandler + * @brief Handles the iteration of a Vector providing read and end of stream functions + * + * @tparam Type Type of the Vector + */ + template class VectorIterationHandler { + public: + VectorIterationHandler(); + ~VectorIterationHandler() = default; + + virtual void on_read(Type); + virtual void on_end_of_stream(); + }; + + /** + * @class Vector + * @brief Dynamically stores an array of elements + * + * @tparam Type Type of the Vector + */ + template class Vector { + protected: + Type* m_elements; ///< The array of elements + uint32_t m_size { 0 }; ///< How many elements are currently stored + uint32_t m_capacity { 1 }; ///< How many elements can be stored without resizing + + public: + typedef Type* iterator; ///< The iterator type for the Vector + + Vector(); + Vector(int size, Type element); + Vector(const Vector& other); + Vector(Vector&& other); + ~Vector(); + + Type& operator [](uint32_t index) const; + Vector& operator =(const Vector& other); + Vector& operator =(Vector&& other); + + [[nodiscard]] bool empty() const; + [[nodiscard]] uint32_t size() const; + + iterator begin() const; + iterator end() const; + iterator find(Type) const; + + iterator push_back(Type); + Type pop_back(); + + iterator push_front(Type); + Type pop_front(); + + void erase(Type); + void erase(typename Vector::iterator position); + void clear(); + + void reserve(size_t amount); + void increase_size(); + + void iterate(VectorIterationHandler*); + void iterate(void callback(Type&)); + }; + + ///______________________________________Implementation__________________________________________________ + /** + * @brief Constructor for Vector + * + * @tparam Type Type of the Vector + */ + template Vector::Vector() { + + // Allocate space for the array + m_elements = new Type[m_capacity]; - } - - /** - * @brief Constructor for Vector - * - * @tparam Type Type of the Vector - * @param size Size of the Vector - * @param element Element to fill the Vector with - */ - template Vector::Vector(int size, Type element) { - - // Allocate space for the array - m_elements = new Type[size]; - m_capacity = size > 0 ? size : 1; - m_size = 0; - - // Push all the elements to the Vector - for (int i = 0; i < size; ++i) - push_back(element); - } + } - /** - * @brief Copy constructor for Vector - * - * @tparam Type The type of data to be stored - * @param other The vector to copy from - */ - template Vector::Vector(const Vector& other) - : m_size(other.m_size), - m_capacity(other.m_capacity) { - // Copy each element into a new array - m_elements = new Type[m_capacity]; - for (uint32_t i = 0; i < m_size; ++i) - m_elements[i] = other.m_elements[i]; - } + /** + * @brief Constructor for Vector + * + * @tparam Type Type of the Vector + * @param size Size of the Vector + * @param element Element to fill the Vector with + */ + template Vector::Vector(int size, Type element) { + + // Allocate space for the array + m_elements = new Type[size]; + m_capacity = size > 0 ? size : 1; + m_size = 0; + + // Push all the elements to the Vector + for(int i = 0; i < size; ++i) + push_back(element); + } - /** - * @brief Move constructor for Vector - * - * @tparam Type The type of data to be stored - * @param other The vector to copy from - */ - template Vector::Vector(Vector&& other) - : m_elements(other.m_elements), - m_size(other.m_size), - m_capacity(other.m_capacity) { - - // Clear the other Vector - other.m_elements = nullptr; - other.m_size = 0; - other.m_capacity = 0; + /** + * @brief Copy constructor for Vector + * + * @tparam Type The type of data to be stored + * @param other The vector to copy from + */ + template Vector::Vector(const Vector& other) + : m_size(other.m_size), + m_capacity(other.m_capacity) { + // Copy each element into a new array + m_elements = new Type[m_capacity]; + for(uint32_t i = 0; i < m_size; ++i) + m_elements[i] = other.m_elements[i]; + } - } + /** + * @brief Move constructor for Vector + * + * @tparam Type The type of data to be stored + * @param other The vector to copy from + */ + template Vector::Vector(Vector&& other) + : m_elements(other.m_elements), + m_size(other.m_size), + m_capacity(other.m_capacity) { + + // Clear the other Vector + other.m_elements = nullptr; + other.m_size = 0; + other.m_capacity = 0; - /** - * @brief Destructor for Vector, de-allocates the array - * - * @tparam Type Type data stored in the Vector - */ - template Vector::~Vector() { + } - // De-allocate the array - delete[] m_elements; + /** + * @brief Destructor for Vector, de-allocates the array + * + * @tparam Type Type data stored in the Vector + */ + template Vector::~Vector() { - } + // De-allocate the array + delete[] m_elements; - /** - * @brief Increases the size of the Vector by doubling the capacity - * - * @tparam Type Type of the Vector - */ - template void Vector::increase_size() { - reserve(m_capacity * 2); - } + } - /** - * @brief Reserves space in the Vector for a certain amount of elements - * - * @tparam Type Type of the Vector - * @param amount The amount of elements to reserve space for - */ - template void Vector::reserve(size_t amount) { + /** + * @brief Increases the size of the Vector by doubling the capacity + * + * @tparam Type Type of the Vector + */ + template void Vector::increase_size() { + reserve(m_capacity * 2); + } + /** + * @brief Reserves space in the Vector for a certain amount of elements + * + * @tparam Type Type of the Vector + * @param amount The amount of elements to reserve space for + */ + template void Vector::reserve(size_t amount) { - // Increase the capacity of the Vector - if (m_capacity < amount) - m_capacity = amount; - // Allocate more space for the array - Type* new_elements = new Type[amount]; + // Increase the capacity of the Vector + if(m_capacity < amount) + m_capacity = amount; - // Copy the elements to the new array - for (uint32_t i = 0; i < m_size; ++i) - new_elements[i] = m_elements[i]; + // Allocate more space for the array + Type* new_elements = new Type[amount]; - // De-allocate the old array - delete[] m_elements; + // Copy the elements to the new array + for(uint32_t i = 0; i < m_size; ++i) + new_elements[i] = m_elements[i]; - // Set the new array - m_elements = new_elements; - } + // De-allocate the old array + delete[] m_elements; + // Set the new array + m_elements = new_elements; + } - /** - * @brief Overloads the [] operator to return the element at the index - * - * @tparam Type Type of the Vector - * @param index The index of the element - * @return the element at the index or the end of the Vector if the index is out of bounds - */ - template Type& Vector::operator [](uint32_t index) const { - // If the index is in the Vector - if (index < m_size) - return m_elements[index]; + /** + * @brief Overloads the [] operator to return the element at the index + * + * @tparam Type Type of the Vector + * @param index The index of the element + * @return the element at the index or the end of the Vector if the index is out of bounds + */ + template Type& Vector::operator [](uint32_t index) const { - // Return the last element of the Vector - return m_elements[m_size - 1]; + // If the index is in the Vector + if(index < m_size) + return m_elements[index]; - } + // Return the last element of the Vector + return m_elements[m_size - 1]; - /** - * @brief Assignment by copy, data is copied into a new buffer stored in this vector - * - * @tparam Type Type of the Vector - * @param other The vector to copy from - * @return This vector, with the copied elements - */ - template Vector& Vector::operator =(const Vector& other) { - - // Setting to itself? - if (this == &other) - return *this; - - // Create a new buffer to store the elements - delete[] m_elements; - m_elements = new Type[other.m_capacity]; - - // Copy data - m_size = other.m_size; - m_capacity = other.m_capacity; - for (uint32_t i = 0; i < m_size; ++i) - m_elements[i] = other.m_elements[i]; + } + /** + * @brief Assignment by copy, data is copied into a new buffer stored in this vector + * + * @tparam Type Type of the Vector + * @param other The vector to copy from + * @return This vector, with the copied elements + */ + template Vector& Vector::operator =(const Vector& other) { + + // Setting to itself? + if(this == &other) return *this; - } - /** - * @brief Assignment by move, data is moved into the buffer stored in this vector and the other vector is cleared - * - * @tparam Type Type of the Vector - * @param other The vector to copy from - * @return This vector, with the copied elements - */ - template Vector& Vector::operator =(Vector&& other) noexcept { - - // Moving to itself? - if (this == &other) - return *this; - - // Move into this vector - delete[] m_elements; - m_elements = other.m_elements; - m_size = other.m_size; - m_capacity = other.m_capacity; - - // Remove from other vector - other.m_elements = nullptr; - other.m_size = 0; - other.m_capacity = 0; + // Create a new buffer to store the elements + delete[] m_elements; + m_elements = new Type[other.m_capacity]; + + // Copy data + m_size = other.m_size; + m_capacity = other.m_capacity; + for(uint32_t i = 0; i < m_size; ++i) + m_elements[i] = other.m_elements[i]; + return *this; + } + + /** + * @brief Assignment by move, data is moved into the buffer stored in this vector and the other vector is cleared + * + * @tparam Type Type of the Vector + * @param other The vector to copy from + * @return This vector, with the copied elements + */ + template Vector& Vector::operator =(Vector&& other) { + + // Moving to itself? + if(this == &other) return *this; - } - /** - * @brief Returns the number of elements in the Vector - * - * @tparam Type Type of the Vector - * @return The size of the Vector - */ - template uint32_t Vector::size() const { - return m_size; - } + // Move into this vector + delete[] m_elements; + m_elements = other.m_elements; + m_size = other.m_size; + m_capacity = other.m_capacity; - /** - * @brief Returns the first element of the Vector - * - * @tparam Type Type of the Vector - * @return The first element of the Vector - */ - template typename Vector::iterator Vector::begin() const { - return &m_elements[0]; - } + // Remove from other vector + other.m_elements = nullptr; + other.m_size = 0; + other.m_capacity = 0; - /** - * @brief Returns the last element of the Vector - * - * @tparam Type Type of the Vector - * @return The last element of the Vector - */ - template typename Vector::iterator Vector::end() const { - return &m_elements[0] + m_size; - } + return *this; + } - /** - * @brief Finds an element in the Vector and returns the iterator of the element - * - * @tparam Type Type of the Vector - * @param element The element to find - * @return The iterator of the element or the end of the Vector if the element is not found - */ - template typename Vector::iterator Vector::find(Type element) const { - - // Find the element - for (iterator i = begin(); i != end(); ++i) - if (*i == element) - return i; - - // The element must not be in the Vector - return end(); - } + /** + * @brief Returns the number of elements in the Vector + * + * @tparam Type Type of the Vector + * @return The size of the Vector + */ + template uint32_t Vector::size() const { + return m_size; + } - /** - * @brief Checks if the Vector is empty - * - * @tparam Type Type of the Vector - * @return True if the Vector is empty, false otherwise - */ - template bool Vector::empty() const { - return begin() == end(); - } + /** + * @brief Returns the first element of the Vector + * + * @tparam Type Type of the Vector + * @return The first element of the Vector + */ + template typename Vector::iterator Vector::begin() const { + return &m_elements[0]; + } + /** + * @brief Returns the last element of the Vector + * + * @tparam Type Type of the Vector + * @return The last element of the Vector + */ + template typename Vector::iterator Vector::end() const { + return &m_elements[0] + m_size; + } - /** - * @brief Adds an element to the end of the vector and returns the iterator of the element - * - * @tparam Type Type of the Vector - * @param element The element to add - * @return The iterator of the element, if the Vector is full it returns the end of the Vector - */ - template typename Vector::iterator Vector::push_back(Type element) { + /** + * @brief Finds an element in the Vector and returns the iterator of the element + * + * @tparam Type Type of the Vector + * @param element The element to find + * @return The iterator of the element or the end of the Vector if the element is not found + */ + template typename Vector::iterator Vector::find(Type element) const { + + // Find the element + for(iterator i = begin(); i != end(); ++i) + if(*i == element) + return i; + + // The element must not be in the Vector + return end(); + } - // Check if we need to allocate more space for the array - if (m_size == m_capacity) - increase_size(); + /** + * @brief Checks if the Vector is empty + * + * @tparam Type Type of the Vector + * @return True if the Vector is empty, false otherwise + */ + template bool Vector::empty() const { + return begin() == end(); + } - // Add the element to the Vector and return the iterator of the element - m_elements[m_size++] = element; - return end() - 1; - } - /** - * @brief Removes the last element from the Vector - * @tparam Type Type of the Vector - * - * @return The element that was removed - */ - template Type Vector::pop_back() { + /** + * @brief Adds an element to the end of the vector and returns the iterator of the element + * + * @tparam Type Type of the Vector + * @param element The element to add + * @return The iterator of the element, if the Vector is full it returns the end of the Vector + */ + template typename Vector::iterator Vector::push_back(Type element) { - // Remove the last element from the Vector - if (m_size > 0) - --m_size; + // Check if we need to allocate more space for the array + if(m_size == m_capacity) + increase_size(); - return m_elements[m_size]; - } + // Add the element to the Vector and return the iterator of the element + m_elements[m_size++] = element; + return end() - 1; + } - /** - * @brief Adds an element to the front of the Vector and returns the iterator of the element - * - * @tparam Type Type of the Vector - * @param element The element to add - * @return The iterator of the element, if the Vector is full it returns the end of the Vector - */ - template typename Vector::iterator Vector::push_front(Type element) { - - // Check if we need to allocate more space for the array - if (m_size == m_capacity) - increase_size(); - - // Move all elements one index to the right - for (iterator i = end(); i > begin(); --i) - *i = *(i - 1); - - // Add the element to the front of the Vector - m_elements[0] = element; - ++m_size; - - // Return the iterator of the element - return begin(); - } + /** + * @brief Removes the last element from the Vector + * @tparam Type Type of the Vector + * + * @return The element that was removed + */ + template Type Vector::pop_back() { - /** - * @brief Removes the m_first_memory_chunk element from the Vector - * - * @tparam Type Type of the Vector - * @return The element that was removed, or a default constructed element if the Vector is empty - */ - template Type Vector::pop_front() { + // Remove the last element from the Vector + if(m_size > 0) + --m_size; - // Make sure the Vector is not empty - if (m_size == 0) - return Type(); + return m_elements[m_size]; + } - // Store the element to return + /** + * @brief Adds an element to the front of the Vector and returns the iterator of the element + * + * @tparam Type Type of the Vector + * @param element The element to add + * @return The iterator of the element, if the Vector is full it returns the end of the Vector + */ + template typename Vector::iterator Vector::push_front(Type element) { + + // Check if we need to allocate more space for the array + if(m_size == m_capacity) + increase_size(); + + // Move all elements one index to the right + for(iterator i = end(); i > begin(); --i) + *i = *(i - 1); + + // Add the element to the front of the Vector + m_elements[0] = element; + ++m_size; + + // Return the iterator of the element + return begin(); + } - Type element = m_elements[0]; + /** + * @brief Removes the m_first_memory_chunk element from the Vector + * + * @tparam Type Type of the Vector + * @return The element that was removed, or a default constructed element if the Vector is empty + */ + template Type Vector::pop_front() { - // Move all elements one index to the left - for (uint32_t i = 0; i < m_size - 1; ++i) - m_elements[i] = m_elements[i + 1]; + // Make sure the Vector is not empty + if(m_size == 0) + return Type(); - // Decrease the size of the Vector - --m_size; - return element; - } + // Store the element to return - /** - * @brief Removes all elements from the Vector that are equal to the element - * - * @tparam Type Type of the Vector - * @param element The element to remove - */ - template void Vector::erase(Type element) { - - // Search for the element - int hits = 0; - for (iterator i = begin(); i != end(); ++i) { - // If it is the element we are looking for - if (*i == element) { - ++hits; - } else { - - // If there are hits move the element to the left - if (hits > 0) - *(i - hits) = *i; - } + Type element = m_elements[0]; + + // Move all elements one index to the left + for(uint32_t i = 0; i < m_size - 1; ++i) + m_elements[i] = m_elements[i + 1]; + + // Decrease the size of the Vector + --m_size; + return element; + } + /** + * @brief Removes all elements from the Vector that are equal to the element + * + * @tparam Type Type of the Vector + * @param element The element to remove + */ + template void Vector::erase(Type element) { + + // Search for the element + int hits = 0; + for(iterator i = begin(); i != end(); ++i) { + // If it is the element we are looking for + if(*i == element) { + ++hits; + } else { + + // If there are hits move the element to the left + if(hits > 0) + *(i - hits) = *i; } - // Decrease the size of the Vector - m_size -= hits; } - /** - * @brief Removes the element at the m_position - * - * @tparam Type The type of the Vector - * @param position The m_position of the element to remove - */ - template void Vector::erase(typename Vector::iterator position) { + // Decrease the size of the Vector + m_size -= hits; + } - // If the m_position is not in the Vector - if (position < begin() || position >= end()) - return; + /** + * @brief Removes the element at the m_position + * + * @tparam Type The type of the Vector + * @param position The m_position of the element to remove + */ + template void Vector::erase(typename Vector::iterator position) { - // Move all elements one index to the left - for (++position; position != end(); ++position) - *(position - 1) = *position; + // If the m_position is not in the Vector + if(position < begin() || position >= end()) + return; - // Decrease the size of the Vector - --m_size; - } + // Move all elements one index to the left + for(++position; position != end(); ++position) + *(position - 1) = *position; - /** - * @brief Removes all elements from the Vector - * - * @tparam Type Type of the Vector - */ - template void Vector::clear() { - m_size = 0; - } + // Decrease the size of the Vector + --m_size; + } - /** - * @brief Iterates over the Vector and calls the OnRead function of the handler for each element - * - * @tparam Type Type of the Vector - * @param vector_iteration_handler The handler - */ - template void Vector::iterate(VectorIterationHandler* vector_iteration_handler) { + /** + * @brief Removes all elements from the Vector + * + * @tparam Type Type of the Vector + */ + template void Vector::clear() { + m_size = 0; + } - // Call the OnRead function of the handler for each element - for (auto& element : m_elements) - vector_iteration_handler->on_read(element); + /** + * @brief Iterates over the Vector and calls the OnRead function of the handler for each element + * + * @tparam Type Type of the Vector + * @param vector_iteration_handler The handler + */ + template void Vector::iterate(VectorIterationHandler* vector_iteration_handler) { - // Call the OnEndOfStream function of the handler - vector_iteration_handler->on_end_of_stream(); - } + // Call the OnRead function of the handler for each element + for(auto& element : m_elements) + vector_iteration_handler->on_read(element); + // Call the OnEndOfStream function of the handler + vector_iteration_handler->on_end_of_stream(); + } - /** - * @brief Iterates over the Vector and calls the callback function for each element - * - * @tparam Type Type of the Vector - * @param callback The callback function - */ - template void Vector::Iterate(void callback(Type&)) { - // Call the callback function for each element - for (auto& element : m_elements) - callback(element); - } + /** + * @brief Iterates over the Vector and calls the callback function for each element + * + * @tparam Type Type of the Vector + * @param callback The callback function + */ + template void Vector::iterate(void callback(Type&)) { - template VectorIterationHandler::VectorIterationHandler() = default; + // Call the callback function for each element + for(auto& element : m_elements) + callback(element); + } - template VectorIterationHandler::~VectorIterationHandler() = default; + template VectorIterationHandler::VectorIterationHandler() = default; - /** - * @brief Called when the end of the stream is reached (overridden by subclasses, no default behavior) - * - * @tparam Type Type of the values stored in the Vector - */ - template void VectorIterationHandler::on_end_of_stream() { - } - /** - * @brief Called when an element is read from the Vector (overridden by subclasses, no default behavior) - * - * @tparam Type Type of the values stored in the Vector - */ - template void VectorIterationHandler::on_read(Type) { + /** + * @brief Called when the end of the stream is reached (overridden by subclasses, no default behavior) + * + * @tparam Type Type of the values stored in the Vector + */ + template void VectorIterationHandler::on_end_of_stream() { + + } + + /** + * @brief Called when an element is read from the Vector (overridden by subclasses, no default behavior) + * + * @tparam Type Type of the values stored in the Vector + */ + template void VectorIterationHandler::on_read(Type) { - } } } diff --git a/kernel/include/drivers/clock/clock.h b/kernel/include/drivers/clock/clock.h index 896ec22f..229d54ea 100644 --- a/kernel/include/drivers/clock/clock.h +++ b/kernel/include/drivers/clock/clock.h @@ -9,7 +9,7 @@ #ifndef MAXOS_DRIVERS_CLOCK_CLOCK_H #define MAXOS_DRIVERS_CLOCK_CLOCK_H -#include +#include #include #include #include @@ -17,162 +17,157 @@ #include #include -namespace MaxOS { - - namespace drivers { - - namespace clock { - - /** - * @enum Channel - * @brief Where should the PIT raise an event to - * - * @warning DRAM_REFRESH may not exist on all systems - */ - enum class Channel { - INTERRUPT, - DRAM_REFRESH, - SPEAKER, - }; - - /** - * @enum AccessMode - * @brief What mode should the PIT use for the selected channel - */ - enum class AccessMode { - LATCH_COUNT, - LOW_BYTE, - HIGH_BYTE, - LOW_HIGH_BYTE, - }; - - /** - * @enum OperatingMode - * @brief What should the PIT do - */ - enum class OperatingMode { - INTERRUPT_ON_TERMINAL_COUNT, - ONE_SHOT, - RATE_GENERATOR, - SQUARE_WAVE, - SOFTWARE_STROBE, - HARDWARE_STROBE, - }; - - /** - * @enum BCDMode - * @brief Specifies the data encoding mode used by the PIT - */ - enum class BCDMode { - BINARY, - BCD, - }; - - /** - * @struct PITCommand - * @brief The command byte to send to the PIT, specifies the channel, access mode, operating mode and BCD mode - * - * @typedef pit_command_t - * @brief Alias for PITCommand struct - */ - typedef struct PITCommand { - - uint8_t bcd_mode: 1; ///< 0 = binary, 1 = BCD - uint8_t operating_mode: 3; ///< What mode the PIT should operate in - uint8_t access_mode: 2; ///< How the data is accessed - uint8_t channel: 2; ///< Which channel to configure - - } pit_command_t; - - - // Forward declaration - class Clock; - - /// How many loops to spin for calibration - constexpr uint16_t TICK_CALIBRATE_LENGTH = 10; - - /** - * @class PIT - * @brief Driver for the Programmable Interval Timer - */ - class PIT : public hardwarecommunication::InterruptHandler { - friend Clock; - - private: - uint64_t m_ticks { 0 }; - - // Ports - hardwarecommunication::Port8Bit m_data_port; - hardwarecommunication::Port8Bit m_command_port; - - // APIC - hardwarecommunication::LocalAPIC* m_local_apic; - hardwarecommunication::IOAPIC* m_io_apic; - - // Funcs - void handle_interrupt() final; - uint32_t ticks_per_ms(); - - public: - PIT(hardwarecommunication::AdvancedProgrammableInterruptController* apic); - ~PIT(); - - }; - - /** - * @class Clock - * @brief Driver for the APIC clock - */ - class Clock : public Driver, public hardwarecommunication::InterruptHandler{ - private: - - uint64_t m_ticks { 0 }; - - bool m_binary = true; - bool m_24_hour_clock = true; - - // Ports - hardwarecommunication::Port8Bit m_data_port { 0x71 }; - hardwarecommunication::Port8Bit m_command_port { 0x70 }; - - // APIC - hardwarecommunication::AdvancedProgrammableInterruptController* m_apic; - - // Time between events - uint16_t m_ticks_between_events = 0; - uint16_t m_ticks_until_next_event = 1; - uint64_t m_pit_ticks_per_ms = 0; - - // Other functions - void handle_interrupt() final; - uint8_t read_hardware_clock(uint8_t address); - [[nodiscard]] uint8_t binary_representation(uint8_t number) const; - - inline static Clock* s_active_clock = nullptr; - - public: - Clock(hardwarecommunication::AdvancedProgrammableInterruptController* apic, uint16_t time_between_events = 10); - ~Clock(); - /// How accurate the clock is in microseconds (how often should an interrupt be raised) - uint64_t clock_accuracy = 1; +namespace MaxOS::drivers::clock { + + /** + * @enum Channel + * @brief Where should the PIT raise an event to + * + * @warning DRAM_REFRESH may not exist on all systems + */ + enum class Channel { + INTERRUPT, + DRAM_REFRESH, + SPEAKER, + }; + + /** + * @enum AccessMode + * @brief What mode should the PIT use for the selected channel + */ + enum class AccessMode { + LATCH_COUNT, + LOW_BYTE, + HIGH_BYTE, + LOW_HIGH_BYTE, + }; + + /** + * @enum OperatingMode + * @brief What should the PIT do + */ + enum class OperatingMode { + INTERRUPT_ON_TERMINAL_COUNT, + ONE_SHOT, + RATE_GENERATOR, + SQUARE_WAVE, + SOFTWARE_STROBE, + HARDWARE_STROBE, + }; + + /** + * @enum BCDMode + * @brief Specifies the data encoding mode used by the PIT + */ + enum class BCDMode { + BINARY, + BCD, + }; + + /** + * @struct PITCommand + * @brief The command byte to send to the PIT, specifies the channel, access mode, operating mode and BCD mode + * + * @typedef pit_command_t + * @brief Alias for PITCommand struct + */ + typedef struct PITCommand { + + uint8_t bcd_mode : 1; ///< 0 = binary, 1 = BCD + uint8_t operating_mode : 3; ///< What mode the PIT should operate in + uint8_t access_mode : 2; ///< How the data is accessed + uint8_t channel : 2; ///< Which channel to configure + + } pit_command_t; + + + // Forward declaration + class Clock; + + /// How many loops to spin for calibration + constexpr uint16_t TICK_CALIBRATE_LENGTH = 10; + + /** + * @class PIT + * @brief Driver for the Programmable Interval Timer + */ + class PIT : public hardwarecommunication::InterruptHandler { + friend Clock; + + private: + uint64_t m_ticks { 0 }; + + // Ports + hardwarecommunication::Port8Bit m_data_port; + hardwarecommunication::Port8Bit m_command_port; + + // APIC + hardwarecommunication::LocalAPIC* m_local_apic; + hardwarecommunication::IOAPIC* m_io_apic; + + // Funcs + void handle_interrupt() final; + uint32_t ticks_per_ms(); + + public: + explicit PIT(hardwarecommunication::AdvancedProgrammableInterruptController* apic); + ~PIT(); + + }; + + /** + * @class Clock + * @brief Driver for the APIC clock + */ + class Clock : public Driver, public hardwarecommunication::InterruptHandler { + private: + + uint64_t m_ticks { 0 }; + + bool m_binary = true; + bool m_24_hour_clock = true; + + // Ports + hardwarecommunication::Port8Bit m_data_port { 0x71 }; + hardwarecommunication::Port8Bit m_command_port { 0x70 }; + + // APIC + hardwarecommunication::AdvancedProgrammableInterruptController* m_apic; + + // Time between events + uint16_t m_ticks_between_events = 0; + uint16_t m_ticks_until_next_event = 1; + uint64_t m_pit_ticks_per_ms = 0; + + // Other functions + void handle_interrupt() final; + uint8_t read_hardware_clock(uint8_t address); + [[nodiscard]] uint8_t binary_representation(uint8_t number) const; + + inline static Clock* s_active_clock = nullptr; + + public: + explicit Clock(hardwarecommunication::AdvancedProgrammableInterruptController* apic, uint16_t time_between_events = 10); + ~Clock(); - void activate() override; - void delay(uint32_t milliseconds) const; + /// How accurate the clock is in microseconds (how often should an interrupt be raised) + uint64_t clock_accuracy = 1; - void calibrate(uint64_t ms_per_tick = 1); - void setup_apic_clock(hardwarecommunication::LocalAPIC* local_apic) const; + void activate() override; + void delay(uint32_t milliseconds) const; - string vendor_name() final; - string device_name() final; + void calibrate(uint64_t ms_per_tick = 1); + void setup_apic_clock(hardwarecommunication::LocalAPIC* local_apic) const; - static Clock* active_clock(); - common::time_t get_time(); - }; + string vendor_name() final; + string device_name() final; - } + static Clock* active_clock(); + common::time_t get_time(); + }; - } } + #endif //MAXOS_DRIVERS_CLOCK_CLOCK_H diff --git a/kernel/include/drivers/console/console.h b/kernel/include/drivers/console/console.h index f9c59026..4ae38392 100644 --- a/kernel/include/drivers/console/console.h +++ b/kernel/include/drivers/console/console.h @@ -9,110 +9,106 @@ #ifndef MAXOS_DRIVERS_CONSOLE_H #define MAXOS_DRIVERS_CONSOLE_H -#include +#include #include #include -namespace MaxOS { - namespace drivers { +namespace MaxOS::drivers::console { - namespace console { + /** + * @class Console + * @brief Abstract class for a console, allows for the printing of characters and strings with colours + */ + class Console { + public: + Console(); + ~Console(); - /** - * @class Console - * @brief Abstract class for a console, allows for the printing of characters and strings with colours - */ - class Console { - public: - Console(); - ~Console(); + virtual uint16_t width(); + virtual uint16_t height(); - virtual uint16_t width(); - virtual uint16_t height(); + virtual void put_character(uint16_t x, uint16_t y, char c); + virtual char get_character(uint16_t x, uint16_t y); - virtual void put_character(uint16_t x, uint16_t y, char c); - virtual char get_character(uint16_t x, uint16_t y); + virtual void set_foreground_color(uint16_t x, uint16_t y, common::ConsoleColour foreground); + virtual void set_background_color(uint16_t x, uint16_t y, common::ConsoleColour background); - virtual void set_foreground_color(uint16_t x, uint16_t y, common::ConsoleColour foreground); - virtual void set_background_color(uint16_t x, uint16_t y, common::ConsoleColour background); + virtual common::ConsoleColour get_foreground_color(uint16_t x, uint16_t y); + virtual common::ConsoleColour get_background_color(uint16_t x, uint16_t y); - virtual common::ConsoleColour get_foreground_color(uint16_t x, uint16_t y); - virtual common::ConsoleColour get_background_color(uint16_t x, uint16_t y); + virtual void put_character(uint16_t x, uint16_t y, char c, common::ConsoleColour foreground, common::ConsoleColour background); + virtual void put_string(uint16_t x, uint16_t y, string s, common::ConsoleColour foreground = common::ConsoleColour::LightGrey, common::ConsoleColour background = common::ConsoleColour::Black); - virtual void put_character(uint16_t x, uint16_t y, char c, common::ConsoleColour foreground, common::ConsoleColour background); - virtual void put_string(uint16_t x, uint16_t y, string s, common::ConsoleColour foreground = common::ConsoleColour::LightGrey, common::ConsoleColour background = common::ConsoleColour::Black); + virtual void scroll_up(); + virtual void scroll_up(uint16_t left, uint16_t top, uint16_t width, uint16_t height, common::ConsoleColour foreground = common::ConsoleColour::LightGrey, common::ConsoleColour background = common::ConsoleColour::Black, char fill = ' '); - virtual void scroll_up(); - virtual void scroll_up(uint16_t left, uint16_t top, uint16_t width, uint16_t height, common::ConsoleColour foreground = common::ConsoleColour::LightGrey, common::ConsoleColour background = common::ConsoleColour::Black, char fill = ' '); + virtual void clear(); + virtual void clear(uint16_t left, uint16_t top, uint16_t width, uint16_t height, common::ConsoleColour foreground = common::ConsoleColour::LightGrey, common::ConsoleColour background = common::ConsoleColour::Black, char fill = ' '); - virtual void clear(); - virtual void clear(uint16_t left, uint16_t top, uint16_t width, uint16_t height, common::ConsoleColour foreground = common::ConsoleColour::LightGrey, common::ConsoleColour background = common::ConsoleColour::Black, char fill = ' '); + virtual void invert_colors(uint16_t x, uint16_t y); - virtual void invert_colors(uint16_t x, uint16_t y); + }; - }; + /** + * @class ConsoleArea + * @brief A console that is a subsection of another console, limited by a width and height + */ + class ConsoleArea : public Console { + private: + Console* m_console; + uint16_t m_left; + uint16_t m_top; + uint16_t m_width; + uint16_t m_height; - /** - * @class ConsoleArea - * @brief A console that is a subsection of another console, limited by a width and height - */ - class ConsoleArea : public Console { - private: - Console* m_console; - uint16_t m_left; - uint16_t m_top; - uint16_t m_width; - uint16_t m_height; + public: + ConsoleArea(Console* console, uint16_t left, uint16_t top, uint16_t width, uint16_t height); + ConsoleArea(Console* console, uint16_t left, uint16_t top, uint16_t width, uint16_t height, common::ConsoleColour foreground, common::ConsoleColour background); + ~ConsoleArea(); - public: - ConsoleArea(Console* console, uint16_t left, uint16_t top, uint16_t width, uint16_t height); - ConsoleArea(Console* console, uint16_t left, uint16_t top, uint16_t width, uint16_t height, common::ConsoleColour foreground, common::ConsoleColour background); - ~ConsoleArea(); + uint16_t width() override; + uint16_t height() override; - uint16_t width() override; - uint16_t height() override; + void put_character(uint16_t x, uint16_t y, char c) override; + void set_foreground_color(uint16_t x, uint16_t y, common::ConsoleColour foreground) override; + void set_background_color(uint16_t x, uint16_t y, common::ConsoleColour background) override; - void put_character(uint16_t x, uint16_t y, char c) override; - void set_foreground_color(uint16_t x, uint16_t y, common::ConsoleColour foreground) override; - void set_background_color(uint16_t x, uint16_t y, common::ConsoleColour background) override; + void scroll_up() override; + void scroll_up(uint16_t left, uint16_t top, uint16_t width, uint16_t height, common::ConsoleColour foreground = common::ConsoleColour::LightGrey, common::ConsoleColour background = common::ConsoleColour::Black, char fill = ' ') override; - void scroll_up() override; - void scroll_up(uint16_t left, uint16_t top, uint16_t width, uint16_t height, common::ConsoleColour foreground = common::ConsoleColour::LightGrey, common::ConsoleColour background = common::ConsoleColour::Black, char fill = ' ') override; + char get_character(uint16_t x, uint16_t y) override; + common::ConsoleColour get_foreground_color(uint16_t x, uint16_t y) override; + common::ConsoleColour get_background_color(uint16_t x, uint16_t y) override; + }; - char get_character(uint16_t x, uint16_t y) override; - common::ConsoleColour get_foreground_color(uint16_t x, uint16_t y) override; - common::ConsoleColour get_background_color(uint16_t x, uint16_t y) override; - }; + /** + * @class ConsoleStream + * @brief A stream that can be used to write to a console + */ + class ConsoleStream : public common::OutputStream { + private: + Console* m_console; - /** - * @class ConsoleStream - * @brief A stream that can be used to write to a console - */ - class ConsoleStream : public common::OutputStream { - private: - Console* m_console; + common::ConsoleColour m_foreground { common::ConsoleColour::LightGrey }; + common::ConsoleColour m_background { common::ConsoleColour::Black }; + bool is_ansi = false; - common::ConsoleColour m_foreground { common::ConsoleColour::LightGrey }; - common::ConsoleColour m_background { common::ConsoleColour::Black }; - bool is_ansi = false; + uint16_t m_cursor_x { 0 }; + uint16_t m_cursor_y { 0 }; - uint16_t m_cursor_x { 0 }; - uint16_t m_cursor_y { 0 }; + public: - public: + explicit ConsoleStream(Console*); + ~ConsoleStream(); - ConsoleStream(Console*); - ~ConsoleStream(); + void write_char(char c) override; + void set_cursor(uint16_t x, uint16_t y); + }; - void write_char(char c) override; - void set_cursor(uint16_t x, uint16_t y); - }; - - } - } } + #endif //MAXOS_DRIVERS_CONSOLE_H diff --git a/kernel/include/drivers/console/serial.h b/kernel/include/drivers/console/serial.h index 2a4ba2f2..802517f1 100644 --- a/kernel/include/drivers/console/serial.h +++ b/kernel/include/drivers/console/serial.h @@ -13,35 +13,33 @@ #include #include -namespace MaxOS { - namespace drivers { +namespace MaxOS::drivers { - /** - * @class SerialConsole - * @brief A driver for the serial output - */ - class SerialConsole : public Driver, public common::OutputStream { + /** + * @class SerialConsole + * @brief A driver for the serial output + */ + class SerialConsole : public Driver, public common::OutputStream { - private: - hardwarecommunication::Port8Bit m_data_port; - hardwarecommunication::Port8Bit m_interrupt_enable_port; - hardwarecommunication::Port8Bit m_fifo_control_port; - hardwarecommunication::Port8Bit m_line_control_port; - hardwarecommunication::Port8Bit m_modem_control_port; - hardwarecommunication::Port8Bit m_line_status_port; + private: + hardwarecommunication::Port8Bit m_data_port; + hardwarecommunication::Port8Bit m_interrupt_enable_port; + hardwarecommunication::Port8Bit m_fifo_control_port; + hardwarecommunication::Port8Bit m_line_control_port; + hardwarecommunication::Port8Bit m_modem_control_port; + hardwarecommunication::Port8Bit m_line_status_port; - public: - SerialConsole(Logger* logger); - ~SerialConsole(); + public: + explicit SerialConsole(Logger* logger); + ~SerialConsole(); - void put_character(char c); - void write_char(char c) final; + void put_character(char c); + void write_char(char c) final; - }; + }; - } } diff --git a/kernel/include/drivers/console/textmode.h b/kernel/include/drivers/console/textmode.h index 10bd3ef9..99384d64 100644 --- a/kernel/include/drivers/console/textmode.h +++ b/kernel/include/drivers/console/textmode.h @@ -9,42 +9,38 @@ #ifndef MAXOS_DRIVERS_CONSOLE_TEXTMODECONSOLE_H #define MAXOS_DRIVERS_CONSOLE_TEXTMODECONSOLE_H -#include +#include #include #include -namespace MaxOS { - namespace drivers { +namespace MaxOS::drivers::console { - namespace console { + /** + * @class TextModeConsole + * @brief Driver for the text mode console, handles the printing of characters and strings to the screen using VGA + */ + class TextModeConsole : public Driver, public Console { + private: + uint16_t* m_video_memory { (uint16_t*) 0xB8000 }; - /** - * @class TextModeConsole - * @brief Driver for the text mode console, handles the printing of characters and strings to the screen using VGA - */ - class TextModeConsole : public Driver, public Console { - private: - uint16_t* m_video_memory { (uint16_t*) 0xB8000 }; + public: + TextModeConsole(); + ~TextModeConsole(); - public: - TextModeConsole(); - ~TextModeConsole(); + uint16_t width() final; + uint16_t height() final; - uint16_t width() final; - uint16_t height() final; + void put_character(uint16_t x, uint16_t y, char c) final; + void set_foreground_color(uint16_t x, uint16_t y, common::ConsoleColour) final; + void set_background_color(uint16_t x, uint16_t y, common::ConsoleColour) final; - void put_character(uint16_t x, uint16_t y, char c) final; - void set_foreground_color(uint16_t x, uint16_t y, common::ConsoleColour) final; - void set_background_color(uint16_t x, uint16_t y, common::ConsoleColour) final; + char get_character(uint16_t x, uint16_t y) final; + common::ConsoleColour get_foreground_color(uint16_t x, uint16_t y) final; + common::ConsoleColour get_background_color(uint16_t x, uint16_t y) final; + }; - char get_character(uint16_t x, uint16_t y) final; - common::ConsoleColour get_foreground_color(uint16_t x, uint16_t y) final; - common::ConsoleColour get_background_color(uint16_t x, uint16_t y) final; - }; - - } - } } + #endif //MAXOS_DRIVERS_CONSOLE_TEXTMODECONSOLE_H diff --git a/kernel/include/drivers/console/vesaboot.h b/kernel/include/drivers/console/vesaboot.h index a76fdc22..0d4762c4 100644 --- a/kernel/include/drivers/console/vesaboot.h +++ b/kernel/include/drivers/console/vesaboot.h @@ -9,7 +9,7 @@ #ifndef MAXOS_DRIVERS_CONSOLE_VESABOOTCONSOLE_H #define MAXOS_DRIVERS_CONSOLE_VESABOOTCONSOLE_H -#include +#include #include #include #include @@ -20,56 +20,52 @@ #include #include -namespace MaxOS { - namespace drivers { +namespace MaxOS::drivers::console { - namespace console { + /** + * @class VESABootConsole + * @brief Driver for the VESA Console during boot, handles the printing of characters and strings to the screen using VESA protocol + */ + class VESABootConsole : public Driver, public Console { - /** - * @class VESABootConsole - * @brief Driver for the VESA Console during boot, handles the printing of characters and strings to the screen using VESA protocol - */ - class VESABootConsole : public Driver, public Console { + private: + uint16_t* m_video_memory_meta; + inline static common::GraphicsContext* s_graphics_context = nullptr; + ConsoleArea* m_console_area; + gui::Font m_font; - private: - uint16_t* m_video_memory_meta; - inline static common::GraphicsContext* s_graphics_context = nullptr; - ConsoleArea* m_console_area; - gui::Font m_font; + uint8_t ansi_code_length = -1; + char ansi_code[8] = "0000000"; - uint8_t ansi_code_length = -1; - char ansi_code[8] = "0000000"; + common::ConsoleColour m_foreground_color = common::ConsoleColour::Uninitialised; + common::ConsoleColour m_background_color = common::ConsoleColour::Uninitialised; - common::ConsoleColour m_foreground_color = common::ConsoleColour::Uninitialised; - common::ConsoleColour m_background_color = common::ConsoleColour::Uninitialised; + public: + explicit VESABootConsole(common::GraphicsContext*); + ~VESABootConsole(); - public: - VESABootConsole(common::GraphicsContext*); - ~VESABootConsole(); + uint16_t width() final; + uint16_t height() final; - uint16_t width() final; - uint16_t height() final; + ConsoleStream* cout; ///< The boot console output stream + void finish() const; - ConsoleStream* cout; ///< The boot console output stream - void finish(); + void put_character(uint16_t x, uint16_t y, char) final; + void set_foreground_color(uint16_t x, uint16_t y, common::ConsoleColour) final; + void set_background_color(uint16_t x, uint16_t y, common::ConsoleColour) final; - void put_character(uint16_t x, uint16_t y, char) final; - void set_foreground_color(uint16_t x, uint16_t y, common::ConsoleColour) final; - void set_background_color(uint16_t x, uint16_t y, common::ConsoleColour) final; + void scroll_up(uint16_t left, uint16_t top, uint16_t width, uint16_t height, common::ConsoleColour foreground, common::ConsoleColour background, char fill) final; - void scroll_up(uint16_t left, uint16_t top, uint16_t width, uint16_t height, common::ConsoleColour foreground, common::ConsoleColour background, char fill) final; + char get_character(uint16_t x, uint16_t y) final; + common::ConsoleColour get_foreground_color(uint16_t x, uint16_t y) final; + common::ConsoleColour get_background_color(uint16_t x, uint16_t y) final; - char get_character(uint16_t x, uint16_t y) final; - common::ConsoleColour get_foreground_color(uint16_t x, uint16_t y) final; - common::ConsoleColour get_background_color(uint16_t x, uint16_t y) final; + static void print_logo(bool is_panic = false); + static void update_progress_bar(uint8_t percentage); + }; - static void print_logo(bool is_panic = false); - static void update_progress_bar(uint8_t percentage); - }; - - } - } } + #endif //MAXOS_DRIVERS_CONSOLE_VESABOOTCONSOLE_H diff --git a/kernel/include/drivers/disk/ata.h b/kernel/include/drivers/disk/ata.h index 1d3eec5e..ecdf858e 100644 --- a/kernel/include/drivers/disk/ata.h +++ b/kernel/include/drivers/disk/ata.h @@ -13,48 +13,43 @@ #include #include #include -#include - - -namespace MaxOS{ - - namespace drivers{ - - namespace disk{ - - /** - * @class AdvancedTechnologyAttachment - * @brief Driver for the ATA controller, handles the reading and writing of data to the hard drive - */ - class AdvancedTechnologyAttachment : public Disk { - - private: - hardwarecommunication::Port16Bit m_data_port; - hardwarecommunication::Port8Bit m_error_port; - hardwarecommunication::Port8Bit m_sector_count_port; - hardwarecommunication::Port8Bit m_LBA_low_port; - hardwarecommunication::Port8Bit m_LBA_mid_port; - hardwarecommunication::Port8Bit m_LBA_high_Port; - hardwarecommunication::Port8Bit m_device_port; - hardwarecommunication::Port8Bit m_command_port; - hardwarecommunication::Port8Bit m_control_port; - bool m_is_master; - uint16_t m_bytes_per_sector { 512 }; - - public: - AdvancedTechnologyAttachment(uint16_t port_base, bool master); - virtual ~AdvancedTechnologyAttachment(); - - bool identify(); - void read(uint32_t sector, common::buffer_t* data_buffer, size_t amount) final; - void write(uint32_t sector, common::buffer_t* data, size_t count) final; - void flush() final; - - string device_name() final; - string vendor_name() final; - }; - } - } +#include + + +namespace MaxOS::drivers::disk { + + /** + * @class AdvancedTechnologyAttachment + * @brief Driver for the ATA controller, handles the reading and writing of data to the hard drive + */ + class AdvancedTechnologyAttachment : public Disk { + + private: + hardwarecommunication::Port16Bit m_data_port; + hardwarecommunication::Port8Bit m_error_port; + hardwarecommunication::Port8Bit m_sector_count_port; + hardwarecommunication::Port8Bit m_LBA_low_port; + hardwarecommunication::Port8Bit m_LBA_mid_port; + hardwarecommunication::Port8Bit m_LBA_high_Port; + hardwarecommunication::Port8Bit m_device_port; + hardwarecommunication::Port8Bit m_command_port; + hardwarecommunication::Port8Bit m_control_port; + bool m_is_master; + uint16_t m_bytes_per_sector { 512 }; + + public: + AdvancedTechnologyAttachment(uint16_t port_base, bool master); + virtual ~AdvancedTechnologyAttachment(); + + bool identify(); + void read(uint32_t sector, common::buffer_t* data_buffer, size_t amount) final; + void write(uint32_t sector, common::buffer_t* data, size_t count) final; + void flush() final; + + string device_name() final; + string vendor_name() final; + }; } + #endif //MAXOS_DRIVERS_DISK_ATA_H diff --git a/kernel/include/drivers/disk/disk.h b/kernel/include/drivers/disk/disk.h index 4e2af451..c96ca511 100644 --- a/kernel/include/drivers/disk/disk.h +++ b/kernel/include/drivers/disk/disk.h @@ -12,40 +12,35 @@ #include #include #include -#include +#include -namespace MaxOS{ +namespace MaxOS::drivers::disk { - namespace drivers{ + /** + * @class Disk + * @brief Generic Disk, handles the reading and writing of data to the hard drive + */ + class Disk : public Driver { - namespace disk{ + public: + Disk(); + ~Disk(); - /** - * @class Disk - * @brief Generic Disk, handles the reading and writing of data to the hard drive - */ - class Disk : public Driver { + void read(uint32_t sector, common::buffer_t* data_buffer); + virtual void read(uint32_t sector, common::buffer_t* data_buffer, size_t amount); - public: - Disk(); - ~Disk(); + void write(uint32_t sector, common::buffer_t* data); + virtual void write(uint32_t sector, common::buffer_t* data, size_t count); - void read(uint32_t sector, common::buffer_t* data_buffer); - virtual void read(uint32_t sector, common::buffer_t* data_buffer, size_t amount); + virtual void flush(); - void write(uint32_t sector, common::buffer_t* data); - virtual void write(uint32_t sector, common::buffer_t* data, size_t count); + void activate() override; - virtual void flush(); - - void activate() override; - - string device_name() override; - string vendor_name() override; - }; - } - } + string device_name() override; + string vendor_name() override; + }; } + #endif //MAXOS_DRIVERS_DISK_H diff --git a/kernel/include/drivers/disk/ide.h b/kernel/include/drivers/disk/ide.h index 2364d9ff..4fec3054 100644 --- a/kernel/include/drivers/disk/ide.h +++ b/kernel/include/drivers/disk/ide.h @@ -10,40 +10,34 @@ #define MAXOS_DRIVERS_IDE_H #include -#include +#include #include #include #include -namespace MaxOS { +namespace MaxOS::drivers::disk { - namespace drivers { + /** + * @class IntegratedDriveElectronicsController + * @brief Driver for the IDE controller, handles the creation and management of the IDE devices + */ + class IntegratedDriveElectronicsController : public Driver { + private: + common::Map devices; - namespace disk { + public: + explicit IntegratedDriveElectronicsController(hardwarecommunication::PCIDeviceDescriptor* device_descriptor); + ~IntegratedDriveElectronicsController(); - /** - * @class IntegratedDriveElectronicsController - * @brief Driver for the IDE controller, handles the creation and management of the IDE devices - */ - class IntegratedDriveElectronicsController : public Driver { - private: - common::Map devices; + void initialise() final; + void activate() final; - public: - IntegratedDriveElectronicsController(hardwarecommunication::PCIDeviceDescriptor* device_descriptor); - ~IntegratedDriveElectronicsController(); + string vendor_name() final; + string device_name() final; - void initialise() final; - void activate() final; - string vendor_name() final; - string device_name() final; - - - }; - } - } + }; } diff --git a/kernel/include/drivers/driver.h b/kernel/include/drivers/driver.h index e8935bae..2a4f28a3 100644 --- a/kernel/include/drivers/driver.h +++ b/kernel/include/drivers/driver.h @@ -9,89 +9,89 @@ #ifndef MAX_OS_DRIVERS_DRIVER_H #define MAX_OS_DRIVERS_DRIVER_H -#include +#include #include #include #include #include #include -namespace MaxOS { - namespace drivers { - - - /** - * @class Driver - * @brief base class for all drivers, handles the activation, deactivation, initialisation and reset of the driver as well as error messages and identifying the device - */ - class Driver { - public: - - Driver(); - ~Driver(); - - virtual void activate(); - virtual void deactivate(); - virtual void initialise(); - virtual uint32_t reset(); - - virtual string vendor_name(); - virtual string device_name(); - }; - - //NOTE: Driver doesn't use the EventHandler class because it doesn't need to be connected to anything (May want to change this later) - /** - * @class DriverSelectorEventHandler - * @brief Event handler for the DriverSelector class, handles the event when a driver is selected - */ - class DriverSelectorEventHandler { - public: - DriverSelectorEventHandler(); - ~DriverSelectorEventHandler(); - virtual void on_driver_selected(Driver*); - }; - - /** - * @class DriverSelector - * @brief Selects the drivers to be used - */ - class DriverSelector { - public: - DriverSelector(); - virtual ~DriverSelector(); - virtual void select_drivers(DriverSelectorEventHandler* handler); - }; - - /** - * @class DriverManager - * @brief Manages the drivers, handles the adding and removing of drivers - */ - class DriverManager : public DriverSelectorEventHandler { - private: - - common::Vector m_driver_selectors; - common::Vector m_drivers; - - public: - DriverManager(); - ~DriverManager(); - - void add_driver_selector(DriverSelector*); - void remove_driver_selector(DriverSelector*); - - void add_driver(Driver*); - void remove_driver(Driver*); - void on_driver_selected(Driver*) final; - - void find_drivers(); - uint32_t reset_devices(); - void initialise_drivers(); - void deactivate_drivers(); - void activate_drivers(); - - - }; - } + +namespace MaxOS::drivers { + + + /** + * @class Driver + * @brief base class for all drivers, handles the activation, deactivation, initialisation and reset of the driver as well as error messages and identifying the device + */ + class Driver { + public: + + Driver(); + ~Driver(); + + virtual void activate(); + virtual void deactivate(); + virtual void initialise(); + virtual uint32_t reset(); + + virtual string vendor_name(); + virtual string device_name(); + }; + + //NOTE: Driver doesn't use the EventHandler class because it doesn't need to be connected to anything (May want to change this later) + /** + * @class DriverSelectorEventHandler + * @brief Event handler for the DriverSelector class, handles the event when a driver is selected + */ + class DriverSelectorEventHandler { + public: + DriverSelectorEventHandler(); + ~DriverSelectorEventHandler(); + virtual void on_driver_selected(Driver*); + }; + + /** + * @class DriverSelector + * @brief Selects the drivers to be used + */ + class DriverSelector { + public: + DriverSelector(); + virtual ~DriverSelector(); + virtual void select_drivers(DriverSelectorEventHandler* handler); + }; + + /** + * @class DriverManager + * @brief Manages the drivers, handles the adding and removing of drivers + */ + class DriverManager : public DriverSelectorEventHandler { + private: + + common::Vector m_driver_selectors; + common::Vector m_drivers; + + public: + DriverManager(); + ~DriverManager(); + + void add_driver_selector(DriverSelector*); + void remove_driver_selector(DriverSelector*); + + void add_driver(Driver*); + void remove_driver(Driver*); + void on_driver_selected(Driver*) final; + + void find_drivers(); + uint32_t reset_devices(); + void initialise_drivers(); + void deactivate_drivers(); + void activate_drivers(); + + + }; } + #endif //MAX_OS_DRIVERS_DRIVER_H diff --git a/kernel/include/drivers/ethernet/amd_am79c973.h b/kernel/include/drivers/ethernet/amd_am79c973.h index 586269e1..3a99d18c 100644 --- a/kernel/include/drivers/ethernet/amd_am79c973.h +++ b/kernel/include/drivers/ethernet/amd_am79c973.h @@ -9,124 +9,118 @@ #ifndef MAXOS_DRIVERS_ETHERNET_AMD_AM79C973_H #define MAXOS_DRIVERS_ETHERNET_AMD_AM79C973_H -#include +#include #include #include #include #include #include -namespace MaxOS { - - namespace drivers { - - namespace ethernet { - - /** - * @struct InitializationBlock - * @brief The initialization block for the AMD AM79C973 Ethernet Controller - * - * @typedef initialisation_block_t - * @brief Alias for InitializationBlock struct - */ - typedef struct PACKED InitializationBlock { - - uint16_t mode; ///< The operation mode - unsigned reserved1: 4; ///< Unused, must be zero - unsigned numSendBuffers: 4; ///< How many buffers are used for sending - unsigned reserved2: 4; ///< Unused, must be zero - unsigned numRecvBuffers: 4; ///< How many buffers are used for receiving - uint64_t physicalAddress: 48; ///< The physical (MAC) address of the device (Not 64 bits but will be treated like it is) - uint16_t reserved3; ///< Unused, must be zero - uint64_t logicalAddress; ///< The logical address filter for the device to use when deciding whether to accept a packet (0 = no filtering) - uint32_t recvBufferDescrAddress; ///< Physical address of the first receive buffer descriptor - uint32_t sendBufferDescrAddress; ///< Physical address of the first send buffer descriptor - - } +namespace MaxOS::drivers::ethernet { + + /** + * @struct InitializationBlock + * @brief The initialization block for the AMD AM79C973 Ethernet Controller + * + * @typedef initialisation_block_t + * @brief Alias for InitializationBlock struct + */ + typedef struct PACKED InitializationBlock { + + uint16_t mode; ///< The operation mode + unsigned reserved1 : 4; ///< Unused, must be zero + unsigned num_send_buffers : 4; ///< How many buffers are used for sending + unsigned reserved2 : 4; ///< Unused, must be zero + unsigned num_recv_buffers : 4; ///< How many buffers are used for receiving + uint64_t physical_address : 48; ///< The physical (MAC) address of the device (Not 64 bits but will be treated like it is) + uint16_t reserved3; ///< Unused, must be zero + uint64_t logical_address; ///< The logical address filter for the device to use when deciding whether to accept a packet (0 = no filtering) + uint32_t recv_buffer_descr_address; ///< Physical address of the first receive buffer descriptor + uint32_t send_buffer_descr_address; ///< Physical address of the first send buffer descriptor + + } initialisation_block_t; - /** - * @struct BufferDescriptor - * @brief Defines the layout of a buffer descriptor for the AMD AM79C973 Ethernet Controller - * - * @typedef buffer_descriptor_t - * @brief Alias for BufferDescriptor struct - */ - typedef struct PACKED BufferDescriptor { - - uint64_t address; ///< Physical address of the buffer - uint32_t flags; ///< Flags for the buffer - uint32_t flags2; ///< Additional flags for the buffer (@todo enum this) - uint32_t avail; ///< Indicates whether the buffer is available to be used - - } - buffer_descriptor_t; + /** + * @struct BufferDescriptor + * @brief Defines the layout of a buffer descriptor for the AMD AM79C973 Ethernet Controller + * + * @typedef buffer_descriptor_t + * @brief Alias for BufferDescriptor struct + */ + typedef struct PACKED BufferDescriptor { + + uint64_t address; ///< Physical address of the buffer + uint32_t flags; ///< Flags for the buffer + uint32_t flags2; ///< Additional flags for the buffer (@todo enum this) + uint32_t avail; ///< Indicates whether the buffer is available to be used - /** - * @class AMD_AM79C973 - * @brief Driver for the AMD AM79C973 Ethernet Controller - */ - class AMD_AM79C973 : public EthernetDriver, public hardwarecommunication::InterruptHandler { + } + buffer_descriptor_t; - private: + /** + * @class AMD_AM79C973 + * @brief Driver for the AMD AM79C973 Ethernet Controller + */ + class AMD_AM79C973 : public EthernetDriver, public hardwarecommunication::InterruptHandler { - //Reading the media access control address (MAC address) - hardwarecommunication::Port16Bit MACAddress0Port; - hardwarecommunication::Port16Bit MACAddress2Port; - hardwarecommunication::Port16Bit MACAddress4Port; + private: - //Register ports - hardwarecommunication::Port16Bit registerDataPort; - hardwarecommunication::Port16Bit registerAddressPort; - hardwarecommunication::Port16Bit busControlRegisterDataPort; + //Reading the media access control address (MAC address) + hardwarecommunication::Port16Bit mac_address_0_port; + hardwarecommunication::Port16Bit mac_address_2_port; + hardwarecommunication::Port16Bit mac_address_4_port; - hardwarecommunication::Port16Bit resetPort; + //Register ports + hardwarecommunication::Port16Bit register_data_port; + hardwarecommunication::Port16Bit register_address_port; + hardwarecommunication::Port16Bit bus_control_register_data_port; - //The main purpose of the initialization block it to hold a pointer to the array of BufferDescriptors, which hold the pointers to the buffers - initialisation_block_t initBlock { }; + hardwarecommunication::Port16Bit reset_port; + //The main purpose of the initialization block it to hold a pointer to the array of BufferDescriptors, which hold the pointers to the buffers + initialisation_block_t init_block { }; - buffer_descriptor_t* sendBufferDescr; //Descriptor entry - uint8_t sendBuffers[2 * 1024 + 15][8] { }; //8 Send Buffers, 2KB + 15 bytes - uint8_t currentSendBuffer; //Which buffers are active - buffer_descriptor_t* recvBufferDescr; //Descriptor entry - uint8_t recvBuffers[2 * 1024 + 15][8] { }; //8 Send Buffers, 2KB + 15 bytes - uint8_t currentRecvBuffer; //Which buffers are active + buffer_descriptor_t* send_buffer_descr; //Descriptor entry + uint8_t send_buffers[2 * 1024 + 15][8] { }; //8 Send Buffers, 2KB + 15 bytes + uint8_t current_send_buffer; //Which buffers are active - //Ethernet Driver functions - MediaAccessControlAddress ownMAC; //MAC address of the device - volatile bool active; //Is the device active - volatile bool initDone; //Is the device initialised + buffer_descriptor_t* recv_buffer_descr; //Descriptor entry + uint8_t recv_buffers[2 * 1024 + 15][8] { }; //8 Send Buffers, 2KB + 15 bytes + uint8_t current_recv_buffer; //Which buffers are active - void FetchDataReceived(); //Fetches the data from the buffer - void FetchDataSent(); //Fetches the data from the buffer + //Ethernet Driver functions + MediaAccessControlAddress own_mac; //MAC address of the device + volatile bool active; //Is the device active + volatile bool init_done; //Is the device initialised - public: - AMD_AM79C973(hardwarecommunication::PCIDeviceDescriptor* dev); - ~AMD_AM79C973(); + void fetch_data_received(); //Fetches the data from the buffer + void fetch_data_sent(); //Fetches the data from the buffer - // Override driver default methods - uint32_t reset() final; - void activate() final; - void deactivate() final; + public: + explicit AMD_AM79C973(hardwarecommunication::PCIDeviceDescriptor* dev); + ~AMD_AM79C973(); - // Naming - string vendor_name() final; - string device_name() final; + // Override driver default methods + uint32_t reset() final; + void activate() final; + void deactivate() final; - //Override Interrupt default methods - void handle_interrupt() final; + // Naming + string vendor_name() final; + string device_name() final; - //Ethernet Driver functions - void DoSend(uint8_t* buffer, uint32_t size) final; - uint64_t GetMediaAccessControlAddress() final; - }; + //Override Interrupt default methods + void handle_interrupt() final; + //Ethernet Driver functions + void do_send(uint8_t* buffer, uint32_t size) final; + uint64_t get_media_access_control_address() final; + }; - } - } } + #endif //MAXOS_DRIVERS_ETHERNET_AMD_AM79C973_H \ No newline at end of file diff --git a/kernel/include/drivers/ethernet/ethernet.h b/kernel/include/drivers/ethernet/ethernet.h index 1d991b9f..f9f6eab0 100644 --- a/kernel/include/drivers/ethernet/ethernet.h +++ b/kernel/include/drivers/ethernet/ethernet.h @@ -9,107 +9,99 @@ #ifndef MAXOS_DRIVERS_ETHERNET_ETHERNET_H #define MAXOS_DRIVERS_ETHERNET_ETHERNET_H -#include +#include #include #include #include -namespace MaxOS{ - - namespace drivers{ - - namespace ethernet { - - /// Used to make MAC addresses more readable @todo make a MacAddress class and use mac_t - typedef uint64_t MediaAccessControlAddress; - - /** - * @enum EthernetDriverEvents - * @brief Events that can be triggered by the Ethernet Driver - */ - enum class EthernetDriverEvents{ - BEFORE_SEND, - DATA_SENT, - DATA_RECEIVED - }; - - /** - * @class BeforeSendEvent - * @brief Event that is triggered before data is sent, holds the buffer and size of the data - */ - class BeforeSendEvent : public common::Event{ - public: - uint8_t* buffer; ///< The buffer to be sent - uint32_t size; ///< The size of the buffer to be sent - BeforeSendEvent(uint8_t* buffer, uint32_t size); - ~BeforeSendEvent(); - }; - - /** - * @class DataSentEvent - * @brief Event that is triggered when data is sent, holds the buffer and size of the data - */ - class DataSentEvent : public common::Event{ - public: - uint8_t* buffer; ///< The buffer that was sent - uint32_t size; ///< The size of the buffer that was sent - DataSentEvent(uint8_t* buffer, uint32_t size); - ~DataSentEvent(); - }; - - /** - * @class DataReceivedEvent - * @brief Event that is triggered when data is received, holds the buffer and size of the data - */ - class DataReceivedEvent : public common::Event{ - public: - uint8_t* buffer; ///< @deprecated WRS - uint32_t size; ///< @deprecated WRS - DataReceivedEvent(uint8_t* buffer, uint32_t size); - ~DataReceivedEvent(); - }; - - /** - * @class EthernetDriverEventHandler - * @brief Handles the events that are triggered by the Ethernet Driver - */ - class EthernetDriverEventHandler : public common::EventHandler - { - public: - EthernetDriverEventHandler(); - ~EthernetDriverEventHandler(); - - virtual common::Event* - on_event(common::Event* event) override; - - virtual void BeforeSend(uint8_t* buffer, uint32_t size); - virtual void DataSent(uint8_t* buffer, uint32_t size); - virtual bool DataReceived(uint8_t* buffer, uint32_t size); - }; - - /** - * @class EthernetDriver - * @brief Driver for the Ethernet Controller, manages the sending and receiving of data, the mac address, and the events - */ - class EthernetDriver : public Driver, public common::EventManager - { - protected: - virtual void DoSend(uint8_t* buffer, uint32_t size); - void FireDataReceived(uint8_t* buffer, uint32_t size); - void FireDataSent(uint8_t* buffer, uint32_t size); - - public: - EthernetDriver(); - ~EthernetDriver(); - - static MediaAccessControlAddress CreateMediaAccessControlAddress(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4, uint8_t digit5, uint8_t digit6); - virtual MediaAccessControlAddress GetMediaAccessControlAddress(); - - void Send(uint8_t* buffer, uint32_t size); - }; - - } - } + +namespace MaxOS::drivers::ethernet { + + /// Used to make MAC addresses more readable @todo make a MacAddress class and use mac_t + typedef uint64_t MediaAccessControlAddress; + + /** + * @enum EthernetDriverEvents + * @brief Events that can be triggered by the Ethernet Driver + */ + enum class EthernetDriverEvents { + BEFORE_SEND, + DATA_SENT, + DATA_RECEIVED + }; + + /** + * @class BeforeSendEvent + * @brief Event that is triggered before data is sent, holds the buffer and size of the data + */ + class BeforeSendEvent : public common::Event { + public: + uint8_t* buffer; ///< The buffer to be sent + uint32_t size; ///< The size of the buffer to be sent + BeforeSendEvent(uint8_t* buffer, uint32_t size); + ~BeforeSendEvent(); + }; + + /** + * @class DataSentEvent + * @brief Event that is triggered when data is sent, holds the buffer and size of the data + */ + class DataSentEvent : public common::Event { + public: + uint8_t* buffer; ///< The buffer that was sent + uint32_t size; ///< The size of the buffer that was sent + DataSentEvent(uint8_t* buffer, uint32_t size); + ~DataSentEvent(); + }; + + /** + * @class DataReceivedEvent + * @brief Event that is triggered when data is received, holds the buffer and size of the data + */ + class DataReceivedEvent : public common::Event { + public: + uint8_t* buffer; ///< @deprecated WRS + uint32_t size; ///< @deprecated WRS + DataReceivedEvent(uint8_t* buffer, uint32_t size); + ~DataReceivedEvent(); + }; + + /** + * @class EthernetDriverEventHandler + * @brief Handles the events that are triggered by the Ethernet Driver + */ + class EthernetDriverEventHandler : public common::EventHandler { + public: + EthernetDriverEventHandler(); + ~EthernetDriverEventHandler(); + + common::Event* on_event(common::Event* event) override; + + virtual void before_send(uint8_t* buffer, uint32_t size); + virtual void data_sent(uint8_t* buffer, uint32_t size); + virtual bool data_received(uint8_t* buffer, uint32_t size); + }; + + /** + * @class EthernetDriver + * @brief Driver for the Ethernet Controller, manages the sending and receiving of data, the mac address, and the events + */ + class EthernetDriver : public Driver, public common::EventManager { + protected: + virtual void do_send(uint8_t* buffer, uint32_t size); + void fire_data_received(uint8_t* buffer, uint32_t size); + void fire_data_sent(uint8_t* buffer, uint32_t size); + + public: + EthernetDriver(); + ~EthernetDriver(); + + static MediaAccessControlAddress create_media_access_control_address(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4, uint8_t digit5, uint8_t digit6); + virtual MediaAccessControlAddress get_media_access_control_address(); + + void send(uint8_t* buffer, uint32_t size); + }; + } diff --git a/kernel/include/drivers/ethernet/intel_i217.h b/kernel/include/drivers/ethernet/intel_i217.h index 61adc625..1fdaab8f 100644 --- a/kernel/include/drivers/ethernet/intel_i217.h +++ b/kernel/include/drivers/ethernet/intel_i217.h @@ -9,7 +9,7 @@ #ifndef MAXOS_DRIVERS_ETHERNET_INTEL_I127_H #define MAXOS_DRIVERS_ETHERNET_INTEL_I127_H -#include +#include #include #include #include @@ -20,139 +20,133 @@ #include #include -namespace MaxOS { - - namespace drivers { - - namespace ethernet { - - /** - * @struct ReceiveDescriptor - * @brief The receive descriptor for the Intel I217 Ethernet Controller - * - * @typedef receive_descriptor_t - * @brief Alias for ReceiveDescriptor struct - */ - typedef struct PACKED ReceiveDescriptor { - uint64_t bufferAddress; ///< The address of the receive buffer - uint16_t length; ///< The length of the received frame - uint16_t checksum; ///< The checksum of the received frame - uint8_t status; ///< The status of the received frame - uint8_t errors; ///< Any errors that occurred - uint16_t special; ///< Special - } receive_descriptor_t; - /** - * @struct SendDescriptor - * @brief The send descriptor for the Intel I217 Ethernet Controller - * - * @typedef send_descriptor_t - * @brief Alias for SendDescriptor struct - */ - typedef struct PACKED SendDescriptor { - uint64_t bufferAddress; ///< The address of the send buffer - uint16_t length; ///< The length of the send frame - uint8_t cso; ///< The checksum offset - uint8_t cmd; ///< The command - uint8_t status; ///< The status - uint8_t css; ///< The checksum start - uint16_t special; ///< Special - } send_descriptor_t; +namespace MaxOS::drivers::ethernet { + + /** + * @struct ReceiveDescriptor + * @brief The receive descriptor for the Intel I217 Ethernet Controller + * + * @typedef receive_descriptor_t + * @brief Alias for ReceiveDescriptor struct + */ + typedef struct PACKED ReceiveDescriptor { + uint64_t buffer_address; ///< The address of the receive buffer + uint16_t length; ///< The length of the received frame + uint16_t checksum; ///< The checksum of the received frame + uint8_t status; ///< The status of the received frame + uint8_t errors; ///< Any errors that occurred + uint16_t special; ///< Special + } receive_descriptor_t; + /** + * @struct SendDescriptor + * @brief The send descriptor for the Intel I217 Ethernet Controller + * + * @typedef send_descriptor_t + * @brief Alias for SendDescriptor struct + */ + typedef struct PACKED SendDescriptor { + uint64_t buffer_address; ///< The address of the send buffer + uint16_t length; ///< The length of the send frame + uint8_t cso; ///< The checksum offset + uint8_t cmd; ///< The command + uint8_t status; ///< The status + uint8_t css; ///< The checksum start + uint16_t special; ///< Special + } send_descriptor_t; - /** - * @class IntelI217 - * @brief Driver for the Intel I217 Ethernet Controller - */ - class IntelI217 : public EthernetDriver, public hardwarecommunication::InterruptHandler { - uint8_t bar_type = { 0 }; - uint16_t portBase = { 0 }; - uint64_t memBase = { 0 }; - uint8_t macAddress[6] = { 0 }; + /** + * @class IntelI217 + * @brief Driver for the Intel I217 Ethernet Controller + */ + class IntelI217 : public EthernetDriver, public hardwarecommunication::InterruptHandler { + uint8_t bar_type = { 0 }; + uint16_t port_base = { 0 }; + uint64_t mem_base = { 0 }; + uint8_t mac_address[6] = { 0 }; - //Registers Addresses (Main Registers) - uint16_t controlRegister; // The control register - uint16_t statusRegister; // The status register - uint16_t epromRegister; // The address of the eeprom register - uint16_t controlExtRegister; // The control extension register - uint16_t interruptMaskRegister; // The interrupt mask register - //Registers Addresses (Receive Registers) - uint16_t receiveControlRegister; // The receive control register - uint16_t receiveDescriptorLowRegister; // The receive descriptor low register - uint16_t receiveDescriptorHighRegister; // The receive descriptor high register - uint16_t receiveDescriptorLengthRegister;// The receive descriptor length register - uint16_t receiveDescriptorHeadRegister; // The receive descriptor head register - uint16_t receiveDescriptorTailRegister; // The receive descriptor tail register + //Registers Addresses (Main Registers) + uint16_t control_register; // The control register + uint16_t status_register; // The status register + uint16_t eprom_register; // The address of the eeprom register + uint16_t control_ext_register; // The control extension register + uint16_t interrupt_mask_register; // The interrupt mask register - //Registers Addresses (Send Registers) - uint16_t sendControlRegister; // The send control register - uint16_t sendDescriptorLowRegister; // The send descriptor low register - uint16_t sendDescriptorHighRegister; // The send descriptor high register - uint16_t sendDescriptorLengthRegister; // The send descriptor length register - uint16_t sendDescriptorHeadRegister; // The send descriptor head register - uint16_t sendDescriptorTailRegister; // The send descriptor tail register + //Registers Addresses (Receive Registers) + uint16_t receive_control_register; // The receive control register + uint16_t receive_descriptor_low_register; // The receive descriptor low register + uint16_t receive_descriptor_high_register; // The receive descriptor high register + uint16_t receive_descriptor_length_register;// The receive descriptor length register + uint16_t receive_descriptor_head_register; // The receive descriptor head register + uint16_t receive_descriptor_tail_register; // The receive descriptor tail register + //Registers Addresses (Send Registers) + uint16_t send_control_register; // The send control register + uint16_t send_descriptor_low_register; // The send descriptor low register + uint16_t send_descriptor_high_register; // The send descriptor high register + uint16_t send_descriptor_length_register; // The send descriptor length register + uint16_t send_descriptor_head_register; // The send descriptor head register + uint16_t send_descriptor_tail_register; // The send descriptor tail register - //Buffers - receive_descriptor_t* receiveDsrctrs[32]; // The receive descriptors - uint16_t currentReceiveBuffer; // The current receive buffer - send_descriptor_t * sendDsrctrs[8]; // The send descriptors - uint16_t currentSendBuffer; // The current send buffer + //Buffers + receive_descriptor_t* receive_dsrctrs[32]; // The receive descriptors + uint16_t current_receive_buffer; // The current receive buffer + send_descriptor_t* send_dsrctrs[8]; // The send descriptors + uint16_t current_send_buffer; // The current send buffer - // write Commands and read results From NICs either using MemIO or IO Ports - void Write(uint16_t address, uint32_t data) const; - uint32_t Read(uint16_t address) const; - //EPROM (Device Memory) - bool epromPresent; // Whether the EPROM is present - bool detectEEProm(); // Return true if EEProm exist, else it returns false and set the error_exists data member - uint32_t eepromRead(uint8_t addr); // read 4 bytes from a specific EEProm Address + // write Commands and read results From NICs either using MemIO or IO Ports + void write(uint16_t address, uint32_t data) const; + [[nodiscard]] uint32_t read(uint16_t address) const; + //EPROM (Device Memory) + bool eprom_present = false; // Whether the EPROM is present + bool detect_ee_prom(); // Return true if EEProm exist, else it returns false and set the error_exists data member + uint32_t eeprom_read(uint8_t addr); // read 4 bytes from a specific EEProm Address - bool readMACAddress(); // read MAC Address - void receiveInit(); // Initialise receive descriptors buffers - void sendInit(); // Initialise transmit descriptors buffers + bool read_mac_address(); // read MAC Address - //Ethernet Driver functions - MediaAccessControlAddress ownMAC; //MAC address of the device - volatile bool active; //Is the device active - volatile bool initDone; //Is the device initialised - - void FetchDataReceived(); //Fetches the data from the buffer - - public: - - IntelI217(hardwarecommunication::PCIDeviceDescriptor* deviceDescriptor); - ~IntelI217(); // Default Destructor + void receive_init(); // Initialise receive descriptors buffers + void send_init(); // Initialise transmit descriptors buffers + //Ethernet Driver functions + MediaAccessControlAddress own_mac; //MAC address of the device + volatile bool active; //Is the device active + volatile bool init_done; //Is the device initialised + + void fetch_data_received(); //Fetches the data from the buffer + + public: + + explicit IntelI217(hardwarecommunication::PCIDeviceDescriptor* device_descriptor); + ~IntelI217(); - //Override driver default methods - uint32_t reset() final; - void activate() final; - void deactivate() final; - //Override Interrupt default methods - void handle_interrupt() final; + //Override driver default methods + uint32_t reset() final; + void activate() final; + void deactivate() final; + //Override Interrupt default methods + void handle_interrupt() final; - //Ethernet Driver functions - string vendor_name() final; - string device_name() final; - void DoSend(uint8_t* buffer, uint32_t size) final; - uint64_t GetMediaAccessControlAddress() final; - }; + //Ethernet Driver functions + string vendor_name() final; + string device_name() final; - } - } + void do_send(uint8_t* buffer, uint32_t size) final; + uint64_t get_media_access_control_address() final; + }; } diff --git a/kernel/include/drivers/ethernet/rawdatahandler.h b/kernel/include/drivers/ethernet/rawdatahandler.h index 2ba0873a..e48b203e 100644 --- a/kernel/include/drivers/ethernet/rawdatahandler.h +++ b/kernel/include/drivers/ethernet/rawdatahandler.h @@ -9,31 +9,24 @@ #ifndef MAXOS_DRIVERS_ETHERNET_RAWDATAHANDLER_H #define MAXOS_DRIVERS_ETHERNET_RAWDATAHANDLER_H -#include +#include -namespace MaxOS { - namespace drivers { +namespace MaxOS::drivers::ethernet { - namespace ethernet { + /** + * @class RawDataHandler + * @brief Handles raw data received from the ethernet controller + */ + class RawDataHandler { + public: + RawDataHandler(); + ~RawDataHandler(); + virtual bool handle_raw_data(uint8_t* data, uint32_t size); + }; - /** - * @class RawDataHandler - * @brief Handles raw data received from the ethernet controller - */ - class RawDataHandler - { - public: - RawDataHandler(); - ~RawDataHandler(); - virtual bool HandleRawData(uint8_t* buffer, uint32_t size); - }; - - - } - - } } + #endif //MAXOS_DRIVERS_ETHERNET_RAWDATAHANDLER_H diff --git a/kernel/include/drivers/peripherals/keyboard.h b/kernel/include/drivers/peripherals/keyboard.h index dca10bde..853d1a65 100644 --- a/kernel/include/drivers/peripherals/keyboard.h +++ b/kernel/include/drivers/peripherals/keyboard.h @@ -18,450 +18,447 @@ #include #include #include -#include - -namespace MaxOS { - namespace drivers { - - namespace peripherals { +#include + + +namespace MaxOS::drivers::peripherals { + + /** + * @enum ScanCodeType + * @brief The type of scan code being sent by the keyboard + */ + enum class ScanCodeType : int { + REGULAR, + EXTENDED, + EXTENDED_BUFFER + }; + + /** + * @enum KeyCode + * @brief A mapping of key codes to their values + */ + enum class KeyCode : uint16_t { + + // Alphabet + A = 'A', a = 'a', + B = 'B', b = 'b', + C = 'C', c = 'c', + D = 'D', d = 'd', + E = 'E', e = 'e', + F = 'F', f = 'f', + G = 'G', g = 'g', + H = 'H', h = 'h', + I = 'I', i = 'i', + J = 'J', j = 'j', + K = 'K', k = 'k', + L = 'L', l = 'l', + M = 'M', m = 'm', + N = 'N', n = 'n', + O = 'O', o = 'o', + P = 'P', p = 'p', + Q = 'Q', q = 'q', + R = 'R', r = 'r', + S = 'S', s = 's', + T = 'T', t = 't', + U = 'U', u = 'u', + V = 'V', v = 'v', + W = 'W', w = 'w', + X = 'X', x = 'x', + Y = 'Y', y = 'y', + Z = 'Z', z = 'z', + + // Numbers + zero = '0', + one = '1', + two = '2', + three = '3', + four = '4', + five = '5', + six = '6', + seven = '7', + eight = '8', + nine = '9', + + // Symbols + comma = ',', + fullStop = '.', + exclamationMark = '!', + questionMark = '?', + quotationMark = '\"', + semicolon = ';', + colon = ':', + apostrophe = '\'', + slantedApostrophe = '`', + + // Signs + powerSign = '^', + dollarSign = '$', + percentSign = '%', + andSign = '&', + atSign = '@', + + // Special Characters + underscore = '_', + lineThing = '|', + hash = '#', + backslash = '\\', + forwardSlash = '/', + squigglyLine = '~', + + // Math Symbols + plus = '+', + minus = '-', + equals = '=', + multiply = '*', + lessThan = '<', + greaterThan = '>', + + // Brackets + openBracket = '(', + closeBracket = ')', + openSquareBracket = '[', + closeSquareBracket = ']', + openCurlyBracket = '{', + closeCurlyBracket = '}', + + // Writing + space = ' ', + tab = '\t', + enter = '\n', + backspace = '\b', + + /// OTHER CODES THAT ARE NOT CHARACTERS /// + + // Functions + f1 = 1000, //force it to start at 1000 so it doesn't conflict with ascii + f2, + f3, + f4, + f5, + f6, + f7, + f8, + f9, + f10, + f11, + f12, + + // Top Row + escape, + printScreen, + scrollLock, + pauseBreak, + + // Arrow s + upArrow, + downArrow, + leftArrow, + rightArrow, + + // Keys Above Arrows + insert, + home, + pageUp, + deleteKey, + end, + pageDown, + + // Left Side + capsLock, + leftShift, + leftControl, + leftOS, //weird ass Windows key or command on Mac + leftAlt, + + // Right Side + rightAlt, + functionKey, + rightControl, + rightShift, + + // Number Pad + numberPadLock, + numberPadForwardSlash, + numberPadMultiply, + numberPadMinus, + numberPadPlus, + numberPadEnter, + numberPadZero, + numberPadOne, + numberPadTwo, + numberPadThree, + numberPadFour, + numberPadFive, + numberPadSix, + numberPadSeven, + numberPadEight, + numberPadNine, + numberPadFullStop, + + // Number Pad (Non Number Lock) + numberPadHome, + numberPadPageDown, + numberPadPageUp, + numberPadEnd, + numberPadInsert, + numberPadUpArrow, + numberPadDownArrow, + numberPadLeftArrow, + numberPadRightArrow, + }; + + /** + * @class KeyboardState + * @brief Holds the state of the keyboard + * + * @todo Add functions like is_shift_pressed() and similar + */ + class KeyboardState { + public: + KeyboardState(); + ~KeyboardState(); + + // Left and Right + bool left_shift = false; ///< Is the left shift key pressed + bool right_shift = false; ///< Is the right shift key pressed + bool left_control = false; ///< Is the left control key pressed + bool right_control = false; ///< Is the right control key pressed + bool left_alt = false; ///< Is the left alt key pressed + bool right_alt = false; ///< Is the right alt key pressed + + // Other Stuff + bool caps_lock = false; ///< Is caps lock enabled + bool number_pad_lock = false; ///< Is number pad lock enabled + bool scroll_lock = false; ///< Is scroll lock enabled + }; + + /** + * @enum KeyboardEvents + * @brief The events that can be triggered by the Keyboard Driver + */ + enum class KeyboardEvents { + KEYDOWN, + KEYUP + }; + + /** + * @class KeyUpEvent + * @brief Event that is triggered when a key is released + */ + class KeyUpEvent : public common::Event { + public: + KeyUpEvent(KeyCode, const KeyboardState&); + ~KeyUpEvent(); + + KeyCode key_code; ///< The key code of the key that was released + KeyboardState keyboard_state; ///< The state of the keyboard when the key was released + }; + + /** + * @class KeyDownEvent + * @brief Event that is triggered when a key is pressed + */ + class KeyDownEvent : public common::Event { + public: + KeyDownEvent(KeyCode, const KeyboardState&); + ~KeyDownEvent(); + + KeyCode key_code; ///< The key code of the key that was pressed + KeyboardState keyboard_state; ///< The state of the keyboard when the key was pressed + }; + + /** + * @class KeyboardEventHandler + * @brief Handles the events that are triggered by the Keyboard Driver + */ + class KeyboardEventHandler : public common::EventHandler { + public: + KeyboardEventHandler(); + ~KeyboardEventHandler(); + + common::Event* on_event(common::Event*) override; + + virtual void on_key_down(KeyCode, const KeyboardState&); + virtual void on_key_up(KeyCode, const KeyboardState&); + }; + + /** + * @class KeyboardInterpreter + * @brief Interprets the scan codes from the keyboard + */ + class KeyboardInterpreter : public common::InputStreamEventHandler, public common::EventManager { + + protected: + KeyboardState m_keyboard_state; ///< The current state of what special keys are pressed on the keyboard + + bool m_next_is_first_extended_code = false; ///< If true, the next code should be interpreted as an extended code (set when receiving 0xE0) + uint8_t m_extended_scan_code_bytes = 0; ///< How many bytes are left to read for the current extended scan code + uint16_t m_extended_code_buffer = 0; ///< The storage for scan codes that take more than one byte + + public: + KeyboardInterpreter(); + ~KeyboardInterpreter(); + + void on_key_read(bool, const KeyboardState&, KeyCode); + + }; + + /** + * @class KeyboardInterpreterEN_US + * @brief Interprets the scan codes from the keyboard for the EN_US keyboard layout + */ + class KeyboardInterpreterEN_US : public KeyboardInterpreter { + + public: /** - * @enum ScanCodeType - * @brief The type of scan code being sent by the keyboard + * @enum KeyCodeEN_US + * @brief The scan codes for the EN_US keyboard layout */ - enum class ScanCodeType : int { - REGULAR, - EXTENDED, - EXTENDED_BUFFER + enum class KeyCodeEN_US { + // First Row + escape = 0x01, + f1 = 0x3B, + f2 = 0x3C, + f3 = 0x3D, + f4 = 0x3E, + f5 = 0x3F, + f6 = 0x40, + f7 = 0x41, + f8 = 0x42, + f9 = 0x43, + f10 = 0x44, + f11 = 0x57, + f12 = 0x58, + printScreen = 0x37, + scrollLock = 0x46, + pauseBreak = 0x45, + + // Second Row + squigglyLine = 0x29, + one = 0x02, + two = 0x03, + three = 0x04, + four = 0x05, + five = 0x06, + six = 0x07, + seven = 0x08, + eight = 0x09, + nine = 0x0A, + zero = 0x0B, + minus = 0x0C, + equals = 0x0D, + backspace = 0x0E, + insert = 0x52, + home = 0x47, + pageUp = 0x49, + numberPadLock = 0x45, + numberPadForwardSlash = 0x35, + numberPadMultiply = 0x37, + numberPadMinus = 0x4A, + + // Third Row + tab = 0x0F, + Q = 0x10, + W = 0x11, + E = 0x12, + R = 0x13, + T = 0x14, + Y = 0x15, + U = 0x16, + I = 0x17, + O = 0x18, + P = 0x19, + openSquareBracket = 0x1A, + closeSquareBracket = 0x1B, + backslash = 0x2B, + deleteKey = 0x53, + end = 0x4F, + pageDown = 0x51, + numberPadSeven = 0x47, + numberPadEight = 0x48, + numberPadNine = 0x49, + numberPadPlus = 0x4E, + + // Fourth Row + capsLock = 0x3A, + A = 0x1E, + S = 0x1F, + D = 0x20, + F = 0x21, + G = 0x22, + H = 0x23, + J = 0x24, + K = 0x25, + L = 0x26, + semicolon = 0x27, + apostrophe = 0x28, + enter = 0x1C, + numberPadFour = 0x4B, + numberPadFive = 0x4C, + numberPadSix = 0x4D, + + // Fifth Row + leftShift = 0x2A, + Z = 0x2C, + X = 0x2D, + C = 0x2E, + V = 0x2F, + B = 0x30, + N = 0x31, + M = 0x32, + comma = 0x33, + fullStop = 0x34, + forwardSlash = 0x35, + rightShift = 0x36, + upArrow = 0x48, + numberPadOne = 0x4F, + numberPadTwo = 0x50, + numberPadThree = 0x51, + numberPadEnter = 0x1C, + + // Sixth Row + leftControl = 0x1D, + leftOS = 0x5B, + leftAlt = 0x38, + space = 0x39, + rightAlt = 0x38, + function = 0x5D, + rightControl = 0x1D, + leftArrow = 0x4B, + downArrow = 0x50, + rightArrow = 0x4D, + numberPadZero = 0x52, + numberPadFullStop = 0x53 }; - /** - * @enum KeyCode - * @brief A mapping of key codes to their values - */ - enum class KeyCode : uint16_t { - - // Alphabet - A = 'A', a = 'a', - B = 'B', b = 'b', - C = 'C', c = 'c', - D = 'D', d = 'd', - E = 'E', e = 'e', - F = 'F', f = 'f', - G = 'G', g = 'g', - H = 'H', h = 'h', - I = 'I', i = 'i', - J = 'J', j = 'j', - K = 'K', k = 'k', - L = 'L', l = 'l', - M = 'M', m = 'm', - N = 'N', n = 'n', - O = 'O', o = 'o', - P = 'P', p = 'p', - Q = 'Q', q = 'q', - R = 'R', r = 'r', - S = 'S', s = 's', - T = 'T', t = 't', - U = 'U', u = 'u', - V = 'V', v = 'v', - W = 'W', w = 'w', - X = 'X', x = 'x', - Y = 'Y', y = 'y', - Z = 'Z', z = 'z', - - // Numbers - zero = '0', - one = '1', - two = '2', - three = '3', - four = '4', - five = '5', - six = '6', - seven = '7', - eight = '8', - nine = '9', - - // Symbols - comma = ',', - fullStop = '.', - exclamationMark = '!', - questionMark = '?', - quotationMark = '\"', - semicolon = ';', - colon = ':', - apostrophe = '\'', - slantedApostrophe = '`', - - // Signs - powerSign = '^', - dollarSign = '$', - percentSign = '%', - andSign = '&', - atSign = '@', - - // Special Characters - underscore = '_', - lineThing = '|', - hash = '#', - backslash = '\\', - forwardSlash = '/', - squigglyLine = '~', - - // Math Symbols - plus = '+', - minus = '-', - equals = '=', - multiply = '*', - lessThan = '<', - greaterThan = '>', - - // Brackets - openBracket = '(', - closeBracket = ')', - openSquareBracket = '[', - closeSquareBracket = ']', - openCurlyBracket = '{', - closeCurlyBracket = '}', - - // Writing - space = ' ', - tab = '\t', - enter = '\n', - backspace = '\b', - - /// OTHER CODES THAT ARE NOT CHARACTERS /// - - // Functions - f1 = 1000, //force it to start at 1000 so it doesn't conflict with ascii - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - - // Top Row - escape, - printScreen, - scrollLock, - pauseBreak, - - // Arrow s - upArrow, - downArrow, - leftArrow, - rightArrow, - - // Keys Above Arrows - insert, - home, - pageUp, - deleteKey, - end, - pageDown, - - // Left Side - capsLock, - leftShift, - leftControl, - leftOS, //weird ass Windows key or command on Mac - leftAlt, - - // Right Side - rightAlt, - functionKey, - rightControl, - rightShift, - - // Number Pad - numberPadLock, - numberPadForwardSlash, - numberPadMultiply, - numberPadMinus, - numberPadPlus, - numberPadEnter, - numberPadZero, - numberPadOne, - numberPadTwo, - numberPadThree, - numberPadFour, - numberPadFive, - numberPadSix, - numberPadSeven, - numberPadEight, - numberPadNine, - numberPadFullStop, - - // Number Pad (Non Number Lock) - numberPadHome, - numberPadPageDown, - numberPadPageUp, - numberPadEnd, - numberPadInsert, - numberPadUpArrow, - numberPadDownArrow, - numberPadLeftArrow, - numberPadRightArrow, - }; + KeyboardInterpreterEN_US(); + ~KeyboardInterpreterEN_US(); - /** - * @class KeyboardState - * @brief Holds the state of the keyboard - * - * @todo Add functions like is_shift_pressed() and similar - */ - class KeyboardState { - public: - KeyboardState(); - ~KeyboardState(); - - // Left and Right - bool left_shift = false; ///< Is the left shift key pressed - bool right_shift = false; ///< Is the right shift key pressed - bool left_control = false; ///< Is the left control key pressed - bool right_control = false; ///< Is the right control key pressed - bool left_alt = false; ///< Is the left alt key pressed - bool right_alt = false; ///< Is the right alt key pressed - - // Other Stuff - bool caps_lock = false; ///< Is caps lock enabled - bool number_pad_lock = false; ///< Is number pad lock enabled - bool scroll_lock = false; ///< Is scroll lock enabled - }; + void on_stream_read(uint8_t scan_code) final; - /** - * @enum KeyboardEvents - * @brief The events that can be triggered by the Keyboard Driver - */ - enum class KeyboardEvents { - KEYDOWN, - KEYUP - }; + }; - /** - * @class KeyUpEvent - * @brief Event that is triggered when a key is released - */ - class KeyUpEvent : public common::Event { - public: - KeyUpEvent(KeyCode, const KeyboardState &); - ~KeyUpEvent(); - - KeyCode key_code; ///< The key code of the key that was released - KeyboardState keyboard_state; ///< The state of the keyboard when the key was released - }; + /** + * @class KeyboardDriver + * @brief Driver for the Keyboard Controller, manages the events and the keyboard state + */ + class KeyboardDriver : public hardwarecommunication::InterruptHandler, public Driver, public common::GenericInputStream { - /** - * @class KeyDownEvent - * @brief Event that is triggered when a key is pressed - */ - class KeyDownEvent : public common::Event { - public: - KeyDownEvent(KeyCode, const KeyboardState &); - ~KeyDownEvent(); + private: + hardwarecommunication::Port8Bit m_data_port; + hardwarecommunication::Port8Bit m_command_port; - KeyCode key_code; ///< The key code of the key that was pressed - KeyboardState keyboard_state; ///< The state of the keyboard when the key was pressed - }; + public: + KeyboardDriver(); + ~KeyboardDriver(); - /** - * @class KeyboardEventHandler - * @brief Handles the events that are triggered by the Keyboard Driver - */ - class KeyboardEventHandler : public common::EventHandler { - public: - KeyboardEventHandler(); - ~KeyboardEventHandler(); - - common::Event* on_event(common::Event*) override; - - virtual void on_key_down(KeyCode, KeyboardState); - virtual void on_key_up(KeyCode, KeyboardState); - }; + void handle_interrupt() final; - /** - * @class KeyboardInterpreter - * @brief Interprets the scan codes from the keyboard - */ - class KeyboardInterpreter : public common::InputStreamEventHandler, public common::EventManager { - - protected: - KeyboardState m_keyboard_state; ///< The current state of what special keys are pressed on the keyboard - - bool m_next_is_first_extended_code = false; ///< If true, the next code should be interpreted as an extended code (set when receiving 0xE0) - uint8_t m_extended_scan_code_bytes = 0; ///< How many bytes are left to read for the current extended scan code - uint16_t m_extended_code_buffer = 0; ///< The storage for scan codes that take more than one byte - - public: - KeyboardInterpreter(); - ~KeyboardInterpreter(); - - void on_key_read(bool, const KeyboardState &, KeyCode); - - }; - - /** - * @class KeyboardInterpreterEN_US - * @brief Interprets the scan codes from the keyboard for the EN_US keyboard layout - */ - class KeyboardInterpreterEN_US : public KeyboardInterpreter { - - public: - - /** - * @enum KeyCodeEN_US - * @brief The scan codes for the EN_US keyboard layout - */ - enum class KeyCodeEN_US { - // First Row - escape = 0x01, - f1 = 0x3B, - f2 = 0x3C, - f3 = 0x3D, - f4 = 0x3E, - f5 = 0x3F, - f6 = 0x40, - f7 = 0x41, - f8 = 0x42, - f9 = 0x43, - f10 = 0x44, - f11 = 0x57, - f12 = 0x58, - printScreen = 0x37, - scrollLock = 0x46, - pauseBreak = 0x45, - - // Second Row - squigglyLine = 0x29, - one = 0x02, - two = 0x03, - three = 0x04, - four = 0x05, - five = 0x06, - six = 0x07, - seven = 0x08, - eight = 0x09, - nine = 0x0A, - zero = 0x0B, - minus = 0x0C, - equals = 0x0D, - backspace = 0x0E, - insert = 0x52, - home = 0x47, - pageUp = 0x49, - numberPadLock = 0x45, - numberPadForwardSlash = 0x35, - numberPadMultiply = 0x37, - numberPadMinus = 0x4A, - - // Third Row - tab = 0x0F, - Q = 0x10, - W = 0x11, - E = 0x12, - R = 0x13, - T = 0x14, - Y = 0x15, - U = 0x16, - I = 0x17, - O = 0x18, - P = 0x19, - openSquareBracket = 0x1A, - closeSquareBracket = 0x1B, - backslash = 0x2B, - deleteKey = 0x53, - end = 0x4F, - pageDown = 0x51, - numberPadSeven = 0x47, - numberPadEight = 0x48, - numberPadNine = 0x49, - numberPadPlus = 0x4E, - - // Fourth Row - capsLock = 0x3A, - A = 0x1E, - S = 0x1F, - D = 0x20, - F = 0x21, - G = 0x22, - H = 0x23, - J = 0x24, - K = 0x25, - L = 0x26, - semicolon = 0x27, - apostrophe = 0x28, - enter = 0x1C, - numberPadFour = 0x4B, - numberPadFive = 0x4C, - numberPadSix = 0x4D, - - // Fifth Row - leftShift = 0x2A, - Z = 0x2C, - X = 0x2D, - C = 0x2E, - V = 0x2F, - B = 0x30, - N = 0x31, - M = 0x32, - comma = 0x33, - fullStop = 0x34, - forwardSlash = 0x35, - rightShift = 0x36, - upArrow = 0x48, - numberPadOne = 0x4F, - numberPadTwo = 0x50, - numberPadThree = 0x51, - numberPadEnter = 0x1C, - - // Sixth Row - leftControl = 0x1D, - leftOS = 0x5B, - leftAlt = 0x38, - space = 0x39, - rightAlt = 0x38, - function = 0x5D, - rightControl = 0x1D, - leftArrow = 0x4B, - downArrow = 0x50, - rightArrow = 0x4D, - numberPadZero = 0x52, - numberPadFullStop = 0x53 - }; - - KeyboardInterpreterEN_US(); - ~KeyboardInterpreterEN_US(); - - void on_stream_read(uint8_t scan_code) final; - - }; - - /** - * @class KeyboardDriver - * @brief Driver for the Keyboard Controller, manages the events and the keyboard state - */ - class KeyboardDriver : public hardwarecommunication::InterruptHandler, public Driver, public common::GenericInputStream { - - private: - hardwarecommunication::Port8Bit m_data_port; - hardwarecommunication::Port8Bit m_command_port; - - public: - KeyboardDriver(); - ~KeyboardDriver(); - - void handle_interrupt() final; - - void activate() final; - string device_name() final; - }; - } - } + void activate() final; + string device_name() final; + }; } + #endif //MAX_OS_DRIVERS_PERIPHERALS_KEYBOARD_H \ No newline at end of file diff --git a/kernel/include/drivers/peripherals/mouse.h b/kernel/include/drivers/peripherals/mouse.h index ab49bf5e..7a54c118 100644 --- a/kernel/include/drivers/peripherals/mouse.h +++ b/kernel/include/drivers/peripherals/mouse.h @@ -10,7 +10,7 @@ #define MAX_OS_DRIVERS_PERIPHERALS_MOUSE_H -#include +#include #include #include #include @@ -18,97 +18,94 @@ #include #include -namespace MaxOS { - namespace drivers { - namespace peripherals { - - /** - * @enum MouseEvents - * @brief The different types of mouse events that can be triggered - */ - enum class MouseEvents { - MOVE, - DOWN, - UP - }; - - /** - * @class MouseMoveEvent - * @brief Event that is triggered when the mouse moves, holds the x and y coordinates - */ - class MouseMoveEvent : public common::Event { - public: - int8_t x; ///< The x coordinate of the mouse - int8_t y; ///< The y coordinate of the mouse - MouseMoveEvent(int8_t x, int8_t y); - ~MouseMoveEvent(); - }; - - /** - * @class MouseDownEvent - * @brief Event that is triggered when a mouse button is pressed, holds the button that was pressed - */ - class MouseDownEvent : public common::Event { - public: - uint8_t button; ///< The button that was pressed - MouseDownEvent(uint8_t); - ~MouseDownEvent(); - }; - - /** - * @class MouseUpEvent - * @brief Event that is triggered when a mouse button is released, holds the button that was released - */ - class MouseUpEvent : public common::Event { - public: - uint8_t button; ///< The button that was released - MouseUpEvent(uint8_t); - ~MouseUpEvent(); - }; - - /** - * @class MouseEventHandler - * @brief Handles events that are triggered by the mouse driver - */ - class MouseEventHandler : public common::EventHandler { - - public: - MouseEventHandler(); - ~MouseEventHandler(); - - common::Event* - on_event(common::Event*) override; - - virtual void on_mouse_down_event(uint8_t button); - virtual void on_mouse_up_event(uint8_t button); - virtual void on_mouse_move_event(int8_t x, int8_t y); - }; - - /** - * @class MouseDriver - * @brief Driver for the PS/2 mouse, manages the mouse and triggers events when the mouse moves or a button is pressed - */ - class MouseDriver : public hardwarecommunication::InterruptHandler, public Driver, public common::EventManager { - - private: - hardwarecommunication::Port8Bit data_port; - hardwarecommunication::Port8Bit command_port; - - void handle_interrupt() final; - - uint8_t m_buffer[3] = { }; - uint8_t m_offset = 0; - uint8_t m_buttons = 0; - - public: - MouseDriver(); - ~MouseDriver(); - - void activate() final; - string device_name() final; - }; - } - } + +namespace MaxOS::drivers::peripherals { + + /** + * @enum MouseEvents + * @brief The different types of mouse events that can be triggered + */ + enum class MouseEvents { + MOVE, + DOWN, + UP + }; + + /** + * @class MouseMoveEvent + * @brief Event that is triggered when the mouse moves, holds the x and y coordinates + */ + class MouseMoveEvent : public common::Event { + public: + int8_t x; ///< The x coordinate of the mouse + int8_t y; ///< The y coordinate of the mouse + MouseMoveEvent(int8_t x, int8_t y); + ~MouseMoveEvent(); + }; + + /** + * @class MouseDownEvent + * @brief Event that is triggered when a mouse button is pressed, holds the button that was pressed + */ + class MouseDownEvent : public common::Event { + public: + uint8_t button; ///< The button that was pressed + explicit MouseDownEvent(uint8_t); + ~MouseDownEvent(); + }; + + /** + * @class MouseUpEvent + * @brief Event that is triggered when a mouse button is released, holds the button that was released + */ + class MouseUpEvent : public common::Event { + public: + uint8_t button; ///< The button that was released + explicit MouseUpEvent(uint8_t); + ~MouseUpEvent(); + }; + + /** + * @class MouseEventHandler + * @brief Handles events that are triggered by the mouse driver + */ + class MouseEventHandler : public common::EventHandler { + + public: + MouseEventHandler(); + ~MouseEventHandler(); + + common::Event* + on_event(common::Event*) override; + + virtual void on_mouse_down_event(uint8_t button); + virtual void on_mouse_up_event(uint8_t button); + virtual void on_mouse_move_event(int8_t x, int8_t y); + }; + + /** + * @class MouseDriver + * @brief Driver for the PS/2 mouse, manages the mouse and triggers events when the mouse moves or a button is pressed + */ + class MouseDriver : public hardwarecommunication::InterruptHandler, public Driver, public common::EventManager { + + private: + hardwarecommunication::Port8Bit data_port; + hardwarecommunication::Port8Bit command_port; + + void handle_interrupt() final; + + uint8_t m_buffer[3] = { }; + uint8_t m_offset = 0; + uint8_t m_buttons = 0; + + public: + MouseDriver(); + ~MouseDriver(); + + void activate() final; + string device_name() final; + }; } diff --git a/kernel/include/drivers/video/vesa.h b/kernel/include/drivers/video/vesa.h index c2868404..886ec9dd 100644 --- a/kernel/include/drivers/video/vesa.h +++ b/kernel/include/drivers/video/vesa.h @@ -9,7 +9,7 @@ #ifndef MAXOS_VIDEO_VESA_H #define MAXOS_VIDEO_VESA_H -#include +#include #include #include #include @@ -17,45 +17,40 @@ #include -namespace MaxOS { +namespace MaxOS::drivers::video { - namespace drivers { + /** + * @class VideoElectronicsStandardsAssociation + * @brief Driver for the VESA video controller, handles the rendering of pixels to the screen using VESA + */ + class VideoElectronicsStandardsAssociation : public VideoDriver { - namespace video { + private: + bool internal_set_mode(uint32_t width, uint32_t height, uint32_t) final; - /** - * @class VideoElectronicsStandardsAssociation - * @brief Driver for the VESA video controller, handles the rendering of pixels to the screen using VESA - */ - class VideoElectronicsStandardsAssociation : public VideoDriver { + void render_pixel_32_bit(uint32_t x, uint32_t y, uint32_t colour) final; + uint32_t get_rendered_pixel_32_bit(uint32_t x, uint32_t y) final; - private: - bool internal_set_mode(uint32_t width, uint32_t height, uint32_t) final; + // Memory + size_t m_framebuffer_size; - void render_pixel_32_bit( uint32_t x, uint32_t y, uint32_t colour) final; - uint32_t get_rendered_pixel_32_bit(uint32_t x, uint32_t y) final; + // Info + multiboot_tag_framebuffer* m_framebuffer_info; + uint8_t m_bpp; + uint16_t m_pitch; - // Memory - size_t m_framebuffer_size; + public: + explicit VideoElectronicsStandardsAssociation(multiboot_tag_framebuffer* framebuffer_info); + ~VideoElectronicsStandardsAssociation(); - // Info - multiboot_tag_framebuffer* m_framebuffer_info; - uint8_t m_bpp; - uint16_t m_pitch; + bool supports_mode(uint32_t width, uint32_t height, uint32_t) final; - public: - VideoElectronicsStandardsAssociation(multiboot_tag_framebuffer* framebuffer_info); - ~VideoElectronicsStandardsAssociation(); + string vendor_name() final; + string device_name() final; - bool supports_mode( uint32_t width, uint32_t height, uint32_t) final; + }; - string vendor_name() final; - string device_name() final; - - }; - - } - } } + #endif //MAXOS_VIDEO_VESA_H diff --git a/kernel/include/drivers/video/video.h b/kernel/include/drivers/video/video.h index a22fe398..c4d765b2 100644 --- a/kernel/include/drivers/video/video.h +++ b/kernel/include/drivers/video/video.h @@ -33,7 +33,7 @@ namespace MaxOS ~VideoDriver(); virtual bool supports_mode(uint32_t width, uint32_t height, uint32_t color_depth); - bool set_mode(uint32_t width, uint32_t height, uint32_t colorDepth); + bool set_mode(uint32_t width, uint32_t height, uint32_t color_depth); }; } diff --git a/kernel/include/filesystem/filesystem.h b/kernel/include/filesystem/filesystem.h index 58ae0748..7a4f555c 100644 --- a/kernel/include/filesystem/filesystem.h +++ b/kernel/include/filesystem/filesystem.h @@ -9,107 +9,105 @@ #ifndef MAXOS_FILESYSTEM_FILESYSTEM_H #define MAXOS_FILESYSTEM_FILESYSTEM_H -#include -#include +#include +#include #include #include #include #include #include -namespace MaxOS { - namespace filesystem { +namespace MaxOS::filesystem { - typedef uint32_t lba_t; ///< Logical Block Addressing type - typedef syscore::filesystem::SeekType SeekType; ///< Seek type for file operations + typedef uint32_t lba_t; ///< Logical Block Addressing type + typedef syscore::filesystem::SeekType SeekType; ///< Seek type for file operations - /** - * @class File - * @brief Handles file operations and information - */ - class File { + /** + * @class File + * @brief Handles file operations and information + */ + class File { - protected: - uint32_t m_offset; ///< The current offset in the file - string m_name; ///< The name of the file - size_t m_size; ///< The size of the file + protected: + uint32_t m_offset = 0; ///< The current offset in the file + string m_name; ///< The name of the file + size_t m_size = 0; ///< The size of the file - public: - File(); - virtual ~File(); + public: + File(); + virtual ~File(); - virtual void write(common::buffer_t* data, size_t size); - virtual void read(common::buffer_t* data, size_t size); - virtual void flush(); + virtual void write(common::buffer_t* data, size_t size); + virtual void read(common::buffer_t* data, size_t size); + virtual void flush(); - void seek(SeekType seek_type, size_t offset); - uint32_t position(); + void seek(SeekType seek_type, size_t offset); + [[nodiscard]] uint32_t position() const; - size_t size(); - string name(); - }; + [[nodiscard]] size_t size() const; + string name(); + }; - /** - * @class Directory - * @brief Handles a group of files (directory) - */ - class Directory { - protected: - common::Vector m_files; ///< The files in this directory - common::Vector m_subdirectories; ///< The subdirectories in this directory + /** + * @class Directory + * @brief Handles a group of files (directory) + */ + class Directory { + protected: + common::Vector m_files; ///< The files in this directory + common::Vector m_subdirectories; ///< The subdirectories in this directory - string m_name; ///< The name of this directory + string m_name; ///< The name of this directory - public: - Directory(); - virtual ~Directory(); + public: + Directory(); + virtual ~Directory(); - virtual void read_from_disk(); + virtual void read_from_disk(); - common::Vector files(); - common::Vector subdirectories(); + common::Vector files(); + common::Vector subdirectories(); - File* open_file(const string &name); - Directory* open_subdirectory(const string &name); + File* open_file(const string& name); + Directory* open_subdirectory(const string& name); - virtual File* create_file(const string &name); - virtual void remove_file(const string &name); + virtual File* create_file(const string& name); + virtual void remove_file(const string& name); - void rename_file(File* file, const string &new_name); - virtual void rename_file(const string &old_name, const string &new_name); + void rename_file(File* file, const string& new_name); + virtual void rename_file(const string& old_name, const string& new_name); - void rename_subdirectory(Directory* directory, const string &new_name); - virtual void rename_subdirectory(const string &old_name, const string &new_name); + void rename_subdirectory(Directory* directory, const string& new_name); + virtual void rename_subdirectory(const string& old_name, const string& new_name); - virtual Directory* create_subdirectory(const string &name); - virtual void remove_subdirectory(const string &name); + virtual Directory* create_subdirectory(const string& name); + virtual void remove_subdirectory(const string& name); - string name(); - size_t size(); - }; + string name(); + size_t size(); + }; - /** - * @class FileSystem - * @brief Handles the disk operations and file system information - */ - class FileSystem { - protected: - Directory* m_root_directory; ///< The fist directory in the file system (not be confused with the system root) + /** + * @class FileSystem + * @brief Handles the disk operations and file system information + */ + class FileSystem { + protected: + Directory* m_root_directory = nullptr; ///< The fist directory in the file system (not be confused with the system root) - public: - FileSystem(); - virtual ~FileSystem(); + public: + FileSystem(); + virtual ~FileSystem(); - Directory* root_directory(); - Directory* get_directory(const string &path); + Directory* root_directory(); + Directory* get_directory(const string& path); - bool exists(const string &path); - }; - - } + bool exists(const string& path); + }; } + #endif //MAXOS_FILESYSTEM_FILESYSTEM_H diff --git a/kernel/include/filesystem/format/ext2.h b/kernel/include/filesystem/format/ext2.h index b9d752a8..19a35e75 100644 --- a/kernel/include/filesystem/format/ext2.h +++ b/kernel/include/filesystem/format/ext2.h @@ -9,7 +9,7 @@ #ifndef MAXOS_FILESYSTEM_EXT2_H #define MAXOS_FILESYSTEM_EXT2_H -#include +#include #include #include #include @@ -17,456 +17,452 @@ #include #include -namespace MaxOS { - namespace filesystem { - namespace format { - namespace ext2 { - - /** - * @struct SuperBlock - * @brief The metadata of the ext2 filesystem. Found at an offset of 1024 bytes from the start of the partition. - * - * @typedef superblock_t - * @brief Alias for SuperBlock struct - */ - typedef struct PACKED SuperBlock { - uint32_t total_inodes; ///< Total number of inodes - uint32_t total_blocks; ///< Total number of blocks - uint32_t reserved_blocks; ///< Number of reserved blocks for superuser - uint32_t unallocated_blocks; ///< Number of free blocks - uint32_t unallocated_inodes; ///< Number of free inodes - uint32_t starting_block; ///< Where the superblock starts (normally 0 but not always) - uint32_t block_size; ///< Block size (as a power of 2, so 1024 << block_size) - uint32_t fragment_size; ///< Fragment size (as a power of 2, so 1024 << fragment_size) - uint32_t blocks_per_group; ///< Number of blocks per group - uint32_t fragments_per_group; ///< Number of fragments per group - uint32_t inodes_per_group; ///< Number of inodes per group - uint32_t last_mount_time; ///< Last time the filesystem was mounted (in seconds since the epoch) - uint32_t late_write_time; ///< Last time a block was written to (in seconds since the epoch) - uint16_t mounts_since_check; ///< Number of mounts since the last consistency check - uint16_t mounts_until_check; ///< Number of mounts allowed before a consistency check is needed (fsck) - uint16_t signature; ///< Filesystem magic signature (0xEF53) - uint16_t state; ///< The state of the filesystem (see FileSystemState) - uint16_t error_operation; ///< What to do when an error is detected (see ErrorOperation) - uint16_t version_minor; ///< Minor version number (combined with version_major to make version number) - uint32_t last_check_time; ///< Time of last consistency check (in seconds since the epoch) - uint32_t time_until_check; ///< Maximum time between checks (in seconds) - uint32_t os_id; ///< ID of the OS which created the filesystem (see CreatorOS) - uint32_t version_major; ///< Major version number (combined with version_minor to make version number) - uint16_t reserved_user; ///< User ID that can use reserved blocks - uint16_t reserved_group; ///< Group ID that can use reserved blocks - - // Extended Fields (version >= 1) - uint32_t first_inode; ///< Number of the first non-reserved inode (version < 1 this is 11) - uint16_t inode_size; ///< Size of each inode structure (version < 1 this is 128 bytes) - uint16_t superblock_group; ///< If there is a backup superblock, which group it is stored in - uint32_t optional_features; ///< Features that are not required for read/write support but can help performance (see OptionalFeatures) - uint32_t required_features; ///< Features that must be present for read/write support (see RequiredFeatures) - uint16_t read_only_features; ///< Features that are only required in read-only mode (see ReadOnlyFeatures) - uint8_t filesystem_id[16]; ///< A unique identifier for the filesystem - uint8_t volume_name[16]; ///< The volume name (is null-terminated) - uint8_t last_mount_path[64]; ///< The path where the filesystem was last mounted (is null-terminated) - uint32_t compression; ///< Compression algorithm used (0 = none, see RequiredFeatures) - uint8_t file_preallocation_blocks; ///< How many blocks should be allocated when creating a file - uint8_t directory_preallocation_blocks; ///< How many blocks should be allocated when creating a directory - uint16_t unused; ///< Reserved - uint8_t journal_id[16]; ///< A unique identifier for the journal - uint32_t journal_inode; ///< The inode number of the journal file - uint32_t journal_device; ///< The device number of the journal file - uint32_t orphan_inodes_start; ///< The start of the list of inodes without a directory entry that need to be deleted - uint8_t free[276]; ///< Reserved for future expansion - - } superblock_t; - - /** - * @enum FileSystemState - * @brief The state of the filesystem - */ - enum class FileSystemState { - CLEAN = 1, - ERROR = 2, - }; - - /** - * @enum ErrorOperation - * @brief What to do when an error occurs - */ - enum class ErrorOperation { - IGNORE = 1, - REMOUNT = 2, - PANIC = 3, - }; - - /** - * @enum CreatorOS - * @brief The OS which created the filesystem - * - * @todo Add MaxOS - */ - enum class CreatorOS { - LINUX, - GNU_HURD, - MASIX, - FREE_BSD, - OTHER_LITES, - }; - - /** - * @enum OptionalFeatures - * @brief What features that are optional are supported by this filesystem - */ - enum class OptionalFeatures { - PREALLOCATE_DIRECTORY = 0x1, - AFS_SERVER_INODES = 0x2, - JOURNAL_ENABLED = 0x4, - ATTRIBUTES_EXTENDED = 0x8, - RESIZEABLE = 0x10, - HASH_INDEXING = 0x20, - }; - - /** - * @enum RequiredFeatures - * @brief What features that are required are supported by this filesystem - */ - enum class RequiredFeatures { - COMPRESSION = 0x1, - DIRECTORY_HAS_TYPE = 0x2, - MUST_REPLAY_JOURNAL = 0x4, - JOURNAL_DEVICE = 0x8, - }; - - /** - * @enum ReadOnlyFeatures - * @brief What features that are only required in read-only mode - */ - enum class ReadOnlyFeatures { - SPARSE_SUPER_BLOCKS = 0x1, - FILES_64_BIT = 0x2, - BINARY_TREE_DIRECTORIES = 0x4, - }; - - /** - * @struct BlockGroupDescriptor - * @brief The metadata for a block group in ext2 - * - * @typedef block_group_descriptor_t - * @brief Alias for BlockGroupDescriptor struct - * - * @todo Support updating directory_count when creating/deleting directories - */ - typedef struct PACKED BlockGroupDescriptor { - uint32_t block_usage_bitmap; ///< The block address of the block usage bitmap - uint32_t block_inode_bitmap; ///< The block address of the inode usage bitmap - uint32_t inode_table_address; ///< The starting block address of the inode table - uint16_t free_blocks; ///< How many free blocks are in this block group - uint16_t free_inodes; ///< How many free inodes are in this block group - uint16_t directory_count; ///< How many directories are in this block group - uint8_t free[14]; ///< Reserved for future expansion - - } block_group_descriptor_t; - - /** - * @struct Inode - * @brief The metadata for a file or directory in ext2 - * - * @typedef inode_t - * @brief Alias for Inode struct - */ - typedef struct PACKED Inode { - union { - uint16_t type_permissions; ///< The type and permissions of the inode - struct { - uint16_t permissions: 12; ///< The permissions of the inode - uint16_t type: 4; ///< The type of the inode - }; - }; - uint16_t user_id; ///< The ID of the user who owns the inode - uint32_t size_lower; ///< The lower 32 bits of the size of the file in bytes - uint32_t last_access_time; ///< The seconds (since the epoch) of the last access time - uint32_t creation_time; ///< The seconds (since the epoch) of the time the inode was first allocated - uint32_t last_modification_time; ///< The seconds (since the epoch) of the last time the inode was written to - uint32_t deletion_time; ///< The seconds (since the epoch) of the time the inode was marked as not used - uint16_t group_id; ///< The ID of the group who owns the inode - uint16_t hard_links; ///< How many directory entries point to this inode - uint32_t sectors_used; ///< How many 512 byte sectors are used by this inode (not blocks) (not including this struct or directory entries linked to it) - uint32_t flags; ///< Flags for the inode (see InodeFlags) - uint32_t os_1; ///< OS specific value (0 for Linux/HURD, 'transaltor' for Masix) - uint32_t block_pointers[12]; ///< Pointers to the blocks that store the file's data (0 marks unused) - uint32_t l1_indirect; ///< Pointer to a block that contains more block pointers (see block_pointers) - uint32_t l2_indirect; ///< Pointer to a block that contains more l1_indirect pointers - uint32_t l3_indirect; ///< Pointer to a block that contains more l2_indirect pointers - uint32_t generation; ///< File version (used by NFS) - uint32_t extended_attribute; ///< File extended attribute block (Access Control List) - uint32_t size_upper; ///< The upper 32 bits of the size of the file in bytes (for files larger than 4GB). If this is a directory, this is the Directory Access Control List. - uint32_t os_2[3]; ///< Second OS specific value (see InodeOS2Linux, ...) - } inode_t; - - /** - * @enum InodeType - * @brief The type of an inode - */ - enum class InodeType { - UNKNOWN, - FIFO = 0x1000, - CHARACTER_DEVICE = 0x2000, - DIRECTORY = 0x4000, - BLOCK_DEVICE = 0x6000, - FILE = 0x8000, - SYMBOLIC_LINK = 0xA000, - SOCKET = 0xC000, - }; - - /** - * @enum InodePermissions - * @brief The permissions that an inode can have - */ - enum class InodePermissions{ - OTHER_EXECUTE = 0x1, - OTHER_WRITE = 0x2, - OTHER_READ = 0x4, - GROUP_EXECUTE = 0x8, - GROUP_WRITE = 0x10, - GROUP_READ = 0x20, - USER_EXECUTE = 0x40, - USER_WRITE = 0x80, - USER_READ = 0x100, - STICKY = 0x200, - GROUP_ID = 0x400, - USER_ID = 0x800, - }; - - /** - * @enum InodePermissionsDefaults - * @brief The default permissions for files and directories - * - * @todo Document these values - */ - enum class InodePermissionsDefaults { - FILE = 0x1A4, - DIRECTORY = 0x1ED, - }; - - /** - * @enum InodeFlags - * @brief The flags that can be set on an inode - */ - enum class InodeFlags { - SECURE_DELETE = 0x1, // Zero out data on deletion - KEEP_DATA = 0x2, - FILE_COMPRESSION = 0x4, - SYNC_UPDATES = 0x8, - FILE_IMMUTABLE = 0x10, - APPEND_ONLY = 0x20, - DONT_DUMP = 0x40, - NO_LAST_ACCESS = 0x80, - HASH_INDEXED = 0x10000, - AFS_DIRECTORY = 0x20000, - JOURNAL_FILE_DATA = 0x40000, - }; - - /** - * @struct InodeOS2Linux - * @brief The OS specific data for Linux created ext2 inodes - * - * @typedef linux_os_2_t - * @brief Alias for InodeOS2Linux struct - * - * @todo HURD, MASIX - */ - typedef struct PACKED InodeOS2Linux { - uint8_t fragment; ///< The fragment number - uint8_t fragment_size; ///< How many 1024 byte fragments are in the file - uint16_t high_type_permissions; ///< The high bits of the type & permissions - uint16_t high_user_id; ///< The high bits of the user ID - uint16_t high_group_id; ///< The high bits of the group ID - uint32_t author_id; ///< The user who created the inode (0xFFFFFFFF if use UID/GID fields) - } linux_os_2_t; - - /** - * @struct DirectoryEntry - * @brief An entry in a directory that points to a file or subdirectory (the name follows this struct) - * - * @typedef directory_entry_t - * @brief Alias for DirectoryEntry struct - */ - typedef struct PACKED DirectoryEntry { - uint32_t inode; ///< The inode number this entry points to (0 = unused) - uint16_t size; ///< The total size of this entry (including name) - uint8_t name_length; ///< The length of the name - uint8_t type; ///< The type of the entry (see EntryType) (only if the high bit of the superblock's optional_features is set) - // Rest are name chars - } directory_entry_t; - - /** - * @enum EntryType - * @brief The type of a directory entry - * - * @warning MaxOS only supports FILE, DIRECTORY - * @todo Support more - */ - enum class EntryType { - UNKNOWN, - FILE, - DIRECTORY, - CHARACTER_DEVICE, - BLOCK_DEVICE, - FIFO, - SOCKET, - SYMBOLIC_LINK - }; - - /** - * @class Ext2Volume - * @brief Common operations for an ext2 volume that are used by both files & directories (like block & inode allocation) - * - * @todo Free blocks - */ - class Ext2Volume { - - private: - common::Vector allocate_group_blocks(uint32_t block_group, uint32_t amount); - void free_group_blocks(uint32_t block_group, uint32_t amount, uint32_t start); - - - void write_back_block_groups() const; - void write_back_superblock(); - - public: - Ext2Volume(drivers::disk::Disk* disk, lba_t partition_offset); - ~Ext2Volume(); - - drivers::disk::Disk* disk; ///< The disk that this volume is on - lba_t partition_offset; ///< How far into the disk this partition starts - - superblock_t superblock; ///< The superblock of the ext2 filesystem - block_group_descriptor_t** block_groups; ///< The block group descriptors - - size_t block_size; ///< How large each block is (in bytes) - uint32_t block_group_descriptor_table_block; ///< Where the block group descriptor table starts - uint32_t block_group_descriptor_table_size; ///< How many block groups are in the block group descriptor table - uint32_t total_block_groups; ///< How many block groups are in the filesystem - size_t pointers_per_block; ///< How many block pointers fit in a block - uint32_t inodes_per_block; ///< How many inodes fit in a block - uint32_t sectors_per_block; ///< How many sectors does a block take - - common::Spinlock ext2_lock; ///< Lock for synchronised access to the volume (@todo: remove public?) - - void write_block(uint32_t block_num, common::buffer_t* buffer); - void write_inode(uint32_t inode_num, inode_t* inode); - - [[nodiscard]] uint32_t create_inode(bool is_directory); - void free_inode(uint32_t inode); - - void read_block(uint32_t block_num, common::buffer_t* buffer) const; - [[nodiscard]] inode_t read_inode(uint32_t inode_num) const; - - [[nodiscard]] uint32_t allocate_block(); - [[nodiscard]] common::Vector allocate_blocks(uint32_t amount); - [[nodiscard]] uint32_t bytes_to_blocks(size_t bytes) const; - - void free_blocks(const common::Vector &blocks); - }; - - /** - * @class InodeHandler - * @brief Simplfies the management of an inode & its blocks - */ - class InodeHandler { - - private: - Ext2Volume* m_volume = nullptr; - - void parse_indirect(uint32_t level, uint32_t block, common::buffer_t* buffer); - void write_indirect(uint32_t level, uint32_t &block, size_t &index); - void store_blocks(const common::Vector &blocks); - - public: - InodeHandler(Ext2Volume* volume, uint32_t inode); - ~InodeHandler(); - - uint32_t inode_number; ///< The index of the inode - inode_t inode; ///< The inode metadata for this file/directory - common::Vector block_cache; ///< All the blocks used by this inode - - [[nodiscard]] size_t size() const; - void set_size(size_t size); - size_t grow(size_t amount, bool flush = true); - - void save(); - void free(); - - }; - - /** - * @class Ext2File - * @brief Handles the file operations on the ext2 filesystem - */ - class Ext2File final : public File { - private: - Ext2Volume* m_volume; - InodeHandler m_inode; - - public: - Ext2File(Ext2Volume* volume, uint32_t inode, const string &name); - ~Ext2File() final; - - void write(common::buffer_t* data, size_t amount) final; - void read(common::buffer_t* data, size_t amount) final; - void flush() final; - }; - /** - * @class Ext2Directory - * @brief Handles the directory operations on the ext2 filesystem - */ - class Ext2Directory final : public Directory { +namespace MaxOS::filesystem::format::ext2 { + + /** + * @struct SuperBlock + * @brief The metadata of the ext2 filesystem. Found at an offset of 1024 bytes from the start of the partition. + * + * @typedef superblock_t + * @brief Alias for SuperBlock struct + */ + typedef struct PACKED SuperBlock { + uint32_t total_inodes; ///< Total number of inodes + uint32_t total_blocks; ///< Total number of blocks + uint32_t reserved_blocks; ///< Number of reserved blocks for superuser + uint32_t unallocated_blocks; ///< Number of free blocks + uint32_t unallocated_inodes; ///< Number of free inodes + uint32_t starting_block; ///< Where the superblock starts (normally 0 but not always) + uint32_t block_size; ///< Block size (as a power of 2, so 1024 << block_size) + uint32_t fragment_size; ///< Fragment size (as a power of 2, so 1024 << fragment_size) + uint32_t blocks_per_group; ///< Number of blocks per group + uint32_t fragments_per_group; ///< Number of fragments per group + uint32_t inodes_per_group; ///< Number of inodes per group + uint32_t last_mount_time; ///< Last time the filesystem was mounted (in seconds since the epoch) + uint32_t late_write_time; ///< Last time a block was written to (in seconds since the epoch) + uint16_t mounts_since_check; ///< Number of mounts since the last consistency check + uint16_t mounts_until_check; ///< Number of mounts allowed before a consistency check is needed (fsck) + uint16_t signature; ///< Filesystem magic signature (0xEF53) + uint16_t state; ///< The state of the filesystem (see FileSystemState) + uint16_t error_operation; ///< What to do when an error is detected (see ErrorOperation) + uint16_t version_minor; ///< Minor version number (combined with version_major to make version number) + uint32_t last_check_time; ///< Time of last consistency check (in seconds since the epoch) + uint32_t time_until_check; ///< Maximum time between checks (in seconds) + uint32_t os_id; ///< ID of the OS which created the filesystem (see CreatorOS) + uint32_t version_major; ///< Major version number (combined with version_minor to make version number) + uint16_t reserved_user; ///< User ID that can use reserved blocks + uint16_t reserved_group; ///< Group ID that can use reserved blocks + + // Extended Fields (version >= 1) + uint32_t first_inode; ///< Number of the first non-reserved inode (version < 1 this is 11) + uint16_t inode_size; ///< Size of each inode structure (version < 1 this is 128 bytes) + uint16_t superblock_group; ///< If there is a backup superblock, which group it is stored in + uint32_t optional_features; ///< Features that are not required for read/write support but can help performance (see OptionalFeatures) + uint32_t required_features; ///< Features that must be present for read/write support (see RequiredFeatures) + uint16_t read_only_features; ///< Features that are only required in read-only mode (see ReadOnlyFeatures) + uint8_t filesystem_id[16]; ///< A unique identifier for the filesystem + uint8_t volume_name[16]; ///< The volume name (is null-terminated) + uint8_t last_mount_path[64]; ///< The path where the filesystem was last mounted (is null-terminated) + uint32_t compression; ///< Compression algorithm used (0 = none, see RequiredFeatures) + uint8_t file_preallocation_blocks; ///< How many blocks should be allocated when creating a file + uint8_t directory_preallocation_blocks; ///< How many blocks should be allocated when creating a directory + uint16_t unused; ///< Reserved + uint8_t journal_id[16]; ///< A unique identifier for the journal + uint32_t journal_inode; ///< The inode number of the journal file + uint32_t journal_device; ///< The device number of the journal file + uint32_t orphan_inodes_start; ///< The start of the list of inodes without a directory entry that need to be deleted + uint8_t free[276]; ///< Reserved for future expansion + + } superblock_t; + + /** + * @enum FileSystemState + * @brief The state of the filesystem + */ + enum class FileSystemState { + CLEAN = 1, + ERROR = 2, + }; + + /** + * @enum ErrorOperation + * @brief What to do when an error occurs + */ + enum class ErrorOperation { + IGNORE = 1, + REMOUNT = 2, + PANIC = 3, + }; + + /** + * @enum CreatorOS + * @brief The OS which created the filesystem + * + * @todo Add MaxOS + */ + enum class CreatorOS { + LINUX, + GNU_HURD, + MASIX, + FREE_BSD, + OTHER_LITES, + }; + + /** + * @enum OptionalFeatures + * @brief What features that are optional are supported by this filesystem + */ + enum class OptionalFeatures { + PREALLOCATE_DIRECTORY = 0x1, + AFS_SERVER_INODES = 0x2, + JOURNAL_ENABLED = 0x4, + ATTRIBUTES_EXTENDED = 0x8, + RESIZEABLE = 0x10, + HASH_INDEXING = 0x20, + }; + + /** + * @enum RequiredFeatures + * @brief What features that are required are supported by this filesystem + */ + enum class RequiredFeatures { + COMPRESSION = 0x1, + DIRECTORY_HAS_TYPE = 0x2, + MUST_REPLAY_JOURNAL = 0x4, + JOURNAL_DEVICE = 0x8, + }; + + /** + * @enum ReadOnlyFeatures + * @brief What features that are only required in read-only mode + */ + enum class ReadOnlyFeatures { + SPARSE_SUPER_BLOCKS = 0x1, + FILES_64_BIT = 0x2, + BINARY_TREE_DIRECTORIES = 0x4, + }; + + /** + * @struct BlockGroupDescriptor + * @brief The metadata for a block group in ext2 + * + * @typedef block_group_descriptor_t + * @brief Alias for BlockGroupDescriptor struct + * + * @todo Support updating directory_count when creating/deleting directories + */ + typedef struct PACKED BlockGroupDescriptor { + uint32_t block_usage_bitmap; ///< The block address of the block usage bitmap + uint32_t block_inode_bitmap; ///< The block address of the inode usage bitmap + uint32_t inode_table_address; ///< The starting block address of the inode table + uint16_t free_blocks; ///< How many free blocks are in this block group + uint16_t free_inodes; ///< How many free inodes are in this block group + uint16_t directory_count; ///< How many directories are in this block group + uint8_t free[14]; ///< Reserved for future expansion + + } block_group_descriptor_t; + + /** + * @struct Inode + * @brief The metadata for a file or directory in ext2 + * + * @typedef inode_t + * @brief Alias for Inode struct + */ + typedef struct PACKED Inode { + union { + uint16_t type_permissions; ///< The type and permissions of the inode + struct { + uint16_t permissions : 12; ///< The permissions of the inode + uint16_t type : 4; ///< The type of the inode + }; + }; + uint16_t user_id; ///< The ID of the user who owns the inode + uint32_t size_lower; ///< The lower 32 bits of the size of the file in bytes + uint32_t last_access_time; ///< The seconds (since the epoch) of the last access time + uint32_t creation_time; ///< The seconds (since the epoch) of the time the inode was first allocated + uint32_t last_modification_time; ///< The seconds (since the epoch) of the last time the inode was written to + uint32_t deletion_time; ///< The seconds (since the epoch) of the time the inode was marked as not used + uint16_t group_id; ///< The ID of the group who owns the inode + uint16_t hard_links; ///< How many directory entries point to this inode + uint32_t sectors_used; ///< How many 512 byte sectors are used by this inode (not blocks) (not including this struct or directory entries linked to it) + uint32_t flags; ///< Flags for the inode (see InodeFlags) + uint32_t os_1; ///< OS specific value (0 for Linux/HURD, 'transaltor' for Masix) + uint32_t block_pointers[12]; ///< Pointers to the blocks that store the file's data (0 marks unused) + uint32_t l1_indirect; ///< Pointer to a block that contains more block pointers (see block_pointers) + uint32_t l2_indirect; ///< Pointer to a block that contains more l1_indirect pointers + uint32_t l3_indirect; ///< Pointer to a block that contains more l2_indirect pointers + uint32_t generation; ///< File version (used by NFS) + uint32_t extended_attribute; ///< File extended attribute block (Access Control List) + uint32_t size_upper; ///< The upper 32 bits of the size of the file in bytes (for files larger than 4GB). If this is a directory, this is the Directory Access Control List. + uint32_t os_2[3]; ///< Second OS specific value (see InodeOS2Linux, ...) + } inode_t; + + /** + * @enum InodeType + * @brief The type of an inode + */ + enum class InodeType { + UNKNOWN, + FIFO = 0x1000, + CHARACTER_DEVICE = 0x2000, + DIRECTORY = 0x4000, + BLOCK_DEVICE = 0x6000, + FILE = 0x8000, + SYMBOLIC_LINK = 0xA000, + SOCKET = 0xC000, + }; + + /** + * @enum InodePermissions + * @brief The permissions that an inode can have + */ + enum class InodePermissions { + OTHER_EXECUTE = 0x1, + OTHER_WRITE = 0x2, + OTHER_READ = 0x4, + GROUP_EXECUTE = 0x8, + GROUP_WRITE = 0x10, + GROUP_READ = 0x20, + USER_EXECUTE = 0x40, + USER_WRITE = 0x80, + USER_READ = 0x100, + STICKY = 0x200, + GROUP_ID = 0x400, + USER_ID = 0x800, + }; + + /** + * @enum InodePermissionsDefaults + * @brief The default permissions for files and directories + * + * @todo Document these values + */ + enum class InodePermissionsDefaults { + FILE = 0x1A4, + DIRECTORY = 0x1ED, + }; + + /** + * @enum InodeFlags + * @brief The flags that can be set on an inode + */ + enum class InodeFlags { + SECURE_DELETE = 0x1, // Zero out data on deletion + KEEP_DATA = 0x2, + FILE_COMPRESSION = 0x4, + SYNC_UPDATES = 0x8, + FILE_IMMUTABLE = 0x10, + APPEND_ONLY = 0x20, + DONT_DUMP = 0x40, + NO_LAST_ACCESS = 0x80, + HASH_INDEXED = 0x10000, + AFS_DIRECTORY = 0x20000, + JOURNAL_FILE_DATA = 0x40000, + }; + + /** + * @struct InodeOS2Linux + * @brief The OS specific data for Linux created ext2 inodes + * + * @typedef linux_os_2_t + * @brief Alias for InodeOS2Linux struct + * + * @todo HURD, MASIX + */ + typedef struct PACKED InodeOS2Linux { + uint8_t fragment; ///< The fragment number + uint8_t fragment_size; ///< How many 1024 byte fragments are in the file + uint16_t high_type_permissions; ///< The high bits of the type & permissions + uint16_t high_user_id; ///< The high bits of the user ID + uint16_t high_group_id; ///< The high bits of the group ID + uint32_t author_id; ///< The user who created the inode (0xFFFFFFFF if use UID/GID fields) + } linux_os_2_t; + + /** + * @struct DirectoryEntry + * @brief An entry in a directory that points to a file or subdirectory (the name follows this struct) + * + * @typedef directory_entry_t + * @brief Alias for DirectoryEntry struct + */ + typedef struct PACKED DirectoryEntry { + uint32_t inode; ///< The inode number this entry points to (0 = unused) + uint16_t size; ///< The total size of this entry (including name) + uint8_t name_length; ///< The length of the name + uint8_t type; ///< The type of the entry (see EntryType) (only if the high bit of the superblock's optional_features is set) + // Rest are name chars + } directory_entry_t; + + /** + * @enum EntryType + * @brief The type of a directory entry + * + * @warning MaxOS only supports FILE, DIRECTORY + * @todo Support more + */ + enum class EntryType { + UNKNOWN, + FILE, + DIRECTORY, + CHARACTER_DEVICE, + BLOCK_DEVICE, + FIFO, + SOCKET, + SYMBOLIC_LINK + }; + + /** + * @class Ext2Volume + * @brief Common operations for an ext2 volume that are used by both files & directories (like block & inode allocation) + * + * @todo Free blocks + */ + class Ext2Volume { + + private: + common::Vector allocate_group_blocks(uint32_t block_group, uint32_t amount); + void free_group_blocks(uint32_t block_group, uint32_t amount, uint32_t start); + + + void write_back_block_groups() const; + void write_back_superblock(); + + public: + Ext2Volume(drivers::disk::Disk* disk, lba_t partition_offset); + ~Ext2Volume(); + + drivers::disk::Disk* disk; ///< The disk that this volume is on + lba_t partition_offset; ///< How far into the disk this partition starts + + superblock_t superblock; ///< The superblock of the ext2 filesystem + block_group_descriptor_t** block_groups; ///< The block group descriptors + + size_t block_size; ///< How large each block is (in bytes) + uint32_t block_group_descriptor_table_block; ///< Where the block group descriptor table starts + uint32_t block_group_descriptor_table_size; ///< How many block groups are in the block group descriptor table + uint32_t total_block_groups; ///< How many block groups are in the filesystem + size_t pointers_per_block; ///< How many block pointers fit in a block + uint32_t inodes_per_block; ///< How many inodes fit in a block + uint32_t sectors_per_block; ///< How many sectors does a block take + + common::Spinlock ext2_lock; ///< Lock for synchronised access to the volume (@todo: remove public?) + + void write_block(uint32_t block_num, common::buffer_t* buffer) const; + void write_inode(uint32_t inode_num, inode_t* inode) const; + + [[nodiscard]] uint32_t create_inode(bool is_directory); + void free_inode(uint32_t inode); + + void read_block(uint32_t block_num, common::buffer_t* buffer) const; + [[nodiscard]] inode_t read_inode(uint32_t inode_num) const; + + [[nodiscard]] uint32_t allocate_block(); + [[nodiscard]] common::Vector allocate_blocks(uint32_t amount); + [[nodiscard]] uint32_t bytes_to_blocks(size_t bytes) const; + + void free_blocks(const common::Vector& blocks); + }; + + /** + * @class InodeHandler + * @brief Simplfies the management of an inode & its blocks + */ + class InodeHandler { + + private: + Ext2Volume* m_volume = nullptr; + + void parse_indirect(uint32_t level, uint32_t block, common::buffer_t* buffer); + void write_indirect(uint32_t level, uint32_t& block, size_t& index); + void store_blocks(const common::Vector& blocks); + + public: + InodeHandler(Ext2Volume* volume, uint32_t inode); + ~InodeHandler(); + + uint32_t inode_number; ///< The index of the inode + inode_t inode; ///< The inode metadata for this file/directory + common::Vector block_cache; ///< All the blocks used by this inode + + [[nodiscard]] size_t size() const; + void set_size(size_t size); + size_t grow(size_t amount, bool flush = true); + + void save(); + void free(); + + }; + + /** + * @class Ext2File + * @brief Handles the file operations on the ext2 filesystem + */ + class Ext2File final : public File { + private: + Ext2Volume* m_volume; + InodeHandler m_inode; + + public: + Ext2File(Ext2Volume* volume, uint32_t inode, const string& name); + ~Ext2File() final; - private: - Ext2Volume* m_volume; - InodeHandler m_inode; + void write(common::buffer_t* data, size_t amount) final; + void read(common::buffer_t* data, size_t amount) final; + void flush() final; + }; - common::Vector m_entries; - common::Vector m_entry_names; + /** + * @class Ext2Directory + * @brief Handles the directory operations on the ext2 filesystem + */ + class Ext2Directory final : public Directory { - void write_entries(); - directory_entry_t create_entry(const string &name, uint32_t inode, bool is_directory = false); + private: + Ext2Volume* m_volume; + InodeHandler m_inode; - void parse_block(common::buffer_t* buffer); + common::Vector m_entries; + common::Vector m_entry_names; - void remove_entry(const string &name, bool is_directory, bool clear = true); - void rename_entry(const string &old_name, const string &new_name, bool is_directory); - - public: - Ext2Directory(Ext2Volume* volume, uint32_t inode, const string &name); - ~Ext2Directory() final; - - void read_from_disk() final; - - File* create_file(const string &name) final; - void remove_file(const string &name) final; - void rename_file(const string &old_name, const string &new_name) final; + void write_entries(); + directory_entry_t create_entry(const string& name, uint32_t inode, bool is_directory = false); - Directory* create_subdirectory(const string &name) final; - void remove_subdirectory(const string &name) final; - void rename_subdirectory(const string &old_name, const string &new_name) final; - }; + void parse_block(common::buffer_t* buffer); + + void remove_entry(const string& name, bool is_directory, bool clear = true); + void rename_entry(const string& old_name, const string& new_name, bool is_directory); + + public: + Ext2Directory(Ext2Volume* volume, uint32_t inode, const string& name); + ~Ext2Directory() final; + + void read_from_disk() final; + + File* create_file(const string& name) final; + void remove_file(const string& name) final; + void rename_file(const string& old_name, const string& new_name) final; + + Directory* create_subdirectory(const string& name) final; + void remove_subdirectory(const string& name) final; + void rename_subdirectory(const string& old_name, const string& new_name) final; + }; + + /** + * @class Ext2FileSystem + * @brief Handles the ext2 filesystem operations + */ + class Ext2FileSystem final : public FileSystem { + private: + Ext2Volume m_volume; + + public: + Ext2FileSystem(drivers::disk::Disk* disk, uint32_t partition_offset); + ~Ext2FileSystem() final; + }; - /** - * @class Ext2FileSystem - * @brief Handles the ext2 filesystem operations - */ - class Ext2FileSystem final : public FileSystem { - private: - Ext2Volume m_volume; - - public: - Ext2FileSystem(drivers::disk::Disk* disk, uint32_t partition_offset); - ~Ext2FileSystem() final; - }; - - } - } - } } + #endif // MAXOS_FILESYSTEM_EXT2_H diff --git a/kernel/include/filesystem/format/fat32.h b/kernel/include/filesystem/format/fat32.h index c54e0f4c..9011bad4 100644 --- a/kernel/include/filesystem/format/fat32.h +++ b/kernel/include/filesystem/format/fat32.h @@ -13,288 +13,286 @@ #ifndef MAXOS_FILESYSTEM_FAT32_H #define MAXOS_FILESYSTEM_FAT32_H -#include +#include #include #include #include -namespace MaxOS { - namespace filesystem { - namespace format { - /** - * @struct BiosParameterBlock32 - * @brief Stores information about the FAT32 filesystem - * - * @typedef bpb32_t - * @brief Alias for BiosParameterBlock32 struct - */ - typedef struct PACKED BiosParameterBlock32 { - - uint8_t jump[3]; ///< Jump instruction to boot code - uint8_t OEM_name[8]; ///< OEM Name in ASCII - uint16_t bytes_per_sector; ///< Bytes per sector - uint8_t sectors_per_cluster; ///< Sectors per cluster - uint16_t reserved_sectors; ///< Number of reserved sectors - uint8_t table_copies; ///< Number of FAT tables - uint16_t root_entries; ///< Number of root directory entries - uint16_t total_sectors_16; ///< Total number of sectors (if zero, use total_sectors_32) - uint8_t media_type; ///< Media descriptor - uint16_t fat_sector_count; ///< Sectors per FAT (FAT12/FAT16 only) - uint16_t sectors_per_track; ///< Sectors per track - uint16_t head_count; ///< Number of heads/sides - uint32_t hidden_sectors; ///< Number of hidden sectors (LBA of start of partition) - uint32_t total_sectors_32; ///< Total number of sectors (if total_sectors_16 is zero) - - uint32_t table_size_32; ///< Sectors per FAT (FAT32 only) - uint16_t extended_flags; ///< Extended flags - uint16_t fat_version; ///< FAT version number (high byte major, low byte minor) - uint32_t root_cluster; ///< Cluster number of root directory start - uint16_t fat_info; ///< Sector number of FSInfo structure - uint16_t backup_sector; ///< Sector number of backup boot sector - uint8_t reserved0[12]; ///< Should be zero - uint8_t drive_number; ///< Drive number (must be identical to BIOS drive number) (0x00 = floppy, 0x80 = first hard disk) - uint8_t reserved_1; ///< Reserved (used by Windows NT) - uint8_t boot_signature; ///< Extended boot signature (0x28 or 0x29) - uint32_t volume_id; ///< Volume serial number - uint8_t volume_label[11]; ///< Volume label in ASCII (spaces padded) - uint8_t file_system_type[8]; ///< System type in ASCII (not null-terminated) - - } bpb32_t; +namespace MaxOS::filesystem::format { + + /** + * @struct BiosParameterBlock32 + * @brief Stores information about the FAT32 filesystem + * + * @typedef bpb32_t + * @brief Alias for BiosParameterBlock32 struct + */ + typedef struct PACKED BiosParameterBlock32 { + + uint8_t jump[3]; ///< Jump instruction to boot code + uint8_t OEM_name[8]; ///< OEM Name in ASCII + uint16_t bytes_per_sector; ///< Bytes per sector + uint8_t sectors_per_cluster; ///< Sectors per cluster + uint16_t reserved_sectors; ///< Number of reserved sectors + uint8_t table_copies; ///< Number of FAT tables + uint16_t root_entries; ///< Number of root directory entries + uint16_t total_sectors_16; ///< Total number of sectors (if zero, use total_sectors_32) + uint8_t media_type; ///< Media descriptor + uint16_t fat_sector_count; ///< Sectors per FAT (FAT12/FAT16 only) + uint16_t sectors_per_track; ///< Sectors per track + uint16_t head_count; ///< Number of heads/sides + uint32_t hidden_sectors; ///< Number of hidden sectors (LBA of start of partition) + uint32_t total_sectors_32; ///< Total number of sectors (if total_sectors_16 is zero) + + uint32_t table_size_32; ///< Sectors per FAT (FAT32 only) + uint16_t extended_flags; ///< Extended flags + uint16_t fat_version; ///< FAT version number (high byte major, low byte minor) + uint32_t root_cluster; ///< Cluster number of root directory start + uint16_t fat_info; ///< Sector number of FSInfo structure + uint16_t backup_sector; ///< Sector number of backup boot sector + uint8_t reserved0[12]; ///< Should be zero + uint8_t drive_number; ///< Drive number (must be identical to BIOS drive number) (0x00 = floppy, 0x80 = first hard disk) + uint8_t reserved_1; ///< Reserved (used by Windows NT) + uint8_t boot_signature; ///< Extended boot signature (0x28 or 0x29) + uint32_t volume_id; ///< Volume serial number + uint8_t volume_label[11]; ///< Volume label in ASCII (spaces padded) + uint8_t file_system_type[8]; ///< System type in ASCII (not null-terminated) + + } bpb32_t; + + /** + * @struct FSInfo + * @brief Stores extra information about the FAT32 filesystem + * + * @typedef fs_info_t + * @brief Alias for FSInfo struct + */ + typedef struct PACKED FSInfo { + uint32_t lead_signature; ///< FSInfo lead signature (0x41615252) + uint8_t reserved1[480]; ///< Reserved (should be zero) + uint32_t structure_signature; ///< FSInfo structure signature (0x61417272) + uint32_t free_cluster_count; ///< Number of free clusters (or 0xFFFFFFFF if unknown) (not reliable, must range check) + uint32_t next_free_cluster; ///< Cluster number of the next free cluster (or 0xFFFFFFFF if unknown, start searching from cluster 2) + uint8_t reserved2[12]; ///< Reserved (should be zero) + uint32_t trail_signature; ///< FSInfo trail signature (0xAA550000) + } fs_info_t; + + /** + * @struct DirectoryEntry + * @brief Stores information about a file or directory + * + * @typedef dir_entry_t + * @brief Alias for DirectoryEntry struct + */ + typedef struct PACKED DirectoryEntry { + + uint8_t name[8]; ///< File name + uint8_t extension[3]; ///< File extension + uint8_t attributes; ///< File attributes (see DirectoryEntryAttributes) + uint8_t reserved; ///< Reserved for Windows NT + + uint8_t creation_time_tenth; ///< Creation time in tenths of a second (or 100ths of a second) (0-199 on Windows, 0/100 on Linux) + uint16_t creation_time; ///< Creation time (HH:MM:SS) (multiply seconds by 2) + uint16_t creation_date; ///< Creation date (YYYY-MM-DD) + uint16_t last_access_date; ///< Last access date (YYYY-MM-DD) + + uint16_t first_cluster_high; ///< High word of this entry's first cluster number (usually 0 for FAT12/FAT16) + + uint16_t last_write_time; ///< Last write time (HH:MM:SS) (multiply seconds by 2) + uint16_t last_write_date; ///< Last write date (YYYY-MM-DD) + + uint16_t first_cluster_low; ///< Low word of this entry's first cluster number + + uint32_t size; ///< File size in bytes + + } dir_entry_t; + + /** + * @enum DirectoryEntryAttributes + * @brief Flags for a directory entry in a FAT32 System + */ + enum class DirectoryEntryAttributes { + FREE = 0x00, + READ_ONLY = 0x01, + HIDDEN = 0x02, + SYSTEM = 0x04, + VOLUME_ID = 0x08, + DIRECTORY = 0x10, + ARCHIVE = 0x20, + LONG_NAME = READ_ONLY | HIDDEN | SYSTEM | VOLUME_ID, + }; + + /** + * @enum DirectoryEntryType + * @brief The type of a directory entry + */ + enum class DirectoryEntryType { + LAST = 0x00, + FREE = 0xE5, + }; + + /** + * @struct LongFileNameEntry + * @brief Directory entry for a long file name + * + * @typedef long_file_name_entry_t + * @brief Alias for LongFileNameEntry struct + */ + typedef struct PACKED LongFileNameEntry { + uint8_t order; ///< Index of this entry in the sequence of LFN entries + uint16_t name1[5]; ///< First 5 characters of the long file name + uint8_t attributes; ///< Attributes (always 0x0F for LFN entries) + uint8_t type; ///< Type (always 0 for LFN entries) + uint8_t checksum; ///< checksum of the corresponding short file name + uint16_t name2[6]; ///< Next 6 characters of the long file name + uint16_t zero; ///< Must be zero + uint16_t name3[2]; ///< Last 2 characters of the long file name + + } long_file_name_entry_t; + + /** + * @enum ClusterState + * @brief The state of a cluster in the FAT32 filesystem + */ + enum class ClusterState : uint32_t { + FREE = 0x00000000, + BAD = 0x0FFFFFF7, + END_OF_CHAIN = 0xFFFFFFFF, + }; + + /// Highest number of characters in a file/directory name + constexpr uint16_t MAX_NAME_LENGTH = 255; + + /** + * @class Fat32Volume + * @brief Handles the FAT table that stores the information about the files on the disk and operations on the disk + */ + class Fat32Volume { + public: + Fat32Volume(drivers::disk::Disk* disk, lba_t partition_offset); + ~Fat32Volume(); + + bpb32_t bpb = { }; ///< The BIOS Parameter Block for the FAT32 volume + fs_info_t fsinfo = { }; ///< The FSInfo structure for the FAT32 volume + + size_t fat_total_clusters; ///< How many clusters are in the FAT table + lba_t fat_lba; ///< The starting LBA of the FAT table + lba_t fat_info_lba; ///< The LBA of the FSInfo structure + lba_t fat_copies; ///< How many FAT tables are present + + lba_t data_lba; ///< The starting LBA of the data region + lba_t root_lba; ///< The starting LBA of the root directory + + drivers::disk::Disk* disk; ///< The disk that this volume is on + + [[nodiscard]] uint32_t next_cluster(uint32_t cluster) const; + uint32_t set_next_cluster(uint32_t cluster, uint32_t next_cluster) const; + uint32_t find_free_cluster() const; + + uint32_t allocate_cluster(uint32_t cluster); + uint32_t allocate_cluster(uint32_t cluster, size_t amount); + + void free_cluster(uint32_t cluster); + void free_cluster(uint32_t cluster, size_t amount); + }; + + // Forward def + class Fat32Directory; + + /** + * @class Fat32File + * @brief Handles the file operations on the FAT32 filesystem + */ + class Fat32File final : public File { + + private: + Fat32Volume* m_volume; + Fat32Directory* m_parent_directory; + + dir_entry_t* m_entry; + uint32_t m_first_cluster; + + public: + Fat32File(Fat32Volume* volume, Fat32Directory* parent, dir_entry_t* info, const string& name); + ~Fat32File() final; + + void write(common::buffer_t* data, size_t amount) final; + void read(common::buffer_t* data, size_t amount) final; + void flush() final; /** - * @struct FSInfo - * @brief Stores extra information about the FAT32 filesystem - * - * @typedef fs_info_t - * @brief Alias for FSInfo struct + * @brief Get the first cluster of the directory + * @return The first cluster of the directory */ - typedef struct PACKED FSInfo { - uint32_t lead_signature; ///< FSInfo lead signature (0x41615252) - uint8_t reserved1[480]; ///< Reserved (should be zero) - uint32_t structure_signature; ///< FSInfo structure signature (0x61417272) - uint32_t free_cluster_count; ///< Number of free clusters (or 0xFFFFFFFF if unknown) (not reliable, must range check) - uint32_t next_free_cluster; ///< Cluster number of the next free cluster (or 0xFFFFFFFF if unknown, start searching from cluster 2) - uint8_t reserved2[12]; ///< Reserved (should be zero) - uint32_t trail_signature; ///< FSInfo trail signature (0xAA550000) - } fs_info_t; + [[nodiscard]] uint32_t first_cluster() const { return m_first_cluster; } + }; - /** - * @struct DirectoryEntry - * @brief Stores information about a file or directory - * - * @typedef dir_entry_t - * @brief Alias for DirectoryEntry struct - */ - typedef struct PACKED DirectoryEntry { + /** + * @class Fat32Directory + * @brief Handles the directory operations on the FAT32 filesystem + */ + class Fat32Directory final : public Directory { + friend class Fat32File; - uint8_t name[8]; ///< File name - uint8_t extension[3]; ///< File extension - uint8_t attributes; ///< File attributes (see DirectoryEntryAttributes) - uint8_t reserved; ///< Reserved for Windows NT + private: + Fat32Volume* m_volume; - uint8_t creation_time_tenth; ///< Creation time in tenths of a second (or 100ths of a second) (0-199 on Windows, 0/100 on Linux) - uint16_t creation_time; ///< Creation time (HH:MM:SS) (multiply seconds by 2) - uint16_t creation_date; ///< Creation date (YYYY-MM-DD) - uint16_t last_access_date; ///< Last access date (YYYY-MM-DD) + lba_t m_first_cluster; + lba_t m_last_cluster = 0; + size_t m_current_cluster_length = 0; - uint16_t first_cluster_high; ///< High word of this entry's first cluster number (usually 0 for FAT12/FAT16) + common::Vector m_entries; - uint16_t last_write_time; ///< Last write time (HH:MM:SS) (multiply seconds by 2) - uint16_t last_write_date; ///< Last write date (YYYY-MM-DD) + dir_entry_t* create_entry(const string& name, bool is_directory); + void remove_entry(lba_t cluster); + void read_all_entries(); - uint16_t first_cluster_low; ///< Low word of this entry's first cluster number + uint32_t entry_index(lba_t cluster); + int64_t find_free_entries(size_t amount); + int expand_directory(size_t amount); - uint32_t size; ///< File size in bytes + static common::Vector to_long_filenames(string name); + static string parse_long_filename(long_file_name_entry_t* entry, const string& current); - } dir_entry_t; + protected: - /** - * @enum DirectoryEntryAttributes - * @brief Flags for a directory entry in a FAT32 System - */ - enum class DirectoryEntryAttributes { - FREE = 0x00, - READ_ONLY = 0x01, - HIDDEN = 0x02, - SYSTEM = 0x04, - VOLUME_ID = 0x08, - DIRECTORY = 0x10, - ARCHIVE = 0x20, - LONG_NAME = READ_ONLY | HIDDEN | SYSTEM | VOLUME_ID, - }; + void save_entry_to_disk(dir_entry_t* entry); + void update_entry_on_disk(size_t index); - /** - * @enum DirectoryEntryType - * @brief The type of a directory entry - */ - enum class DirectoryEntryType { - LAST = 0x00, - FREE = 0xE5, - }; + public: + Fat32Directory(Fat32Volume* volume, lba_t cluster, const string& name); + ~Fat32Directory() final; - /** - * @struct LongFileNameEntry - * @brief Directory entry for a long file name - * - * @typedef long_file_name_entry_t - * @brief Alias for LongFileNameEntry struct - */ - typedef struct PACKED LongFileNameEntry { - uint8_t order; ///< Index of this entry in the sequence of LFN entries - uint16_t name1[5]; ///< First 5 characters of the long file name - uint8_t attributes; ///< Attributes (always 0x0F for LFN entries) - uint8_t type; ///< Type (always 0 for LFN entries) - uint8_t checksum; ///< Checksum of the corresponding short file name - uint16_t name2[6]; ///< Next 6 characters of the long file name - uint16_t zero; ///< Must be zero - uint16_t name3[2]; ///< Last 2 characters of the long file name - - } long_file_name_entry_t; + void read_from_disk() final; - /** - * @enum ClusterState - * @brief The state of a cluster in the FAT32 filesystem - */ - enum class ClusterState : uint32_t { - FREE = 0x00000000, - BAD = 0x0FFFFFF7, - END_OF_CHAIN = 0xFFFFFFFF, - }; + File* create_file(const string& name) final; + void remove_file(const string& name) final; - /// Highest number of characters in a file/directory name - constexpr uint16_t MAX_NAME_LENGTH = 255; + Directory* create_subdirectory(const string& name) final; + void remove_subdirectory(const string& name) final; /** - * @class Fat32Volume - * @brief Handles the FAT table that stores the information about the files on the disk and operations on the disk + * @brief Get the first cluster of the directory + * @return The first cluster of the directory */ - class Fat32Volume { - public: - Fat32Volume(drivers::disk::Disk* disk, lba_t partition_offset); - ~Fat32Volume(); - - bpb32_t bpb; ///< The BIOS Parameter Block for the FAT32 volume - fs_info_t fsinfo; ///< The FSInfo structure for the FAT32 volume - - size_t fat_total_clusters; ///< How many clusters are in the FAT table - lba_t fat_lba; ///< The starting LBA of the FAT table - lba_t fat_info_lba; ///< The LBA of the FSInfo structure - lba_t fat_copies; ///< How many FAT tables are present - - lba_t data_lba; ///< The starting LBA of the data region - lba_t root_lba; ///< The starting LBA of the root directory - - drivers::disk::Disk* disk; ///< The disk that this volume is on - - uint32_t next_cluster(uint32_t cluster); - uint32_t set_next_cluster(uint32_t cluster, uint32_t next_cluster); - uint32_t find_free_cluster(); - - uint32_t allocate_cluster(uint32_t cluster); - uint32_t allocate_cluster(uint32_t cluster, size_t amount); - - void free_cluster(uint32_t cluster); - void free_cluster(uint32_t cluster, size_t amount); - }; - - // Forward def - class Fat32Directory; - - /** - * @class Fat32File - * @brief Handles the file operations on the FAT32 filesystem - */ - class Fat32File final : public File { - - private: - Fat32Volume* m_volume; - Fat32Directory* m_parent_directory; - - dir_entry_t* m_entry; - uint32_t m_first_cluster; + [[nodiscard]] lba_t first_cluster() const { return m_first_cluster; } + }; + + /** + * @class Fat32FileSystem + * @brief Handles the FAT32 filesystem operations + */ + class Fat32FileSystem final : public FileSystem { + private: + Fat32Volume m_volume; + + public: + Fat32FileSystem(drivers::disk::Disk* disk, uint32_t partition_offset); + ~Fat32FileSystem() final; + }; - public: - Fat32File(Fat32Volume* volume, Fat32Directory* parent, dir_entry_t* info, const string &name); - ~Fat32File() final; - - void write(common::buffer_t* data, size_t amount) final; - void read(common::buffer_t* data, size_t amount) final; - void flush() final; - - /** - * @brief Get the first cluster of the directory - * @return The first cluster of the directory - */ - [[nodiscard]] uint32_t first_cluster() const { return m_first_cluster; } - }; - - /** - * @class Fat32Directory - * @brief Handles the directory operations on the FAT32 filesystem - */ - class Fat32Directory : public Directory { - friend class Fat32File; - - private: - Fat32Volume* m_volume; - - lba_t m_first_cluster; - lba_t m_last_cluster; - size_t m_current_cluster_length = 0; - - common::Vector m_entries; - - dir_entry_t* create_entry(const string &name, bool is_directory); - void remove_entry(lba_t cluster, const string &name); - void read_all_entries(); - - uint32_t entry_index(lba_t cluster); - int find_free_entries(size_t amount); - int expand_directory(size_t amount); - - static common::Vector to_long_filenames(string name); - static string parse_long_filename(long_file_name_entry_t* entry, const string ¤t); - - protected: - - void save_entry_to_disk(dir_entry_t* entry); - void update_entry_on_disk(int index); - - public: - Fat32Directory(Fat32Volume* volume, lba_t cluster, const string &name); - ~Fat32Directory(); - - void read_from_disk() final; - - File* create_file(const string &name) final; - void remove_file(const string &name) final; - - Directory* create_subdirectory(const string &name) final; - void remove_subdirectory(const string &name) final; - - /** - * @brief Get the first cluster of the directory - * @return The first cluster of the directory - */ - [[nodiscard]] lba_t first_cluster() const { return m_first_cluster; } - }; - - /** - * @class Fat32FileSystem - * @brief Handles the FAT32 filesystem operations - */ - class Fat32FileSystem : public FileSystem { - private: - Fat32Volume m_volume; - - public: - Fat32FileSystem(drivers::disk::Disk* disk, uint32_t partition_offset); - ~Fat32FileSystem(); - }; - - } - } } + #endif //MAXOS_FILESYSTEM_FAT32_H diff --git a/kernel/include/filesystem/partition/msdos.h b/kernel/include/filesystem/partition/msdos.h index 7eb5c36c..751eb254 100644 --- a/kernel/include/filesystem/partition/msdos.h +++ b/kernel/include/filesystem/partition/msdos.h @@ -9,353 +9,349 @@ #ifndef MAXOS_FILESYSTEM_PARTITION_MSDOS_H #define MAXOS_FILESYSTEM_PARTITION_MSDOS_H -#include +#include #include #include #include #include -namespace MaxOS { - - namespace filesystem { - - namespace partition { - - /// Credit: http://www.osdever.net/documents/pdf/partitiontypes.pdf - enum class PartitionType { - EMPTY, // 0x00 - FAT12, // 0x01 - XENIX_ROOT, // 0x02 - XENIX_USR, // 0x03 - FAT16, // 0x04 - EXTENDED, // 0x05 - FAT16_32MB, // 0x06 - NTFS, // 0x07 - QNX_QNY, // 0x08 - AIX_DATA, // 0x09 - OS2_BOOT_MANAGER, // 0x0A - FAT32, // 0x0B - FAT32_LBA, // 0x0C - UNUSED_1, // 0x0D - FAT16_LBA, // 0x0E - EXTENDED_LBA, // 0x0F - OPUS, // 0x10 - FAT12_HIDDEN, // 0x11 - COMPAQ, // 0x12 - UNUSED_2, // 0x13 - FAT16_HIDDEN, // 0x14 - UNUSED_3, // 0x15 - FAT16_32MB_HIDDEN, // 0x16 - IFS_HIDDEN, // 0x17 - AST_SMART_SLEEP, // 0x18 - UNUSED_4, // 0x19 - UNUSED_5, // 0x1A - FAT32_HIDDEN, // 0x1B - FAT32_LBA_HIDDEN, // 0x1C - UNUSED_6, // 0x1D - FAT16_LBA_HIDDEN, // 0x1E - - UNUSED_7, // 0x1F - UNUSED_8, // 0x20 - RESERVED_1, // 0x21 - UNUSED_10, // 0x22 - RESERVED_2, // 0x23 - NEC_DOS, // 0x24 - UNUSED_11, // 0x25 - RESERVED_3, // 0x26 - - // 0x27 - 0x30: unassigned - UNUSED_12, // 0x27 - UNUSED_13, // 0x28 - UNUSED_14, // 0x29 - UNUSED_15, // 0x2A - UNUSED_16, // 0x2B - UNUSED_17, // 0x2C - UNUSED_18, // 0x2D - UNUSED_19, // 0x2E - UNUSED_20, // 0x2F - UNUSED_21, // 0x30 - - RESERVED_4, // 0x31 - NOS, // 0x32 - RESERVED_5, // 0x33 - RESERVED_6, // 0x34 - JFS, // 0x35 - RESERVED_7, // 0x36 - UNUSED_22, // 0x37 - THEOS_3_2, // 0x38 - PLAN9, // 0x39 - THEOS_4_4GB, // 0x3A - THEOS_4_EXTENDED, // 0x3B - PARTITIONMAGIC_RECOVERY, // 0x3C - HIDDEN_NETWARE, // 0x3D - UNUSED_23, // 0x3E - UNUSED_24, // 0x3F - - VENIX, // 0x40 - LINUX_MINIX, // 0x41 - LINUX_SWAP, // 0x42 - LINUX_NATIVE, // 0x43 - GOBACK, // 0x44 - BOOT_US, // 0x45 - EUMEL_ELAN_46, // 0x46 - EUMEL_ELAN_47, // 0x47 - EUMEL_ELAN_48, // 0x48 - UNUSED_25, // 0x49 - ADAOS, // 0x4A - UNUSED_26, // 0x4B - OBERON, // 0x4C - QNX4, // 0x4D - QNX4_SECOND, // 0x4E - QNX4_THIRD, // 0x4F - - ONTRACK_DM, // 0x50 - ONTRACK_DM_RW, // 0x51 - CPM, // 0x52 - DISK_MANAGER_AUX3, // 0x53 - DISK_MANAGER_DDO, // 0x54 - EZ_DRIVE, // 0x55 - GOLDEN_BOW, // 0x56 - DRIVE_PRO, // 0x57 - - UNUSED_27, // 0x58 - UNUSED_28, // 0x59 - UNUSED_29, // 0x5A - UNUSED_30, // 0x5B - PRIAM_EDISK, // 0x5C - UNUSED_31, // 0x5D - UNUSED_32, // 0x5E - UNUSED_33, // 0x5F - - UNUSED_34, // 0x60 - SPEEDSTOR, // 0x61 - UNUSED_35, // 0x62 - UNIX, // 0x63 - PC_ARMOUR, // 0x64 - NOVELL_NETWARE386, // 0x65 - NOVELL_SMS, // 0x66 - NOVELL, // 0x67 - NOVELL_OLD, // 0x68 - NOVELL_NETWARE_NSS, // 0x69 - - UNUSED_36, // 0x6A - UNUSED_37, // 0x6B - UNUSED_38, // 0x6C - UNUSED_39, // 0x6D - UNUSED_40, // 0x6E - UNUSED_41, // 0x6F - - DISKSECURE, // 0x70 - RESERVED_8, // 0x71 - UNUSED_42, // 0x72 - RESERVED_9, // 0x73 - SCRAMDISK, // 0x74 - IBM_PCIX, // 0x75 - RESERVED_10, // 0x76 - M2FS, // 0x77 - XOSL_FS, // 0x78 - UNUSED_43, // 0x79 - UNUSED_44, // 0x7A - UNUSED_45, // 0x7B - UNUSED_46, // 0x7C - UNUSED_47, // 0x7D - UNUSED_48, // 0x7E - UNUSED_49, // 0x7F - - MINIX, // 0x80 - MINIX2, // 0x81 - LINUX_SWAP_ALT, // 0x82 - LINUX_EXT2, // 0x83 - HIBERNATION, // 0x84 - LINUX_EXTENDED, // 0x85 - LINUX_RAID, // 0x86 - NTFS_VOLUME_SET, // 0x87 - UNUSED_50, // 0x88 - UNUSED_51, // 0x89 - LINUX_KERNEL, // 0x8A - FAULT_TOLERANT_FAT32, // 0x8B - FT_FAT32_LBA, // 0x8C - FREEFDISK_FAT12, // 0x8D - LINUX_LVM, // 0x8E - UNUSED_52, // 0x8F - FREEFDISK_FAT16, // 0x90 - FREEFDISK_EXTENDED, // 0x91 - FREEFDISK_FAT16_LARGE, // 0x92 - HIDDEN_LINUX_NATIVE, // 0x93 - AMOEBA_BAD_BLOCK, // 0x94 - MIT_EXOPC, // 0x95 - UNUSED_53, // 0x96 - FREEFDISK_FAT32, // 0x97 - FREEFDISK_FAT32_LBA, // 0x98 - DCE376, // 0x99 - FREEFDISK_FAT16_LBA, // 0x9A - FREEFDISK_EXTENDED_LBA,// 0x9B - - UNUSED_54, // 0x9C - UNUSED_55, // 0x9D - UNUSED_56, // 0x9E - - BSD_OS, // 0x9F - LAPTOP_HIBERNATION, // 0xA0 - HP_VOLUME_EXPANSION, // 0xA1 - UNUSED_57, // 0xA2 - RESERVED_11, // 0xA3 - RESERVED_12, // 0xA4 - BSD_386, // 0xA5 - OPENBSD, // 0xA6 - NEXTSTEP, // 0xA7 - MAC_OS_X, // 0xA8 - NETBSD, // 0xA9 - OLIVETTI_SERVICE, // 0xAA - MAC_OS_X_BOOT, // 0xAB - UNUSED_58, // 0xAC - UNUSED_59, // 0xAD - SHAGOS, // 0xAE - SHAGOS_SWAP, // 0xAF - BOOTSTAR, // 0xB0 - - RESERVED_13, // 0xB1 - UNUSED_60, // 0xB2 - RESERVED_14, // 0xB3 - RESERVED_15, // 0xB4 - UNUSED_61, // 0xB5 - RESERVED_16, // 0xB6 - - BSDI_BSD386_FS, // 0xB7 - BSDI_BSD386_SWAP, // 0xB8 - UNUSED_62, // 0xB9 - UNUSED_63, // 0xBA - BOOT_WIZARD_HIDDEN, // 0xBB - UNUSED_64, // 0xBC - UNUSED_65, // 0xBD - SOLARIS8_BOOT, // 0xBE - UNUSED_66, // 0xBF - CTOS, // 0xC0 - DRDOS_FAT12, // 0xC1 - RESERVED_17, // 0xC2 - HIDDEN_LINUX_SWAP, // 0xC3 - DRDOS_FAT16, // 0xC4 - DRDOS_EXTENDED, // 0xC5 - DRDOS_FAT16_LARGE, // 0xC6 - NTFS_CORRUPT, // 0xC7 - - UNUSED_67, // 0xC8 - UNUSED_68, // 0xC9 - UNUSED_69, // 0xCA - - DRDOS_FAT32, // 0xCB - DRDOS_FAT32_LBA, // 0xCC - CTOS_MEMDUMP, // 0xCD - DRDOS_FAT16_LBA, // 0xCE - UNUSED_70, // 0xCF - REAL32_SECURE_BIG, // 0xD0 - OLD_MULTIUSER_DOS_FAT12,// 0xD1 - UNUSED_71, // 0xD2 - UNUSED_72, // 0xD3 - OLD_MULTIUSER_DOS_FAT16,// 0xD4 - OLD_MULTIUSER_DOS_EXTENDED,// 0xD5 - OLD_MULTIUSER_DOS_FAT16_LARGE,// 0xD6 - UNUSED_73, // 0xD7 - CPM86, // 0xD8 - UNUSED_74, // 0xD9 - NON_FS_DATA, // 0xDA - DIGITAL_RESEARCH_CPM, // 0xDB - UNUSED_75, // 0xDC - HIDDEN_CTOS_MEMDUMP, // 0xDD - DELL_POWEREDGE, // 0xDE - DGUX, // 0xDF - STM_AVFS, // 0xE0 - SPEEDSTOR_FAT_EXTENDED,// 0xE1 - UNUSED_76, // 0xE2 - SPEEDSTOR_RO, // 0xE3 - SPEEDSTOR_EXTENDED, // 0xE4 - TANDY_DOS, // 0xE5 - - RESERVED_18, // 0xE6 - UNUSED_77, // 0xE7 - UNUSED_78, // 0xE8 - UNUSED_79, // 0xE9 - - BEFS, // 0xEA - SPRYTIX, // 0xEB - EFI_PROTECTIVE, // 0xEE - EFI_SYSTEM, // 0xEF - LINUX_PA_RISC, // 0xF0 - SPEEDSTOR_2, // 0xF1 - DOS_3_3_SECONDARY, // 0xF2 - RESERVED_19, // 0xF3 - SPEEDSTOR_LARGE, // 0xF4 - PROLOGUE_MULTI, // 0xF5 - RESERVED_20, // 0xF6 - UNUSED_80, // 0xF7 - UNUSED_81, // 0xF8 - UNUSED_82, // 0xF9 - BOCHS, // 0xFA - VMFS, // 0xFB - VMWARE_SWAP, // 0xFC - LINUX_RAID_AUTO, // 0xFD - NT_HIDDEN, // 0xFE - XENIX_BAD_BLOCK // 0xFF - }; - - /** - * @struct PartitionTableEntry - * @brief Stores information about a partition - * - * @typedef partition_table_entry_t - * @brief Alias for PartitionTableEntry struct - */ - typedef struct PACKED PartitionTableEntry { - - uint8_t bootable; ///< Is this partition bootable? (0x80 = bootable, 0x00 = not bootable) - - uint8_t start_head; ///< The starting head of the partition - uint8_t start_sector: 6; ///< The first sector of the partition - uint16_t start_cylinder: 10; ///< The starting cylinder of the partition - - uint8_t type; ///< The partition type (see PartitionType enum) - - uint8_t end_head; ///< The last head of the partition - uint8_t end_sector: 6; ///< The last sector of the partition - uint16_t end_cylinder: 10; ///< The last cylinder of the partition - - uint32_t start_LBA; ///< The starting LBA of the partition - uint32_t length; ///< The length of the partition in sectors - - } partition_table_entry_t; - - /** - * @struct MasterBootRecord - * @brief Stores information about the master boot record - * - * @typedef master_boot_record_t - * @brief Alias for MasterBootRecord struct - */ - typedef struct PACKED MasterBootRecord { - - uint8_t bootloader[440]; ///< The assembly bytes that make up the bootloader software - uint32_t disk_signature; ///< Unique disk signature (optional) - uint16_t unused; ///< Reserved (usually zero) - - PartitionTableEntry primary_partition[4]; ///< The partition table entries - - uint16_t magic; ///< The magic number that identifies this as a valid MBR (0xAA55) - - } master_boot_record_t; - - - /** - * @class MSDOSPartition - * @brief Handles mounting of partitions documented in an MSDOS partition table - * - * @todo Abstract some of this into a base class and use it for GPT and other partition tables - */ - class MSDOSPartition { - public: - static void mount_partitions(drivers::disk::Disk* disk); - }; - } - } + +namespace MaxOS::filesystem::partition { + + /// Credit: http://www.osdever.net/documents/pdf/partitiontypes.pdf + enum class PartitionType { + EMPTY, // 0x00 + FAT12, // 0x01 + XENIX_ROOT, // 0x02 + XENIX_USR, // 0x03 + FAT16, // 0x04 + EXTENDED, // 0x05 + FAT16_32MB, // 0x06 + NTFS, // 0x07 + QNX_QNY, // 0x08 + AIX_DATA, // 0x09 + OS2_BOOT_MANAGER, // 0x0A + FAT32, // 0x0B + FAT32_LBA, // 0x0C + UNUSED_1, // 0x0D + FAT16_LBA, // 0x0E + EXTENDED_LBA, // 0x0F + OPUS, // 0x10 + FAT12_HIDDEN, // 0x11 + COMPAQ, // 0x12 + UNUSED_2, // 0x13 + FAT16_HIDDEN, // 0x14 + UNUSED_3, // 0x15 + FAT16_32MB_HIDDEN, // 0x16 + IFS_HIDDEN, // 0x17 + AST_SMART_SLEEP, // 0x18 + UNUSED_4, // 0x19 + UNUSED_5, // 0x1A + FAT32_HIDDEN, // 0x1B + FAT32_LBA_HIDDEN, // 0x1C + UNUSED_6, // 0x1D + FAT16_LBA_HIDDEN, // 0x1E + + UNUSED_7, // 0x1F + UNUSED_8, // 0x20 + RESERVED_1, // 0x21 + UNUSED_10, // 0x22 + RESERVED_2, // 0x23 + NEC_DOS, // 0x24 + UNUSED_11, // 0x25 + RESERVED_3, // 0x26 + + // 0x27 - 0x30: unassigned + UNUSED_12, // 0x27 + UNUSED_13, // 0x28 + UNUSED_14, // 0x29 + UNUSED_15, // 0x2A + UNUSED_16, // 0x2B + UNUSED_17, // 0x2C + UNUSED_18, // 0x2D + UNUSED_19, // 0x2E + UNUSED_20, // 0x2F + UNUSED_21, // 0x30 + + RESERVED_4, // 0x31 + NOS, // 0x32 + RESERVED_5, // 0x33 + RESERVED_6, // 0x34 + JFS, // 0x35 + RESERVED_7, // 0x36 + UNUSED_22, // 0x37 + THEOS_3_2, // 0x38 + PLAN9, // 0x39 + THEOS_4_4GB, // 0x3A + THEOS_4_EXTENDED, // 0x3B + PARTITIONMAGIC_RECOVERY, // 0x3C + HIDDEN_NETWARE, // 0x3D + UNUSED_23, // 0x3E + UNUSED_24, // 0x3F + + VENIX, // 0x40 + LINUX_MINIX, // 0x41 + LINUX_SWAP, // 0x42 + LINUX_NATIVE, // 0x43 + GOBACK, // 0x44 + BOOT_US, // 0x45 + EUMEL_ELAN_46, // 0x46 + EUMEL_ELAN_47, // 0x47 + EUMEL_ELAN_48, // 0x48 + UNUSED_25, // 0x49 + ADAOS, // 0x4A + UNUSED_26, // 0x4B + OBERON, // 0x4C + QNX4, // 0x4D + QNX4_SECOND, // 0x4E + QNX4_THIRD, // 0x4F + + ONTRACK_DM, // 0x50 + ONTRACK_DM_RW, // 0x51 + CPM, // 0x52 + DISK_MANAGER_AUX3, // 0x53 + DISK_MANAGER_DDO, // 0x54 + EZ_DRIVE, // 0x55 + GOLDEN_BOW, // 0x56 + DRIVE_PRO, // 0x57 + + UNUSED_27, // 0x58 + UNUSED_28, // 0x59 + UNUSED_29, // 0x5A + UNUSED_30, // 0x5B + PRIAM_EDISK, // 0x5C + UNUSED_31, // 0x5D + UNUSED_32, // 0x5E + UNUSED_33, // 0x5F + + UNUSED_34, // 0x60 + SPEEDSTOR, // 0x61 + UNUSED_35, // 0x62 + UNIX, // 0x63 + PC_ARMOUR, // 0x64 + NOVELL_NETWARE386, // 0x65 + NOVELL_SMS, // 0x66 + NOVELL, // 0x67 + NOVELL_OLD, // 0x68 + NOVELL_NETWARE_NSS, // 0x69 + + UNUSED_36, // 0x6A + UNUSED_37, // 0x6B + UNUSED_38, // 0x6C + UNUSED_39, // 0x6D + UNUSED_40, // 0x6E + UNUSED_41, // 0x6F + + DISKSECURE, // 0x70 + RESERVED_8, // 0x71 + UNUSED_42, // 0x72 + RESERVED_9, // 0x73 + SCRAMDISK, // 0x74 + IBM_PCIX, // 0x75 + RESERVED_10, // 0x76 + M2FS, // 0x77 + XOSL_FS, // 0x78 + UNUSED_43, // 0x79 + UNUSED_44, // 0x7A + UNUSED_45, // 0x7B + UNUSED_46, // 0x7C + UNUSED_47, // 0x7D + UNUSED_48, // 0x7E + UNUSED_49, // 0x7F + + MINIX, // 0x80 + MINIX2, // 0x81 + LINUX_SWAP_ALT, // 0x82 + LINUX_EXT2, // 0x83 + HIBERNATION, // 0x84 + LINUX_EXTENDED, // 0x85 + LINUX_RAID, // 0x86 + NTFS_VOLUME_SET, // 0x87 + UNUSED_50, // 0x88 + UNUSED_51, // 0x89 + LINUX_KERNEL, // 0x8A + FAULT_TOLERANT_FAT32, // 0x8B + FT_FAT32_LBA, // 0x8C + FREEFDISK_FAT12, // 0x8D + LINUX_LVM, // 0x8E + UNUSED_52, // 0x8F + FREEFDISK_FAT16, // 0x90 + FREEFDISK_EXTENDED, // 0x91 + FREEFDISK_FAT16_LARGE, // 0x92 + HIDDEN_LINUX_NATIVE, // 0x93 + AMOEBA_BAD_BLOCK, // 0x94 + MIT_EXOPC, // 0x95 + UNUSED_53, // 0x96 + FREEFDISK_FAT32, // 0x97 + FREEFDISK_FAT32_LBA, // 0x98 + DCE376, // 0x99 + FREEFDISK_FAT16_LBA, // 0x9A + FREEFDISK_EXTENDED_LBA,// 0x9B + + UNUSED_54, // 0x9C + UNUSED_55, // 0x9D + UNUSED_56, // 0x9E + + BSD_OS, // 0x9F + LAPTOP_HIBERNATION, // 0xA0 + HP_VOLUME_EXPANSION, // 0xA1 + UNUSED_57, // 0xA2 + RESERVED_11, // 0xA3 + RESERVED_12, // 0xA4 + BSD_386, // 0xA5 + OPENBSD, // 0xA6 + NEXTSTEP, // 0xA7 + MAC_OS_X, // 0xA8 + NETBSD, // 0xA9 + OLIVETTI_SERVICE, // 0xAA + MAC_OS_X_BOOT, // 0xAB + UNUSED_58, // 0xAC + UNUSED_59, // 0xAD + SHAGOS, // 0xAE + SHAGOS_SWAP, // 0xAF + BOOTSTAR, // 0xB0 + + RESERVED_13, // 0xB1 + UNUSED_60, // 0xB2 + RESERVED_14, // 0xB3 + RESERVED_15, // 0xB4 + UNUSED_61, // 0xB5 + RESERVED_16, // 0xB6 + + BSDI_BSD386_FS, // 0xB7 + BSDI_BSD386_SWAP, // 0xB8 + UNUSED_62, // 0xB9 + UNUSED_63, // 0xBA + BOOT_WIZARD_HIDDEN, // 0xBB + UNUSED_64, // 0xBC + UNUSED_65, // 0xBD + SOLARIS8_BOOT, // 0xBE + UNUSED_66, // 0xBF + CTOS, // 0xC0 + DRDOS_FAT12, // 0xC1 + RESERVED_17, // 0xC2 + HIDDEN_LINUX_SWAP, // 0xC3 + DRDOS_FAT16, // 0xC4 + DRDOS_EXTENDED, // 0xC5 + DRDOS_FAT16_LARGE, // 0xC6 + NTFS_CORRUPT, // 0xC7 + + UNUSED_67, // 0xC8 + UNUSED_68, // 0xC9 + UNUSED_69, // 0xCA + + DRDOS_FAT32, // 0xCB + DRDOS_FAT32_LBA, // 0xCC + CTOS_MEMDUMP, // 0xCD + DRDOS_FAT16_LBA, // 0xCE + UNUSED_70, // 0xCF + REAL32_SECURE_BIG, // 0xD0 + OLD_MULTIUSER_DOS_FAT12,// 0xD1 + UNUSED_71, // 0xD2 + UNUSED_72, // 0xD3 + OLD_MULTIUSER_DOS_FAT16,// 0xD4 + OLD_MULTIUSER_DOS_EXTENDED,// 0xD5 + OLD_MULTIUSER_DOS_FAT16_LARGE,// 0xD6 + UNUSED_73, // 0xD7 + CPM86, // 0xD8 + UNUSED_74, // 0xD9 + NON_FS_DATA, // 0xDA + DIGITAL_RESEARCH_CPM, // 0xDB + UNUSED_75, // 0xDC + HIDDEN_CTOS_MEMDUMP, // 0xDD + DELL_POWEREDGE, // 0xDE + DGUX, // 0xDF + STM_AVFS, // 0xE0 + SPEEDSTOR_FAT_EXTENDED,// 0xE1 + UNUSED_76, // 0xE2 + SPEEDSTOR_RO, // 0xE3 + SPEEDSTOR_EXTENDED, // 0xE4 + TANDY_DOS, // 0xE5 + + RESERVED_18, // 0xE6 + UNUSED_77, // 0xE7 + UNUSED_78, // 0xE8 + UNUSED_79, // 0xE9 + + BEFS, // 0xEA + SPRYTIX, // 0xEB + EFI_PROTECTIVE, // 0xEE + EFI_SYSTEM, // 0xEF + LINUX_PA_RISC, // 0xF0 + SPEEDSTOR_2, // 0xF1 + DOS_3_3_SECONDARY, // 0xF2 + RESERVED_19, // 0xF3 + SPEEDSTOR_LARGE, // 0xF4 + PROLOGUE_MULTI, // 0xF5 + RESERVED_20, // 0xF6 + UNUSED_80, // 0xF7 + UNUSED_81, // 0xF8 + UNUSED_82, // 0xF9 + BOCHS, // 0xFA + VMFS, // 0xFB + VMWARE_SWAP, // 0xFC + LINUX_RAID_AUTO, // 0xFD + NT_HIDDEN, // 0xFE + XENIX_BAD_BLOCK // 0xFF + }; + + /** + * @struct PartitionTableEntry + * @brief Stores information about a partition + * + * @typedef partition_table_entry_t + * @brief Alias for PartitionTableEntry struct + */ + typedef struct PACKED PartitionTableEntry { + + uint8_t bootable; ///< Is this partition bootable? (0x80 = bootable, 0x00 = not bootable) + + uint8_t start_head; ///< The starting head of the partition + uint8_t start_sector : 6; ///< The first sector of the partition + uint16_t start_cylinder : 10; ///< The starting cylinder of the partition + + uint8_t type; ///< The partition type (see PartitionType enum) + + uint8_t end_head; ///< The last head of the partition + uint8_t end_sector : 6; ///< The last sector of the partition + uint16_t end_cylinder : 10; ///< The last cylinder of the partition + + uint32_t start_LBA; ///< The starting LBA of the partition + uint32_t length; ///< The length of the partition in sectors + + } partition_table_entry_t; + + /** + * @struct MasterBootRecord + * @brief Stores information about the master boot record + * + * @typedef master_boot_record_t + * @brief Alias for MasterBootRecord struct + */ + typedef struct PACKED MasterBootRecord { + + uint8_t bootloader[440]; ///< The assembly bytes that make up the bootloader software + uint32_t disk_signature; ///< Unique disk signature (optional) + uint16_t unused; ///< Reserved (usually zero) + + PartitionTableEntry primary_partition[4]; ///< The partition table entries + + uint16_t magic; ///< The magic number that identifies this as a valid MBR (0xAA55) + + } master_boot_record_t; + + + /** + * @class MSDOSPartition + * @brief Handles mounting of partitions documented in an MSDOS partition table + * + * @todo Abstract some of this into a base class and use it for GPT and other partition tables + */ + class MSDOSPartition { + public: + static void mount_partitions(drivers::disk::Disk* disk); + }; } -#endif //MSDOS_H + +#endif //MAXOS_FILESYSTEM_PARTITION_MSDOS_H diff --git a/kernel/include/filesystem/path.h b/kernel/include/filesystem/path.h index e7c88c3d..4c8ec883 100644 --- a/kernel/include/filesystem/path.h +++ b/kernel/include/filesystem/path.h @@ -11,33 +11,31 @@ #include -namespace MaxOS { - namespace filesystem { +namespace MaxOS::filesystem { - /** - * @class Path - * @brief Handles file & directory paths - */ - class Path - { + /** + * @class Path + * @brief Handles file & directory paths + */ + class Path { public: - static bool valid(string path); - static bool is_file(const string& path); + static bool valid(const string& path); + static bool is_file(const string& path); - static string file_name(string path); - static string file_extension(string path); - static string file_path(string path); + static string file_name(const string& path); + static string file_extension(const string& path); + static string file_path(const string& path); - static string top_directory(string path); - static string parent_directory(string path); + static string top_directory(const string& path); + static string parent_directory(const string& path); - static string absolute_path(string path); - static string join_path(string base, string extended); - }; + static string absolute_path(const string& path); + static string join_path(const string& base, const string& extended); + }; - } } + #endif //MAXOS_FILESYSTEM_PATH_H diff --git a/kernel/include/filesystem/vfs.h b/kernel/include/filesystem/vfs.h index dc593264..3c0ab1a3 100644 --- a/kernel/include/filesystem/vfs.h +++ b/kernel/include/filesystem/vfs.h @@ -14,60 +14,59 @@ #include #include -namespace MaxOS { - namespace filesystem { +namespace MaxOS::filesystem { - /** - * @class VirtualFileSystem - * @brief Combines all the filesystems across the partitions on each disk into a single filesystems and exposes - * a single API to interact with them - */ - class VirtualFileSystem { + /** + * @class VirtualFileSystem + * @brief Combines all the filesystems across the partitions on each disk into a single filesystems and exposes + * a single API to interact with them + */ + class VirtualFileSystem { - private: - common::Map filesystems; - inline static VirtualFileSystem* s_current_file_system = nullptr; + private: + common::Map filesystems; + inline static VirtualFileSystem* s_current_file_system = nullptr; - public: - VirtualFileSystem(); - ~VirtualFileSystem(); + public: + VirtualFileSystem(); + ~VirtualFileSystem(); - static VirtualFileSystem* current_file_system(); + static VirtualFileSystem* current_file_system(); - void mount_filesystem(FileSystem* filesystem); - void mount_filesystem(FileSystem* filesystem, const string &mount_point); - void unmount_filesystem(FileSystem* filesystem); - void unmount_filesystem(const string &mount_point); - void unmount_all(); + void mount_filesystem(FileSystem* filesystem); + void mount_filesystem(FileSystem* filesystem, const string& mount_point); + void unmount_filesystem(FileSystem* filesystem); + void unmount_filesystem(const string& mount_point); + void unmount_all(); - Directory* root_directory(); - FileSystem* root_filesystem(); + Directory* root_directory(); + FileSystem* root_filesystem(); - FileSystem* get_filesystem(const string &mount_point); - FileSystem* find_filesystem(string path); - string get_relative_path(FileSystem* filesystem, string path); + FileSystem* get_filesystem(const string& mount_point); + FileSystem* find_filesystem(string path); + string get_relative_path(FileSystem* filesystem, string path); - Directory* open_directory(const string &path); - static Directory* open_directory(Directory* parent, const string &name); + Directory* open_directory(const string& path); + static Directory* open_directory(Directory* parent, const string& name); - Directory* create_directory(string path); - static Directory* create_directory(Directory* parent, const string &name); + Directory* create_directory(string path); + static Directory* create_directory(Directory* parent, const string& name); - void delete_directory(string path); - static void delete_directory(Directory* parent, const string &name); - static void delete_directory(Directory* parent, Directory* directory); + void delete_directory(string path); + static void delete_directory(Directory* parent, const string& name); + static void delete_directory(Directory* parent, Directory* directory); - File* create_file(const string &path); - static File* create_file(Directory* parent, const string &name); + File* create_file(const string& path); + static File* create_file(Directory* parent, const string& name); - File* open_file(const string &path, size_t offset = 0); - static File* open_file(Directory* parent, const string &name, size_t offset = 0); + File* open_file(const string& path, size_t offset = 0); + static File* open_file(Directory* parent, const string& name, size_t offset = 0); - void delete_file(const string &path); - static void delete_file(Directory* parent, const string &name); - }; - } + void delete_file(const string& path); + static void delete_file(Directory* parent, const string& name); + }; } + #endif //MAXOS_FILESYSTEM_VFS_H diff --git a/kernel/include/gui/desktop.h b/kernel/include/gui/desktop.h index 100048b9..3324e507 100644 --- a/kernel/include/gui/desktop.h +++ b/kernel/include/gui/desktop.h @@ -9,62 +9,61 @@ #ifndef MaxOS_GUI_DESKTOP_H #define MaxOS_GUI_DESKTOP_H -#include +#include #include #include #include #include -namespace MaxOS{ - namespace gui{ +namespace MaxOS::gui { - /** - * @class Desktop - * @brief The desktop that contains all the windows, handles the drawing of the screen and the mouse on every tick - * - * @todo It is not a good idea to hardcode the mouse into the desktop as a tablet or touch screen device won't have a mouse cursor - */ - class Desktop : public CompositeWidget, public drivers::peripherals::MouseEventHandler{ + /** + * @class Desktop + * @brief The desktop that contains all the windows, handles the drawing of the screen and the mouse on every tick + * + * @todo It is not a good idea to hardcode the mouse into the desktop as a tablet or touch screen device won't have a mouse cursor + */ + class Desktop : public CompositeWidget, public drivers::peripherals::MouseEventHandler { - protected: - int32_t m_mouse_x; ///< The horizontal position of the mouse cursor - int32_t m_mouse_y; ///< The vertical position of the mouse cursor + protected: + uint32_t m_mouse_x; ///< The horizontal position of the mouse cursor + uint32_t m_mouse_y; ///< The vertical position of the mouse cursor - common::GraphicsContext* m_graphics_context; ///< Where to draw the desktop to + common::GraphicsContext* m_graphics_context; ///< Where to draw the desktop to - Widget* m_focussed_widget { nullptr }; ///< The widget that currently is receiving keyboard input and is at the front - drivers::peripherals::MouseEventHandler* m_dragged_widget { nullptr }; ///< The widget that the mouse is currently dragging + Widget* m_focussed_widget { nullptr }; ///< The widget that currently is receiving keyboard input and is at the front + drivers::peripherals::MouseEventHandler* m_dragged_widget { nullptr }; ///< The widget that the mouse is currently dragging - void set_focus(Widget*) final; - void bring_to_front(Widget*) final; - void invert_mouse_cursor(); + void set_focus(Widget*) final; + void bring_to_front(Widget*) final; + void invert_mouse_cursor(); - common::Vector > m_invalid_areas; ///< The areas of the desktop that need to be redrawn - void internal_invalidate(common::Rectangle& area, common::Vector >::iterator start, common::Vector >::iterator stop); - void draw_self(common::GraphicsContext* gc, common::Rectangle& area) final; + common::Vector> m_invalid_areas; ///< The areas of the desktop that need to be redrawn + void internal_invalidate(common::Rectangle& area, common::Vector>::iterator start, common::Vector>::iterator stop); + void draw_self(common::GraphicsContext* gc, common::Rectangle& area) final; - public: - common::Colour colour; ///< The background colour of the desktop (@todo: replace with image, make priv) + public: + common::Colour colour; ///< The background colour of the desktop (@todo: replace with image, make priv) - Desktop(common::GraphicsContext* gc); - ~Desktop(); + explicit Desktop(common::GraphicsContext* gc); + ~Desktop(); - void add_child(Widget*) final; - void on_time(const common::Time& time); - void invalidate(common::Rectangle& area) final; + void add_child(Widget*) final; + void on_time(const common::Time& time); + void invalidate(common::Rectangle& area) final; - // Mouse Events - void on_mouse_move_event(int8_t x, int8_t y) final; - void on_mouse_down_event(uint8_t button) final; - void on_mouse_up_event(uint8_t button) final; + // Mouse Events + void on_mouse_move_event(int8_t x, int8_t y) final; + void on_mouse_down_event(uint8_t button) final; + void on_mouse_up_event(uint8_t button) final; - // Keyboard Events - void on_key_down(drivers::peripherals::KeyCode keyDownCode, drivers::peripherals::KeyboardState keyDownState) final; - void on_key_up(drivers::peripherals::KeyCode keyUpCode, drivers::peripherals::KeyboardState keyUpState) final; + // Keyboard Events + void on_key_down(drivers::peripherals::KeyCode key_down_code, const drivers::peripherals::KeyboardState& key_down_state) final; + void on_key_up(drivers::peripherals::KeyCode key_up_code, const drivers::peripherals::KeyboardState& key_up_state) final; - }; - } + }; } + #endif //MaxOS_GUI_DESKTOP_H diff --git a/kernel/include/gui/font.h b/kernel/include/gui/font.h index 88dc3e2a..4d66f8d1 100644 --- a/kernel/include/gui/font.h +++ b/kernel/include/gui/font.h @@ -9,46 +9,42 @@ #ifndef MAXOS_COMMON_FONT_H #define MAXOS_COMMON_FONT_H -#include +#include #include #include #include -namespace MaxOS{ +namespace MaxOS::gui { - namespace gui{ + constexpr uint8_t FONT_PADDING = 3; ///< How many vertical pixels to add to the top and bottom of the font to prevent squishing + constexpr uint8_t FONT_HEIGHT = 8 + (2 * FONT_PADDING); ///< How many pixels tall the font is + constexpr uint8_t FONT_WIDTH = 8; ///< How many pixels wide the font is - constexpr uint8_t FONT_PADDING = 3; ///< How many vertical pixels to add to the top and bottom of the font to prevent squishing - constexpr uint8_t FONT_HEIGHT = 8 + (2 * FONT_PADDING); ///< How many pixels tall the font is - constexpr uint8_t FONT_WIDTH = 8; ///< How many pixels wide the font is + /** + * @class Font + * @brief A class that can be used to draw text + */ + class Font { + protected: + bool m_is_8_by_8 = { true }; ///< Is the font 8 pixels by 8 pixels per character + uint8_t m_font8x8[2048] = { 0 }; ///< The 8x8 font data - /** - * @class Font - * @brief A class that can be used to draw text - */ - class Font{ - protected: - bool m_is_8_by_8 = { true }; ///< Is the font 8 pixels by 8 pixels per character - uint8_t m_font8x8[2048] = {0}; ///< The 8x8 font data + public: - public: + explicit Font(const uint8_t* font_data); + ~Font(); - Font(const uint8_t* font_data); - ~Font(); + bool is_bold { false }; ///< Should the font be drawn in bold + bool is_italic { false }; ///< Should the font be drawn in italic + bool is_underlined { false }; ///< Should the font be drawn with an underline + bool is_strikethrough { false }; ///< Should the font be drawn with a strikethrough - bool is_bold { false }; ///< Should the font be drawn in bold - bool is_italic { false }; ///< Should the font be drawn in italic - bool is_underlined { false }; ///< Should the font be drawn with an underline - bool is_strikethrough { false }; ///< Should the font be drawn with a strikethrough - - virtual void draw_text(int32_t x, int32_t y, common::Colour foreground_colour, common::Colour background_colour, common::GraphicsContext *context, string text); - virtual void draw_text(int32_t x, int32_t y, common::Colour foreground_colour, common::Colour background_colour, common::GraphicsContext *context, string text, common::Rectangle limitArea); - - virtual int32_t get_text_height(string); - virtual int32_t get_text_width(string); - }; - } + virtual void draw_text(int32_t x, int32_t y, common::Colour foreground_colour, common::Colour background_colour, common::GraphicsContext* context, string text); + virtual void draw_text(int32_t x, int32_t y, common::Colour foreground_colour, common::Colour background_colour, common::GraphicsContext* context, string text, common::Rectangle limit_area); + virtual size_t get_text_height(string); + virtual size_t get_text_width(string); + }; } #endif //MAXOS_COMMON_FONT_H diff --git a/kernel/include/gui/font/amiga_font.h b/kernel/include/gui/font/amiga_font.h index bf52770e..7e433b56 100644 --- a/kernel/include/gui/font/amiga_font.h +++ b/kernel/include/gui/font/amiga_font.h @@ -11,7 +11,7 @@ #ifndef MAXOS_AMIGA_FONT_H #define MAXOS_AMIGA_FONT_H -#include +#include const static uint8_t AMIGA_FONT[2048] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/kernel/include/gui/widget.h b/kernel/include/gui/widget.h index 9d4656bb..7d75219a 100644 --- a/kernel/include/gui/widget.h +++ b/kernel/include/gui/widget.h @@ -18,174 +18,173 @@ #include -namespace MaxOS{ +namespace MaxOS { - namespace gui{ - - /** - * @class Widget - * @brief A graphical object that can be drawn on the screen - */ - class Widget : public drivers::peripherals::KeyboardEventHandler{ - template friend class WidgetMoverResizer; - friend class CompositeWidget; - - protected: - common::Rectangle m_position; ///< The position and size of the widget (relative to its parent) + namespace gui { - Widget* m_parent { nullptr }; ///< The widget that owns this widget - bool m_valid { false }; ///< Is the widget drawn to the screen and up to date + /** + * @class Widget + * @brief A graphical object that can be drawn on the screen + */ + class Widget : public drivers::peripherals::KeyboardEventHandler { + template friend class WidgetMoverResizer; - uint32_t m_min_width { 5 }; ///< The smallest m_width the widget can be resized to - uint32_t m_min_height { 5 }; ///< The smallest m_height the widget can be resized to + friend class CompositeWidget; + + protected: + common::Rectangle m_position; ///< The position and size of the widget (relative to its parent) - uint32_t m_max_width { 0x8FFFFFFF }; ///< The largest m_width the widget can be resized to - uint32_t m_max_height { 0x8FFFFFFF }; ///< The largest m_height the widget can be resized to + Widget* m_parent { nullptr }; ///< The widget that owns this widget + bool m_valid { false }; ///< Is the widget drawn to the screen and up to date - virtual void set_focus(Widget*); - virtual void bring_to_front(Widget*); + uint32_t m_min_width { 5 }; ///< The smallest m_width the widget can be resized to + uint32_t m_min_height { 5 }; ///< The smallest m_height the widget can be resized to - public: + uint32_t m_max_width { 0x8FFFFFFF }; ///< The largest m_width the widget can be resized to + uint32_t m_max_height { 0x8FFFFFFF }; ///< The largest m_height the widget can be resized to - // Initializing functions - Widget(); - Widget(int32_t left, int32_t top, uint32_t width, uint32_t height); - ~Widget(); + virtual void set_focus(Widget*); + virtual void bring_to_front(Widget*); - // Drawing functions - virtual void draw(common::GraphicsContext* gc, common::Rectangle& area); - void invalidate(); - virtual void invalidate(common::Rectangle& area); - virtual void add_child(Widget* child); + public: - // Positioning functions - virtual common::Coordinates absolute_coordinates(common::Coordinates coordinates); - virtual bool contains_coordinate(uint32_t x, uint32_t y); - common::Rectangle position(); - void move(int32_t left, int32_t top); - void resize(int32_t width, int32_t height); + // Initializing functions + Widget(); + Widget(int32_t left, int32_t top, uint32_t width, uint32_t height); + ~Widget(); - // Focus functions - void focus(); - virtual void on_focus(); - virtual void on_focus_lost(); - void bring_to_front(); + // Drawing functions + virtual void draw(common::GraphicsContext* gc, common::Rectangle& area); + void invalidate(); + virtual void invalidate(common::Rectangle& area); + virtual void add_child(Widget* child); - // Mouse functions - virtual void on_mouse_enter_widget(uint32_t toX, uint32_t toY); - virtual void on_mouse_leave_widget(uint32_t fromX, uint32_t fromY); - virtual void on_mouse_move_widget(uint32_t fromX, uint32_t fromY, uint32_t toX, uint32_t toY); - virtual drivers::peripherals::MouseEventHandler* on_mouse_button_pressed(uint32_t x, uint32_t y, uint8_t button); - virtual void on_mouse_button_released(uint32_t x, uint32_t y, uint8_t button); + // Positioning functions + virtual common::Coordinates absolute_coordinates(common::Coordinates coordinates); + virtual bool contains_coordinate(uint32_t x, uint32_t y); + common::Rectangle position(); + void move(int32_t left, int32_t top); + void resize(int32_t width, int32_t height); - }; + // Focus functions + void focus(); + virtual void on_focus(); + virtual void on_focus_lost(); + void bring_to_front(); - /** - * @class CompositeWidget - * @brief A widget that can contain other widgets - */ - class CompositeWidget : public Widget{ + // Mouse functions + virtual void on_mouse_enter_widget(uint32_t to_x, uint32_t to_y); + virtual void on_mouse_leave_widget(uint32_t from_x, uint32_t from_y); + virtual void on_mouse_move_widget(uint32_t from_x, uint32_t from_y, uint32_t to_x, uint32_t to_y); + virtual drivers::peripherals::MouseEventHandler* on_mouse_button_pressed(uint32_t x, uint32_t y, uint8_t button); + virtual void on_mouse_button_released(uint32_t x, uint32_t y, uint8_t button); - protected: + }; - common::Vector m_children; ///< Widgets contained within this composite widget - void draw(common::GraphicsContext* gc, common::Rectangle& area, common::Vector::iterator start); - virtual void draw_self(common::GraphicsContext* gc, common::Rectangle& area); + /** + * @class CompositeWidget + * @brief A widget that can contain other widgets + */ + class CompositeWidget : public Widget { + protected: - public: + common::Vector m_children; ///< Widgets contained within this composite widget + void draw(common::GraphicsContext* gc, common::Rectangle& area, common::Vector::iterator start); + virtual void draw_self(common::GraphicsContext* gc, common::Rectangle& area); - // Initializing functions - CompositeWidget(); - CompositeWidget(int32_t left, int32_t top, uint32_t width, uint32_t height); - ~CompositeWidget(); - // Drawing functions - void draw(common::GraphicsContext* gc, common::Rectangle& area) override; - void add_child(Widget* child) override; + public: - // Mouse functions - void on_mouse_enter_widget(uint32_t toX, uint32_t toY) override; - void on_mouse_leave_widget(uint32_t fromX, uint32_t fromY) override; - void on_mouse_move_widget(uint32_t fromX, uint32_t fromY, uint32_t toX, uint32_t toY) override; - drivers::peripherals::MouseEventHandler* on_mouse_button_pressed(uint32_t x, uint32_t y, uint8_t button) override; - void on_mouse_button_released(uint32_t x, uint32_t y, uint8_t button) override; + // Initializing functions + CompositeWidget(); + CompositeWidget(int32_t left, int32_t top, uint32_t width, uint32_t height); + ~CompositeWidget(); - }; + // Drawing functions + void draw(common::GraphicsContext* gc, common::Rectangle& area) override; + void add_child(Widget* child) override; + // Mouse functions + void on_mouse_enter_widget(uint32_t to_x, uint32_t to_y) override; + void on_mouse_leave_widget(uint32_t from_x, uint32_t from_y) override; + void on_mouse_move_widget(uint32_t from_x, uint32_t from_y, uint32_t to_x, uint32_t to_y) override; + drivers::peripherals::MouseEventHandler* on_mouse_button_pressed(uint32_t x, uint32_t y, uint8_t button) override; + void on_mouse_button_released(uint32_t x, uint32_t y, uint8_t button) override; - /** - * @class WidgetMoverResizer - * @brief A template class that allows you to move and resize a widget - * - * @tparam Left Left - * @tparam Top Top - * @tparam Width Width - * @tparam Height Height - */ - template class WidgetMoverResizer : public drivers::peripherals::MouseEventHandler{ - private: - Widget* targetedWidget; + }; - public: - WidgetMoverResizer(Widget* widget); - ~WidgetMoverResizer(); - void on_mouse_move_event(int8_t x, int8_t y) override; + /** + * @class WidgetMoverResizer + * @brief A template class that allows you to move and resize a widget + * + * @tparam Left Left + * @tparam Top Top + * @tparam Width Width + * @tparam Height Height + */ + template class WidgetMoverResizer : public drivers::peripherals::MouseEventHandler { + private: + Widget* targeted_widget; - }; + public: + WidgetMoverResizer(Widget* widget); + ~WidgetMoverResizer(); - typedef WidgetMoverResizer<1, 1, 0, 0> WidgetMover; ///< A widget mover that moves the widget without resizing it + void on_mouse_move_event(int8_t x, int8_t y) override; - typedef WidgetMoverResizer<0, 1, 0, -1> WidgetMoverResizerTop; ///< A widget mover and resizer that resizes the top edge of the widget - typedef WidgetMoverResizer<0, 0, 0, 1> WidgetMoverResizerBottom; ///< A widget mover andresizer that resizes the bottom edge of the widget - typedef WidgetMoverResizer<1, 0, -1, 0> WidgetMoverResizerLeft; ///< A widget mover and resizer that resizes the left edge of the widget - typedef WidgetMoverResizer<0, 0, 1, 0> WidgetMoverResizerRight; ///< A widget mover and resizer that resizes the right edge of the widget + }; - typedef WidgetMoverResizer<1, 1, -1, -1> WidgetMoverResizerTopLeft; ///< A widget mover and resizer that resizes the top-left corner of the widget - typedef WidgetMoverResizer<0, 1, 1, -1> WidgetMoverResizerTopRight; ///< A widget mover and resizer that resizes the top-right corner of the widget - typedef WidgetMoverResizer<1, 0, -1, 1> WidgetMoverResizerBottomLeft; ///< A widget mover and resizer that resizes the bottom-left corner of the widget - typedef WidgetMoverResizer<0, 0, 1, 1> WidgetMoverResizerBottomRight; ///< A widget mover and resizer that resizes the bottom-right corner of the widget + typedef WidgetMoverResizer<1, 1, 0, 0> WidgetMover; ///< A widget mover that moves the widget without resizing it + + typedef WidgetMoverResizer<0, 1, 0, -1> WidgetMoverResizerTop; ///< A widget mover and resizer that resizes the top edge of the widget + typedef WidgetMoverResizer<0, 0, 0, 1> WidgetMoverResizerBottom; ///< A widget mover andresizer that resizes the bottom edge of the widget + typedef WidgetMoverResizer<1, 0, -1, 0> WidgetMoverResizerLeft; ///< A widget mover and resizer that resizes the left edge of the widget + typedef WidgetMoverResizer<0, 0, 1, 0> WidgetMoverResizerRight; ///< A widget mover and resizer that resizes the right edge of the widget + + typedef WidgetMoverResizer<1, 1, -1, -1> WidgetMoverResizerTopLeft; ///< A widget mover and resizer that resizes the top-left corner of the widget + typedef WidgetMoverResizer<0, 1, 1, -1> WidgetMoverResizerTopRight; ///< A widget mover and resizer that resizes the top-right corner of the widget + typedef WidgetMoverResizer<1, 0, -1, 1> WidgetMoverResizerBottomLeft; ///< A widget mover and resizer that resizes the bottom-left corner of the widget + typedef WidgetMoverResizer<0, 0, 1, 1> WidgetMoverResizerBottomRight; ///< A widget mover and resizer that resizes the bottom-right corner of the widget ////@TODO move this to the cpp file - /** - * @details WidgetMoverResizer is a template class that allows you to move and resize a widget - * - * @tparam Left The left edge of the widget - * @tparam Top The top edge of the widget - * @tparam Width The m_width of the widget - * @tparam Height The m_height of the widget - * @param target The widget to move and resize - */ - template WidgetMoverResizer::WidgetMoverResizer(Widget* target) - : drivers::peripherals::MouseEventHandler() - { - this ->targetedWidget = target; - } - - template WidgetMoverResizer::~WidgetMoverResizer() = default; - - /** - * @details OnMouseMoved is called when the mouse is moved. Resizes and moves the widget when this happens. - * - * @param x The x m_position of the mouse - * @param y The y m_position of the mouse - */ - template void WidgetMoverResizer::on_mouse_move_event(int8_t x, int8_t y) - { - - Widget* targ = this->targetedWidget; - - // If there is actually a size of the widget to change - if(Left != 0 || Top != 0) - // Move the widget to the left or right, and up or down - targ -> move(targ ->m_position.left + Left * x, targ ->m_position.top + Top * y); - - // If there is actually a size of the widget to change - if(Width != 0 || Height != 0) - // Resize the widget to the left or right, and up or down - targ -> resize( targ ->m_position.width + Width*x, targ ->m_position.height + Height*y); - } - } + /** + * @details WidgetMoverResizer is a template class that allows you to move and resize a widget + * + * @tparam Left The left edge of the widget + * @tparam Top The top edge of the widget + * @tparam Width The m_width of the widget + * @tparam Height The m_height of the widget + * @param target The widget to move and resize + */ + template WidgetMoverResizer::WidgetMoverResizer(Widget* target) + : drivers::peripherals::MouseEventHandler() { + this->targeted_widget = target; + } + + template WidgetMoverResizer::~WidgetMoverResizer() = default; + + /** + * @details OnMouseMoved is called when the mouse is moved. Resizes and moves the widget when this happens. + * + * @param x The x m_position of the mouse + * @param y The y m_position of the mouse + */ + template void WidgetMoverResizer::on_mouse_move_event(int8_t x, int8_t y) { + + Widget* targ = this->targeted_widget; + + // If there is actually a size of the widget to change + if(Left != 0 || Top != 0) + // Move the widget to the left or right, and up or down + targ->move(targ->m_position.left + Left * x, targ->m_position.top + Top * y); + + // If there is actually a size of the widget to change + if(Width != 0 || Height != 0) + // Resize the widget to the left or right, and up or down + targ->resize(targ->m_position.width + Width * x, targ->m_position.height + Height * y); + } + } } #endif //MaxOS_GUI_WIDGET_H diff --git a/kernel/include/gui/widgets/button.h b/kernel/include/gui/widgets/button.h index 239cf587..58f480a1 100644 --- a/kernel/include/gui/widgets/button.h +++ b/kernel/include/gui/widgets/button.h @@ -9,95 +9,89 @@ #ifndef MAXOS_GUI_WIDGETS_BUTTON_H #define MAXOS_GUI_WIDGETS_BUTTON_H -#include +#include #include #include #include -namespace MaxOS { - - namespace gui { - - namespace widgets { - - //forward declaration - class Button; - - /** - * @enum ButtonEvents - * @brief The events that a button can trigger - */ - enum class ButtonEvents{ - PRESSED, - RELEASED - }; - - /** - * @class ButtonPressedEvent - * @brief Event that is triggered when a button is pressed - */ - class ButtonPressedEvent : public common::Event{ - public: - ButtonPressedEvent(Button*); - ~ButtonPressedEvent(); - - Button* source; ///< The button that triggered the event - }; - - /** - * @class ButtonReleasedEvent - * @brief Event that is triggered when a button is released - */ - class ButtonReleasedEvent : public common::Event{ - public: - ButtonReleasedEvent(Button*); - ~ButtonReleasedEvent(); - - Button* source; ///< The button that triggered the event - }; - - /** - * @class ButtonEventHandler - * - * @brief Handles button events - */ - class ButtonEventHandler : public common::EventHandler{ - public: - ButtonEventHandler(); - ~ButtonEventHandler(); - - common::Event* on_event(common::Event*) override; - - virtual void on_button_pressed(Button* source); - virtual void on_button_released(Button* source); - }; - - /** - * @class Button - * @brief A button widget, can be clicked - */ - class Button : public Widget, public common::EventManager { - - public: - Button(int32_t left, int32_t top, uint32_t width, uint32_t height, const string& text); - ~Button(); - - // Widget Stuff - void draw(common::GraphicsContext* gc, common::Rectangle& area) override; - drivers::peripherals::MouseEventHandler* on_mouse_button_pressed(uint32_t x, uint32_t y, uint8_t button) override; - void on_mouse_button_released(uint32_t x, uint32_t y, uint8_t button) override; - - // Button Stuff - common::Colour background_colour; ///< The colour of the button background - common::Colour foreground_colour; ///< The colour of the button text - common::Colour border_colour; ///< The colour of the bar around the button - gui::Font font; ///< The font to use for the button text - string text; ///< The text to display on the button - }; - } - } - +namespace MaxOS::gui::widgets { + + //forward declaration + class Button; + + /** + * @enum ButtonEvents + * @brief The events that a button can trigger + */ + enum class ButtonEvents { + PRESSED, + RELEASED + }; + + /** + * @class ButtonPressedEvent + * @brief Event that is triggered when a button is pressed + */ + class ButtonPressedEvent : public common::Event { + public: + explicit ButtonPressedEvent(Button*); + ~ButtonPressedEvent(); + + Button* source; ///< The button that triggered the event + }; + + /** + * @class ButtonReleasedEvent + * @brief Event that is triggered when a button is released + */ + class ButtonReleasedEvent : public common::Event { + public: + explicit ButtonReleasedEvent(Button*); + ~ButtonReleasedEvent(); + + Button* source; ///< The button that triggered the event + }; + + /** + * @class ButtonEventHandler + * + * @brief Handles button events + */ + class ButtonEventHandler : public common::EventHandler { + public: + ButtonEventHandler(); + ~ButtonEventHandler(); + + common::Event* on_event(common::Event*) override; + + virtual void on_button_pressed(Button* source); + virtual void on_button_released(Button* source); + }; + + /** + * @class Button + * @brief A button widget, can be clicked + */ + class Button : public Widget, public common::EventManager { + + public: + Button(int32_t left, int32_t top, uint32_t width, uint32_t height, const string& text); + ~Button(); + + // Widget Stuff + void draw(common::GraphicsContext* gc, common::Rectangle& area) override; + drivers::peripherals::MouseEventHandler* on_mouse_button_pressed(uint32_t x, uint32_t y, uint8_t button) override; + void on_mouse_button_released(uint32_t x, uint32_t y, uint8_t button) override; + + // Button Stuff + common::Colour background_colour; ///< The colour of the button background + common::Colour foreground_colour; ///< The colour of the button text + common::Colour border_colour; ///< The colour of the bar around the button + gui::Font font; ///< The font to use for the button text + string text; ///< The text to display on the button + }; } + #endif //MAXOS_GUI_WIDGETS_BUTTON_H diff --git a/kernel/include/gui/widgets/inputbox.h b/kernel/include/gui/widgets/inputbox.h index 2430f9a0..ef27ca40 100644 --- a/kernel/include/gui/widgets/inputbox.h +++ b/kernel/include/gui/widgets/inputbox.h @@ -9,85 +9,81 @@ #ifndef MAXOS_GUI_WIDGETS_INPUTBOX_H #define MAXOS_GUI_WIDGETS_INPUTBOX_H -#include +#include #include #include #include -namespace MaxOS{ +namespace MaxOS::gui::widgets { - namespace gui { - namespace widgets { + /** + * @enum InputBoxEvents + * @brief The events that an input box can trigger + */ + enum class InputBoxEvents { + TEXT_CHANGED + }; - /** - * @enum InputBoxEvents - * @brief The events that an input box can trigger - */ - enum class InputBoxEvents{ - TEXT_CHANGED - }; + /** + * @class InputBoxTextChangedEvent + * @brief Event that is triggered when the text in an input box is changed + */ + class InputBoxTextChangedEvent : public common::Event { + public: + InputBoxTextChangedEvent(const string&); + ~InputBoxTextChangedEvent(); - /** - * @class InputBoxTextChangedEvent - * @brief Event that is triggered when the text in an input box is changed - */ - class InputBoxTextChangedEvent : public common::Event{ - public: - InputBoxTextChangedEvent(const string&); - ~InputBoxTextChangedEvent(); + string new_text; ///< The new text in the input box + }; - string new_text; ///< The new text in the input box - }; + /** + * @class InputBoxEventHandler + * @brief Handles input box events + */ + class InputBoxEventHandler : public common::EventHandler { + public: + InputBoxEventHandler(); + ~InputBoxEventHandler(); - /** - * @class InputBoxEventHandler - * @brief Handles input box events - */ - class InputBoxEventHandler : public common::EventHandler{ - public: - InputBoxEventHandler(); - ~InputBoxEventHandler(); + common::Event* on_event(common::Event* event) override; - common::Event* on_event(common::Event* event) override; + virtual void on_input_box_text_changed(const string& text); + }; - virtual void on_input_box_text_changed(string); - }; + /** + * @class InputBox + * @brief A box that can be used to input text + */ + class InputBox : public Widget, public common::EventManager { - /** - * @class InputBox - * @brief A box that can be used to input text - */ - class InputBox : public Widget, public common::EventManager{ + protected: + /// The text in the input box + string m_widget_text = " "; - protected: - string m_widget_text = " "; ///< The text in the input box + public: + InputBox(int32_t left, int32_t top, uint32_t width, uint32_t height); + InputBox(int32_t left, int32_t top, uint32_t width, uint32_t height, const string& text); + ~InputBox(); - public: - InputBox(int32_t left, int32_t top, uint32_t width, uint32_t height); - InputBox(int32_t left, int32_t top, uint32_t width, uint32_t height, const string& text); - ~InputBox(); + void draw(common::GraphicsContext* gc, common::Rectangle& area) override; - void draw(common::GraphicsContext* gc, common::Rectangle& area) override; + void on_focus() override; + void on_focus_lost() override; - void on_focus() override; - void on_focus_lost() override; + void on_key_down(drivers::peripherals::KeyCode key_down_code, const drivers::peripherals::KeyboardState& key_down_state) override; - void on_key_down(drivers::peripherals::KeyCode key_down_code, drivers::peripherals::KeyboardState key_down_state) override; + void update_text(const string&); + string text(); - void update_text(const string&); - string text(); + // InputBox Variables + common::Colour background_colour; ///< The background colour of the input box + common::Colour foreground_colour; ///< The colour of the text in the input box + common::Colour border_colour; ///< The colour of the bar around the input box + gui::Font font; ///< The font to use for the input box text + uint32_t cursor_position { 0 }; ///< How many characters into the text the cursor is - // InputBox Variables - common::Colour background_colour; ///< The background colour of the input box - common::Colour foreground_colour; ///< The colour of the text in the input box - common::Colour border_colour; ///< The colour of the bar around the input box - gui::Font font; ///< The font to use for the input box text - uint32_t cursor_position { 0 }; ///< How many characters into the text the cursor is - - }; - } - } + }; } #endif //MAXOS_GUI_WIDGETS_INPUTBOX_H diff --git a/kernel/include/gui/widgets/text.h b/kernel/include/gui/widgets/text.h index ef4126f1..0f154e70 100644 --- a/kernel/include/gui/widgets/text.h +++ b/kernel/include/gui/widgets/text.h @@ -9,43 +9,38 @@ #ifndef MAXOS_GUI_WDIGETS_TEXT_H #define MAXOS_GUI_WDIGETS_TEXT_H -#include +#include #include #include #include -namespace MaxOS { - namespace gui { +namespace MaxOS::gui::widgets { - namespace widgets { + /** + * @class Text + * @brief A box that can be used to display text + */ + class Text : public Widget { - /** - * @class Text - * @brief A box that can be used to display text - */ - class Text : public Widget { + private: + string m_widget_text; - private: - string m_widget_text; + public: - public: + gui::Font font; ///< The font to use for the text - gui::Font font; ///< The font to use for the text + common::Colour foreground_colour; ///< The colour of the text characters + common::Colour background_colour; ///< The colour to draw behind the text characters - common::Colour foreground_colour; ///< The colour of the text characters - common::Colour background_colour; ///< The colour to draw behind the text characters + Text(int32_t left, int32_t top, uint32_t width, uint32_t height, const string& text); + ~Text(); - Text(int32_t left, int32_t top, uint32_t width, uint32_t height, const string &text); - ~Text(); + void draw(common::GraphicsContext* gc, common::Rectangle& area) override; + void update_text(const string&); - void draw(common::GraphicsContext* gc, common::Rectangle &area) override; - void update_text(const string &); - - }; - } - - } + }; } + #endif //MAXOS_GUI_WDIGETS_TEXT_H diff --git a/kernel/include/gui/window.h b/kernel/include/gui/window.h index 608053f1..82765dcd 100644 --- a/kernel/include/gui/window.h +++ b/kernel/include/gui/window.h @@ -48,7 +48,7 @@ namespace MaxOS{ common::Colour frame_border_colour; ///< The colour of the border around the bar around the window Window(int32_t left, int32_t top, uint32_t width, uint32_t height, const string& title_text); - Window(Widget* containedWidget, const string& title_text); + Window(Widget* contained_widget, const string& title_text); ~Window(); void draw_self(common::GraphicsContext* gc, common::Rectangle& area) override; diff --git a/kernel/include/hardwarecommunication/acpi.h b/kernel/include/hardwarecommunication/acpi.h index 542be048..a3f5513b 100644 --- a/kernel/include/hardwarecommunication/acpi.h +++ b/kernel/include/hardwarecommunication/acpi.h @@ -9,122 +9,121 @@ #ifndef MAXOS_HARDWARECOMMUNICATION_ACPI_H #define MAXOS_HARDWARECOMMUNICATION_ACPI_H -#include -#include +#include +#include #include #include #include #include #include -namespace MaxOS { - namespace hardwarecommunication { - - /** - * @struct RSDPDescriptor - * @brief Root System Description Pointer (RSDP) structure for ACPI 1. - * - * @typedef rsdp_descriptor_t - * @brief Alias for RSDPDescriptor struct - */ - typedef struct PACKED RSDPDescriptor { - char signature[8]; ///< Indicates a valid RSDP structure if it contains "RSD PTR " (null-terminated) - uint8_t checksum; ///< This byte added to all bytes in the table must equal zero for the table to be valid - char OEMID[6]; ///< A string supplied by the OEM to identify the OEM - uint8_t revision; ///< The version of the ACPI specification that is supported (higher means more features and is backwards compatible) - uint32_t rsdt_address; ///< The physical address of the RSDT (@deprecated in ACPI 2 and above) - } rsdp_descriptor_t; - - /** - * @struct RSDPDescriptor2 - * @brief Root System Description Pointer (RSDP) structure for ACPI 2 and above - * - * @typedef rsdp_descriptor2_t - * @brief Alias for RSDPDescriptor2 struct - */ - typedef struct PACKED RSDPDescriptor2 { - RSDPDescriptor version_1_info; ///< The ACPI 1 RSDP structure (see rsdp_descriptor_t) - uint32_t length; ///< The total length of the RSDP structure (including the version 1 part) - uint64_t xsdt_address; ///< The physical address of the XSDT - uint8_t extended_checksum; ///< This byte added to all bytes in the table must equal zero for the table to be valid (including the version 1 part) - uint8_t reserved[3]; ///< Reserved, must be zero - } rsdp_descriptor2_t; - - /** - * @struct ACPISDTHeader - * @brief Common header for all ACPI System Description Tables (SDTs) - * - * @typedef acpi_sdt_header_t - * @brief Alias for ACPISDTHeader struct - */ - typedef struct PACKED ACPISDTHeader { - char signature[4]; ///< The signature that identifies the type of the table - uint32_t length; ///< The size of the entire table, including the header, in bytes - uint8_t revision; ///< The version of the ACPI specification that is supported (higher means more features and is backwards compatible) - uint8_t checksum; ///< This byte added to all bytes in the table must equal zero mod 0x100 for the table to be valid (including the header) - char OEM_id[6]; ///< A string supplied by the OEM to identify the OEM - char OEM_table_id[8]; ///< A string supplied by the OEM to identify the particular table - uint32_t OEM_revision; ///< The revision number of the table as supplied by the OEM - uint32_t creator_id; ///< A vendor ID of the utility that created the table - uint32_t creator_revision; ///< The revision number of the utility that created the table - } acpi_sdt_header_t; - - /** - * @struct RSDT - * @brief Root System Description Table (RSDT) structure for ACPI 1. Contains the header and an array of pointers to other SDTs - * - * @typedef rsdt_t - * @brief Alias for RSDT struct - */ - typedef struct RSDT { - ACPISDTHeader header; ///< The common header for all ACPI SDTs (see acpi_sdt_header_t) - uint32_t pointers[]; ///< An array of physical addresses pointing to other ACPI SDTs - } rsdt_t; - - /** - * @struct XSDT - * @brief Extended System Description Table (XSDT) structure for ACPI 2 and above. Contains the header and an array of pointers to other SDTs - * - * @typedef xsdt_t - * @brief Alias for XSDT struct - */ - typedef struct XSDT { - ACPISDTHeader header; ///< The common header for all ACPI SDTs (see acpi_sdt_header_t) - uint64_t pointers[]; ///< An array of physical addresses pointing to other ACPI SDTs - } xsdt_t; - - /** - * @class AdvancedConfigurationAndPowerInterface - * @brief Handles ACPI table parsing and retrieval - */ - class AdvancedConfigurationAndPowerInterface { - private: - bool m_using_new_acpi = false; - acpi_sdt_header_t* m_header; - - xsdt_t* m_xsdt; - rsdt_t* m_rsdt; - - rsdp_descriptor_t * m_rsdp; - rsdp_descriptor2_t * m_rsdp2; - - static bool validate(const char* descriptor, size_t length); - - void map_tables(uint8_t size_of_table); - memory::virtual_address_t* map_descriptor(uint64_t physical); - - uint64_t get_rsdt_pointer(size_t index); - - bool valid_checksum(); - - public: - AdvancedConfigurationAndPowerInterface(system::Multiboot* multiboot); - ~AdvancedConfigurationAndPowerInterface(); - - acpi_sdt_header_t* find(const char* signature); - }; - - } +namespace MaxOS::hardwarecommunication { + + /** + * @struct RSDPDescriptor + * @brief Root System Description Pointer (RSDP) structure for ACPI 1. + * + * @typedef rsdp_descriptor_t + * @brief Alias for RSDPDescriptor struct + */ + typedef struct PACKED RSDPDescriptor { + char signature[8]; ///< Indicates a valid RSDP structure if it contains "RSD PTR " (null-terminated) + uint8_t checksum; ///< This byte added to all bytes in the table must equal zero for the table to be valid + char OEMID[6]; ///< A string supplied by the OEM to identify the OEM + uint8_t revision; ///< The version of the ACPI specification that is supported (higher means more features and is backwards compatible) + uint32_t rsdt_address; ///< The physical address of the RSDT (@deprecated in ACPI 2 and above) + } rsdp_descriptor_t; + + /** + * @struct RSDPDescriptor2 + * @brief Root System Description Pointer (RSDP) structure for ACPI 2 and above + * + * @typedef rsdp_descriptor2_t + * @brief Alias for RSDPDescriptor2 struct + */ + typedef struct PACKED RSDPDescriptor2 { + RSDPDescriptor version_1_info; ///< The ACPI 1 RSDP structure (see rsdp_descriptor_t) + uint32_t length; ///< The total length of the RSDP structure (including the version 1 part) + uint64_t xsdt_address; ///< The physical address of the XSDT + uint8_t extended_checksum; ///< This byte added to all bytes in the table must equal zero for the table to be valid (including the version 1 part) + uint8_t reserved[3]; ///< Reserved, must be zero + } rsdp_descriptor2_t; + + /** + * @struct ACPISDTHeader + * @brief Common header for all ACPI System Description Tables (SDTs) + * + * @typedef acpi_sdt_header_t + * @brief Alias for ACPISDTHeader struct + */ + typedef struct PACKED ACPISDTHeader { + char signature[4]; ///< The signature that identifies the type of the table + uint32_t length; ///< The size of the entire table, including the header, in bytes + uint8_t revision; ///< The version of the ACPI specification that is supported (higher means more features and is backwards compatible) + uint8_t checksum; ///< This byte added to all bytes in the table must equal zero mod 0x100 for the table to be valid (including the header) + char OEM_id[6]; ///< A string supplied by the OEM to identify the OEM + char OEM_table_id[8]; ///< A string supplied by the OEM to identify the particular table + uint32_t OEM_revision; ///< The revision number of the table as supplied by the OEM + uint32_t creator_id; ///< A vendor ID of the utility that created the table + uint32_t creator_revision; ///< The revision number of the utility that created the table + } acpi_sdt_header_t; + + /** + * @struct RSDT + * @brief Root System Description Table (RSDT) structure for ACPI 1. Contains the header and an array of pointers to other SDTs + * + * @typedef rsdt_t + * @brief Alias for RSDT struct + */ + typedef struct RSDT { + ACPISDTHeader header; ///< The common header for all ACPI SDTs (see acpi_sdt_header_t) + uint32_t pointers[]; ///< An array of physical addresses pointing to other ACPI SDTs + } rsdt_t; + + /** + * @struct XSDT + * @brief Extended System Description Table (XSDT) structure for ACPI 2 and above. Contains the header and an array of pointers to other SDTs + * + * @typedef xsdt_t + * @brief Alias for XSDT struct + */ + typedef struct XSDT { + ACPISDTHeader header; ///< The common header for all ACPI SDTs (see acpi_sdt_header_t) + uint64_t pointers[]; ///< An array of physical addresses pointing to other ACPI SDTs + } xsdt_t; + + /** + * @class AdvancedConfigurationAndPowerInterface + * @brief Handles ACPI table parsing and retrieval + */ + class AdvancedConfigurationAndPowerInterface { + private: + bool m_using_new_acpi = false; + acpi_sdt_header_t* m_header; + + xsdt_t* m_xsdt; + rsdt_t* m_rsdt; + + rsdp_descriptor_t* m_rsdp; + rsdp_descriptor2_t* m_rsdp2; + + static bool validate(const char* descriptor, size_t length); + + void map_tables(uint8_t size_of_table); + memory::virtual_address_t* map_descriptor(uint64_t physical); + + uint64_t get_rsdt_pointer(size_t index); + + bool valid_checksum(); + + public: + explicit AdvancedConfigurationAndPowerInterface(system::Multiboot* multiboot); + ~AdvancedConfigurationAndPowerInterface(); + + acpi_sdt_header_t* find(const char* signature); + }; + } + #endif // MAXOS_HARDWARECOMMUNICATION_ACPI_H diff --git a/kernel/include/hardwarecommunication/apic.h b/kernel/include/hardwarecommunication/apic.h index f9ee9e50..164c55c3 100644 --- a/kernel/include/hardwarecommunication/apic.h +++ b/kernel/include/hardwarecommunication/apic.h @@ -14,240 +14,240 @@ #include #include -namespace MaxOS { - namespace hardwarecommunication { - - /** - * @class LocalAPIC - * @brief Handles the local APIC for the current core - */ - class LocalAPIC { - - private: - uint64_t m_apic_base{}; - uint64_t m_apic_base_high{}; - uint32_t m_id{}; - bool m_x2apic{}; - - public: - LocalAPIC(); - ~LocalAPIC(); - - [[nodiscard]] uint32_t read(uint32_t reg) const; - void write(uint32_t reg, uint32_t value) const; - - [[nodiscard]] uint32_t id() const; - void send_eoi() const; - - void send_init(uint8_t apic_id, bool assert); - void send_startup(uint8_t apic_id, uint8_t vector); - - }; - - /** - * @struct MADT - * @brief Multiple APIC Description Table (MADT) (ACPI 2 or higher). Provides information about the APICs in - * the system. Following this header are multiple entries describing the APICs (see MADTEntry). - * - * @typedef madt_t - * @brief Alias for MADT struct - */ - typedef struct PACKED MADT { - ACPISDTHeader header; ///< Common ACPI SDT header - uint32_t local_apic_address; ///< The physical address of the local APIC - uint32_t flags; ///< Flags indicating the capabilities of the system (1 = Legacy PICs are present) - } madt_t; - - /** - * @struct MADTEntry - * @brief An item in the MADT table - * - * @typedef madt_entry_t - * @brief Alias for MADTEntry struct - */ - typedef struct PACKED MADTEntry { - uint8_t type; ///< The type of the MADT entry (see MADT_TYPE) - uint8_t length; ///< How many bytes this entry takes up (including the type and length fields) - } madt_entry_t; - - /** - * @enum MADT_TYPE - * @brief The types of MADT entries - */ - enum class MADT_TYPE { - PROCESSOR_APIC, - IO_APIC, - INTERRUPT_SOURCE_OVERRIDE, - NMI_SOURCE, - APIC_NMIS, - APIC_ADDRESS_OVERRIDE, - PROCESSOR_X2APIC, - }; - - /** - * @struct MADT_IO_APIC - * @brief An entry in the MADT table describing an IO APIC - * - * @typedef madt_io_apic_t - * @brief Alias for MADT_IO_APIC struct - * - * @todo Rename for consistency - */ - typedef struct PACKED MADT_IO_APIC { - uint8_t io_apic_id; ///< The ID of the IO APIC - uint8_t reserved; ///< Reserved - uint32_t io_apic_address; ///< The physical address of the IO APIC - uint32_t global_system_interrupt_base; ///< The first GSI number that this IO APIC handles - } madt_io_apic_t; - - /** - * @struct MADT_PROCESSOR_APIC - * @brief An entry in the MADT table describing a processor local APIC - * - * @typedef madt_processor_apic_t - * @brief Alias for MADT_PROCESSOR_APIC struct - */ - typedef struct PACKED MADT_PROCESSOR_APIC { - uint8_t processor_id; ///< The ID for the core - uint8_t apic_id; ///< The ID for the APIC that the core uses - uint32_t flags; ///< Flags indicating the status of the core (bit 0 = core enabled, bit 1 = can be enabled) - } madt_processor_apic_t; - - /** - * @union RedirectionEntry - * @brief An IO APIC redirection entry. Describes how an interrupt is routed. - * - * @typedef redirection_entry_t - * @brief Alias for RedirectionEntry union - */ - typedef union RedirectionEntry { - struct PACKED { - uint64_t vector: 8; ///< The interrupt that will be triggered when this redirection entry is used - uint64_t delivery_mode: 3; ///< How the interrupt will be delvied to the core(s) (see DeliveryMode) - uint64_t destination_mode: 1; ///< How to interpret the destination field (0 = means its the core ID, 1 = means a bitmask of cores) - uint64_t delivery_status: 1; ///< Indicates whether, when setting this entry, the interrupt is still being sent - uint64_t pin_polarity: 1; ///< Defines the electrical signal that indicates an active interrupt line (0 = high active, 1 = low active) (must match the MADT override flags) - uint64_t remote_irr: 1; ///< ? - uint64_t trigger_mode: 1; ///< How the electrical signal is interpreted (0 = edge triggered, 1 = level triggered) (must match the MADT override flags) - uint64_t mask: 1; ///< Whether the interrupt is disabled or not - uint64_t reserved: 39; ///< Reserved bits (should be zero) - uint64_t destination: 8; ///< The core(s) the interrupt should be sent to (interpreted based on destination_mode) - }; ///< Packed because the bitfields should be one uint64_t together - - uint64_t raw; ///< The raw 64-bit value of the redirection entry - } redirection_entry_t; - - /** - * @enum DeliveryMode - * @brief How the interrupt should be delivered (can it override others etc). Set fixed/lowest priority for normal interrupts. - * - * @todo use this - */ - enum DeliveryMode { - FIXED = 0, - LOWEST_PRIORITY = 1, - SMI = 2, - NMI = 4, - INIT = 5, - EXTINT = 7, - }; - - /** - * @struct InterruptRedirect - * @brief Defines how an interrupt input is redirected to a specific processor via the I/O APIC - * - * @typedef interrupt_redirect_t - * @brief Alias for InterruptRedirect struct - */ - typedef struct InterruptRedirect { - - uint8_t type; ///< The type of redirect (should be 0 for normal interrupts) - uint8_t index; ///< Where in the IO APIC redirection table this redirect should be placed - uint8_t interrupt; ///< The interrupt number to trigger when this redirect is used - uint8_t destination; ///< The ID of the core the interrupt should be sent to - uint32_t flags; ///< Configuration flags for the interrupt (see MADT override flags) - bool mask; ///< Should the interrupt be disabled initially - - } interrupt_redirect_t; - - /** - * @struct Override - * @brief Specifies how a specific interrupt source is mapped to a global system interrupt - * - * @typedef override_t - * @brief Alias for Override struct - */ - typedef struct PACKED Override { - - uint8_t bus; ///< Identifies the hardware bus the interrupt comes from (0 = ISA, 1 = PCI) - uint8_t source; ///< The interrupt source number on the specified bus - uint32_t global_system_interrupt; ///< The global system interrupt that the source is mapped to - uint16_t flags; ///< Flags describing the polarity and trigger mode of the interrupt source (see MADT override flags) - - } override_t; - - /** - * @class IOAPIC - * @brief Handles the IO APIC in the system (one per system) - */ - class IOAPIC { - private: - AdvancedConfigurationAndPowerInterface* m_acpi; - MADT* m_madt = {nullptr}; - uint64_t m_address = 0; - uint64_t m_address_high = 0; - uint32_t m_version = 0; - uint8_t m_max_redirect_entry = 0; - - uint8_t m_override_array_size = 0; - Override m_override_array[0x10] = {}; - - void read_redirect(uint8_t index, RedirectionEntry* entry); - void write_redirect(uint8_t index, RedirectionEntry* entry); - - public: - IOAPIC(AdvancedConfigurationAndPowerInterface* acpi); - ~IOAPIC(); - - uint32_t read(uint32_t reg) const; - void write(uint32_t reg, uint32_t value) const; - - void set_redirect(interrupt_redirect_t* redirect); - void set_redirect_mask(uint8_t index, bool mask); - - MADTEntry* get_madt_item(MADT_TYPE type, uint8_t index); - - }; - - /** - * @class AdvancedProgrammableInterruptController - * @brief Handles both the Local APIC (boot core) and IO APIC - * - * @todo Should either handle all Local APICs or none (only boot core right now, others accessed per core directly which is inconsistent) - */ - class AdvancedProgrammableInterruptController { - - private: - LocalAPIC* m_local_apic; - IOAPIC* m_io_apic; - - Port8BitSlow m_pic_master_command_port; - Port8BitSlow m_pic_master_data_port; - Port8BitSlow m_pic_slave_command_port; - Port8BitSlow m_pic_slave_data_port; - - void disable_pic(); - - public: - AdvancedProgrammableInterruptController(AdvancedConfigurationAndPowerInterface* acpi); - ~AdvancedProgrammableInterruptController(); - - LocalAPIC* local_apic() const; - IOAPIC* io_apic() const; - - }; - - } + +namespace MaxOS::hardwarecommunication { + + /** + * @class LocalAPIC + * @brief Handles the local APIC for the current core + */ + class LocalAPIC { + + private: + uint64_t m_apic_base { }; + uint64_t m_apic_base_high { }; + uint32_t m_id { }; + bool m_x2apic { }; + + public: + LocalAPIC(); + ~LocalAPIC(); + + [[nodiscard]] uint32_t read(uint32_t reg) const; + void write(uint32_t reg, uint32_t value) const; + + [[nodiscard]] uint32_t id() const; + void send_eoi() const; + + void send_init(uint8_t apic_id, bool assert) const; + void send_startup(uint8_t apic_id, uint8_t vector) const; + + }; + + /** + * @struct MADT + * @brief Multiple APIC Description Table (MADT) (ACPI 2 or higher). Provides information about the APICs in + * the system. Following this header are multiple entries describing the APICs (see MADTEntry). + * + * @typedef madt_t + * @brief Alias for MADT struct + */ + typedef struct PACKED MADT { + ACPISDTHeader header; ///< Common ACPI SDT header + uint32_t local_apic_address; ///< The physical address of the local APIC + uint32_t flags; ///< Flags indicating the capabilities of the system (1 = Legacy PICs are present) + } madt_t; + + /** + * @struct MADTEntry + * @brief An item in the MADT table + * + * @typedef madt_entry_t + * @brief Alias for MADTEntry struct + */ + typedef struct PACKED MADTEntry { + uint8_t type; ///< The type of the MADT entry (see MADT_TYPE) + uint8_t length; ///< How many bytes this entry takes up (including the type and length fields) + } madt_entry_t; + + /** + * @enum MADT_TYPE + * @brief The types of MADT entries + */ + enum class MADT_TYPE { + PROCESSOR_APIC, + IO_APIC, + INTERRUPT_SOURCE_OVERRIDE, + NMI_SOURCE, + APIC_NMIS, + APIC_ADDRESS_OVERRIDE, + PROCESSOR_X2APIC, + }; + + /** + * @struct MADT_IO_APIC + * @brief An entry in the MADT table describing an IO APIC + * + * @typedef madt_io_apic_t + * @brief Alias for MADT_IO_APIC struct + * + * @todo Rename for consistency + */ + typedef struct PACKED MADT_IO_APIC { + uint8_t io_apic_id; ///< The ID of the IO APIC + uint8_t reserved; ///< Reserved + uint32_t io_apic_address; ///< The physical address of the IO APIC + uint32_t global_system_interrupt_base; ///< The first GSI number that this IO APIC handles + } madt_io_apic_t; + + /** + * @struct MADT_PROCESSOR_APIC + * @brief An entry in the MADT table describing a processor local APIC + * + * @typedef madt_processor_apic_t + * @brief Alias for MADT_PROCESSOR_APIC struct + */ + typedef struct PACKED MADT_PROCESSOR_APIC { + uint8_t processor_id; ///< The ID for the core + uint8_t apic_id; ///< The ID for the APIC that the core uses + uint32_t flags; ///< Flags indicating the status of the core (bit 0 = core enabled, bit 1 = can be enabled) + } madt_processor_apic_t; + + /** + * @union RedirectionEntry + * @brief An IO APIC redirection entry. Describes how an interrupt is routed. + * + * @typedef redirection_entry_t + * @brief Alias for RedirectionEntry union + */ + typedef union RedirectionEntry { + struct PACKED { + uint64_t vector : 8; ///< The interrupt that will be triggered when this redirection entry is used + uint64_t delivery_mode : 3; ///< How the interrupt will be delvied to the core(s) (see DeliveryMode) + uint64_t destination_mode : 1; ///< How to interpret the destination field (0 = means its the core ID, 1 = means a bitmask of cores) + uint64_t delivery_status : 1; ///< Indicates whether, when setting this entry, the interrupt is still being sent + uint64_t pin_polarity : 1; ///< Defines the electrical signal that indicates an active interrupt line (0 = high active, 1 = low active) (must match the MADT override flags) + uint64_t remote_irr : 1; ///< ? + uint64_t trigger_mode : 1; ///< How the electrical signal is interpreted (0 = edge triggered, 1 = level triggered) (must match the MADT override flags) + uint64_t mask : 1; ///< Whether the interrupt is disabled or not + uint64_t reserved : 39; ///< Reserved bits (should be zero) + uint64_t destination : 8; ///< The core(s) the interrupt should be sent to (interpreted based on destination_mode) + }; ///< Packed because the bitfields should be one uint64_t together + + uint64_t raw; ///< The raw 64-bit value of the redirection entry + } redirection_entry_t; + + /** + * @enum DeliveryMode + * @brief How the interrupt should be delivered (can it override others etc). Set fixed/lowest priority for normal interrupts. + * + * @todo use this + */ + enum DeliveryMode { + FIXED = 0, + LOWEST_PRIORITY = 1, + SMI = 2, + NMI = 4, + INIT = 5, + EXTINT = 7, + }; + + /** + * @struct InterruptRedirect + * @brief Defines how an interrupt input is redirected to a specific processor via the I/O APIC + * + * @typedef interrupt_redirect_t + * @brief Alias for InterruptRedirect struct + */ + typedef struct InterruptRedirect { + + uint8_t type; ///< The type of redirect (should be 0 for normal interrupts) + uint8_t index; ///< Where in the IO APIC redirection table this redirect should be placed + uint8_t interrupt; ///< The interrupt number to trigger when this redirect is used + uint8_t destination; ///< The ID of the core the interrupt should be sent to + uint32_t flags; ///< Configuration flags for the interrupt (see MADT override flags) + bool mask; ///< Should the interrupt be disabled initially + + } interrupt_redirect_t; + + /** + * @struct Override + * @brief Specifies how a specific interrupt source is mapped to a global system interrupt + * + * @typedef override_t + * @brief Alias for Override struct + */ + typedef struct PACKED Override { + + uint8_t bus; ///< Identifies the hardware bus the interrupt comes from (0 = ISA, 1 = PCI) + uint8_t source; ///< The interrupt source number on the specified bus + uint32_t global_system_interrupt; ///< The global system interrupt that the source is mapped to + uint16_t flags; ///< Flags describing the polarity and trigger mode of the interrupt source (see MADT override flags) + + } override_t; + + /** + * @class IOAPIC + * @brief Handles the IO APIC in the system (one per system) + */ + class IOAPIC { + private: + AdvancedConfigurationAndPowerInterface* m_acpi; + MADT* m_madt = { nullptr }; + uint64_t m_address = 0; + uint64_t m_address_high = 0; + uint32_t m_version = 0; + uint8_t m_max_redirect_entry = 0; + + uint8_t m_override_array_size = 0; + Override m_override_array[0x10] = { }; + + void read_redirect(uint8_t index, RedirectionEntry* entry) const; + void write_redirect(uint8_t index, RedirectionEntry* entry) const; + + public: + explicit IOAPIC(AdvancedConfigurationAndPowerInterface* acpi); + ~IOAPIC(); + + [[nodiscard]] uint32_t read(uint32_t reg) const; + void write(uint32_t reg, uint32_t value) const; + + void set_redirect(interrupt_redirect_t* redirect); + void set_redirect_mask(uint8_t index, bool mask); + + MADTEntry* get_madt_item(MADT_TYPE type, uint8_t index); + + }; + + /** + * @class AdvancedProgrammableInterruptController + * @brief Handles both the Local APIC (boot core) and IO APIC + * + * @todo Should either handle all Local APICs or none (only boot core right now, others accessed per core directly which is inconsistent) + */ + class AdvancedProgrammableInterruptController { + + private: + LocalAPIC* m_local_apic; + IOAPIC* m_io_apic; + + Port8BitSlow m_pic_master_command_port; + Port8BitSlow m_pic_master_data_port; + Port8BitSlow m_pic_slave_command_port; + Port8BitSlow m_pic_slave_data_port; + + void disable_pic(); + + public: + explicit AdvancedProgrammableInterruptController(AdvancedConfigurationAndPowerInterface* acpi); + ~AdvancedProgrammableInterruptController(); + + [[nodiscard]] LocalAPIC* local_apic() const; + [[nodiscard]] IOAPIC* io_apic() const; + + }; + } + #endif // MAXOS_HARDWARECOMMUNICATION_APIC_H diff --git a/kernel/include/hardwarecommunication/interrupts.h b/kernel/include/hardwarecommunication/interrupts.h index 54b97478..cc5a3a43 100644 --- a/kernel/include/hardwarecommunication/interrupts.h +++ b/kernel/include/hardwarecommunication/interrupts.h @@ -9,7 +9,7 @@ #ifndef MAX_OS_HARDWARECOMMUNICATION_INTERRUPTS_H #define MAX_OS_HARDWARECOMMUNICATION_INTERRUPTS_H -#include +#include #include #include #include @@ -19,169 +19,168 @@ #include -namespace MaxOS { - namespace hardwarecommunication { - - class InterruptManager; - - /** - * @class InterruptHandler - * @brief Handles a certain interrupt number - */ - class InterruptHandler { - protected: - uint8_t m_interrupt_number; ///< The interrupt number this handler handles - - InterruptHandler(uint8_t interrupt_number, int64_t redirect = -1, uint64_t redirect_index = 0); - ~InterruptHandler(); - - public: - virtual void handle_interrupt(); - virtual system::cpu_status_t* handle_interrupt(system::cpu_status_t* status); - - }; - - /** - * @struct IDTR - * @brief A struct that holds the Interrupt Descriptor Table Register (IDTR) - * - * @typedef idtr_t - * @brief Alias for IDTR struct - */ - typedef struct PACKED IDTR { - uint16_t limit; ///< The size of the IDT - uint64_t base; ///< The start address of the IDT - } idtr_t; - - /** - * @struct InterruptDescriptor - * @brief An entry in the Interrupt Descriptor Table (IDT) - * - * @typedef interrupt_descriptor_t - * @brief Alias for InterruptDescriptor struct - */ - typedef struct PACKED InterruptDescriptor{ - - uint16_t address_low_bits; ///< The low bits of the handler function address - uint16_t segment_selector; ///< The code segment selector in the GDT to use when this interrupt fires - uint8_t ist; ///< The offset into the Interrupt Stack Table (0 if not used) (see TSS) - uint8_t flags; ///< Flags: The type of gate this entry represents (0xE for interrupt gate, 0xF for trap gate), The privilege level required to invoke this interrupt and whether the interrupt is present (@todo substruct this) - uint16_t address_mid_bits; ///< The middle bits of the handler function address - uint32_t address_high_bits; ///< The high bits of the handler function address - uint32_t reserved; ///< Reserved, must be zero - - } interrupt_descriptor_t; - - constexpr uint16_t HARDWARE_INTERRUPT_OFFSET = 0x20; ///< The offset in the IDT where interrupts from hardware start - constexpr uint16_t MAX_INTERRUPT_HANDLERS = 256; ///< The maximum number of interrupt handlers - - /** - * @class InterruptManager - * @brief Handles all interrupts and passes them to the correct handler - * - * @todo Remove the max array of handler make vector, add static handlers for page faults and gpe. Make it so that multiple handlers can be registered for the same interrupt - * @todo Have a single stub so that we don't need to have 256 different functions for each interrupt - */ - class InterruptManager { - friend class InterruptHandler; - - private: - AdvancedProgrammableInterruptController* m_apic = nullptr; - - static system::cpu_status_t* page_fault(system::cpu_status_t* status); - static system::cpu_status_t* general_protection_fault(system::cpu_status_t* status); - - protected: - - inline static InterruptManager* s_active_interrupt_manager = nullptr; ///< The interrupt manger that is currently handling interrupts and is loaded into the IDTR - - InterruptHandler* m_interrupt_handlers[MAX_INTERRUPT_HANDLERS] = {}; ///< A map of index-to-interrupt of interrupt handlers to fire when an interrupt occurs - inline static InterruptDescriptor s_interrupt_descriptor_table[MAX_INTERRUPT_HANDLERS] = {}; ///< The Interrupt Descriptor Table (IDT) - - static void set_interrupt_descriptor_table_entry(uint8_t interrupt, void (*handler)(), uint8_t descriptor_privilege_level); - - //Various Interrupts - static void HandleInterruptRequest0x00(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x01(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x02(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x03(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x04(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x05(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x06(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x07(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x08(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x09(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x0A(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x0B(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x0C(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x0D(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x0E(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x80(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x0F(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x31(); ///< Stub (see interrupts.s) - static void HandleInterruptRequest0x60(); ///< Stub (see interrupts.s) - - // Exceptions - static void HandleException0x00(); ///< Stub (see interrupts.s) - static void HandleException0x01(); ///< Stub (see interrupts.s) - static void HandleException0x02(); ///< Stub (see interrupts.s) - static void HandleException0x03(); ///< Stub (see interrupts.s) - static void HandleException0x04(); ///< Stub (see interrupts.s) - static void HandleException0x05(); ///< Stub (see interrupts.s) - static void HandleException0x06(); ///< Stub (see interrupts.s) - static void HandleException0x07(); ///< Stub (see interrupts.s) - static void HandleInterruptError0x08(); ///< Stub (see interrupts.s) - static void HandleException0x09(); ///< Stub (see interrupts.s) - static void HandleInterruptError0x0A(); ///< Stub (see interrupts.s) - static void HandleInterruptError0x0B(); ///< Stub (see interrupts.s) - static void HandleInterruptError0x0C(); ///< Stub (see interrupts.s) - static void HandleInterruptError0x0D(); ///< Stub (see interrupts.s) - static void HandleInterruptError0x0E(); ///< Stub (see interrupts.s) - static void HandleException0x0F(); ///< Stub (see interrupts.s) - static void HandleException0x10(); ///< Stub (see interrupts.s) - static void HandleInterruptError0x11(); ///< Stub (see interrupts.s) - static void HandleException0x12(); ///< Stub (see interrupts.s) - static void HandleException0x13(); ///< Stub (see interrupts.s) - static void HandleException0x14(); ///< Stub (see interrupts.s) - static void HandleException0x15(); ///< Stub (see interrupts.s) - static void HandleException0x16(); ///< Stub (see interrupts.s) - static void HandleException0x17(); ///< Stub (see interrupts.s) - static void HandleException0x18(); ///< Stub (see interrupts.s) - static void HandleException0x19(); ///< Stub (see interrupts.s) - static void HandleException0x1A(); ///< Stub (see interrupts.s) - static void HandleException0x1B(); ///< Stub (see interrupts.s) - static void HandleException0x1C(); ///< Stub (see interrupts.s) - static void HandleException0x1D(); ///< Stub (see interrupts.s) - static void HandleException0x1E(); ///< Stub (see interrupts.s) - static void HandleException0x1F(); ///< Stub (see interrupts.s) - - static system::cpu_status_t* HandleInterrupt(system::cpu_status_t* status); - system::cpu_status_t* handle_interrupt_request(system::cpu_status_t* status); - - public: - InterruptManager(); - ~InterruptManager(); - - static InterruptManager* active_interrupt_manager(); - - void set_interrupt_handler(uint8_t interrupt, InterruptHandler *handler); - void remove_interrupt_handler(uint8_t interrupt); - - void set_apic(AdvancedProgrammableInterruptController* apic); - AdvancedProgrammableInterruptController* active_apic(); - - static void load_current(); - void activate(); - void deactivate(); - - /** - * @brief Force the CPU to return from an interrupt (see interrupts.s) - * @param state the state to return to - */ - static void ForceInterruptReturn(system::cpu_status_t* state); - - }; - } +namespace MaxOS::hardwarecommunication { + + class InterruptManager; + + /** + * @class InterruptHandler + * @brief Handles a certain interrupt number + */ + class InterruptHandler { + protected: + uint8_t m_interrupt_number; ///< The interrupt number this handler handles + + explicit InterruptHandler(uint8_t interrupt_number, int64_t redirect = -1, uint64_t redirect_index = 0); + ~InterruptHandler(); + + public: + virtual void handle_interrupt(); + virtual system::cpu_status_t* handle_interrupt(system::cpu_status_t* status); + + }; + + /** + * @struct IDTR + * @brief A struct that holds the Interrupt Descriptor Table Register (IDTR) + * + * @typedef idtr_t + * @brief Alias for IDTR struct + */ + typedef struct PACKED IDTR { + uint16_t limit; ///< The size of the IDT + uint64_t base; ///< The start address of the IDT + } idtr_t; + + /** + * @struct InterruptDescriptor + * @brief An entry in the Interrupt Descriptor Table (IDT) + * + * @typedef interrupt_descriptor_t + * @brief Alias for InterruptDescriptor struct + */ + typedef struct PACKED InterruptDescriptor { + + uint16_t address_low_bits; ///< The low bits of the handler function address + uint16_t segment_selector; ///< The code segment selector in the GDT to use when this interrupt fires + uint8_t ist; ///< The offset into the Interrupt Stack Table (0 if not used) (see TSS) + uint8_t flags; ///< Flags: The type of gate this entry represents (0xE for interrupt gate, 0xF for trap gate), The privilege level required to invoke this interrupt and whether the interrupt is present (@todo substruct this) + uint16_t address_mid_bits; ///< The middle bits of the handler function address + uint32_t address_high_bits; ///< The high bits of the handler function address + uint32_t reserved; ///< Reserved, must be zero + + } interrupt_descriptor_t; + + constexpr uint16_t HARDWARE_INTERRUPT_OFFSET = 0x20; ///< The offset in the IDT where interrupts from hardware start + constexpr uint16_t MAX_INTERRUPT_HANDLERS = 256; ///< The maximum number of interrupt handlers + + /** + * @class InterruptManager + * @brief Handles all interrupts and passes them to the correct handler + * + * @todo Remove the max array of handler make vector, add static handlers for page faults and gpe. Make it so that multiple handlers can be registered for the same interrupt + * @todo Have a single stub so that we don't need to have 256 different functions for each interrupt + */ + class InterruptManager { + friend class InterruptHandler; + + private: + AdvancedProgrammableInterruptController* m_apic = nullptr; + + static system::cpu_status_t* page_fault(system::cpu_status_t* status); + static system::cpu_status_t* general_protection_fault(system::cpu_status_t* status); + + protected: + + inline static InterruptManager* s_active_interrupt_manager = nullptr; ///< The interrupt manger that is currently handling interrupts and is loaded into the IDTR + + InterruptHandler* m_interrupt_handlers[MAX_INTERRUPT_HANDLERS] = { }; ///< A map of index-to-interrupt of interrupt handlers to fire when an interrupt occurs + inline static InterruptDescriptor s_interrupt_descriptor_table[MAX_INTERRUPT_HANDLERS] = { }; ///< The Interrupt Descriptor Table (IDT) + + static void set_interrupt_descriptor_table_entry(uint8_t interrupt, void (* handler)(), uint8_t descriptor_privilege_level); + + //Various Interrupts + static void HandleInterruptRequest0x00(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x01(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x02(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x03(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x04(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x05(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x06(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x07(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x08(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x09(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x0A(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x0B(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x0C(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x0D(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x0E(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x80(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x0F(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x31(); ///< Stub (see interrupts.s) + static void HandleInterruptRequest0x60(); ///< Stub (see interrupts.s) + + // Exceptions + static void HandleException0x00(); ///< Stub (see interrupts.s) + static void HandleException0x01(); ///< Stub (see interrupts.s) + static void HandleException0x02(); ///< Stub (see interrupts.s) + static void HandleException0x03(); ///< Stub (see interrupts.s) + static void HandleException0x04(); ///< Stub (see interrupts.s) + static void HandleException0x05(); ///< Stub (see interrupts.s) + static void HandleException0x06(); ///< Stub (see interrupts.s) + static void HandleException0x07(); ///< Stub (see interrupts.s) + static void HandleInterruptError0x08(); ///< Stub (see interrupts.s) + static void HandleException0x09(); ///< Stub (see interrupts.s) + static void HandleInterruptError0x0A(); ///< Stub (see interrupts.s) + static void HandleInterruptError0x0B(); ///< Stub (see interrupts.s) + static void HandleInterruptError0x0C(); ///< Stub (see interrupts.s) + static void HandleInterruptError0x0D(); ///< Stub (see interrupts.s) + static void HandleInterruptError0x0E(); ///< Stub (see interrupts.s) + static void HandleException0x0F(); ///< Stub (see interrupts.s) + static void HandleException0x10(); ///< Stub (see interrupts.s) + static void HandleInterruptError0x11(); ///< Stub (see interrupts.s) + static void HandleException0x12(); ///< Stub (see interrupts.s) + static void HandleException0x13(); ///< Stub (see interrupts.s) + static void HandleException0x14(); ///< Stub (see interrupts.s) + static void HandleException0x15(); ///< Stub (see interrupts.s) + static void HandleException0x16(); ///< Stub (see interrupts.s) + static void HandleException0x17(); ///< Stub (see interrupts.s) + static void HandleException0x18(); ///< Stub (see interrupts.s) + static void HandleException0x19(); ///< Stub (see interrupts.s) + static void HandleException0x1A(); ///< Stub (see interrupts.s) + static void HandleException0x1B(); ///< Stub (see interrupts.s) + static void HandleException0x1C(); ///< Stub (see interrupts.s) + static void HandleException0x1D(); ///< Stub (see interrupts.s) + static void HandleException0x1E(); ///< Stub (see interrupts.s) + static void HandleException0x1F(); ///< Stub (see interrupts.s) + + static system::cpu_status_t* HandleInterrupt(system::cpu_status_t* status); + system::cpu_status_t* handle_interrupt_request(system::cpu_status_t* status); + + public: + InterruptManager(); + ~InterruptManager(); + + static InterruptManager* active_interrupt_manager(); + + void set_interrupt_handler(uint8_t interrupt, InterruptHandler* handler); + void remove_interrupt_handler(uint8_t interrupt); + + void set_apic(AdvancedProgrammableInterruptController* apic); + AdvancedProgrammableInterruptController* active_apic(); + + static void load_current(); + void activate(); + static void deactivate(); + + /** + * @brief Force the CPU to return from an interrupt (see interrupts.s) + * @param state the state to return to + */ + static void ForceInterruptReturn(system::cpu_status_t* state); + + }; } + #endif //MAX_OS_HARDWARECOMMUNICATION_INTERRUPTS_H diff --git a/kernel/include/hardwarecommunication/pci.h b/kernel/include/hardwarecommunication/pci.h index bd25e368..f896ca29 100644 --- a/kernel/include/hardwarecommunication/pci.h +++ b/kernel/include/hardwarecommunication/pci.h @@ -9,7 +9,7 @@ #ifndef MAX_OS_HARDWARECOMMUNICATION_PCI_H #define MAX_OS_HARDWARECOMMUNICATION_PCI_H -#include +#include #include #include #include @@ -17,98 +17,98 @@ #include #include -namespace MaxOS { - namespace hardwarecommunication { - - /** - * @enum BARType - * @brief Determines whether the PCI device communicates via IO ports or memory. - */ - enum class BARType { - MemoryMapped, - InputOutput - }; - - /** - * @class BaseAddressRegister - * @brief Used to store the Base Address Register (BAR) of a PCI device - * - * @todo Should be a struct - */ - class BaseAddressRegister { - public: - bool pre_fetchable; ///< Reading from this address wont change the state of the device and data can be cached by the CPU - uint8_t* address; ///< The address of the device (IO port or memory address, can be 32 or 64 bit) - uint32_t size; ///< @todo Document Size of the address space - BARType type; ///< Where to access the device - - }; - - - /** - * @class PCIDeviceDescriptor - * @brief Stores information about a PCI device - * - * @todo Should be a struct aswell - */ - class PCIDeviceDescriptor { - public: - bool has_port_base = false; ///< Whether the device has an IO port base address - uint32_t port_base = 0; ///< The IO port base address - - bool has_memory_base = false; ///< Whether the device has a memory base address - uint32_t memory_base = 0; ///< The memory base address - - uint32_t interrupt = 0; ///< The interrupt number the device uses to communicate with the CPU - - uint16_t bus = 0; ///< The PCI bus the device is connected to - uint16_t device = 0; ///< The device number on the PCI bus - uint16_t function = 0; ///< The function number of the device - - uint16_t vendor_id = 0; ///< The company's that made the device unique identifier - uint16_t device_id = 0; ///< The device's unique identifier - - uint8_t class_id = 0; ///< The class type of the device - uint8_t subclass_id = 0; ///< The subclass type of the device - uint8_t interface_id = 0; ///< The interface type of the device - - uint8_t revision = 0; ///< The device version number - - PCIDeviceDescriptor(); - ~PCIDeviceDescriptor(); - - string get_type() const; - }; - - - /** - * @class PCIController - * @brief Handles the selecting and loading of drivers for PCI devices - */ - class PCIController : public drivers::DriverSelector { - private: - // Ports - Port32Bit m_data_port; - Port32Bit m_command_port; - - // I/O - uint32_t read(uint16_t bus, uint16_t device, uint16_t function, uint32_t register_offset); - void write(uint16_t bus, uint16_t device, uint16_t function, uint32_t register_offset, uint32_t value); - - // Device - PCIDeviceDescriptor get_device_descriptor(uint16_t bus, uint16_t device, uint16_t function); - BaseAddressRegister get_base_address_register(uint16_t bus, uint16_t device, uint16_t function, uint16_t bar); - bool device_has_functions(uint16_t bus, uint16_t device); - - public: - PCIController(); - ~PCIController(); - - void select_drivers(drivers::DriverSelectorEventHandler* handler) override; - static drivers::Driver* get_driver(PCIDeviceDescriptor dev); - static void list_known_device(const PCIDeviceDescriptor& dev); - }; - } + +namespace MaxOS::hardwarecommunication { + + /** + * @enum BARType + * @brief Determines whether the PCI device communicates via IO ports or memory. + */ + enum class BARType { + MemoryMapped, + InputOutput + }; + + /** + * @class BaseAddressRegister + * @brief Used to store the Base Address Register (BAR) of a PCI device + * + * @todo Should be a struct + */ + class BaseAddressRegister { + public: + bool pre_fetchable; ///< Reading from this address wont change the state of the device and data can be cached by the CPU + uint8_t* address; ///< The address of the device (IO port or memory address, can be 32 or 64 bit) + uint32_t size; ///< @todo Document Size of the address space + BARType type; ///< Where to access the device + + }; + + + /** + * @class PCIDeviceDescriptor + * @brief Stores information about a PCI device + * + * @todo Should be a struct aswell + */ + class PCIDeviceDescriptor { + public: + bool has_port_base = false; ///< Whether the device has an IO port base address + uint32_t port_base = 0; ///< The IO port base address + + bool has_memory_base = false; ///< Whether the device has a memory base address + uint32_t memory_base = 0; ///< The memory base address + + uint32_t interrupt = 0; ///< The interrupt number the device uses to communicate with the CPU + + uint16_t bus = 0; ///< The PCI bus the device is connected to + uint16_t device = 0; ///< The device number on the PCI bus + uint16_t function = 0; ///< The function number of the device + + uint16_t vendor_id = 0; ///< The company's that made the device unique identifier + uint16_t device_id = 0; ///< The device's unique identifier + + uint8_t class_id = 0; ///< The class type of the device + uint8_t subclass_id = 0; ///< The subclass type of the device + uint8_t interface_id = 0; ///< The interface type of the device + + uint8_t revision = 0; ///< The device version number + + PCIDeviceDescriptor(); + ~PCIDeviceDescriptor(); + + [[nodiscard]] string get_type() const; + }; + + + /** + * @class PCIController + * @brief Handles the selecting and loading of drivers for PCI devices + */ + class PCIController final : public drivers::DriverSelector { + private: + // Ports + Port32Bit m_data_port; + Port32Bit m_command_port; + + // I/O + uint32_t read(uint16_t bus, uint16_t device, uint16_t function, uint32_t register_offset); + void write(uint16_t bus, uint16_t device, uint16_t function, uint32_t register_offset, uint32_t value); + + // Device + PCIDeviceDescriptor get_device_descriptor(uint16_t bus, uint16_t device, uint16_t function); + BaseAddressRegister get_base_address_register(uint16_t bus, uint16_t device, uint16_t function, uint16_t bar); + bool device_has_functions(uint16_t bus, uint16_t device); + + public: + PCIController(); + ~PCIController() final; + + void select_drivers(drivers::DriverSelectorEventHandler* handler) override; + static drivers::Driver* get_driver(PCIDeviceDescriptor dev); + static void list_known_device(const PCIDeviceDescriptor& dev); + }; } + #endif //MAX_OS_HARDWARECOMMUNICATION_PCI_H diff --git a/kernel/include/hardwarecommunication/port.h b/kernel/include/hardwarecommunication/port.h index e87bc720..ec655e2d 100644 --- a/kernel/include/hardwarecommunication/port.h +++ b/kernel/include/hardwarecommunication/port.h @@ -9,73 +9,73 @@ #ifndef MAX_OS_HARDWARECOMMUNICATION_PORT_H #define MAX_OS_HARDWARECOMMUNICATION_PORT_H -#include -namespace MaxOS { - namespace hardwarecommunication { +#include - /** - * @class Port - * @brief base class for all ports - */ - class Port { - protected: - uint16_t m_port_number; ///< The port to write to / read from +namespace MaxOS::hardwarecommunication { - Port(uint16_t port_number); - ~Port(); - }; + /** + * @class Port + * @brief base class for all ports + */ + class Port { + protected: + uint16_t m_port_number; ///< The port to write to / read from - /** - * @class Port8Bit - * @brief Handles 8 bit ports - */ - class Port8Bit : public Port { - public: - Port8Bit(uint16_t port_number); - ~Port8Bit(); + explicit Port(uint16_t port_number); + ~Port(); + }; - virtual void write(uint8_t data); - virtual uint8_t read(); - }; + /** + * @class Port8Bit + * @brief Handles 8 bit ports + */ + class Port8Bit : public Port { + public: + explicit Port8Bit(uint16_t port_number); + ~Port8Bit(); - /** - * @class Port8BitSlow - * @brief Handles 8 bit ports (slow) - */ - class Port8BitSlow : public Port8Bit { - public: - Port8BitSlow(uint16_t port_number); - ~Port8BitSlow(); + virtual void write(uint8_t data); + virtual uint8_t read(); + }; - void write(uint8_t data) final; - }; + /** + * @class Port8BitSlow + * @brief Handles 8 bit ports (slow) + */ + class Port8BitSlow : public Port8Bit { + public: + explicit Port8BitSlow(uint16_t port_number); + ~Port8BitSlow(); - /** - * @class Port16Bit - * @brief Handles 16 bit ports - */ - class Port16Bit : public Port { - public: - Port16Bit(uint16_t port_number); - ~Port16Bit(); + void write(uint8_t data) final; + }; - virtual void write(uint16_t data); - virtual uint16_t read(); - }; + /** + * @class Port16Bit + * @brief Handles 16 bit ports + */ + class Port16Bit : public Port { + public: + explicit Port16Bit(uint16_t port_number); + ~Port16Bit(); - /** - * @class Port32Bit - * @brief Handles 32 bit ports - */ - class Port32Bit : public Port { - public: - Port32Bit(uint16_t port_number); - ~Port32Bit(); + virtual void write(uint16_t data); + virtual uint16_t read(); + }; - virtual void write(uint32_t data); - virtual uint32_t read(); - }; - } + /** + * @class Port32Bit + * @brief Handles 32 bit ports + */ + class Port32Bit : public Port { + public: + explicit Port32Bit(uint16_t port_number); + ~Port32Bit(); + + virtual void write(uint32_t data); + virtual uint32_t read(); + }; } + #endif //MAX_OS_HARDWARECOMMUNICATION_PORT_H \ No newline at end of file diff --git a/kernel/include/memory/memoryIO.h b/kernel/include/memory/memoryIO.h index 955527a1..be22634f 100644 --- a/kernel/include/memory/memoryIO.h +++ b/kernel/include/memory/memoryIO.h @@ -9,81 +9,81 @@ #ifndef MAXOS_MEMORY_MEMORYINPUTOUTPUT_H #define MAXOS_MEMORY_MEMORYINPUTOUTPUT_H -#include -#include - -namespace MaxOS{ - namespace memory{ - - /** - * @class MemIO - * @brief base class for all memory IO - * - * @todo Not used, delete? - */ - class MemIO { - protected: - uintptr_t m_address; ///< The memory address to read from / write to - - MemIO(uintptr_t address); - ~MemIO(); - }; - - /** - * @class MemIO8Bit - * @brief Handles 8 bit memory IO - */ - class MemIO8Bit : public MemIO { - public: - MemIO8Bit(uintptr_t address); - ~MemIO8Bit(); - - virtual void write(uint8_t data); - virtual uint8_t read(); - }; - - /** - * @class MemIO16Bit - * @brief Handles 16 bit memory IO - */ - class MemIO16Bit : public MemIO { - public: - MemIO16Bit(uintptr_t address); - ~MemIO16Bit(); - - virtual void write(uint16_t data); - virtual uint16_t read(); - }; - - /** - * @class MemIO32Bit - * @brief Handles 32 bit memory IO - */ - class MemIO32Bit : public MemIO { - public: - MemIO32Bit(uintptr_t address); - ~MemIO32Bit(); - - virtual void write(uint32_t data); - virtual uint32_t read(); - }; - - /** - * @class MemIO64Bit - * @brief Handles 64 bit memory IO - */ - class MemIO64Bit : public MemIO { - public: - MemIO64Bit(uintptr_t address); - ~MemIO64Bit(); - - virtual void write(uint64_t data); - virtual uint64_t read(); - }; - - } +#include +#include + + +namespace MaxOS::memory { + + /** + * @class MemIO + * @brief base class for all memory IO + * + * @todo Not used, delete? + */ + class MemIO { + protected: + uintptr_t m_address; ///< The memory address to read from / write to + + explicit MemIO(uintptr_t address); + ~MemIO(); + }; + + /** + * @class MemIO8Bit + * @brief Handles 8 bit memory IO + */ + class MemIO8Bit : public MemIO { + public: + explicit MemIO8Bit(uintptr_t address); + ~MemIO8Bit(); + + virtual void write(uint8_t data); + virtual uint8_t read(); + }; + + /** + * @class MemIO16Bit + * @brief Handles 16 bit memory IO + */ + class MemIO16Bit : public MemIO { + public: + explicit MemIO16Bit(uintptr_t address); + ~MemIO16Bit(); + + virtual void write(uint16_t data); + virtual uint16_t read(); + }; + + /** + * @class MemIO32Bit + * @brief Handles 32 bit memory IO + */ + class MemIO32Bit : public MemIO { + public: + explicit MemIO32Bit(uintptr_t address); + ~MemIO32Bit(); + + virtual void write(uint32_t data); + virtual uint32_t read(); + }; + + /** + * @class MemIO64Bit + * @brief Handles 64 bit memory IO + */ + class MemIO64Bit : public MemIO { + public: + explicit MemIO64Bit(uintptr_t address); + ~MemIO64Bit(); + + virtual void write(uint64_t data); + virtual uint64_t read(); + }; + } + void* memcpy(void* destination, const void* source, uint64_t num); void* memset(void* ptr, uint32_t value, uint64_t num); void* memmove(void* destination, const void* source, uint64_t num); diff --git a/kernel/include/memory/memorymanagement.h b/kernel/include/memory/memorymanagement.h index 6c78fad9..6cb47acc 100644 --- a/kernel/include/memory/memorymanagement.h +++ b/kernel/include/memory/memorymanagement.h @@ -9,71 +9,69 @@ #ifndef MAXOS_SYSTEM_MEMORYMANAGEMENT_H #define MAXOS_SYSTEM_MEMORYMANAGEMENT_H -#include -#include +#include +#include #include #include -namespace MaxOS { - namespace memory { +namespace MaxOS::memory { - /** - * @struct MemoryChunk - * @brief A span of memory in the heap, can be allocated or free. Used as a node in a doubly linked list. - */ - struct MemoryChunk { + /** + * @struct MemoryChunk + * @brief A span of memory in the heap, can be allocated or free. Used as a node in a doubly linked list. + */ + struct MemoryChunk { - MemoryChunk* next; ///< Pointer to the chunk after this one in the list - MemoryChunk* prev; ///< Pointer to the chunk before this one in the list + MemoryChunk* next; ///< Pointer to the chunk after this one in the list + MemoryChunk* prev; ///< Pointer to the chunk before this one in the list - bool allocated; ///< Whether this chunk is in use or can be allocated - size_t size; ///< The size of this span of memory (not including the MemoryChunk struct itself) + bool allocated; ///< Whether this chunk is in use or can be allocated + size_t size; ///< The size of this span of memory (not including the MemoryChunk struct itself) - }; + }; - constexpr size_t CHUNK_ALIGNMENT = 0x10; ///< How many bytes the chunks should be a multiple of (round up to this) + constexpr size_t CHUNK_ALIGNMENT = 0x10; ///< How many bytes the chunks should be a multiple of (round up to this) - /** - * @class MemoryManager - * @brief Handles memory allocation and deallocation - */ - class MemoryManager { + /** + * @class MemoryManager + * @brief Handles memory allocation and deallocation + */ + class MemoryManager { - private: - MemoryChunk* m_first_memory_chunk; - MemoryChunk* m_last_memory_chunk; + private: + MemoryChunk* m_first_memory_chunk; + MemoryChunk* m_last_memory_chunk; - VirtualMemoryManager* m_virtual_memory_manager; + VirtualMemoryManager* m_virtual_memory_manager; - MemoryChunk* expand_heap(size_t size); + MemoryChunk* expand_heap(size_t size); - public: - inline static MemoryManager* s_current_memory_manager = nullptr; ///< The memory manager for the current process - inline static MemoryManager* s_kernel_memory_manager = nullptr; ///< The memory manager for any kernel processes and all kernel allocations + public: + inline static MemoryManager* s_current_memory_manager = nullptr; ///< The memory manager for the current process + inline static MemoryManager* s_kernel_memory_manager = nullptr; ///< The memory manager for any kernel processes and all kernel allocations - MemoryManager(VirtualMemoryManager* virtual_memory_manager = nullptr); - ~MemoryManager(); + explicit MemoryManager(VirtualMemoryManager* virtual_memory_manager = nullptr); + ~MemoryManager(); - // Public Memory Management - static void* malloc(size_t size); - static void free(void* pointer); + // Public Memory Management + static void* malloc(size_t size); + static void free(void* pointer); - // Kernel Memory Management - static void* kmalloc(size_t size); - static void kfree(void* pointer); + // Kernel Memory Management + static void* kmalloc(size_t size); + static void kfree(void* pointer); - // Internal Memory Management - void* handle_malloc(size_t size); - void handle_free(void* pointer); - VirtualMemoryManager* vmm(); + // Internal Memory Management + void* handle_malloc(size_t size); + void handle_free(void* pointer); + VirtualMemoryManager* vmm(); - // Utility Functions - int memory_used(); - static size_t align(size_t size); - static void switch_active_memory_manager(MemoryManager* manager); - }; - } + // Utility Functions + size_t memory_used(); + static size_t align(size_t size); + static void switch_active_memory_manager(MemoryManager* manager); + }; } diff --git a/kernel/include/memory/physical.h b/kernel/include/memory/physical.h index 1aeceeb2..248c8afc 100644 --- a/kernel/include/memory/physical.h +++ b/kernel/include/memory/physical.h @@ -9,202 +9,200 @@ #ifndef MAXOS_MEMORY_PHYSICAL_H #define MAXOS_MEMORY_PHYSICAL_H -#include -#include +#include +#include #include #include #include -namespace MaxOS { - - namespace memory { - - #define ENTRIES_TO_ADDRESS(pml4, pdpr, pd, pt)((pml4 << 39) | (pdpr << 30) | (pd << 21) | (pt << 12)) ///< Convert page map level indices to a virtual address - #define PMLX_GET_INDEX(ADDR, LEVEL) (((uint64_t)ADDR & ((uint64_t)0x1ff << (12 + LEVEL * 9))) >> (12 + LEVEL * 9)) ///< Get the index for a given page map level from a virtual address - - #define PML4_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 3) ///< Get the PML4 index from a virtual address - #define PML3_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 2) ///< Get the PDPT index from a virtual address - #define PML2_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 1) ///< Get the PDP index from a virtual address - #define PML1_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 0) ///< Get the PT index from a virtual address - - typedef void virtual_address_t; ///< A type representing a virtual address (used for readability) - typedef void physical_address_t; ///< A type representing a physical address (used for readability) - - /** - * @enum PageFlags - * @brief Flags for page table entries - * - * @typedef page_flags_t - * @brief Alias for PageFlags enum - * - * @todo: fix. this is stupid: Leave as enum not enum class for bitwise operations - */ - typedef enum PageFlags { - NONE = 0, ///< No flags - PRESENT = (1 << 0), ///< The page is present in memory - WRITE = (1 << 1), ///< Memory in this page is writable - USER = (1 << 2), ///< This page is accessible from user mode - WRITE_THROUGH = (1 << 3), ///< Write through caching is enabled - CACHE_DISABLED = (1 << 4), ///< Dont let the CPU cache this page - ACCESSED = (1 << 5), ///< This page has been read from or written to - DIRTY = (1 << 6), ///< This page has been written to - HUGE_PAGE = (1 << 7), ///< This page is not 4Kib (2MB or 1GB) - GLOBAL = (1 << 8), ///< The page can be shared between processes - NO_EXECUTE = (1ULL << 63) ///< Dont let the CPU execute code on this page - } page_flags_t; - - /** - * @struct PageTableEntry - * @brief Struct for a page table entry - * - * @typedef pte_t - * @brief Alias for PageTableEntry struct - */ - typedef struct PACKED PageTableEntry { - - bool present: 1; ///< *copydoc PageFlags::PRESENT - bool write: 1; ///< *copydoc PageFlags::WRITE - bool user: 1; ///< *copydoc PageFlags::USER - bool write_through: 1; ///< *copydoc PageFlags::WRITE_THROUGH - bool cache_disabled: 1; ///< *copydoc PageFlags::CACHE_DISABLED - bool accessed: 1; ///< *copydoc PageFlags::ACCESSED - bool dirty: 1; ///< *copydoc PageFlags::DIRTY - bool huge_page: 1; ///< *copydoc PageFlags::HUGE_PAGE - bool global: 1; ///< *copydoc PageFlags::GLOBAL - uint8_t available: 3; ///< Extra metadata bytes available for OS use - uint64_t physical_address: 52; ///< The address the page represents in memory - - } pte_t; - - /** - * @struct PageMapLevel - * @brief Struct for a page map level (PML4, PDPT, PD, PT) - * - * @typedef pml_t - * @brief Alias for PageMapLevel struct - */ - typedef struct PACKED PageMapLevel { - - pte_t entries[512]; ///< The entries in this page map level. If it is a PT then these are page table entries, otherwise they are pointers to the next level. Indexed by the relevant bits in the virtual address. - - } pml_t; - - constexpr uint64_t PAGE_SIZE = 0x1000; ///< The size of a page (4KB) - constexpr uint8_t ROW_BITS = 64; ///< The number of bits in the bitmap row - - constexpr uint64_t HIGHER_HALF_KERNEL_OFFSET = 0xFFFFFFFF80000000; ///< Where the kernel is mapped in higher half memory - constexpr uint64_t HIGHER_HALF_MEM_OFFSET = 0xFFFF800000000000; ///< Where higher half memory starts - constexpr uint64_t HIGHER_HALF_MEM_RESERVED = 0x280000000; ///< Reserved higher half memory for kernel use (10GB) - constexpr uint64_t HIGHER_HALF_OFFSET = HIGHER_HALF_MEM_OFFSET + HIGHER_HALF_MEM_RESERVED; ///< Where higher half memory usable space starts - constexpr uint64_t HIGHER_HALF_DIRECT_MAP = HIGHER_HALF_OFFSET + PAGE_SIZE; ///< Where the map of physical memory to higher half starts - - /** - * @class PhysicalMemoryManager - * @brief Manages the physical memory of the system such as what pages are allocated/free and mapping of virtual to physical addresses - * - * @todo Global paging so dont have map in every process - */ - class PhysicalMemoryManager { - - private: - - uint64_t* m_bit_map = nullptr; - uint32_t m_total_entries; - uint32_t m_bitmap_size; - uint32_t m_used_frames = 0; - uint32_t m_setup_frames = 0; - uint64_t m_memory_size; - - uint64_t m_kernel_start_page; - uint64_t m_kernel_end; - - system::Multiboot* m_multiboot; - multiboot_mmap_entry* m_mmap; - multiboot_tag_mmap* m_mmap_tag; - - uint64_t* m_pml4_root_address; - pte_t* m_pml4_root; - - bool m_initialised; - bool m_nx_allowed; - - common::Spinlock m_lock; - - // Table Management - pml_t* get_or_create_table(pml_t* table, size_t index, size_t flags); - pml_t* get_and_create_table(pml_t* parent_table, uint64_t table_index, pml_t* table); - pte_t create_page_table_entry(uintptr_t address, size_t flags) const; - - static uint64_t physical_address_of_entry(pte_t* entry); - pte_t* get_entry(virtual_address_t* virtual_address, pml_t* pml4_root); - static pml_t* get_higher_half_table(uint64_t index, uint64_t index2 = 510, uint64_t index3 = 510); - - void initialise_bit_map(); - - public: - - PhysicalMemoryManager(system::Multiboot* multiboot); - ~PhysicalMemoryManager(); - - // Vars - [[nodiscard]] uint64_t memory_size() const; - [[nodiscard]] uint64_t memory_used() const; - - // Pml4 - uint64_t* pml4_root_address(); - static void unmap_lower_kernel(); - - // Frame Management - void* allocate_frame(); - void free_frame(void* address); - - void* allocate_area(uint64_t start_address, size_t size); - void free_area(uint64_t start_address, size_t size); - - // Map - virtual_address_t* map(virtual_address_t* virtual_address, size_t flags); - virtual_address_t* map(physical_address_t* physical, virtual_address_t* virtual_address, size_t flags); - virtual_address_t* map(physical_address_t* physical, virtual_address_t* virtual_address, size_t flags, - uint64_t* pml4_root); - void map_area(virtual_address_t* virtual_address_start, size_t length, size_t flags); - void map_area(physical_address_t* physical_address_start, virtual_address_t* virtual_address_start, - size_t length, size_t flags); - void identity_map(physical_address_t* physical_address, size_t flags); - - void unmap(virtual_address_t* virtual_address); - void unmap(virtual_address_t* virtual_address, uint64_t* pml4_root); - void unmap_area(virtual_address_t* virtual_address_start, size_t length); - - // Tools - static size_t size_to_frames(size_t size); - static size_t align_to_page(size_t size); - static size_t align_direct_to_page(size_t size); - static size_t align_up_to_page(size_t size, size_t s_page_size); - static bool check_aligned(size_t size); - - ///@todo Make private with getter, maybe make mapping static? - inline static PhysicalMemoryManager* s_current_manager = nullptr; ///< The current physical memory manager in use - static void clean_page_table(uint64_t* table); - - void reserve(uint64_t address); - void reserve(uint64_t address, size_t size, const char* = "Unknown"); - void reserve_kernel_regions(system::Multiboot* multiboot); - - physical_address_t* get_physical_address(virtual_address_t* virtual_address, uint64_t* pml4_root); - bool is_mapped(uintptr_t physical_address, uintptr_t virtual_address, uint64_t* pml4_root); - - void change_page_flags(virtual_address_t* virtual_address, size_t flags, uint64_t* pml4_root); - - // Higher Half Memory Management - static void* to_higher_region(uintptr_t physical_address); - static void* to_lower_region(uintptr_t virtual_address); - static void* to_io_region(uintptr_t physical_address); - static void* to_dm_region(uintptr_t physical_address); - static void* from_dm_region(uintptr_t physical_address); - static bool in_higher_region(uintptr_t virtual_address); - }; - } +#define ENTRIES_TO_ADDRESS(pml4, pdpr, pd, pt)((pml4 << 39) | (pdpr << 30) | (pd << 21) | (pt << 12)) ///< Convert page map level indices to a virtual address +#define PMLX_GET_INDEX(ADDR, LEVEL) (((uint64_t)ADDR & ((uint64_t)0x1ff << (12 + LEVEL * 9))) >> (12 + LEVEL * 9)) ///< Get the index for a given page map level from a virtual address + +#define PML4_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 3) ///< Get the PML4 index from a virtual address +#define PML3_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 2) ///< Get the PDPT index from a virtual address +#define PML2_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 1) ///< Get the PDP index from a virtual address +#define PML1_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 0) ///< Get the PT index from a virtual address + +namespace MaxOS::memory { + + typedef void virtual_address_t; ///< A type representing a virtual address (used for readability) + typedef void physical_address_t; ///< A type representing a physical address (used for readability) + + /** + * @enum PageFlags + * @brief Flags for page table entries + * + * @typedef page_flags_t + * @brief Alias for PageFlags enum + * + * @todo: fix. this is stupid: Leave as enum not enum class for bitwise operations + */ + typedef enum PageFlags { + NONE = 0, ///< No flags + PRESENT = (1 << 0), ///< The page is present in memory + WRITE = (1 << 1), ///< Memory in this page is writable + USER = (1 << 2), ///< This page is accessible from user mode + WRITE_THROUGH = (1 << 3), ///< write through caching is enabled + CACHE_DISABLED = (1 << 4), ///< Dont let the CPU cache this page + ACCESSED = (1 << 5), ///< This page has been read from or written to + DIRTY = (1 << 6), ///< This page has been written to + HUGE_PAGE = (1 << 7), ///< This page is not 4Kib (2MB or 1GB) + GLOBAL = (1 << 8), ///< The page can be shared between processes + NO_EXECUTE = (1ULL << 63) ///< Dont let the CPU execute code on this page + } page_flags_t; + + /** + * @struct PageTableEntry + * @brief Struct for a page table entry + * + * @typedef pte_t + * @brief Alias for PageTableEntry struct + */ + typedef struct PACKED PageTableEntry { + + bool present : 1; ///< *copydoc PageFlags::PRESENT + bool write : 1; ///< *copydoc PageFlags::WRITE + bool user : 1; ///< *copydoc PageFlags::USER + bool write_through : 1; ///< *copydoc PageFlags::WRITE_THROUGH + bool cache_disabled : 1; ///< *copydoc PageFlags::CACHE_DISABLED + bool accessed : 1; ///< *copydoc PageFlags::ACCESSED + bool dirty : 1; ///< *copydoc PageFlags::DIRTY + bool huge_page : 1; ///< *copydoc PageFlags::HUGE_PAGE + bool global : 1; ///< *copydoc PageFlags::GLOBAL + uint8_t available : 3; ///< Extra metadata bytes available for OS use + uint64_t physical_address : 52; ///< The address the page represents in memory + + } pte_t; + + /** + * @struct PageMapLevel + * @brief Struct for a page map level (PML4, PDPT, PD, PT) + * + * @typedef pml_t + * @brief Alias for PageMapLevel struct + */ + typedef struct PACKED PageMapLevel { + + pte_t entries[512]; ///< The entries in this page map level. If it is a PT then these are page table entries, otherwise they are pointers to the next level. Indexed by the relevant bits in the virtual address. + + } pml_t; + + constexpr uint64_t PAGE_SIZE = 0x1000; ///< The size of a page (4KB) + constexpr uint8_t ROW_BITS = 64; ///< The number of bits in the bitmap row + + constexpr uint64_t HIGHER_HALF_KERNEL_OFFSET = 0xFFFFFFFF80000000; ///< Where the kernel is mapped in higher half memory + constexpr uint64_t HIGHER_HALF_MEM_OFFSET = 0xFFFF800000000000; ///< Where higher half memory starts + constexpr uint64_t HIGHER_HALF_MEM_RESERVED = 0x280000000; ///< Reserved higher half memory for kernel use (10GB) + constexpr uint64_t HIGHER_HALF_OFFSET = HIGHER_HALF_MEM_OFFSET + + HIGHER_HALF_MEM_RESERVED; ///< Where higher half memory usable space starts + constexpr uint64_t HIGHER_HALF_DIRECT_MAP = HIGHER_HALF_OFFSET + + PAGE_SIZE; ///< Where the map of physical memory to higher half starts + + /** + * @class PhysicalMemoryManager + * @brief Manages the physical memory of the system such as what pages are allocated/free and mapping of virtual to physical addresses + * + * @todo Global paging so dont have map in every process + */ + class PhysicalMemoryManager { + + private: + + uint64_t* m_bit_map = nullptr; + uint32_t m_total_entries; + uint32_t m_bitmap_size; + uint32_t m_used_frames = 0; + uint32_t m_setup_frames = 0; + uint64_t m_memory_size; + + uint64_t m_kernel_start_page; + uint64_t m_kernel_end; + + system::Multiboot* m_multiboot; + multiboot_mmap_entry* m_mmap; + multiboot_tag_mmap* m_mmap_tag; + + uint64_t* m_pml4_root_address; + pte_t* m_pml4_root; + + bool m_initialised; + bool m_nx_allowed; + + common::Spinlock m_lock; + + // Table Management + pml_t* get_or_create_table(pml_t* table, size_t index, size_t flags); + pml_t* get_and_create_table(pml_t* parent_table, uint64_t table_index, pml_t* table); + [[nodiscard]] pte_t create_page_table_entry(uintptr_t address, size_t flags) const; + + static uint64_t physical_address_of_entry(pte_t* entry); + pte_t* get_entry(virtual_address_t* virtual_address, pml_t* pml4_root); + static pml_t* get_higher_half_table(uint64_t index, uint64_t index2 = 510, uint64_t index3 = 510); + + void initialise_bit_map(); + + public: + + explicit PhysicalMemoryManager(system::Multiboot* multiboot); + ~PhysicalMemoryManager(); + + // Vars + [[nodiscard]] uint64_t memory_size() const; + [[nodiscard]] uint64_t memory_used() const; + + // Pml4 + uint64_t* pml4_root_address(); + static void unmap_lower_kernel(); + + // Frame Management + void* allocate_frame(); + void free_frame(void* address); + + void* allocate_area(uint64_t start_address, size_t size); + void free_area(uint64_t start_address, size_t size); + + // Map + virtual_address_t* map(virtual_address_t* virtual_address, size_t flags); + virtual_address_t* map(physical_address_t* physical, virtual_address_t* virtual_address, size_t flags); + virtual_address_t* map(physical_address_t* physical, virtual_address_t* virtual_address, size_t flags, uint64_t* pml4_root); + void map_area(virtual_address_t* virtual_address_start, size_t length, size_t flags); + void map_area(physical_address_t* physical_address_start, virtual_address_t* virtual_address_start, size_t length, size_t flags); + void identity_map(physical_address_t* physical_address, size_t flags); + + void unmap(virtual_address_t* virtual_address); + void unmap(virtual_address_t* virtual_address, uint64_t* pml4_root); + void unmap_area(virtual_address_t* virtual_address_start, size_t length); + + // Tools + static size_t size_to_frames(size_t size); + static size_t align_to_page(size_t size); + static size_t align_direct_to_page(size_t size); + static size_t align_up_to_page(size_t size, size_t s_page_size); + static bool check_aligned(size_t size); + + ///@todo Make private with getter, maybe make mapping static? + inline static PhysicalMemoryManager* s_current_manager = nullptr; ///< The current physical memory manager in use + static void clean_page_table(uint64_t* table); + + void reserve(uint64_t address); + void reserve(uint64_t address, size_t size, const char* = "Unknown"); + void reserve_kernel_regions(system::Multiboot* multiboot); + + physical_address_t* get_physical_address(virtual_address_t* virtual_address, uint64_t* pml4_root); + bool is_mapped(uintptr_t physical_address, uintptr_t virtual_address, uint64_t* pml4_root); + + void change_page_flags(virtual_address_t* virtual_address, size_t flags, uint64_t* pml4_root); + + // Higher Half Memory Management + static void* to_higher_region(uintptr_t physical_address); + static void* to_lower_region(uintptr_t virtual_address); + static void* to_io_region(uintptr_t physical_address); + static void* to_dm_region(uintptr_t physical_address); + static void* from_dm_region(uintptr_t physical_address); + static bool in_higher_region(uintptr_t virtual_address); + }; } + #endif // MAXOS_MEMORY_PHYSICAL_H \ No newline at end of file diff --git a/kernel/include/net/arp.h b/kernel/include/net/arp.h index c4e71b9a..0dd01106 100644 --- a/kernel/include/net/arp.h +++ b/kernel/include/net/arp.h @@ -9,61 +9,58 @@ #ifndef MAXOS_NET_ARP_H #define MAXOS_NET_ARP_H -#include +#include #include -namespace MaxOS { - namespace net { +namespace MaxOS::net { - /** - * @struct ARPMessage - * @brief An ARP message - * - * @typedef arp_message_t - * @brief Alias for ARPMessage struct - */ - typedef struct PACKED ARPMessage { + /** + * @struct ARPMessage + * @brief An ARP message + * + * @typedef arp_message_t + * @brief Alias for ARPMessage struct + */ + typedef struct PACKED ARPMessage { - uint16_t hardwareType; ///< The type of device that sent the ARP message (1 = Ethernet) - uint16_t protocol; ///< The protocol being used (0x0800 = IPv4) - uint8_t hardwareAddressSize; ///< The size of the hardware address (6 for MAC) - uint8_t protocolAddressSize; ///< The size of the protocol address (4 for IPv4) + uint16_t hardware_type; ///< The type of device that sent the ARP message (1 = Ethernet) + uint16_t protocol; ///< The protocol being used (0x0800 = IPv4) + uint8_t hardware_address_size; ///< The size of the hardware address (6 for MAC) + uint8_t protocol_address_size; ///< The size of the protocol address (4 for IPv4) - uint16_t command; ///< The ARP command (1 = request, 2 = reply) + uint16_t command; ///< The ARP command (1 = request, 2 = reply) - uint64_t srcMAC: 48; ///< The MAC address of the sender - uint32_t srcIP; ///< The IP address of the sender - uint64_t dstMAC: 48; ///< The MAC address of the target - uint32_t dstIP; ///< The IP address of the target + uint64_t src_mac : 48; ///< The MAC address of the sender + uint32_t src_ip; ///< The IP address of the sender + uint64_t dst_mac : 48; ///< The MAC address of the target + uint32_t dst_ip; ///< The IP address of the target - } arp_message_t; + } arp_message_t; - /** - * @class AddressResolutionProtocol - * @brief Handles ARP requests and replies - */ - class AddressResolutionProtocol : public EthernetFramePayloadHandler, public IPV4AddressResolver { + /** + * @class AddressResolutionProtocol + * @brief Handles ARP requests and replies + */ + class AddressResolutionProtocol : public EthernetFramePayloadHandler, public IPV4AddressResolver { - private: - common::Map addressCache; - InternetProtocolHandler* internetProtocolHandler; - common::OutputStream* errorMessages; + private: + common::Map address_cache; + InternetProtocolHandler* internet_protocol_handler; + common::OutputStream* error_messages; - public: - AddressResolutionProtocol(EthernetFrameHandler* ethernetFrameHandler, InternetProtocolHandler* internetProtocolHandler, common::OutputStream* errorMessages); - ~AddressResolutionProtocol(); + public: + AddressResolutionProtocol(EthernetFrameHandler* ethernet_frame_handler, InternetProtocolHandler* internet_protocol_handler, common::OutputStream* error_messages); + ~AddressResolutionProtocol(); - bool handleEthernetframePayload(uint8_t* data, uint32_t size); + bool handle_ethernetframe_payload(uint8_t* etherframe_payload, uint32_t size) final; - void RequestMACAddress(InternetProtocolAddress address); - drivers::ethernet::MediaAccessControlAddress Resolve(InternetProtocolAddress address) final; - void Store(InternetProtocolAddress internetProtocolAddress, drivers::ethernet::MediaAccessControlAddress mediaAccessControlAddress) final; - }; - - } + void request_mac_address(InternetProtocolAddress address); + drivers::ethernet::MediaAccessControlAddress resolve(InternetProtocolAddress address) final; + void store(InternetProtocolAddress internet_protocol_address, drivers::ethernet::MediaAccessControlAddress media_access_control_address) final; + }; } diff --git a/kernel/include/net/ethernetframe.h b/kernel/include/net/ethernetframe.h index e6c36937..c84c0ad5 100644 --- a/kernel/include/net/ethernetframe.h +++ b/kernel/include/net/ethernetframe.h @@ -11,88 +11,87 @@ #ifndef MAXOS_NET_ETHERNETFRAME_H #define MAXOS_NET_ETHERNETFRAME_H -#include +#include #include #include #include -namespace MaxOS { - namespace net { +namespace MaxOS::net { - /** - * @struct EthernetFrameHeader - * @brief Structure the raw data. This is the header of an Ethernet Frame - * - * @typedef ethernet_frame_header_t - * @brief Alias for EthernetFrameHeader struct - */ - typedef struct PACKED EthernetFrameHeader { + /** + * @struct EthernetFrameHeader + * @brief Structure the raw data. This is the header of an Ethernet Frame + * + * @typedef ethernet_frame_header_t + * @brief Alias for EthernetFrameHeader struct + */ + typedef struct PACKED EthernetFrameHeader { - uint64_t destinationMAC: 48; ///< The mac address of the target (Big Endian) - uint64_t sourceMAC: 48; ///< The mac address of the sender (Big Endian) + uint64_t destination_mac : 48; ///< The mac address of the target (Big Endian) + uint64_t source_mac : 48; ///< The mac address of the sender (Big Endian) - uint16_t type; ///< The type (Big Endian) 0x0800 = IPv4, 0x0806 = ARP, 0x86DD = IPv6 + uint16_t type; ///< The type (Big Endian) 0x0800 = IPv4, 0x0806 = ARP, 0x86DD = IPv6 - } ethernet_frame_header_t; + } ethernet_frame_header_t; - /** - * @struct EthernetFrameFooter - * @brief Structure the raw data. This is the footer of an Ethernet Frame - * - * @typedef ethernet_frame_footer_t - * @brief Alias for EthernetFrameFooter struct - */ - typedef struct PACKED EthernetFrameFooter { + /** + * @struct EthernetFrameFooter + * @brief Structure the raw data. This is the footer of an Ethernet Frame + * + * @typedef ethernet_frame_footer_t + * @brief Alias for EthernetFrameFooter struct + */ + typedef struct PACKED EthernetFrameFooter { - uint32_t checksum; ///< Checksum of the payload + uint32_t checksum; ///< checksum of the payload - } ethernet_frame_footer_t; + } ethernet_frame_footer_t; - class EthernetFrameHandler; + class EthernetFrameHandler; - /** - * @class EthernetFramePayloadHandler - * @brief Handles a specific type of Ethernet Frame payload - */ - class EthernetFramePayloadHandler { + /** + * @class EthernetFramePayloadHandler + * @brief Handles a specific type of Ethernet Frame payload + */ + class EthernetFramePayloadHandler { friend class EthernetFrameHandler; - protected: - EthernetFrameHandler* frameHandler; ///< The Ethernet frame handler this payload handler is connected to - uint16_t handledType; ///< The Ethernet frame type this handler handles + protected: + EthernetFrameHandler* frame_handler; ///< The Ethernet frame handler this payload handler is connected to + uint16_t handled_type; ///< The Ethernet frame type this handler handles - public: - EthernetFramePayloadHandler(EthernetFrameHandler* frameHandler, uint16_t handledType); - ~EthernetFramePayloadHandler(); + public: + EthernetFramePayloadHandler(EthernetFrameHandler* frame_handler, uint16_t handled_type); + ~EthernetFramePayloadHandler(); - virtual bool handleEthernetframePayload(uint8_t* ethernetframePayload, uint32_t size); - void Send(uint64_t destinationMAC, uint8_t* data, uint32_t size); - }; + virtual bool handle_ethernetframe_payload(uint8_t* ethernetframe_payload, uint32_t size); + void send(uint64_t destination, uint8_t* data, uint32_t size); + }; - /** - * @class EthernetFrameHandler - * @brief Handles incoming Ethernet Frames and routes them to the appropriate payload handlers - */ - class EthernetFrameHandler : public drivers::ethernet::EthernetDriverEventHandler { - protected: + /** + * @class EthernetFrameHandler + * @brief Handles incoming Ethernet Frames and routes them to the appropriate payload handlers + */ + class EthernetFrameHandler : public drivers::ethernet::EthernetDriverEventHandler { + protected: - common::Map frameHandlers; ///< The map of frame handlers by type + common::Map frame_handlers; ///< The map of frame handlers by type - drivers::ethernet::EthernetDriver* ethernetDriver; ///< The driver this frame handler is using - common::OutputStream* errorMessages; ///< The output stream for error messages + drivers::ethernet::EthernetDriver* ethernet_driver; ///< The driver this frame handler is using + common::OutputStream* error_messages; ///< The output stream for error messages - public: - EthernetFrameHandler(drivers::ethernet::EthernetDriver* driver, common::OutputStream* errorMessages); - ~EthernetFrameHandler(); + public: + EthernetFrameHandler(drivers::ethernet::EthernetDriver* driver, common::OutputStream* error_messages); + ~EthernetFrameHandler(); - drivers::ethernet::MediaAccessControlAddress getMAC(); - bool DataReceived(uint8_t* data, uint32_t size) override; - void connectHandler(EthernetFramePayloadHandler* handler); - void sendEthernetFrame(uint64_t destinationMAC, uint16_t frameType, uint8_t* data, uint32_t size); + drivers::ethernet::MediaAccessControlAddress get_mac(); + bool data_received(uint8_t* data, uint32_t size) override; + void connect_handler(EthernetFramePayloadHandler* handler); + void send_ethernet_frame(uint64_t destination_mac, uint16_t frame_type, uint8_t* data, uint32_t size); - }; - } + }; } + #endif //MAXOS_NET_ETHERNETFRAME_H diff --git a/kernel/include/net/icmp.h b/kernel/include/net/icmp.h index 9e60e804..e9acfb9c 100644 --- a/kernel/include/net/icmp.h +++ b/kernel/include/net/icmp.h @@ -10,49 +10,47 @@ #define MAXOS_NET_ICMP_H #include -#include +#include #include -namespace MaxOS { - namespace net { +namespace MaxOS::net { - /** - * @struct ICMPHeader - * @brief The header of an ICMP packet - * - * @typedef icmp_header_t - * @brief Alias for ICMPHeader struct - */ - typedef struct PACKED ICMPHeader { + /** + * @struct ICMPHeader + * @brief The header of an ICMP packet + * + * @typedef icmp_header_t + * @brief Alias for ICMPHeader struct + */ + typedef struct PACKED ICMPHeader { - uint8_t type; ///< The type of ICMP message - uint8_t code; ///< The code of the ICMP message + uint8_t type; ///< The type of ICMP message + uint8_t code; ///< The code of the ICMP message - uint16_t checksum; ///< Checksum to verify integrity - uint32_t data; ///< Payload data (Varies by type and code) + uint16_t checksum; ///< checksum to verify integrity + uint32_t data; ///< Payload data (Varies by type and code) - } icmp_header_t; + } icmp_header_t; - /** - * @class InternetControlMessageProtocol - * @brief Handles ICMP packets - */ - class InternetControlMessageProtocol : IPV4PayloadHandler { + /** + * @class InternetControlMessageProtocol + * @brief Handles ICMP packets + */ + class InternetControlMessageProtocol : IPV4PayloadHandler { - common::OutputStream* errorMessages; + common::OutputStream* error_messages; - public: - InternetControlMessageProtocol(InternetProtocolHandler* internetProtocolHandler, common::OutputStream* errorMessages); - ~InternetControlMessageProtocol(); + public: + InternetControlMessageProtocol(InternetProtocolHandler* internet_protocol_handler, common::OutputStream* error_messages); + ~InternetControlMessageProtocol(); - bool handleInternetProtocolPayload(InternetProtocolAddress sourceIP, InternetProtocolAddress destinationIP, uint8_t* payloadData, uint32_t size) final; - void RequestEchoReply(InternetProtocolAddress ip_be); - }; - - } + bool handle_internet_protocol_payload(net::InternetProtocolAddress src_ip_be, net::InternetProtocolAddress dst_ip_be, uint8_t* payload_data, uint32_t size) final; + void request_echo_reply(uint32_t ip_be); + }; } + #endif //MAXOS_NET_ICMP_H diff --git a/kernel/include/net/ipv4.h b/kernel/include/net/ipv4.h index 9a6caad2..af8b29de 100644 --- a/kernel/include/net/ipv4.h +++ b/kernel/include/net/ipv4.h @@ -9,121 +9,119 @@ #ifndef MAXOS_NET_IPV4_H #define MAXOS_NET_IPV4_H -#include +#include #include -namespace MaxOS { - namespace net { +namespace MaxOS::net { - typedef uint32_t InternetProtocolAddress; ///< An IPv4 address @todo: Make IPv4Address class and do ip_t - typedef uint32_t SubnetMask; ///< A subnet mask @todo: Make SubnetMask class and do subnetmask_t + typedef uint32_t InternetProtocolAddress; ///< An IPv4 address @todo: Make IPv4Address class and do ip_t + typedef uint32_t SubnetMask; ///< A subnet mask @todo: Make SubnetMask class and do subnetmask_t - /** - * @struct IPV4Header - * @brief The header of an IPv4 packet - * - * @typedef ipv4_header_t - * @brief Alias for IPV4Header struct - */ - typedef struct PACKED IPV4Header { + /** + * @struct IPV4Header + * @brief The header of an IPv4 packet + * + * @typedef ipv4_header_t + * @brief Alias for IPV4Header struct + */ + typedef struct PACKED IPV4Header { - uint8_t headerLength: 4; ///< The length of the header in 32-bit words (min 5, max 15) - uint8_t version: 4; ///< The version of the IP protocol (4 for IPv4) - uint8_t typeOfService; ///< The type of service (low delay, high throughput, high reliability, etc. @todo: enum - uint16_t totalLength; ///< The total length of the IP packet (header + data) in bytes + uint8_t header_length : 4; ///< The length of the header in 32-bit words (min 5, max 15) + uint8_t version : 4; ///< The version of the IP protocol (4 for IPv4) + uint8_t type_of_service; ///< The type of service (low delay, high throughput, high reliability, etc. @todo: enum + uint16_t total_length; ///< The total length of the IP packet (header + data) in bytes - uint16_t identifier; ///< Unique identifier for the group of fragments of a single IP packet - uint16_t flagsAndOffset; ///< Flags (3 bits) and Fragment Offset (13 bits) @todo: bitfield struct? + uint16_t identifier; ///< Unique identifier for the group of fragments of a single IP packet + uint16_t flags_and_offset; ///< Flags (3 bits) and Fragment Offset (13 bits) @todo: bitfield struct? - uint8_t timeToLive; ///< The maximum hops between devices before the packet is discarded - uint8_t protocol; ///< The protocol of the payload (TCP, UDP, ICMP, etc. @todo: enum - uint16_t checksum; ///< The checksum of the header + uint8_t time_to_live; ///< The maximum hops between devices before the packet is discarded + uint8_t protocol; ///< The protocol of the payload (TCP, UDP, ICMP, etc. @todo: enum + uint16_t checksum; ///< The checksum of the header - uint32_t sourceIP; ///< The IP of the sender - uint32_t destinationIP; ///< The IP of the receiver + uint32_t source_ip; ///< The IP of the sender + uint32_t destination_ip; ///< The IP of the receiver - } ipv4_header_t; + } ipv4_header_t; - class InternetProtocolHandler; + class InternetProtocolHandler; - /** - * @class IPV4AddressResolver - * @brief Resolves IP addresses to MAC addresses - */ - class IPV4AddressResolver { - public: - IPV4AddressResolver(InternetProtocolHandler* internetProtocolHandler); - ~IPV4AddressResolver(); - virtual drivers::ethernet::MediaAccessControlAddress Resolve(InternetProtocolAddress address); - virtual void Store(InternetProtocolAddress internetProtocolAddress, drivers::ethernet::MediaAccessControlAddress mediaAccessControlAddress); - }; + /** + * @class IPV4AddressResolver + * @brief Resolves IP addresses to MAC addresses + */ + class IPV4AddressResolver { + public: + explicit IPV4AddressResolver(InternetProtocolHandler* internet_protocol_handler); + ~IPV4AddressResolver(); + virtual drivers::ethernet::MediaAccessControlAddress resolve(InternetProtocolAddress address); + virtual void store(InternetProtocolAddress internet_protocol_address, drivers::ethernet::MediaAccessControlAddress media_access_control_address); + }; - /** - * @class IPV4PayloadHandler - * @brief Handles the payload of a specific IP protocol - */ - class IPV4PayloadHandler { - friend class InternetProtocolHandler; + /** + * @class IPV4PayloadHandler + * @brief Handles the payload of a specific IP protocol + */ + class IPV4PayloadHandler { + friend class InternetProtocolHandler; - protected: - InternetProtocolHandler* internetProtocolHandler; ///< The Internet protocol handler this payload handler is connected to - uint8_t ipProtocol; ///< The IP protocol this handler handles + protected: + InternetProtocolHandler* internet_protocol_handler; ///< The Internet protocol handler this payload handler is connected to + uint8_t ip_protocol; ///< The IP protocol this handler handles - public: - IPV4PayloadHandler(InternetProtocolHandler* internetProtocolHandler, uint8_t protocol); - ~IPV4PayloadHandler(); + public: + IPV4PayloadHandler(InternetProtocolHandler* internet_protocol_handler, uint8_t protocol); + ~IPV4PayloadHandler(); - virtual bool handleInternetProtocolPayload(InternetProtocolAddress sourceIP, InternetProtocolAddress destinationIP, uint8_t* payloadData, uint32_t size); - void Send(InternetProtocolAddress destinationIP, uint8_t* payloadData, uint32_t size); - }; + virtual bool handle_internet_protocol_payload(net::InternetProtocolAddress src_ip_be, net::InternetProtocolAddress dst_ip_be, uint8_t* internetprotocol_payload, uint32_t size); + void send(InternetProtocolAddress destination_ip, uint8_t* payload_data, uint32_t size); + }; - /** - * @class InternetProtocolHandler - * @brief Handles IPv4 packets over Ethernet frames - */ - class InternetProtocolHandler : public EthernetFramePayloadHandler { + /** + * @class InternetProtocolHandler + * @brief Handles IPv4 packets over Ethernet frames + */ + class InternetProtocolHandler : public EthernetFramePayloadHandler { friend class IPV4AddressResolver; - protected: + protected: - common::Map IPV4PayloadHandlers; ///< Map of IP protocol numbers to their payload handlers + common::Map ipv_4_payload_handlers; ///< Map of IP protocol numbers to their payload handlers - IPV4AddressResolver* resolver = nullptr; ///< The IP address resolver - common::OutputStream* errorMessages; ///< Stream to output error messages to + IPV4AddressResolver* resolver = nullptr; ///< The IP address resolver + common::OutputStream* error_messages; ///< Stream to output error messages to - InternetProtocolAddress ownInternetProtocolAddress; ///< The IP address of this device - InternetProtocolAddress defaultGatewayInternetProtocolAddress; ///< The IP address of the default gateway - SubnetMask subnetMask; ///< The subnet mask + InternetProtocolAddress own_internet_protocol_address; ///< The IP address of this device + InternetProtocolAddress default_gateway_internet_protocol_address; ///< The IP address of the default gateway + SubnetMask subnet_mask; ///< The subnet mask - void RegisterIPV4AddressResolver(IPV4AddressResolver* resolver); + void register_ipv_4_address_resolver(IPV4AddressResolver* ipv4_resolver); - public: - InternetProtocolHandler(EthernetFrameHandler* backend, - InternetProtocolAddress ownInternetProtocolAddress, - InternetProtocolAddress defaultGatewayInternetProtocolAddress, - SubnetMask subnetMask, - common::OutputStream* errorMessages); - ~InternetProtocolHandler(); + public: + InternetProtocolHandler(EthernetFrameHandler* backend, + InternetProtocolAddress own_internet_protocol_address, + InternetProtocolAddress default_gateway_internet_protocol_address, + SubnetMask subnet_mask, + common::OutputStream* error_messages); + ~InternetProtocolHandler(); - bool handleEthernetframePayload(uint8_t* ethernetframePayload, uint32_t size) override; - void sendInternetProtocolPacket(uint32_t dstIP_BE, uint8_t protocol, const uint8_t* data, uint32_t size); + bool handle_ethernetframe_payload(uint8_t* ethernetframe_payload, uint32_t size) override; + void send_internet_protocol_packet(uint32_t dst_ip_be, uint8_t protocol, const uint8_t* data, uint32_t size); - static uint16_t Checksum(const uint16_t* data, uint32_t lengthInBytes); + static uint16_t checksum(const uint16_t* data, uint32_t length_in_bytes); - static InternetProtocolAddress CreateInternetProtocolAddress(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4); - static InternetProtocolAddress Parse(string address); - static SubnetMask CreateSubnetMask(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4); - InternetProtocolAddress GetInternetProtocolAddress() const; - drivers::ethernet::MediaAccessControlAddress GetMediaAccessControlAddress(); + static InternetProtocolAddress create_internet_protocol_address(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4); + static InternetProtocolAddress parse(string address); + static SubnetMask create_subnet_mask(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4); + [[nodiscard]] InternetProtocolAddress get_internet_protocol_address() const; + drivers::ethernet::MediaAccessControlAddress get_media_access_control_address(); - void connectIPV4PayloadHandler(IPV4PayloadHandler* IPV4PayloadHandler); + void connect_ipv_4_payload_handler(IPV4PayloadHandler* ipv_4_payload_handler); - }; - } + }; } diff --git a/kernel/include/net/tcp.h b/kernel/include/net/tcp.h index 5dc13015..ce036ea3 100644 --- a/kernel/include/net/tcp.h +++ b/kernel/include/net/tcp.h @@ -9,227 +9,227 @@ #ifndef MAXOS_NET_TCP_H #define MAXOS_NET_TCP_H -#include +#include #include #include -namespace MaxOS { - - namespace net { - - typedef uint16_t TransmissionControlProtocolPort; ///< TCP port @todo: Make TCPPort class and do tcp_port_t - - /** - * @enum TCPSocketState - * @brief The state of a TCP socket - */ - enum class TCPSocketState { - CLOSED, - LISTEN, - SYN_SENT, - SYN_RECEIVED, - - ESTABLISHED, - - FIN_WAIT1, - FIN_WAIT2, - CLOSING, - TIME_WAIT, - - CLOSE_WAIT, - LAST_ACK - }; - - /** - * @enum TCPFlag - * @brief The flags in a TCP header - */ - enum class TCPFlag { - FIN = 1, - SYN = 2, - RST = 4, - PSH = 8, - ACK = 16, - URG = 32, - ECE = 64, - CWR = 128, - NS = 256 - }; - - /** - * @struct TCPHeader - * @brief The header of a TCP packet - * - * @typedef tcp_header_t - * @brief Alias for TCPHeader struct - */ - typedef struct PACKED TCPHeader { - - uint16_t srcPort; ///< The port of the sender - uint16_t dstPort; ///< The port of the receiver - uint32_t sequenceNumber; ///< Where this packet's data fits in the overall order of the data stream - uint32_t acknowledgementNumber; ///< The next expected sequence number from the sender (used by the receiver to request the next data) - - uint8_t reserved: 4; ///< Unused, must be 0 - uint8_t headerSize32: 4; ///< The size of the header in 32-bit words - uint8_t flags; ///< The flags of the TCP packet (see TCPFlag enum) - - uint16_t windowSize; ///< How many bytes the sender is willing to receive - uint16_t checksum; ///< The checksum of the header - uint16_t urgentPtr; ///< Where in the data the urgent data *ends* (if the URG flag is set) - - uint32_t options; ///< The options for the TCP packet (MSS, Window Scale, SACK Permitted) @todo: make this a struct - - } tcp_header_t; - - /** - * @struct TCPPseudoHeader - * @brief The pseudo header used for TCP checksum calculation - * - * @details The pseudo header is used to calculate the checksum of the TCP header. It is a copy of the IP - * header, but with the protocol field set to 6 (TCP) and the length field set to the length of the TCP header. - * - * @typedef tcp_pseudo_header_t - * @brief Alias for TCPPseudoHeader struct - */ - typedef struct PACKED TCPPseudoHeader { - - uint32_t srcIP; ///< The IP address of the sender - uint32_t dstIP; ///< The IP address of the receiver - uint16_t protocol; ///< The protocol (set to 6 for TCP) - uint16_t totalLength; ///< The total length of the TCP header and data - - } tcp_pseudo_header_t; - - - // Forward declarations - class TCPSocket; - class TransmissionControlProtocolHandler; - - /** - * @enum TCPPayloadHandlerEvents - * @brief Events for the TCPPayloadHandler - */ - enum class TCPPayloadHandlerEvents { - CONNECTED, - DISCONNECTED, - DATA_RECEIVED - }; - - /** - * @class DataReceivedEvent - * @brief Event for when data is received on a TCP socket - */ - class DataReceivedEvent : public common::Event { - public: - TCPSocket* socket; ///< The socket that received the data - uint8_t* data; ///< The data received - uint16_t size; ///< The size of the data received - DataReceivedEvent(TCPSocket* socket, uint8_t* data, uint16_t size); - ~DataReceivedEvent(); - }; - - /** - * @class ConnectedEvent - * @brief Event for when a TCP socket is connected - */ - class ConnectedEvent : public common::Event { - public: - TCPSocket* socket; ///< The socket that is connected - ConnectedEvent(TCPSocket* socket); - ~ConnectedEvent(); - }; - - /** - * @class DisconnectedEvent - * @brief Event for when a TCP socket is disconnected - */ - class DisconnectedEvent : public common::Event { - public: - TCPSocket* socket; ///< The socket that is disconnected - DisconnectedEvent(TCPSocket* socket); - ~DisconnectedEvent(); - }; - - /** - * @class TCPPayloadHandler - * @brief Handler for TCP payloads - */ - class TCPPayloadHandler : public common::EventHandler { - public: - TCPPayloadHandler(); - ~TCPPayloadHandler(); - - common::Event* on_event(common::Event* event) override; - - virtual void handleTransmissionControlProtocolPayload(TCPSocket* socket, uint8_t* data, uint16_t size); - virtual void Connected(TCPSocket* socket); - virtual void Disconnected(TCPSocket* socket); - }; - - /** - * @class TCPSocket - * @brief A TCP socket. Allows for sending and receiving data over TCP at a port - */ - class TCPSocket: public common::EventManager { + +namespace MaxOS::net { + + typedef uint16_t TransmissionControlProtocolPort; ///< TCP port @todo: Make TCPPort class and do tcp_port_t + + /** + * @enum TCPSocketState + * @brief The state of a TCP socket + */ + enum class TCPSocketState { + CLOSED, + LISTEN, + SYN_SENT, + SYN_RECEIVED, + + ESTABLISHED, + + FIN_WAIT1, + FIN_WAIT2, + CLOSING, + TIME_WAIT, + + CLOSE_WAIT, + LAST_ACK + }; + + /** + * @enum TCPFlag + * @brief The flags in a TCP header + */ + enum class TCPFlag { + FIN = 1, + SYN = 2, + RST = 4, + PSH = 8, + ACK = 16, + URG = 32, + ECE = 64, + CWR = 128, + NS = 256 + }; + + /** + * @struct TCPHeader + * @brief The header of a TCP packet + * + * @typedef tcp_header_t + * @brief Alias for TCPHeader struct + */ + typedef struct PACKED TCPHeader { + + uint16_t src_port; ///< The port of the sender + uint16_t dst_port; ///< The port of the receiver + uint32_t sequence_number; ///< Where this packet's data fits in the overall order of the data stream + uint32_t acknowledgement_number; ///< The next expected sequence number from the sender (used by the receiver to request the next data) + + uint8_t reserved : 4; ///< Unused, must be 0 + uint8_t header_size_32 : 4; ///< The size of the header in 32-bit words + uint8_t flags; ///< The flags of the TCP packet (see TCPFlag enum) + + uint16_t window_size; ///< How many bytes the sender is willing to receive + uint16_t checksum; ///< The checksum of the header + uint16_t urgent_ptr; ///< Where in the data the urgent data *ends* (if the URG flag is set) + + uint32_t options; ///< The options for the TCP packet (MSS, Window Scale, SACK Permitted) @todo: make this a struct + + } tcp_header_t; + + /** + * @struct TCPPseudoHeader + * @brief The pseudo header used for TCP checksum calculation + * + * @details The pseudo header is used to calculate the checksum of the TCP header. It is a copy of the IP + * header, but with the protocol field set to 6 (TCP) and the length field set to the length of the TCP header. + * + * @typedef tcp_pseudo_header_t + * @brief Alias for TCPPseudoHeader struct + */ + typedef struct PACKED TCPPseudoHeader { + + uint32_t src_ip; ///< The IP address of the sender + uint32_t dst_ip; ///< The IP address of the receiver + uint16_t protocol; ///< The protocol (set to 6 for TCP) + uint16_t total_length; ///< The total length of the TCP header and data + + } tcp_pseudo_header_t; + + + // Forward declarations + class TCPSocket; + + class TransmissionControlProtocolHandler; + + /** + * @enum TCPPayloadHandlerEvents + * @brief Events for the TCPPayloadHandler + */ + enum class TCPPayloadHandlerEvents { + CONNECTED, + DISCONNECTED, + DATA_RECEIVED + }; + + /** + * @class DataReceivedEvent + * @brief Event for when data is received on a TCP socket + */ + class DataReceivedEvent : public common::Event { + public: + TCPSocket* socket; ///< The socket that received the data + uint8_t* data; ///< The data received + uint16_t size; ///< The size of the data received + DataReceivedEvent(TCPSocket* socket, uint8_t* data, uint16_t size); + ~DataReceivedEvent(); + }; + + /** + * @class ConnectedEvent + * @brief Event for when a TCP socket is connected + */ + class ConnectedEvent : public common::Event { + public: + TCPSocket* socket; ///< The socket that is connected + explicit ConnectedEvent(TCPSocket* socket); + ~ConnectedEvent(); + }; + + /** + * @class DisconnectedEvent + * @brief Event for when a TCP socket is disconnected + */ + class DisconnectedEvent : public common::Event { + public: + TCPSocket* socket; ///< The socket that is disconnected + explicit DisconnectedEvent(TCPSocket* socket); + ~DisconnectedEvent(); + }; + + /** + * @class TCPPayloadHandler + * @brief Handler for TCP payloads + */ + class TCPPayloadHandler : public common::EventHandler { + public: + TCPPayloadHandler(); + ~TCPPayloadHandler(); + + common::Event* on_event(common::Event* event) override; + + virtual void handle_transmission_control_protocol_payload(TCPSocket* socket, uint8_t* data, uint16_t size); + virtual void connected(TCPSocket* socket); + virtual void disconnected(TCPSocket* socket); + }; + + /** + * @class TCPSocket + * @brief A TCP socket. Allows for sending and receiving data over TCP at a port + */ + class TCPSocket : public common::EventManager { friend class TransmissionControlProtocolHandler; + friend class TransmissionControlProtocolPortListener; - protected: - uint16_t remotePort = 0; ///< The port on the external device - uint32_t remoteIP = 0; ///< The IP address of the external device - uint16_t localPort = 0; ///< The port on this device - uint32_t localIP = 0; ///< The IP address of this device - uint32_t sequenceNumber = 0; ///< The current order number of the data being sent - uint32_t acknowledgementNumber = 0; ///< The number used to keep track of what has been received, incremented by 1 each time - - TransmissionControlProtocolHandler* transmissionControlProtocolHandler; ///< The TCP handler this socket is using - TCPSocketState state; ///< The state of the socket - public: - TCPSocket(TransmissionControlProtocolHandler* transmissionControlProtocolHandler); - ~TCPSocket(); - - virtual void Send(uint8_t* data, uint16_t size); - virtual void Disconnect(); - - void Disconnected(); - void Connected(); - - bool handleTransmissionControlProtocolPayload(uint8_t* data, uint16_t size); - }; - - /** - * @class TransmissionControlProtocolHandler - * @brief Handles TCP packets and manages TCP sockets - */ - class TransmissionControlProtocolHandler : IPV4PayloadHandler { + protected: + uint16_t remotePort = 0; ///< The port on the external device + uint32_t remote_ip = 0; ///< The IP address of the external device + uint16_t local_port = 0; ///< The port on this device + uint32_t local_ip = 0; ///< The IP address of this device + uint32_t sequence_number = 0; ///< The current order number of the data being sent + uint32_t acknowledgement_number = 0; ///< The number used to keep track of what has been received, incremented by 1 each time + + TransmissionControlProtocolHandler* transmission_control_protocol_handler; ///< The TCP handler this socket is using + TCPSocketState state; ///< The state of the socket + public: + explicit TCPSocket(TransmissionControlProtocolHandler* transmission_control_protocol_handler); + ~TCPSocket(); + + virtual void send(uint8_t* data, uint16_t size); + virtual void disconnect(); + + void disconnected(); + void connected(); + + bool handle_transmission_control_protocol_payload(uint8_t* data, uint16_t size); + }; + + /** + * @class TransmissionControlProtocolHandler + * @brief Handles TCP packets and manages TCP sockets + */ + class TransmissionControlProtocolHandler : IPV4PayloadHandler { friend class TCPSocket; - protected: - common::OutputStream* errorMessages; ///< Where to write error messages - common::Vector sockets; ///< The list of connected sockets + protected: + common::OutputStream* error_messages; ///< Where to write error messages + common::Vector sockets; ///< The list of connected sockets - static TransmissionControlProtocolPort freePorts; ///< The next free port to use for new sockets - void sendTransmissionControlProtocolPacket(TCPSocket* socket, const uint8_t* data, uint16_t size, uint16_t flags = 0); + static TransmissionControlProtocolPort free_ports; ///< The next free port to use for new sockets + void send_transmission_control_protocol_packet(TCPSocket* socket, const uint8_t* data, uint16_t size, uint16_t flags = 0); - public: - TransmissionControlProtocolHandler(InternetProtocolHandler* internetProtocolHandler, common::OutputStream* errorMessages); - ~TransmissionControlProtocolHandler(); + public: + TransmissionControlProtocolHandler(InternetProtocolHandler* internet_protocol_handler, common::OutputStream* error_messages); + ~TransmissionControlProtocolHandler(); - bool handleInternetProtocolPayload(InternetProtocolAddress sourceIP, InternetProtocolAddress destinationIP, uint8_t* payloadData, uint32_t size) override; + bool handle_internet_protocol_payload(net::InternetProtocolAddress source_ip, net::InternetProtocolAddress destination_ip, uint8_t* payload_data, uint32_t size) override; - TCPSocket* Connect(InternetProtocolAddress ip, TransmissionControlProtocolPort port); - static TCPSocket* Connect(const string &address); + TCPSocket* connect(InternetProtocolAddress ip, TransmissionControlProtocolPort port); + static TCPSocket* connect(const string& address); - void Disconnect(TCPSocket* socket); + void disconnect(TCPSocket* socket); - virtual TCPSocket* Listen(uint16_t port); - virtual void Bind(TCPSocket* socket, TCPPayloadHandler* handler); - }; + virtual TCPSocket* listen(uint16_t port); + virtual void bind(TCPSocket* socket, TCPPayloadHandler* handler); + }; - } - } + #endif //MAXOS_NET_TCP_H diff --git a/kernel/include/net/udp.h b/kernel/include/net/udp.h index d93f6bec..3137b139 100644 --- a/kernel/include/net/udp.h +++ b/kernel/include/net/udp.h @@ -10,129 +10,130 @@ #define MAXOS_NET_UDP_H -#include +#include #include #include #include -namespace MaxOS { - namespace net { - - /** - * @struct UDPHeader - * @brief The header of a UDP packet - * - * @typedef udp_header_t - * @brief Alias for UDPHeader struct - */ - typedef struct PACKED UDPHeader { - - uint16_t sourcePort; ///< The port of the sender - uint16_t destinationPort; ///< The port of the receiver - uint16_t length; ///< The length of the UDP header and data - uint16_t checksum; ///< The checksum of the header and data - } udp_header_t; +namespace MaxOS::net { + + /** + * @struct UDPHeader + * @brief The header of a UDP packet + * + * @typedef udp_header_t + * @brief Alias for UDPHeader struct + */ + typedef struct PACKED UDPHeader { - /** - * @enum UDPEvents - * @brief The events that can be fired by the UDP protocol - */ - enum class UDPEvents { - DATA_RECEIVED, - }; + uint16_t source_port; ///< The port of the sender + uint16_t destination_port; ///< The port of the receiver + uint16_t length; ///< The length of the UDP header and data + uint16_t checksum; ///< The checksum of the header and data - //Predefine - class UDPSocket; - class UserDatagramProtocolHandler; + } udp_header_t; - typedef uint16_t UserDatagramProtocolPort; ///< UDP port @todo: Make UDPPort class and do udp_port_t (or generic port that can be used for TCP and UDP) + /** + * @enum UDPEvents + * @brief The events that can be fired by the UDP protocol + */ + enum class UDPEvents { + DATA_RECEIVED, + }; - /** - * @class UDPDataReceivedEvent - * @brief Event fired when data is received on a UDP socket - */ - class UDPDataReceivedEvent : public common::Event { - public: - UDPSocket* socket; ///< The socket that received the data - uint8_t* data; ///< The data received - uint16_t size; ///< The size of the data received + //Predefine + class UDPSocket; - UDPDataReceivedEvent(UDPSocket* socket, uint8_t* data, uint16_t size); - ~UDPDataReceivedEvent(); - }; + class UserDatagramProtocolHandler; - /** - * @class UDPPayloadHandler - * @brief Handles the payload of a UDP packet - */ - class UDPPayloadHandler : public common::EventHandler { - public: - UDPPayloadHandler(); - ~UDPPayloadHandler(); + typedef uint16_t UserDatagramProtocolPort; ///< UDP port @todo: Make UDPPort class and do udp_port_t (or generic port that can be used for TCP and UDP) - common::Event* on_event(common::Event* event) override; + /** + * @class UDPDataReceivedEvent + * @brief Event fired when data is received on a UDP socket + */ + class UDPDataReceivedEvent : public common::Event { + public: + UDPSocket* socket; ///< The socket that received the data + uint8_t* data; ///< The data received + uint16_t size; ///< The size of the data received - virtual void handleUserDatagramProtocolMessage(UDPSocket* socket, uint8_t* data, uint16_t size); + UDPDataReceivedEvent(UDPSocket* socket, uint8_t* data, uint16_t size); + ~UDPDataReceivedEvent(); + }; - }; + /** + * @class UDPPayloadHandler + * @brief Handles the payload of a UDP packet + */ + class UDPPayloadHandler : public common::EventHandler { + public: + UDPPayloadHandler(); + ~UDPPayloadHandler(); - /** - * @class UDPSocket - * @brief A UDP socket - */ - class UDPSocket : public common::EventManager { - friend class UserDatagramProtocolHandler; + common::Event* on_event(common::Event* event) override; - protected: - bool listening; ///< Wether the port is waiting for incoming connections + virtual void handle_user_datagram_protocol_message(UDPSocket* socket, uint8_t* data, uint16_t size); - uint16_t localPort = 0; ///< The port on this device - uint16_t remotePort = 0; ///< The port on the remote device + }; - uint32_t localIP = 0; ///< The IP of this device - uint32_t remoteIP = 0; ///< The IP of the remote device + /** + * @class UDPSocket + * @brief A UDP socket + */ + class UDPSocket : public common::EventManager { + friend class UserDatagramProtocolHandler; - UserDatagramProtocolHandler* userDatagramProtocolHandler; ///< The UDP handler this socket is connected to + protected: + bool listening; ///< Wether the port is waiting for incoming connections - public: - UDPSocket(); - ~UDPSocket(); + uint16_t local_port = 0; ///< The port on this device + uint16_t remote_port = 0; ///< The port on the remote device - virtual void handleUserDatagramProtocolPayload(uint8_t* data, uint16_t size); - virtual void Send(uint8_t* data, uint16_t size); - virtual void Disconnect(); + uint32_t local_ip = 0; ///< The IP of this device + uint32_t remote_ip = 0; ///< The IP of the remote device - }; + UserDatagramProtocolHandler* user_datagram_protocol_handler; ///< The UDP handler this socket is connected to - /** - * @class UserDatagramProtocolHandler - * @brief Handles the UDP protocol - */ - class UserDatagramProtocolHandler : IPV4PayloadHandler { - protected: - common::Vector sockets; ///< The list of UDP sockets - static UserDatagramProtocolPort freePorts; ///< The next free port number - common::OutputStream* errorMessages; ///< Where to write error messages + public: + UDPSocket(); + ~UDPSocket(); - public: - UserDatagramProtocolHandler(InternetProtocolHandler* internetProtocolHandler, common::OutputStream* errorMessages); - ~UserDatagramProtocolHandler(); - - bool handleInternetProtocolPayload(InternetProtocolAddress sourceIP, InternetProtocolAddress destinationIP, uint8_t* payloadData, uint32_t size) override; - - UDPSocket* Connect(uint32_t ip, uint16_t port); - static UDPSocket* Connect(const string &address); + virtual void handle_user_datagram_protocol_payload(uint8_t* data, uint16_t size); + virtual void send(uint8_t* data, uint16_t size); + virtual void disconnect(); - UDPSocket* Listen(uint16_t port); + }; - void Disconnect(UDPSocket* socket); - void Send(UDPSocket* socket, const uint8_t* data, uint16_t size); + /** + * @class UserDatagramProtocolHandler + * @brief Handles the UDP protocol + */ + class UserDatagramProtocolHandler : IPV4PayloadHandler { + protected: + common::Vector sockets; ///< The list of UDP sockets + static UserDatagramProtocolPort free_ports; ///< The next free port number + common::OutputStream* errorMessages; ///< Where to write error messages - static void Bind(UDPSocket* socket, UDPPayloadHandler* UDPPayloadHandler); - }; + public: + UserDatagramProtocolHandler(InternetProtocolHandler* internet_protocol_handler, common::OutputStream* error_messages); + ~UserDatagramProtocolHandler(); + + bool handle_internet_protocol_payload(net::InternetProtocolAddress source_ip, net::InternetProtocolAddress destination_ip, uint8_t* payload_data, uint32_t size) override; + + UDPSocket* connect(uint32_t ip, uint16_t port); + static UDPSocket* connect(const string& address); + + UDPSocket* listen(uint16_t port); + + void disconnect(UDPSocket* socket); + void send(UDPSocket* socket, const uint8_t* data, uint16_t size); + + static void bind(UDPSocket* socket, UDPPayloadHandler* udp_payload_handler); + }; - } } + #endif //MAXOS_NET_UDP_H diff --git a/kernel/include/processes/elf.h b/kernel/include/processes/elf.h index 58dfb374..6c181e67 100644 --- a/kernel/include/processes/elf.h +++ b/kernel/include/processes/elf.h @@ -9,234 +9,233 @@ #ifndef MAXOS_PROCESSES_ELF_H #define MAXOS_PROCESSES_ELF_H -#include -#include +#include +#include #include #include -namespace MaxOS { - namespace processes { - - /// The expected ELF magic number at the start of the file - constexpr char ELF_MAGIC[4] = { 0x7F, 'E', 'L', 'F' }; - - /** - * @enum ELFIdentification - * @brief The indexes of the ELF identification array - */ - enum class ELFIdentification { - Magic0, - Magic1, - Magic2, - Magic3, - Class, - Data, - Version, - OSABI, - ABIVersion, - Padding, - }; - - /** - * @enum ELFClass - * @brief The class of the ELF file (32-bit or 64-bit) - */ - enum class ELFClass { - Invalid, - Bits32, - Bits64 - }; - - /** - * @enum ELFData - * @brief The data encoding of the ELF file (little-endian or big-endian) - */ - enum class ELFData { - InvalidData, - LittleEndian, - BigEndian - }; - - /** - * @enum ELFType - * @brief The type of the ELF file (executable, shared object, etc.) - */ - enum class ELFType { - None, - Relocatable, - Executable, - Shared, - Core, - ProcessorSpecificLow = 0xFF0, - ProcessorSpecificHigh = 0xFFF - }; - - /** - * @enum ELFMachine - * @brief The target architecture of the ELF file - */ - enum class ELFMachine { - NoMachine, - ATnTWe32100, - SPARC, - x86, - MIPS = 0x8, - PowerPC = 0x14, - ARM = 0x28, - SuperH = 0x2A, - IA_64 = 0x32, - x86_64 = 0x3E, - AArch64 = 0xB7, - RISC_V = 0xF3 - }; - - /** - * @enum ELFVersion - * @brief The version of the ELF file - */ - enum class ELFVersion { - Invalid, - Current - }; - - /** - * @struct ELFHeader64 - * @brief The header of a 64-bit ELF file - * - * @typedef elf_64_header_t - * @brief Alias for ELFHeader64 struct - */ - typedef struct ELFHeader64 { - - unsigned char identification[16]; ///< Identifies the file as an ELF file and contains metadata about the file (class, data encoding, version, OS ABI, etc.) - uint16_t type; ///< The type of the ELF file (see ELFType) - uint16_t machine; ///< The target architecture of the ELF file (see ELFMachine) - uint32_t version; ///< The version of the ELF file (see ELFVersion) - uint64_t entry; ///< The starting RIP address where the program begins execution - uint64_t program_header_offset; ///< The offset in the file where the program header table starts - uint64_t section_header_offset; ///< The offset in the file where the section header table starts - uint32_t flags; ///< Architecture-specific flags - uint16_t elf_header_size; ///< The size of this ELF header - uint16_t program_header_size; ///< The size of each entry in the program header table - uint16_t program_header_count; ///< The number of entries in the program header table - uint16_t section_header_size; ///< The size of each entry in the section header table - uint16_t section_header_count; ///< The number of entries in the section header table - uint16_t section_header_string_table_index; ///< Where the section header string table is located (index into the section header table) - - } elf_64_header_t; - - /** - * @enum ELFProgramType - * @brief The type of a program header in the ELF file - */ - enum class ELFProgramType { - Null, - Load, - Dynamic, - Interpreter, - Note, - SharedLibrary, - HeaderTable, - TableProcessorSpecificLow = 0x70000000, - TableProcessorSpecificHigh = 0x7FFFFFFF - }; - - /** - * @enum ELFProgramFlags - * @brief The flags of a program header in the ELF file - */ - enum ELFProgramFlags { - ELFExecute = (1 << 0), - ELFWrite = (1 << 1), - ELFRead = (1 << 2) - }; - - /** - * @struct ELFProgramHeader64 - * @brief The header for the program segments in a 64-bit ELF file - * - * @typedef elf_64_program_header_t - * @brief Alias for ELFProgramHeader64 struct - */ - typedef struct ELFProgramHeader64 { - - uint32_t type; ///< The type of the program header (see ELFProgramType) - uint32_t flags; ///< The flags of the program header (see ELFProgramFlags) - uint64_t offset; ///< The offset in the file where the segment is located - uint64_t virtual_address; ///< Where the segment is to be loaded in memory - uint64_t physical_address; ///< Reserved for physical address (not used in modern systems) - uint64_t file_size; ///< The size of the segment in the file - uint64_t memory_size; ///< The size of the segment in memory (should be >= file_size) - uint64_t align; ///< The required alignment of the segment in memory (normally 2^n) - - } elf_64_program_header_t; - - /** - * @enum ELFSectionType - * @brief The type of a section in the ELF file - */ - enum class ELFSectionType { - Null, - ProgramBits, - SymbolTable, - StringTable, - RelocationAddends, - SymbolHashTable, - DynamicLinkingTable, - SectionNote, - NoBits, - }; - - /** - * @struct ELFSectionHeader64 - * @brief The header for the sections in a 64-bit ELF file - * - * @typedef elf_64_section_header_t - * @brief Alias for ELFSectionHeader64 struct - */ - typedef struct ELFSectionHeader64 { - - uint32_t name_index; ///< The index into the section header string table where the name of this section is located - uint32_t type; ///< The type of the section (see ELFSectionType) - uint64_t sh_flags; ///< The flags of the section (see ELFSectionFlags) - uint64_t virtual_address; ///< Where the section is to be loaded in memory - uint64_t offset; ///< The offset in the file where the section is located - uint64_t size; ///< The size of the section in the file - uint32_t link; ///< Section index link (meaning depends on section type) - uint32_t info; ///< Extra information (meaning depends on section type) - uint64_t address_alignment; ///< The required alignment of the section in memory (normally 2^n) - uint64_t entry_size; ///< The size of each entry in the section if it contains a table of fixed-size entries - - } elf_64_section_header_t; - - /** - * @class ELF64 - * @brief Handles the loading and parsing of 64-bit ELF files - */ - class ELF64 { - private: - uintptr_t m_elf_header_address; - - void load_program_headers() const; - - public: - ELF64(uintptr_t elf_header_address); - ~ELF64(); - - void load(); - bool is_valid() const; - - [[nodiscard]] elf_64_header_t* header() const; - elf_64_program_header_t* get_program_header(size_t index) const; - elf_64_section_header_t* get_section_header(size_t index) const; - - static uint64_t to_vmm_flags(uint32_t type); - - }; - - } + +namespace MaxOS::processes { + + /// The expected ELF magic number at the start of the file + constexpr char ELF_MAGIC[4] = { 0x7F, 'E', 'L', 'F' }; + + /** + * @enum ELFIdentification + * @brief The indexes of the ELF identification array + */ + enum class ELFIdentification { + Magic0, + Magic1, + Magic2, + Magic3, + Class, + Data, + Version, + OSABI, + ABIVersion, + Padding, + }; + + /** + * @enum ELFClass + * @brief The class of the ELF file (32-bit or 64-bit) + */ + enum class ELFClass { + Invalid, + Bits32, + Bits64 + }; + + /** + * @enum ELFData + * @brief The data encoding of the ELF file (little-endian or big-endian) + */ + enum class ELFData { + InvalidData, + LittleEndian, + BigEndian + }; + + /** + * @enum ELFType + * @brief The type of the ELF file (executable, shared object, etc.) + */ + enum class ELFType { + None, + Relocatable, + Executable, + Shared, + Core, + ProcessorSpecificLow = 0xFF0, + ProcessorSpecificHigh = 0xFFF + }; + + /** + * @enum ELFMachine + * @brief The target architecture of the ELF file + */ + enum class ELFMachine { + NoMachine, + ATnTWe32100, + SPARC, + x86, + MIPS = 0x8, + PowerPC = 0x14, + ARM = 0x28, + SuperH = 0x2A, + IA_64 = 0x32, + x86_64 = 0x3E, + AArch64 = 0xB7, + RISC_V = 0xF3 + }; + + /** + * @enum ELFVersion + * @brief The version of the ELF file + */ + enum class ELFVersion { + Invalid, + Current + }; + + /** + * @struct ELFHeader64 + * @brief The header of a 64-bit ELF file + * + * @typedef elf_64_header_t + * @brief Alias for ELFHeader64 struct + */ + typedef struct ELFHeader64 { + + unsigned char identification[16]; ///< Identifies the file as an ELF file and contains metadata about the file (class, data encoding, version, OS ABI, etc.) + uint16_t type; ///< The type of the ELF file (see ELFType) + uint16_t machine; ///< The target architecture of the ELF file (see ELFMachine) + uint32_t version; ///< The version of the ELF file (see ELFVersion) + uint64_t entry; ///< The starting RIP address where the program begins execution + uint64_t program_header_offset; ///< The offset in the file where the program header table starts + uint64_t section_header_offset; ///< The offset in the file where the section header table starts + uint32_t flags; ///< Architecture-specific flags + uint16_t elf_header_size; ///< The size of this ELF header + uint16_t program_header_size; ///< The size of each entry in the program header table + uint16_t program_header_count; ///< The number of entries in the program header table + uint16_t section_header_size; ///< The size of each entry in the section header table + uint16_t section_header_count; ///< The number of entries in the section header table + uint16_t section_header_string_table_index; ///< Where the section header string table is located (index into the section header table) + + } elf_64_header_t; + + /** + * @enum ELFProgramType + * @brief The type of a program header in the ELF file + */ + enum class ELFProgramType { + Null, + Load, + Dynamic, + Interpreter, + Note, + SharedLibrary, + HeaderTable, + TableProcessorSpecificLow = 0x70000000, + TableProcessorSpecificHigh = 0x7FFFFFFF + }; + + /** + * @enum ELFProgramFlags + * @brief The flags of a program header in the ELF file + */ + enum ELFProgramFlags { + ELFExecute = (1 << 0), + ELFWrite = (1 << 1), + ELFRead = (1 << 2) + }; + + /** + * @struct ELFProgramHeader64 + * @brief The header for the program segments in a 64-bit ELF file + * + * @typedef elf_64_program_header_t + * @brief Alias for ELFProgramHeader64 struct + */ + typedef struct ELFProgramHeader64 { + + uint32_t type; ///< The type of the program header (see ELFProgramType) + uint32_t flags; ///< The flags of the program header (see ELFProgramFlags) + uint64_t offset; ///< The offset in the file where the segment is located + uint64_t virtual_address; ///< Where the segment is to be loaded in memory + uint64_t physical_address; ///< Reserved for physical address (not used in modern systems) + uint64_t file_size; ///< The size of the segment in the file + uint64_t memory_size; ///< The size of the segment in memory (should be >= file_size) + uint64_t align; ///< The required alignment of the segment in memory (normally 2^n) + + } elf_64_program_header_t; + + /** + * @enum ELFSectionType + * @brief The type of a section in the ELF file + */ + enum class ELFSectionType { + Null, + ProgramBits, + SymbolTable, + StringTable, + RelocationAddends, + SymbolHashTable, + DynamicLinkingTable, + SectionNote, + NoBits, + }; + + /** + * @struct ELFSectionHeader64 + * @brief The header for the sections in a 64-bit ELF file + * + * @typedef elf_64_section_header_t + * @brief Alias for ELFSectionHeader64 struct + */ + typedef struct ELFSectionHeader64 { + + uint32_t name_index; ///< The index into the section header string table where the name of this section is located + uint32_t type; ///< The type of the section (see ELFSectionType) + uint64_t sh_flags; ///< The flags of the section (see ELFSectionFlags) + uint64_t virtual_address; ///< Where the section is to be loaded in memory + uint64_t offset; ///< The offset in the file where the section is located + uint64_t size; ///< The size of the section in the file + uint32_t link; ///< Section index link (meaning depends on section type) + uint32_t info; ///< Extra information (meaning depends on section type) + uint64_t address_alignment; ///< The required alignment of the section in memory (normally 2^n) + uint64_t entry_size; ///< The size of each entry in the section if it contains a table of fixed-size entries + + } elf_64_section_header_t; + + /** + * @class ELF64 + * @brief Handles the loading and parsing of 64-bit ELF files + */ + class ELF64 { + private: + uintptr_t m_elf_header_address; + + void load_program_headers() const; + + public: + explicit ELF64(uintptr_t elf_header_address); + ~ELF64(); + + void load(); + [[nodiscard]] bool is_valid() const; + + [[nodiscard]] elf_64_header_t* header() const; + [[nodiscard]] elf_64_program_header_t* get_program_header(size_t index) const; + [[nodiscard]] elf_64_section_header_t* get_section_header(size_t index) const; + + static uint64_t to_vmm_flags(uint32_t type); + + }; } + #endif // MAXOS_PROCESSES_ELF_H diff --git a/kernel/include/processes/ipc.h b/kernel/include/processes/ipc.h index f790fb25..32ed8e4d 100644 --- a/kernel/include/processes/ipc.h +++ b/kernel/include/processes/ipc.h @@ -9,8 +9,8 @@ #ifndef MAXOS_PROCESSES_IPC_H #define MAXOS_PROCESSES_IPC_H -#include -#include +#include +#include #include #include #include @@ -19,53 +19,52 @@ #include #include -namespace MaxOS { - namespace processes { - /** - * @class SharedMemory - * @brief A block memory that is mapped into multiple processes - */ - class SharedMemory final : public Resource { +namespace MaxOS::processes { - private: - uintptr_t m_physical_address; - size_t m_size; + /** + * @class SharedMemory + * @brief A block memory that is mapped into multiple processes + */ + class SharedMemory final : public Resource { - common::Map m_mappings; + private: + uintptr_t m_physical_address; + size_t m_size; - public: - SharedMemory(const string &name, size_t size, resource_type_t type); - ~SharedMemory() final; + common::Map m_mappings; - void open(size_t flags) final; - void close(size_t flags) final; + public: + SharedMemory(const string& name, size_t size, resource_type_t type); + ~SharedMemory() final; - int read(void* buffer, size_t size, size_t flags) final; + void open(size_t flags) final; + void close(size_t flags) final; - [[nodiscard]] uintptr_t physical_address() const; - [[nodiscard]] size_t size() const; - }; + int read(void* buffer, size_t size, size_t flags) final; - /** - * @class SharedMessageEndpoint - * @brief A endpoint that allows processes to queue messages on - */ - class SharedMessageEndpoint final : public Resource { + [[nodiscard]] uintptr_t physical_address() const; + [[nodiscard]] size_t size() const; + }; - private: - common::Vector m_queue{ }; - common::Spinlock m_message_lock; + /** + * @class SharedMessageEndpoint + * @brief A endpoint that allows processes to queue messages on + */ + class SharedMessageEndpoint final : public Resource { - public: - SharedMessageEndpoint(const string &name, size_t size, resource_type_t type); - ~SharedMessageEndpoint() final; + private: + common::Vector m_queue { }; + common::Spinlock m_message_lock; - int read(void* buffer, size_t size, size_t flags) final; - int write(const void* buffer, size_t size, size_t flags) final; - }; - } + public: + SharedMessageEndpoint(const string& name, size_t size, resource_type_t type); + ~SharedMessageEndpoint() final; + int read(void* buffer, size_t size, size_t flags) final; + int write(const void* buffer, size_t size, size_t flags) final; + }; } + #endif // MAXOS_PROCESSES_IPC_H diff --git a/kernel/include/processes/process.h b/kernel/include/processes/process.h index 0e6522fa..e936a49f 100644 --- a/kernel/include/processes/process.h +++ b/kernel/include/processes/process.h @@ -13,110 +13,105 @@ #include #include #include -#include +#include #include #include #include #include #include -namespace MaxOS -{ - namespace processes - { - class Process; +namespace MaxOS::processes { + class Process; - /** - * @enum ThreadState - * @brief The different operational states a thread can be in - * - * @typedef thread_state_t - * @brief Alias for ThreadState enum - */ - typedef enum class ThreadState{ - NEW, - RUNNING, - READY, - SLEEPING, - WAITING, - STOPPED - } thread_state_t; + /** + * @enum ThreadState + * @brief The different operational states a thread can be in + * + * @typedef thread_state_t + * @brief Alias for ThreadState enum + */ + typedef enum class ThreadState { + NEW, + RUNNING, + READY, + SLEEPING, + WAITING, + STOPPED + } thread_state_t; - /// The size of the stack for each thread (4KB) - constexpr size_t STACK_SIZE = 0x10000; + /// The size of the stack for each thread (4KB) + constexpr size_t STACK_SIZE = 0x10000; - /** - * @class Thread - * @brief The execution context of a sub-process thread - */ - class Thread{ + /** + * @class Thread + * @brief The execution context of a sub-process thread + */ + class Thread { - private: + private: - uintptr_t m_stack_pointer; - uintptr_t m_tss_stack_pointer; + uintptr_t m_stack_pointer; + uintptr_t m_tss_stack_pointer; - char m_sse_save_region[512] __attribute__((aligned(16))); + char m_sse_save_region[512] __attribute__((aligned(16))); - public: - Thread(void (*_entry_point)(void *) , void* args, int arg_amount, Process* parent); - ~Thread(); + public: + Thread(void (* _entry_point)(void*), void* args, int arg_amount, Process* parent); + ~Thread(); - void sleep(size_t milliseconds); + void sleep(size_t milliseconds); - uint64_t tid; ///< The thread ID - uint64_t parent_pid; ///< The parent process ID + uint64_t tid; ///< The thread ID + uint64_t parent_pid; ///< The parent process ID - system::cpu_status_t execution_state; ///< The CPU state of the thread - thread_state_t thread_state; ///< The current state of the thread + system::cpu_status_t execution_state; ///< The CPU state of the thread + thread_state_t thread_state; ///< The current state of the thread - size_t ticks; ///< The number of ticks the thread has run for - size_t wakeup_time; ///< The time at which the thread should wake up (if sleeping) + size_t ticks; ///< The number of ticks the thread has run for + size_t wakeup_time; ///< The time at which the thread should wake up (if sleeping) - [[nodiscard]] uintptr_t tss_pointer() const { return m_tss_stack_pointer; } ///< Gets the stack pointer to use for the TSS when switching to this thread @return tss + [[nodiscard]] uintptr_t tss_pointer() const { return m_tss_stack_pointer; } ///< Gets the stack pointer to use for the TSS when switching to this thread @return tss - void save_sse_state(); - void restore_sse_state(); + void save_sse_state(); + void restore_sse_state(); - void save_cpu_state(); - }; + void save_cpu_state(); + }; - /** - * @class Process - * @brief A process that can be scheduled by the Scheduler, wraps & manages threads as well as its own address space and resources. - */ - class Process - { + /** + * @class Process + * @brief A process that can be scheduled by the Scheduler, wraps & manages threads as well as its own address space and resources. + */ + class Process { - private: - common::Vector m_threads; + private: + common::Vector m_threads; - uint64_t m_pid = 0; - common::Spinlock m_lock; + uint64_t m_pid = 0; + common::Spinlock m_lock; - public: - Process(const string& name, bool is_kernel = false); - Process(const string& name, void (*_entry_point)(void *), void *args, int arg_amount, bool is_kernel = false); - Process(const string& name, void *args, int arg_amount, ELF64* elf, bool is_kernel = false); - ~Process(); + public: + explicit Process(const string& name, bool is_kernel = false); + Process(const string& name, void (* _entry_point)(void*), void* args, int arg_amount, bool is_kernel = false); + Process(const string& name, void* args, int arg_amount, ELF64* elf, bool is_kernel = false); + ~Process(); - common::Vector threads(); - void add_thread(Thread* thread); - void remove_thread(uint64_t tid); + common::Vector threads(); + void add_thread(Thread* thread); + void remove_thread(uint64_t tid); - void set_pid(uint64_t pid); - uint64_t pid() const; - uint64_t total_ticks(); + void set_pid(uint64_t pid); + [[nodiscard]] uint64_t pid() const; + [[nodiscard]] uint64_t total_ticks(); - bool is_kernel; ///< Whether this process is a kernel process + bool is_kernel; ///< Whether this process is a kernel process - string name; ///< The name of the process - string working_directory = "/"; ///< The working directory of the process + string name; ///< The name of the process + string working_directory = "/"; ///< The working directory of the process - memory::MemoryManager* memory_manager = nullptr; ///< The manager for memory used by this process - ResourceManager resource_manager; ///< The manger for resources used by this process - }; - } + memory::MemoryManager* memory_manager = nullptr; ///< The manager for memory used by this process + ResourceManager resource_manager; ///< The manger for resources used by this process + }; } #endif // MAXOS_PROCESSES_PROCESS_H diff --git a/kernel/include/processes/resource.h b/kernel/include/processes/resource.h index f1c3fe6d..204ae832 100644 --- a/kernel/include/processes/resource.h +++ b/kernel/include/processes/resource.h @@ -9,154 +9,155 @@ #ifndef MAXOS_PROCESSES_RESOURCE_H #define MAXOS_PROCESSES_RESOURCE_H -#include +#include #include #include #include #include #include -namespace MaxOS { - namespace processes { - typedef ::syscore::ResourceType resource_type_t; ///< Alias to make the libsyscore ResourceType accessible here - typedef ::syscore::ResourceErrorBase resource_error_base_t; ///< Alias to make the libsyscore ResourceErrorBase accessible here +namespace MaxOS::processes { - /** - * @class Resource - * @brief Represents a generic resource that can be opened, closed, read from and written to - */ - class Resource { + typedef ::syscore::ResourceType resource_type_t; ///< Alias to make the libsyscore ResourceType accessible here + typedef ::syscore::ResourceErrorBase resource_error_base_t; ///< Alias to make the libsyscore ResourceErrorBase accessible here - private: - string m_name; - resource_type_t m_type; + /** + * @class Resource + * @brief Represents a generic resource that can be opened, closed, read from and written to + */ + class Resource { - public: + private: + string m_name; + resource_type_t m_type; - Resource(const string &name, size_t flags, resource_type_t type); - virtual ~Resource(); + public: - string name(); - resource_type_t type(); + Resource(const string& name, size_t flags, resource_type_t type); + virtual ~Resource(); - virtual void open(size_t flags); - virtual void close(size_t flags); + string name(); + resource_type_t type(); - virtual int read(void* buffer, size_t size, size_t flags); - virtual int write(const void* buffer, size_t size, size_t flags); - }; + virtual void open(size_t flags); + virtual void close(size_t flags); - /** - * @class BaseResourceRegistry - * @brief Manages the creation, retention and destruction of resources of a certain type. Should be subclassed for each resource type - */ - class BaseResourceRegistry { + virtual int read(void* buffer, size_t size, size_t flags); + virtual int write(const void* buffer, size_t size, size_t flags); + }; - protected: - common::Map m_resources; ///< The map of resource names to resource instances - common::Map m_resource_uses; ///< The map of resource names to how many processes are using them + /** + * @class BaseResourceRegistry + * @brief Manages the creation, retention and destruction of resources of a certain type. Should be subclassed for each resource type + */ + class BaseResourceRegistry { - resource_type_t m_type; ///< The resource type that this registry manages + protected: + common::Map m_resources; ///< The map of resource names to resource instances + common::Map m_resource_uses; ///< The map of resource names to how many processes are using them - public: - explicit BaseResourceRegistry(resource_type_t type); - ~BaseResourceRegistry(); + resource_type_t m_type; ///< The resource type that this registry manages - resource_type_t type(); + public: + explicit BaseResourceRegistry(resource_type_t type); + ~BaseResourceRegistry(); - virtual Resource* get_resource(const string &name); - virtual bool register_resource(Resource* resource); + resource_type_t type(); - virtual void close_resource(Resource* resource, size_t flags); - virtual Resource* create_resource(const string &name, size_t flags); - }; + virtual Resource* get_resource(const string& name); + virtual bool register_resource(Resource* resource); - /** - * @class ResourceRegistry - * @brief A resource registry for a specific resource type - * - * @tparam Type The resource type that this registry manages - */ - template class ResourceRegistry : public BaseResourceRegistry { + virtual void close_resource(Resource* resource, size_t flags); + virtual Resource* create_resource(const string& name, size_t flags); + }; - public: - explicit ResourceRegistry(resource_type_t type); - ~ResourceRegistry() = default; + /** + * @class ResourceRegistry + * @brief A resource registry for a specific resource type + * + * @tparam Type The resource type that this registry manages + */ + template class ResourceRegistry : public BaseResourceRegistry { - /** - * @brief Create a new resource of the specific type - * - * @param name The name of the resource - * @param flags The flags to open the resource with - * @return The created resource, or nullptr on failure - */ - Resource* create_resource(const string &name, size_t flags) override { + public: + explicit ResourceRegistry(resource_type_t type); + ~ResourceRegistry() = default; - auto resource = new Type(name, flags, type()); + /** + * @brief Create a new resource of the specific type + * + * @param name The name of the resource + * @param flags The flags to open the resource with + * @return The created resource, or nullptr on failure + */ + Resource* create_resource(const string& name, size_t flags) override { - // Creation failed - if (!register_resource(resource)) { - delete resource; - return nullptr; - } + auto resource = new Type(name, flags, type()); - return resource; + // Creation failed + if(!register_resource(resource)) { + delete resource; + return nullptr; } - }; - /** - * @brief Constructor for ResourceRegistry of a specific type - * - * @tparam Type The resource type that this registry manages - * @param type The resource type enum value - */ - template ResourceRegistry::ResourceRegistry(resource_type_t type):BaseResourceRegistry(type) {} + return resource; + } + }; - /** - * @class GlobalResourceRegistry - * @brief Manages all the resource registries for each resource type - */ - class GlobalResourceRegistry { + /** + * @brief Constructor for ResourceRegistry of a specific type + * + * @tparam Type The resource type that this registry manages + * @param type The resource type enum value + */ + template ResourceRegistry::ResourceRegistry(resource_type_t type) + :BaseResourceRegistry(type) { } - private: - common::Map m_registries; - inline static GlobalResourceRegistry* s_current; + /** + * @class GlobalResourceRegistry + * @brief Manages all the resource registries for each resource type + */ + class GlobalResourceRegistry { - public: - GlobalResourceRegistry(); - ~GlobalResourceRegistry(); + private: + common::Map m_registries; + inline static GlobalResourceRegistry* s_current; - static BaseResourceRegistry* get_registry(resource_type_t type); + public: + GlobalResourceRegistry(); + ~GlobalResourceRegistry(); - static void add_registry(resource_type_t type, BaseResourceRegistry* registry); - static void remove_registry(BaseResourceRegistry* registry); - }; + static BaseResourceRegistry* get_registry(resource_type_t type); - /** - * @class ResourceManager - * @brief Manages the open resources for a process - */ - class ResourceManager { + static void add_registry(resource_type_t type, BaseResourceRegistry* registry); + static void remove_registry(BaseResourceRegistry* registry); + }; - private: - common::Map m_resources; + /** + * @class ResourceManager + * @brief Manages the open resources for a process + */ + class ResourceManager { - uint64_t m_next_handle = 1; + private: + common::Map m_resources; - public: - ResourceManager(); - ~ResourceManager(); + uint64_t m_next_handle = 1; - common::Map resources(); + public: + ResourceManager(); + ~ResourceManager(); - uint64_t open_resource(resource_type_t type, const string &name, size_t flags); - void close_resource(uint64_t handle, size_t flags); + common::Map resources(); - Resource* get_resource(uint64_t handle); - Resource* get_resource(const string &name); - }; - } + uint64_t open_resource(resource_type_t type, const string& name, size_t flags); + void close_resource(uint64_t handle, size_t flags); + + Resource* get_resource(uint64_t handle); + Resource* get_resource(const string& name); + }; } + #endif //MAXOS_PROCESSES_RESOURCE_H diff --git a/kernel/include/processes/scheduler.h b/kernel/include/processes/scheduler.h index 68eff845..9241c99c 100644 --- a/kernel/include/processes/scheduler.h +++ b/kernel/include/processes/scheduler.h @@ -16,113 +16,113 @@ #include #include -namespace MaxOS { - namespace processes { - /** - * @class GlobalScheduler - * @brief The global scheduler that manages all processes and threads across all cores - */ - class GlobalScheduler : public hardwarecommunication::InterruptHandler { +namespace MaxOS::processes { - private: - inline static GlobalScheduler* s_instance = nullptr; - bool m_active = false; + /** + * @class GlobalScheduler + * @brief The global scheduler that manages all processes and threads across all cores + */ + class GlobalScheduler : public hardwarecommunication::InterruptHandler { - GlobalResourceRegistry m_global_resource_registry = { }; - ResourceRegistry m_shared_memory_registry; - ResourceRegistry m_shared_messages_registry; + private: + inline static GlobalScheduler* s_instance = nullptr; + bool m_active = false; - common::Spinlock m_lock; + GlobalResourceRegistry m_global_resource_registry = { }; + ResourceRegistry m_shared_memory_registry; + ResourceRegistry m_shared_messages_registry; - uint64_t m_next_pid; - uint64_t m_next_tid; + common::Spinlock m_lock; - common::Map m_core_pids; - common::Map m_core_tids; + uint64_t m_next_pid; + uint64_t m_next_tid; - public: - GlobalScheduler(system::Multiboot &multiboot); - ~GlobalScheduler(); + common::Map m_core_pids; + common::Map m_core_tids; - static GlobalScheduler* system_scheduler(); - static Scheduler* core_scheduler(); + public: + explicit GlobalScheduler(system::Multiboot& multiboot); + ~GlobalScheduler(); - system::cpu_status_t* handle_interrupt(system::cpu_status_t* status) final; - static system::cpu_status_t* yield(system::cpu_status_t* current); + static GlobalScheduler* system_scheduler(); + static Scheduler* core_scheduler(); - static void activate(); - static void deactivate(); - static bool is_active(); + system::cpu_status_t* handle_interrupt(system::cpu_status_t* status) final; + static system::cpu_status_t* yield(system::cpu_status_t* current); - void balance(); + static void activate(); + static void deactivate(); + static bool is_active(); - static void load_multiboot_elfs(system::Multiboot* multiboot); - static void print_running_header(); + void balance(); - uint64_t add_process(Process* process); - uint64_t add_thread(Thread* thread); + static void load_multiboot_elfs(system::Multiboot* multiboot); + static void print_running_header(); - uint64_t remove_process(Process* process); - system::cpu_status_t* force_remove_process(Process* process); + uint64_t add_process(Process* process); + uint64_t add_thread(Thread* thread); - static Process* current_process(); - static Process* get_process(uint64_t pid); - static uint64_t next_pid(); + static uint64_t remove_process(Process* process); + static system::cpu_status_t* force_remove_process(Process* process); - static Thread* current_thread(); - static Thread* get_thread(uint64_t tid); - static uint64_t next_tid(); - }; + static Process* current_process(); + static Process* get_process(uint64_t pid); + static uint64_t next_pid(); - /// Number of times the clock has to interrupt before switching to the next process/thread - constexpr size_t TICKS_PER_EVENT = 20; + static Thread* current_thread(); + static Thread* get_thread(uint64_t tid); + static uint64_t next_tid(); + }; - /** - * @class Scheduler - * @brief Schedules processes to run on the core via their threads - */ - class Scheduler { + /// Number of times the clock has to interrupt before switching to the next process/thread + constexpr size_t TICKS_PER_EVENT = 20; - private: - common::Vector m_processes; - common::Vector m_threads; + /** + * @class Scheduler + * @brief Schedules processes to run on the core via their threads + */ + class Scheduler { - uint64_t m_next_thread_index; - bool m_active; + private: + common::Vector m_processes; + common::Vector m_threads; - uint64_t m_ticks; + uint64_t m_next_thread_index; + bool m_active; - static system::cpu_status_t* load_process(Process* process, Thread* thread); + uint64_t m_ticks; - public: - Scheduler(); - ~Scheduler(); + static system::cpu_status_t* load_process(Process* process, Thread* thread); - system::cpu_status_t* schedule(system::cpu_status_t* cpu_state); - system::cpu_status_t* schedule_next(system::cpu_status_t* status); - system::cpu_status_t* yield(); + public: + Scheduler(); + ~Scheduler(); - uint64_t add_process(Process* process); - uint64_t remove_process(Process* process); - system::cpu_status_t* force_remove_process(Process* process); - uint64_t add_thread(Thread* thread); + system::cpu_status_t* schedule(system::cpu_status_t* cpu_state); + system::cpu_status_t* schedule_next(system::cpu_status_t* status); + system::cpu_status_t* yield(); - Process* current_process(); - Process* get_process(uint64_t pid); - uint64_t process_amount(); + uint64_t add_process(Process* process); + uint64_t remove_process(Process* process); + system::cpu_status_t* force_remove_process(Process* process); + uint64_t add_thread(Thread* thread); - Thread* current_thread(); - Thread* get_thread(uint64_t tid); - uint64_t thread_amount(); + Process* current_process(); + Process* get_process(uint64_t pid); + uint64_t process_amount(); - [[nodiscard]] uint64_t ticks() const; + Thread* current_thread(); + Thread* get_thread(uint64_t tid); + uint64_t thread_amount(); - void activate(); - void deactivate(); - }; + [[nodiscard]] uint64_t ticks() const; + + void activate(); + void deactivate(); + }; - } } + #endif // MAXOS_PROCESSES_SCHEDULER_H diff --git a/kernel/include/runtime/cplusplus.h b/kernel/include/runtime/cplusplus.h index 48bea211..9cf9902f 100644 --- a/kernel/include/runtime/cplusplus.h +++ b/kernel/include/runtime/cplusplus.h @@ -11,52 +11,52 @@ #ifndef MAXOS_RUNTIME_CPLUSPLUS_H #define MAXOS_RUNTIME_CPLUSPLUS_H -#include - -namespace MaxOS { - namespace runtime { - - typedef void (* constructor)(); ///< A pointer to a constructor function - typedef unsigned uarch_t; ///< An unsigned architecture specific type - - extern "C" { - - /** - * @struct atexit_func_entry_t - * @brief An entry in the list of functions to call at program exit (not used in kernel but needed for linking) - */ - struct atexit_func_entry_t { - void (* destructor_func)(void*); ///< The destructor function to call - void* obj_ptr; ///< The pointer to the object to destroy - void* dso_handle; ///< The DSO handle (not used) - }; - - /** - * @brief Register a function to be called at program exit - * - * @param f The function to call - * @param objptr The object pointer to pass to the function - * @param dso The DSO handle (not used) - * @return int 0 on success, non-zero on failure - */ - int __cxa_atexit(void (* f)(void*), void* objptr, void* dso); - - /** - * @brief Finalise all global objects by calling their destructors - * - * @param f The DSO handle to finalise (nullptr for all) - */ - void __cxa_finalize(void* f); - - /// The stack canary value used to detect stack buffer overflows (@todo make random at runtime) - uintptr_t __stack_chk_guard = 0x595e9fbd94fda766; - - /** - * @brief Called when a stack buffer overflow is detected - */ - void __stack_chk_fail(void); - } +#include + + +namespace MaxOS::runtime { + + typedef void (* constructor)(); ///< A pointer to a constructor function + typedef unsigned uarch_t; ///< An unsigned architecture specific type + + extern "C" { + + /** + * @struct atexit_func_entry_t + * @brief An entry in the list of functions to call at program exit (not used in kernel but needed for linking) + */ + struct atexit_func_entry_t { + void (* destructor_func)(void*); ///< The destructor function to call + void* obj_ptr; ///< The pointer to the object to destroy + void* dso_handle; ///< The DSO handle (not used) + }; + + /** + * @brief Register a function to be called at program exit + * + * @param f The function to call + * @param objptr The object pointer to pass to the function + * @param dso The DSO handle (not used) + * @return int 0 on success, non-zero on failure + */ + int __cxa_atexit(void (* f)(void*), void* objptr, void* dso); + + /** + * @brief Finalise all global objects by calling their destructors + * + * @param f The DSO handle to finalise (nullptr for all) + */ + void __cxa_finalize(void* f); + + /// The stack canary value used to detect stack buffer overflows (@todo make random at runtime) + uintptr_t __stack_chk_guard = 0x595e9fbd94fda766; + + /** + * @brief Called when a stack buffer overflow is detected + */ + void __stack_chk_fail(void); } } + #endif // MAXOS_RUNTIME_CPLUSPLUS_H diff --git a/kernel/include/runtime/ubsan.h b/kernel/include/runtime/ubsan.h index 6e1bceca..6c0fd6bc 100644 --- a/kernel/include/runtime/ubsan.h +++ b/kernel/include/runtime/ubsan.h @@ -9,191 +9,189 @@ #ifndef MAXOS_RUNTIME_UBSAN_H #define MAXOS_RUNTIME_UBSAN_H -#include - -namespace MaxOS { - namespace runtime { - - /// Check if a value is aligned to the given alignment - #define ubsan_aligned(value, alignment) !(value & (alignment - 1)) - - /** - * @struct SourceLocation - * @brief The location in the source code where the undefined behaviour occurred - * - * @typedef source_location_t - * @brief Alias for SourceLocation struct - */ - typedef struct SourceLocation { - - const char* file; ///< The name of the source file - uint32_t line; ///< The line number in the source file - uint32_t column; ///< The column number in the source file - - } source_location_t; - - /** - * @struct TypeDescriptor - * @brief Describes a type in the program - * - * @typedef type_descriptor_t - * @brief Alias for TypeDescriptor struct - */ - typedef struct TypeDescriptor { - - uint16_t kind; ///< The kind of type (e.g., struct, class, union) - uint16_t info; ///< Additional type information - char name[]; ///< The name of the type - - } type_descriptor_t; - - /** - * @struct TypeMismatchInfo - * @brief Information about a type mismatch error - * - * @typedef type_mismatch_info_t - * @brief Alias for TypeMismatchInfo struct - */ - typedef struct TypeMismatchInfo { - - source_location_t location; ///< The location of the type mismatch - type_descriptor_t* type; ///< The type that was expected - uintptr_t alignment; ///< The required alignment - uint8_t type_check_kind; ///< The kind of type check that failed - - } type_mismatch_info_t; - - /** - * @struct TypeMismatchInfoV1 - * @brief Information about a type mismatch error (version 1) - * - * @typedef type_mismatch_info_v1_t - * @brief Alias for TypeMismatchInfoV1 struct - */ - typedef struct TypeMismatchInfoV1 { - - source_location_t location; ///< The location of the type mismatch - type_descriptor_t* type; ///< The type that was expected - unsigned char log_alignment; ///< The log2 of the required alignment - unsigned char type_check_kind; ///< The kind of type check that failed - - } type_mismatch_info_v1_t; - - /** - * @struct OverflowInfo - * @brief Information about an overflow error - * - * @typedef overflow_info_t - * @brief Alias for OverflowInfo struct - */ - typedef struct OverflowInfo { - - source_location_t location; ///< The location of the overflow - type_descriptor_t* base_type; ///< The base type of the operation - - } overflow_info_t; - - /** - * @struct ShiftOutOfBoundsInfo - * @brief Information about a shift out of bounds error - * - * @typedef shift_out_of_bounds_info_t - * @brief Alias for ShiftOutOfBoundsInfo struct - */ - typedef struct ShiftOutOfBoundsInfo { - - source_location_t location; ///< The location of the shift out of bounds - type_descriptor_t* left_type; ///< The type of the left operand - type_descriptor_t* right_type; ///< The type of the right operand - - } shift_out_of_bounds_info_t; - - /** - * @struct OutOfBoundsInfo - * @brief Information about an out of bounds error - * - * @typedef out_of_bounds_info_t - * @brief Alias for OutOfBoundsInfo struct - */ - typedef struct OutOfBoundsInfo { - - source_location_t location; ///< The location of the out of bounds access - type_descriptor_t* array_type; ///< The type of the array - type_descriptor_t* index_type; ///< The type of the index - - } out_of_bounds_info_t; - - /** - * @struct LocationOnlyInfo - * @brief Information that an error that only has a location - * - * @typedef location_only_info_t - * @brief Alias for LocationOnlyInfo struct - */ - typedef struct LocationOnlyInfo { - - source_location_t location; ///< The location of the error - - } location_only_info_t; - - /** - * @struct InvaildValueInfo - * @brief Information about an invalid value error - * - * @typedef invalid_value_info_t - * @brief Alias for InvaildValueInfo struct - */ - typedef struct InvaildValueInfo { - - source_location_t location; ///< The location of the invalid value - type_descriptor_t* type; ///< The type of the invalid value - - } invalid_value_info_t; - - /** - * @struct VLABoundNotPositiveInfo - * @brief Information about a VLA bound not positive error - * - * @typedef vla_bound_not_positive_info_t - * @brief Alias for VLABoundNotPositiveInfo struct - */ - typedef struct VLABoundNotPositiveInfo { - - source_location_t location; ///< The location of the VLA bound not positive - type_descriptor_t* type; ///< The type of the VLA bound - - } vla_bound_not_positive_info_t; - - /// List of type check errors - const char* TYPE_CHECK_KINDS[] = { - "load of", - "store to", - "reference binding to", - "member access within", - "member call on", - "constructor call on", - "downcast of", - "downcast of", - "upcast of", - "cast to virtual base of", - }; - - /** - * @class UBSanHandler - * @brief Handles undefined behaviour sanitizer runtime errors - */ - class UBSanHandler { - - public: - UBSanHandler(); - ~UBSanHandler(); - - static void handle(source_location_t location, const char* msg); - - static void print_type_mismatch(type_mismatch_info_t* info, uintptr_t ptr); - static void print_type_mismatch_v1(type_mismatch_info_v1_t* info, uintptr_t ptr); - }; - } +#include + +/// Check if a value is aligned to the given alignment +#define ubsan_aligned(value, alignment) !(value & (alignment - 1)) + +namespace MaxOS::runtime { + + /** + * @struct SourceLocation + * @brief The location in the source code where the undefined behaviour occurred + * + * @typedef source_location_t + * @brief Alias for SourceLocation struct + */ + typedef struct SourceLocation { + + const char* file; ///< The name of the source file + uint32_t line; ///< The line number in the source file + uint32_t column; ///< The column number in the source file + + } source_location_t; + + /** + * @struct TypeDescriptor + * @brief Describes a type in the program + * + * @typedef type_descriptor_t + * @brief Alias for TypeDescriptor struct + */ + typedef struct TypeDescriptor { + + uint16_t kind; ///< The kind of type (e.g., struct, class, union) + uint16_t info; ///< Additional type information + char name[]; ///< The name of the type + + } type_descriptor_t; + + /** + * @struct TypeMismatchInfo + * @brief Information about a type mismatch error + * + * @typedef type_mismatch_info_t + * @brief Alias for TypeMismatchInfo struct + */ + typedef struct TypeMismatchInfo { + + source_location_t location; ///< The location of the type mismatch + type_descriptor_t* type; ///< The type that was expected + uintptr_t alignment; ///< The required alignment + uint8_t type_check_kind; ///< The kind of type check that failed + + } type_mismatch_info_t; + + /** + * @struct TypeMismatchInfoV1 + * @brief Information about a type mismatch error (version 1) + * + * @typedef type_mismatch_info_v1_t + * @brief Alias for TypeMismatchInfoV1 struct + */ + typedef struct TypeMismatchInfoV1 { + + source_location_t location; ///< The location of the type mismatch + type_descriptor_t* type; ///< The type that was expected + unsigned char log_alignment; ///< The log2 of the required alignment + unsigned char type_check_kind; ///< The kind of type check that failed + + } type_mismatch_info_v1_t; + + /** + * @struct OverflowInfo + * @brief Information about an overflow error + * + * @typedef overflow_info_t + * @brief Alias for OverflowInfo struct + */ + typedef struct OverflowInfo { + + source_location_t location; ///< The location of the overflow + type_descriptor_t* base_type; ///< The base type of the operation + + } overflow_info_t; + + /** + * @struct ShiftOutOfBoundsInfo + * @brief Information about a shift out of bounds error + * + * @typedef shift_out_of_bounds_info_t + * @brief Alias for ShiftOutOfBoundsInfo struct + */ + typedef struct ShiftOutOfBoundsInfo { + + source_location_t location; ///< The location of the shift out of bounds + type_descriptor_t* left_type; ///< The type of the left operand + type_descriptor_t* right_type; ///< The type of the right operand + + } shift_out_of_bounds_info_t; + + /** + * @struct OutOfBoundsInfo + * @brief Information about an out of bounds error + * + * @typedef out_of_bounds_info_t + * @brief Alias for OutOfBoundsInfo struct + */ + typedef struct OutOfBoundsInfo { + + source_location_t location; ///< The location of the out of bounds access + type_descriptor_t* array_type; ///< The type of the array + type_descriptor_t* index_type; ///< The type of the index + + } out_of_bounds_info_t; + + /** + * @struct LocationOnlyInfo + * @brief Information that an error that only has a location + * + * @typedef location_only_info_t + * @brief Alias for LocationOnlyInfo struct + */ + typedef struct LocationOnlyInfo { + + source_location_t location; ///< The location of the error + + } location_only_info_t; + + /** + * @struct InvaildValueInfo + * @brief Information about an invalid value error + * + * @typedef invalid_value_info_t + * @brief Alias for InvaildValueInfo struct + */ + typedef struct InvaildValueInfo { + + source_location_t location; ///< The location of the invalid value + type_descriptor_t* type; ///< The type of the invalid value + + } invalid_value_info_t; + + /** + * @struct VLABoundNotPositiveInfo + * @brief Information about a VLA bound not positive error + * + * @typedef vla_bound_not_positive_info_t + * @brief Alias for VLABoundNotPositiveInfo struct + */ + typedef struct VLABoundNotPositiveInfo { + + source_location_t location; ///< The location of the VLA bound not positive + type_descriptor_t* type; ///< The type of the VLA bound + + } vla_bound_not_positive_info_t; + + /// List of type check errors + const char* TYPE_CHECK_KINDS[] = { + "load of", + "store to", + "reference binding to", + "member access within", + "member call on", + "constructor call on", + "downcast of", + "downcast of", + "upcast of", + "cast to virtual base of", + }; + + /** + * @class UBSanHandler + * @brief Handles undefined behaviour sanitizer runtime errors + */ + class UBSanHandler { + + public: + UBSanHandler(); + ~UBSanHandler(); + + static void handle(source_location_t location, const char* msg); + + static void print_type_mismatch(type_mismatch_info_t* info, uintptr_t ptr); + static void print_type_mismatch_v1(type_mismatch_info_v1_t* info, uintptr_t ptr); + }; } diff --git a/kernel/include/system/cpu.h b/kernel/include/system/cpu.h index 6e6a7375..8fa910cf 100644 --- a/kernel/include/system/cpu.h +++ b/kernel/include/system/cpu.h @@ -10,286 +10,283 @@ #define MAXOS_SYSTEM_CPU_H #include -#include -#include +#include +#include #include #include #include #include // Forward declare -namespace MaxOS { - namespace processes { - class Scheduler; - } + +namespace MaxOS::processes { + class Scheduler; } -namespace MaxOS { - - namespace system { - - /** - * @struct CPUStatus - * @brief Structure representing the CPU state during an interrupt - * - * @typedef cpu_status_t - * @brief Alias for CPUStatus struct - * - */ - typedef struct PACKED CPUStatus { - - uint64_t r15; ///< Register r15 - uint64_t r14; ///< Register r14 - uint64_t r13; ///< Register r13 - uint64_t r12; ///< Register r12 - uint64_t r11; ///< Register r11 - uint64_t r10; ///< Register r10 - uint64_t r9; ///< Register r9 - uint64_t r8; ///< Register r8 - uint64_t rdi; ///< Register rdi (used for first argument) - uint64_t rsi; ///< Register rsi (used for second argument) - uint64_t rbp; ///< Register rbp (base pointer) - uint64_t rdx; ///< Register rdx (used for third argument) - uint64_t rcx; ///< Register rcx (used for fourth argument) - uint64_t rbx; ///< Register rbx (base register) - uint64_t rax; ///< Register rax (accumulator) - - uint64_t interrupt_number; ///< The interrupt number - uint64_t error_code; ///< The error code (if applicable) - - uint64_t rip; ///< Instruction pointer - uint64_t cs; ///< Code segment - uint64_t rflags; ///< Flags register - uint64_t rsp; ///< Stack pointer - uint64_t ss; ///< Stack segment - - } cpu_status_t; - - /** - * @struct TaskStateSegment - * @brief Structure representing the Task State Segment (TSS) - * - * @typedef tss_t - * @brief Alias for TaskStateSegment struct - */ - typedef struct PACKED TaskStateSegment { - - uint32_t reserved0; ///< Unused, must be zero - uint64_t rsp0; ///< Stack pointer for ring 0 - uint64_t rsp1; ///< Stack pointer for ring 1 - uint64_t rsp2; ///< Stack pointer for ring 2 - uint64_t reserved1; ///< Unused, must be zero - uint64_t reserved2; ///< Unused, must be zero - uint64_t ist1; ///< Interrupt Stack Table entry 1 - uint64_t ist2; ///< Interrupt Stack Table entry 2 - uint64_t ist3; ///< Interrupt Stack Table entry 3 - uint64_t ist4; ///< Interrupt Stack Table entry 4 - uint64_t ist5; ///< Interrupt Stack Table entry 5 - uint64_t ist6; ///< Interrupt Stack Table entry 6 - uint64_t ist7; ///< Interrupt Stack Table entry 7 - uint64_t reserved3; ///< Unused, must be zero - uint16_t reserved4; ///< Unused, must be zero - uint16_t io_bitmap_offset; ///< Offset to the I/O bitmap - - } tss_t; - - /** - * @enum CPU_FEATURE_ECX - * @brief CPU features indicated by the ECX register after calling CPUID with EAX = 1 - * - * @see https://wiki.osdev.org/CPUID as the original author - */ - enum class CPU_FEATURE_ECX : int32_t { - SSE3 = 1 << 0, - PCLMUL = 1 << 1, - DTES64 = 1 << 2, - MONITOR = 1 << 3, - DS_CPL = 1 << 4, - VMX = 1 << 5, - SMX = 1 << 6, - EST = 1 << 7, - TM2 = 1 << 8, - SSSE3 = 1 << 9, - CID = 1 << 10, - SDBG = 1 << 11, - FMA = 1 << 12, - CX16 = 1 << 13, - XTPR = 1 << 14, - PDCM = 1 << 15, - PCID = 1 << 17, - DCA = 1 << 18, - SSE4_1 = 1 << 19, - SSE4_2 = 1 << 20, - X2APIC = 1 << 21, - MOVBE = 1 << 22, - POPCNT = 1 << 23, - TSC = 1 << 24, - AES = 1 << 25, - XSAVE = 1 << 26, - OSXSAVE = 1 << 27, - AVX = 1 << 28, - F16C = 1 << 29, - RDRAND = 1 << 30, - HYPERVISOR = 1 << 31, - }; - - /** - * @enum CPU_FEATURE_EDX - * @brief CPU features indicated by the EDX register after calling CPUID with EAX = 1 - * - * @see https://wiki.osdev.org/CPUID as the original author - */ - enum class CPU_FEATURE_EDX : int32_t { - FPU = 1 << 0, - VME = 1 << 1, - DE = 1 << 2, - PSE = 1 << 3, - TSC = 1 << 4, - MSR = 1 << 5, - PAE = 1 << 6, - MCE = 1 << 7, - CX8 = 1 << 8, - APIC = 1 << 9, - SEP = 1 << 11, - MTRR = 1 << 12, - PGE = 1 << 13, - MCA = 1 << 14, - CMOV = 1 << 15, - PAT = 1 << 16, - PSE36 = 1 << 17, - PSN = 1 << 18, - CLFLUSH = 1 << 19, - DS = 1 << 21, - ACPI = 1 << 22, - MMX = 1 << 23, - FXSR = 1 << 24, - SSE = 1 << 25, - SSE2 = 1 << 26, - SS = 1 << 27, - HTT = 1 << 28, - TM = 1 << 29, - IA64 = 1 << 30, - PBE = 1 << 31 - }; - - /** - * @struct StackFrame - * @brief A snapshot of the a frame in the call stack - * - * @typedef stack_frame_t - * @brief Alias for StackFrame struct - */ - typedef struct PACKED StackFrame { - - StackFrame* next; ///< Pointer to the next stack frame (up the call stack) - uintptr_t rip; ///< The instruction pointer at this frame - - } stack_frame_t; - - /** - * @struct CoreBootInfo - * @brief Information needed when booting a core - * - * @typedef core_boot_info_t - * @brief Alias for CoreBootInfo struct - */ - typedef struct PACKED CoreBootInfo { - - uint64_t stack; ///< The stack pointer for the core - uint64_t p4_table; ///< The physical address of the P4 page table - uint8_t id; ///< The ID of the core - bool activated; ///< Whether the core has been activated - void* gdt_64_base; ///< The base of the 64-bit GDT - - } core_boot_info_t; - - /// The size of the stack allocated for booting a core (should align with the startup assembly code for the kernel) - constexpr size_t BOOT_STACK_SIZE = 16384; - - class CPU; - - /** - * @class Core - * @brief Represents a CPU core in the system - */ - class Core { + +namespace MaxOS::system { + + /** + * @struct CPUStatus + * @brief Structure representing the CPU state during an interrupt + * + * @typedef cpu_status_t + * @brief Alias for CPUStatus struct + * + */ + typedef struct PACKED CPUStatus { + + uint64_t r15; ///< Register r15 + uint64_t r14; ///< Register r14 + uint64_t r13; ///< Register r13 + uint64_t r12; ///< Register r12 + uint64_t r11; ///< Register r11 + uint64_t r10; ///< Register r10 + uint64_t r9; ///< Register r9 + uint64_t r8; ///< Register r8 + uint64_t rdi; ///< Register rdi (used for first argument) + uint64_t rsi; ///< Register rsi (used for second argument) + uint64_t rbp; ///< Register rbp (base pointer) + uint64_t rdx; ///< Register rdx (used for third argument) + uint64_t rcx; ///< Register rcx (used for fourth argument) + uint64_t rbx; ///< Register rbx (base register) + uint64_t rax; ///< Register rax (accumulator) + + uint64_t interrupt_number; ///< The interrupt number + uint64_t error_code; ///< The error code (if applicable) + + uint64_t rip; ///< Instruction pointer + uint64_t cs; ///< Code segment + uint64_t rflags; ///< Flags register + uint64_t rsp; ///< Stack pointer + uint64_t ss; ///< Stack segment + + } cpu_status_t; + + /** + * @struct TaskStateSegment + * @brief Structure representing the Task State Segment (TSS) + * + * @typedef tss_t + * @brief Alias for TaskStateSegment struct + */ + typedef struct PACKED TaskStateSegment { + + uint32_t reserved0; ///< Unused, must be zero + uint64_t rsp0; ///< Stack pointer for ring 0 + uint64_t rsp1; ///< Stack pointer for ring 1 + uint64_t rsp2; ///< Stack pointer for ring 2 + uint64_t reserved1; ///< Unused, must be zero + uint64_t reserved2; ///< Unused, must be zero + uint64_t ist1; ///< Interrupt Stack Table entry 1 + uint64_t ist2; ///< Interrupt Stack Table entry 2 + uint64_t ist3; ///< Interrupt Stack Table entry 3 + uint64_t ist4; ///< Interrupt Stack Table entry 4 + uint64_t ist5; ///< Interrupt Stack Table entry 5 + uint64_t ist6; ///< Interrupt Stack Table entry 6 + uint64_t ist7; ///< Interrupt Stack Table entry 7 + uint64_t reserved3; ///< Unused, must be zero + uint16_t reserved4; ///< Unused, must be zero + uint16_t io_bitmap_offset; ///< Offset to the I/O bitmap + + } tss_t; + + /** + * @enum CPU_FEATURE_ECX + * @brief CPU features indicated by the ECX register after calling CPUID with EAX = 1 + * + * @see https://wiki.osdev.org/CPUID as the original author + */ + enum class CPU_FEATURE_ECX : int32_t { + SSE3 = 1 << 0, + PCLMUL = 1 << 1, + DTES64 = 1 << 2, + MONITOR = 1 << 3, + DS_CPL = 1 << 4, + VMX = 1 << 5, + SMX = 1 << 6, + EST = 1 << 7, + TM2 = 1 << 8, + SSSE3 = 1 << 9, + CID = 1 << 10, + SDBG = 1 << 11, + FMA = 1 << 12, + CX16 = 1 << 13, + XTPR = 1 << 14, + PDCM = 1 << 15, + PCID = 1 << 17, + DCA = 1 << 18, + SSE4_1 = 1 << 19, + SSE4_2 = 1 << 20, + X2APIC = 1 << 21, + MOVBE = 1 << 22, + POPCNT = 1 << 23, + TSC = 1 << 24, + AES = 1 << 25, + XSAVE = 1 << 26, + OSXSAVE = 1 << 27, + AVX = 1 << 28, + F16C = 1 << 29, + RDRAND = 1 << 30, + HYPERVISOR = 1 << 31, + }; + + /** + * @enum CPU_FEATURE_EDX + * @brief CPU features indicated by the EDX register after calling CPUID with EAX = 1 + * + * @see https://wiki.osdev.org/CPUID as the original author + */ + enum class CPU_FEATURE_EDX : int32_t { + FPU = 1 << 0, + VME = 1 << 1, + DE = 1 << 2, + PSE = 1 << 3, + TSC = 1 << 4, + MSR = 1 << 5, + PAE = 1 << 6, + MCE = 1 << 7, + CX8 = 1 << 8, + APIC = 1 << 9, + SEP = 1 << 11, + MTRR = 1 << 12, + PGE = 1 << 13, + MCA = 1 << 14, + CMOV = 1 << 15, + PAT = 1 << 16, + PSE36 = 1 << 17, + PSN = 1 << 18, + CLFLUSH = 1 << 19, + DS = 1 << 21, + ACPI = 1 << 22, + MMX = 1 << 23, + FXSR = 1 << 24, + SSE = 1 << 25, + SSE2 = 1 << 26, + SS = 1 << 27, + HTT = 1 << 28, + TM = 1 << 29, + IA64 = 1 << 30, + PBE = 1 << 31 + }; + + /** + * @struct StackFrame + * @brief A snapshot of the a frame in the call stack + * + * @typedef stack_frame_t + * @brief Alias for StackFrame struct + */ + typedef struct PACKED StackFrame { + + StackFrame* next; ///< Pointer to the next stack frame (up the call stack) + uintptr_t rip; ///< The instruction pointer at this frame + + } stack_frame_t; + + /** + * @struct CoreBootInfo + * @brief Information needed when booting a core + * + * @typedef core_boot_info_t + * @brief Alias for CoreBootInfo struct + */ + typedef struct PACKED CoreBootInfo { + + uint64_t stack; ///< The stack pointer for the core + uint64_t p4_table; ///< The physical address of the P4 page table + uint8_t id; ///< The ID of the core + bool activated; ///< Whether the core has been activated + void* gdt_64_base; ///< The base of the 64-bit GDT + + } core_boot_info_t; + + /// The size of the stack allocated for booting a core (should align with the startup assembly code for the kernel) + constexpr size_t BOOT_STACK_SIZE = 16384; + + class CPU; + + /** + * @class Core + * @brief Represents a CPU core in the system + */ + class Core { friend class CPU; - protected: - hardwarecommunication::madt_processor_apic_t* m_madt; ///< The MADT entry for this core + protected: + hardwarecommunication::madt_processor_apic_t* m_madt; ///< The MADT entry for this core - bool m_enabled = false; ///< Whether the core is enabled - bool m_can_enable = false; ///< Whether the core can be enabled - bool m_bsp = false; ///< Whether this core is the bootstrap processor + bool m_enabled = false; ///< Whether the core is enabled + bool m_can_enable = false; ///< Whether the core can be enabled + bool m_bsp = false; ///< Whether this core is the bootstrap processor - uint8_t m_apic_id; ///< The ID of the apic for this core - uint64_t m_stack; ///< The stack pointer for this core + uint8_t m_apic_id; ///< The ID of the apic for this core + uint64_t m_stack = 0; ///< The stack pointer for this core - void init_tss(); - void init_sse(); + void init_tss(); + void init_sse(); - public: - explicit Core(hardwarecommunication::madt_processor_apic_t* madt_item); - ~Core(); + public: + explicit Core(hardwarecommunication::madt_processor_apic_t* madt_item); + ~Core(); - bool xsave_enabled = false; ///< Whether XSAVE is enabled - bool avx_enabled = false; ///< Whether AVX is enabled + bool xsave_enabled = false; ///< Whether XSAVE is enabled + bool avx_enabled = false; ///< Whether AVX is enabled - void wake_up(CPU* cpu); - void init(); + void wake_up(CPU* cpu); + void init(); - uint8_t id; ///< The ID of this core - tss_t tss = { }; ///< The Task State Segment for this core - bool active = false; ///< Whether this core is active + uint8_t id; ///< The ID of this core + tss_t tss = { }; ///< The Task State Segment for this core + bool active = false; ///< Whether this core is active - hardwarecommunication::LocalAPIC* local_apic; ///< The local APIC for this core - GlobalDescriptorTable* gdt; ///< The GDT for this core - processes::Scheduler* scheduler; ///< The scheduler for this core - }; + hardwarecommunication::LocalAPIC* local_apic = nullptr; ///< The local APIC for this core + GlobalDescriptorTable* gdt = nullptr; ///< The GDT for this core + processes::Scheduler* scheduler = nullptr; ///< The scheduler for this core + }; - /** - * @class CPU - * @brief Manages the CPU and its cores - */ - class CPU { + /** + * @class CPU + * @brief Manages the CPU and its cores + */ + class CPU { - public: + public: - CPU(GlobalDescriptorTable* gdt, Multiboot* multiboot); - ~CPU(); + CPU(GlobalDescriptorTable* gdt, Multiboot* multiboot); + ~CPU(); - hardwarecommunication::AdvancedConfigurationAndPowerInterface acpi; ///< The ACPI interface for the CPU - hardwarecommunication::AdvancedProgrammableInterruptController apic; ///< The APIC interface for the CPU + hardwarecommunication::AdvancedConfigurationAndPowerInterface acpi; ///< The ACPI interface for the CPU + hardwarecommunication::AdvancedProgrammableInterruptController apic; ///< The APIC interface for the CPU - static inline Core* panic_core = nullptr; ///< The core that triggered the panic - static inline common::Spinlock panic_lock; ///< Lock to prevent multiple panics at once + static inline Core* panic_core = nullptr; ///< The core that triggered the panic + static inline common::Spinlock panic_lock; ///< Lock to prevent multiple panics at once - static cpu_status_t* prepare_for_panic(cpu_status_t* status = nullptr, const string &msg = ""); - static void PANIC(const char* message, cpu_status_t* status = nullptr); - [[noreturn]] static void halt(); + static cpu_status_t* prepare_for_panic(cpu_status_t* status = nullptr, const string& msg = ""); + static void PANIC(const char* message, cpu_status_t* status = nullptr); + [[noreturn]] static void halt(); - inline static common::Vector cores; ///< The list of CPU cores in the system (populated during initialization, includes the BSP and cores that failed to start) - void find_cores(); - void init_cores(); - static Core* executing_core(); + inline static common::Vector cores; ///< The list of CPU cores in the system (populated during initialization, includes the BSP and cores that failed to start) + void find_cores() const; + void init_cores(); + static Core* executing_core(); - static bool check_nx(); + static bool check_nx(); - static void get_status(cpu_status_t* status); - static void set_status(cpu_status_t* status); - static void print_registers(cpu_status_t* status); + static void get_status(cpu_status_t* status); + static void set_status(cpu_status_t* status); + static void print_registers(cpu_status_t* status); - static uint64_t read_msr(uint32_t msr); - static void write_msr(uint32_t msr, uint64_t value); + static uint64_t read_msr(uint32_t msr); + static void write_msr(uint32_t msr, uint64_t value); - static void cpuid(uint32_t leaf, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx); - static bool check_cpu_feature(CPU_FEATURE_ECX feature); - static bool check_cpu_feature(CPU_FEATURE_EDX feature); + static void cpuid(uint32_t leaf, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx); + static bool check_cpu_feature(CPU_FEATURE_ECX feature); + static bool check_cpu_feature(CPU_FEATURE_EDX feature); - static void stack_trace(size_t); - }; - } + static void stack_trace(size_t); + }; } diff --git a/kernel/include/system/gdt.h b/kernel/include/system/gdt.h index d1ebb7cb..ab8dff48 100644 --- a/kernel/include/system/gdt.h +++ b/kernel/include/system/gdt.h @@ -9,59 +9,59 @@ #ifndef MAX_OS_SYSTEM_GDT_H #define MAX_OS_SYSTEM_GDT_H -#include +#include #include #include -namespace MaxOS { - namespace system { - - - /** - * @static DescriptorFlags - * @brief Flags for the GDT entries - */ - enum class DescriptorFlags : uint64_t { - Write = (1ULL << 41), - Execute = (1ULL << 43), - CodeOrDataSegment = (1ULL << 44), - GrowDown = (1ULL << 45), - ConformFromLower = (1ULL << 46), - Present = (1ULL << 47), - LongMode = (1ULL << 53), - }; - - - /** - * @struct GDTRegister - * @brief How the CPU stores the GDT - * - * @typedef gdtr_t - * @brief Alias for GDTRegister struct - */ - typedef struct PACKED GDTRegister { - - uint16_t size; ///< The size of the GDT - uint64_t address; ///< The address of the GDT - - } gdtr_t; - - /** - * @class GlobalDescriptorTable - * @brief Sets up the GDT in the CPU - */ - class GlobalDescriptorTable { - - public: - GlobalDescriptorTable(); - ~GlobalDescriptorTable(); - - uint64_t table[7]; ///< The GDT entries - - gdtr_t gdtr = {}; ///< The GDTR structure - void load(); - }; - } + +namespace MaxOS::system { + + + /** + * @static DescriptorFlags + * @brief Flags for the GDT entries + */ + enum class DescriptorFlags : uint64_t { + Write = (1ULL << 41), + Execute = (1ULL << 43), + CodeOrDataSegment = (1ULL << 44), + GrowDown = (1ULL << 45), + ConformFromLower = (1ULL << 46), + Present = (1ULL << 47), + LongMode = (1ULL << 53), + }; + + + /** + * @struct GDTRegister + * @brief How the CPU stores the GDT + * + * @typedef gdtr_t + * @brief Alias for GDTRegister struct + */ + typedef struct PACKED GDTRegister { + + uint16_t size; ///< The size of the GDT + uint64_t address; ///< The address of the GDT + + } gdtr_t; + + /** + * @class GlobalDescriptorTable + * @brief Sets up the GDT in the CPU + */ + class GlobalDescriptorTable { + + public: + GlobalDescriptorTable(); + ~GlobalDescriptorTable(); + + uint64_t table[7]; ///< The GDT entries + + gdtr_t gdtr = { }; ///< The GDTR structure + void load(); + }; } + #endif //MAX_OS_SYSTEM_GDT_H diff --git a/kernel/include/system/multiboot.h b/kernel/include/system/multiboot.h index 0f9649f8..3daf346a 100644 --- a/kernel/include/system/multiboot.h +++ b/kernel/include/system/multiboot.h @@ -508,43 +508,42 @@ struct multiboot_tag_load_base_addr { multiboot_uint32_t load_base_addr; ///< Where the OS image was loaded }; -namespace MaxOS { - namespace system { - - /** - * @class Multiboot - * @brief Parses and provides access to Multiboot 2 information - */ - class Multiboot { - private: - multiboot_tag_framebuffer* m_framebuffer; - multiboot_tag_basic_meminfo* m_basic_meminfo; - multiboot_tag_string* m_bootloader_name; - multiboot_tag_mmap* m_mmap; - multiboot_tag_old_acpi* m_old_acpi; - multiboot_tag_new_acpi* m_new_acpi; - multiboot_tag_module* m_module; - - public: - Multiboot(unsigned long address, unsigned long magic); - ~Multiboot(); - - multiboot_tag_framebuffer* framebuffer(); - multiboot_tag_basic_meminfo* basic_meminfo(); - multiboot_tag_string* bootloader_name(); - multiboot_tag_mmap* mmap(); - multiboot_tag_old_acpi* old_acpi(); - multiboot_tag_new_acpi* new_acpi(); - - unsigned long start_address; ///< The start address of the multiboot info struct - unsigned long end_address; ///< The end address of the multiboot info struct - - [[nodiscard]] multiboot_tag* start_tag() const; - - bool is_reserved(multiboot_uint64_t address); - }; - } +namespace MaxOS::system { + + /** + * @class Multiboot + * @brief Parses and provides access to Multiboot 2 information + */ + class Multiboot { + private: + multiboot_tag_framebuffer* m_framebuffer; + multiboot_tag_basic_meminfo* m_basic_meminfo; + multiboot_tag_string* m_bootloader_name; + multiboot_tag_mmap* m_mmap; + multiboot_tag_old_acpi* m_old_acpi; + multiboot_tag_new_acpi* m_new_acpi; + multiboot_tag_module* m_module; + + public: + Multiboot(unsigned long address, unsigned long magic); + ~Multiboot(); + + multiboot_tag_framebuffer* framebuffer(); + multiboot_tag_basic_meminfo* basic_meminfo(); + multiboot_tag_string* bootloader_name(); + multiboot_tag_mmap* mmap(); + multiboot_tag_old_acpi* old_acpi(); + multiboot_tag_new_acpi* new_acpi(); + + unsigned long start_address; ///< The start address of the multiboot info struct + unsigned long end_address; ///< The end address of the multiboot info struct + + [[nodiscard]] multiboot_tag* start_tag() const; + + [[nodiscard]] bool is_reserved(multiboot_uint64_t address) const; + + }; } diff --git a/kernel/include/system/syscalls.h b/kernel/include/system/syscalls.h index e0b1b298..b59b8721 100644 --- a/kernel/include/system/syscalls.h +++ b/kernel/include/system/syscalls.h @@ -11,8 +11,8 @@ #ifndef MAXOS_SYSTEM_SYSCALLS_H #define MAXOS_SYSTEM_SYSCALLS_H -#include -#include +#include +#include #include #include #include @@ -20,71 +20,71 @@ #include #include -namespace MaxOS { - namespace system { - - // Forward declaration - class SyscallManager; - - /** - * @struct SyscallArguments - * @brief The arguments passed to a syscall (simplified representation of values in registers) - * - * @typedef syscall_args_t - * @brief Alias for SyscallArguments struct - */ - typedef struct SyscallArguments { - - uint64_t arg0; ///< First argument (in rdi) - uint64_t arg1; ///< Second argument (in rsi) - uint64_t arg2; ///< Third argument (in rdx) - uint64_t arg3; ///< Fourth argument (in rcx) - uint64_t arg4; ///< Fifth argument (in r8) - uint64_t arg5; ///< Sixth argument (in r9) - uint64_t return_value; ///< The return value of the syscall (in rax) - cpu_status_t* return_state; ///< The CPU state to return to after the syscall - - } syscall_args_t; - - /// @todo Could use a class based response but a single class might want multiple handlers e.g. fs - typedef syscall_args_t* (* syscall_func_t)(syscall_args_t* args); - - /** - * @class SyscallManager - * @brief Provides an API for userspace applications to interact with the kernel - * - * @todo Very c style, should be made class based that automatically registers - */ - class SyscallManager : hardwarecommunication::InterruptHandler { - - private: - syscall_func_t m_syscall_handlers[256] = { }; - - inline static common::Spinlock s_lock = { }; - - public: - SyscallManager(); - ~SyscallManager(); - - cpu_status_t* handle_interrupt(cpu_status_t* esp) final; - - void set_syscall_handler(::syscore::SyscallType syscall, syscall_func_t handler); - void remove_syscall_handler(::syscore::SyscallType syscall); - - static syscall_args_t* syscall_close_process(syscall_args_t* args); - static syscall_args_t* syscall_klog(syscall_args_t* args); - static syscall_args_t* syscall_allocate_memory(syscall_args_t* args); - static syscall_args_t* syscall_free_memory(syscall_args_t* args); - static syscall_args_t* syscall_resource_create(syscall_args_t* args); - static syscall_args_t* syscall_resource_open(syscall_args_t* args); - static syscall_args_t* syscall_resource_close(syscall_args_t* args); - static syscall_args_t* syscall_resource_write(syscall_args_t* args); - static syscall_args_t* syscall_resource_read(syscall_args_t* args); - static syscall_args_t* syscall_thread_yield(syscall_args_t* args); - static syscall_args_t* syscall_thread_sleep(syscall_args_t* args); - static syscall_args_t* syscall_thread_close(syscall_args_t* args); - }; - } + +namespace MaxOS::system { + + // Forward declaration + class SyscallManager; + + /** + * @struct SyscallArguments + * @brief The arguments passed to a syscall (simplified representation of values in registers) + * + * @typedef syscall_args_t + * @brief Alias for SyscallArguments struct + */ + typedef struct SyscallArguments { + + uint64_t arg0; ///< First argument (in rdi) + uint64_t arg1; ///< Second argument (in rsi) + uint64_t arg2; ///< Third argument (in rdx) + uint64_t arg3; ///< Fourth argument (in rcx) + uint64_t arg4; ///< Fifth argument (in r8) + uint64_t arg5; ///< Sixth argument (in r9) + uint64_t return_value; ///< The return value of the syscall (in rax) + cpu_status_t* return_state; ///< The CPU state to return to after the syscall + + } syscall_args_t; + + /// @todo Could use a class based response but a single class might want multiple handlers e.g. fs + typedef syscall_args_t* (* syscall_func_t)(syscall_args_t* args); + + /** + * @class SyscallManager + * @brief Provides an API for userspace applications to interact with the kernel + * + * @todo Very c style, should be made class based that automatically registers + */ + class SyscallManager : hardwarecommunication::InterruptHandler { + + private: + syscall_func_t m_syscall_handlers[256] = { }; + + inline static common::Spinlock s_lock = { }; + + public: + SyscallManager(); + ~SyscallManager(); + + cpu_status_t* handle_interrupt(cpu_status_t* esp) final; + + void set_syscall_handler(::syscore::SyscallType syscall, syscall_func_t handler); + void remove_syscall_handler(::syscore::SyscallType syscall); + + static syscall_args_t* syscall_close_process(syscall_args_t* args); + static syscall_args_t* syscall_klog(syscall_args_t* args); + static syscall_args_t* syscall_allocate_memory(syscall_args_t* args); + static syscall_args_t* syscall_free_memory(syscall_args_t* args); + static syscall_args_t* syscall_resource_create(syscall_args_t* args); + static syscall_args_t* syscall_resource_open(syscall_args_t* args); + static syscall_args_t* syscall_resource_close(syscall_args_t* args); + static syscall_args_t* syscall_resource_write(syscall_args_t* args); + static syscall_args_t* syscall_resource_read(syscall_args_t* args); + static syscall_args_t* syscall_thread_yield(syscall_args_t* args); + static syscall_args_t* syscall_thread_sleep(syscall_args_t* args); + static syscall_args_t* syscall_thread_close(syscall_args_t* args); + }; } + #endif //MAXOS_SYSTEM_SYSCALLS_H diff --git a/kernel/src/common/graphicsContext.cpp b/kernel/src/common/graphicsContext.cpp index 4c2778c6..10965c65 100644 --- a/kernel/src/common/graphicsContext.cpp +++ b/kernel/src/common/graphicsContext.cpp @@ -89,7 +89,7 @@ GraphicsContext::GraphicsContext() { // Set the rest of the palette to black - for (uint8_t color_code = 255; color_code >= 0x40; --color_code) + for(uint8_t color_code = 255; color_code >= 0x40; --color_code) m_colour_pallet[color_code] = Colour(0, 0, 0); @@ -107,7 +107,7 @@ GraphicsContext::~GraphicsContext() = default; void GraphicsContext::render_pixel(uint32_t x, uint32_t y, uint32_t colour) { // Call the correct put_pixel function based on the color depth - switch (m_color_depth) { + switch(m_color_depth) { case 8: render_pixel_8_bit(x, y, colour); break; @@ -178,7 +178,7 @@ void GraphicsContext::render_pixel_32_bit(uint32_t, uint32_t, uint32_t) { */ uint32_t GraphicsContext::get_rendered_pixel(uint32_t x, uint32_t y) { // Call the correct get_pixel function based on the color depth - switch (m_color_depth) { + switch(m_color_depth) { case 8: return get_rendered_pixel_8_bit(x, y); case 16: @@ -242,19 +242,19 @@ uint32_t GraphicsContext::get_rendered_pixel_32_bit(uint32_t, uint32_t) { * @param colour The colour class to convert * @return The integer value of the colour */ -uint32_t GraphicsContext::colour_to_int(const Colour &colour) { +uint32_t GraphicsContext::colour_to_int(const Colour& colour) { - switch (m_color_depth) { + switch(m_color_depth) { case 8: { uint32_t result = 0; int mindistance = 0xfffffff; - for (uint32_t i = 0; i <= 255; ++i) { - Colour *c = &m_colour_pallet[i]; + for(uint32_t i = 0; i <= 255; ++i) { + Colour* c = &m_colour_pallet[i]; int distance = ((int) colour.red - (int) c->red) * ((int) colour.red - (int) c->red) + ((int) colour.green - (int) c->green) * ((int) colour.green - (int) c->green) + ((int) colour.blue - (int) c->blue) * ((int) colour.blue - (int) c->blue); - if (distance < mindistance) { + if(distance < mindistance) { mindistance = distance; result = i; } @@ -264,13 +264,13 @@ uint32_t GraphicsContext::colour_to_int(const Colour &colour) { case 16: { // 16-Bit colours RRRRRGGGGGGBBBBB return ((uint16_t) (colour.red & 0xF8)) << 8 - | ((uint16_t) (colour.green & 0xFC)) << 3 - | ((uint16_t) (colour.blue & 0xF8) >> 3); + | ((uint16_t) (colour.green & 0xFC)) << 3 + | ((uint16_t) (colour.blue & 0xF8) >> 3); } case 24: { return (uint32_t) colour.red << 16 - | (uint32_t) colour.green << 8 - | (uint32_t) colour.blue; + | (uint32_t) colour.green << 8 + | (uint32_t) colour.blue; } default: case 32: { @@ -279,10 +279,10 @@ uint32_t GraphicsContext::colour_to_int(const Colour &colour) { uint32_t blue_hex = (uint32_t) colour.blue & 0xFF; uint32_t alpha_hex = ((uint32_t) colour.alpha & 0xFF) << 24; - uint32_t hexValue = red_hex | green_hex | blue_hex | alpha_hex; + uint32_t hex_value = red_hex | green_hex | blue_hex | alpha_hex; - return hexValue; + return hex_value; } } } @@ -294,7 +294,7 @@ uint32_t GraphicsContext::colour_to_int(const Colour &colour) { * @return The colour class of the integer value */ Colour GraphicsContext::int_to_colour(uint32_t colour) { - switch (m_color_depth) { + switch(m_color_depth) { case 8: { // Return the colour from the palette @@ -372,10 +372,10 @@ uint32_t GraphicsContext::color_depth() const { * @param y The y coordinate of the pixel * @param colour The colour of the pixel */ -void GraphicsContext::put_pixel(int32_t x, int32_t y, const Colour &colour) { +void GraphicsContext::put_pixel(uint32_t x, uint32_t y, const Colour& colour) { // Convert the colour to an integer and then print it - putPixel(x, y, colour_to_int(colour)); + put_pixel(x, y, colour_to_int(colour)); } /** @@ -387,16 +387,11 @@ void GraphicsContext::put_pixel(int32_t x, int32_t y, const Colour &colour) { * * @todo make them uint32_t */ -void GraphicsContext::putPixel(int32_t x, int32_t y, uint32_t colour) { +void GraphicsContext::put_pixel(uint32_t x, uint32_t y, uint32_t colour) { - if (0 > x || x >= m_width) { + // Check bounds + if(x >= m_width || y >= m_height) return; - } - - // Check if the pixel is within the m_height of the screen - if (0 > y || y >= m_height) { - return; - } // Render the pixel render_pixel(x, mirror_y_axis ? m_height - y - 1 : y, colour); @@ -410,11 +405,11 @@ void GraphicsContext::putPixel(int32_t x, int32_t y, uint32_t colour) { * @param y The y coordinate of the pixel * @return The colour of the pixel or black if the pixel is outside the screen */ -Colour GraphicsContext::get_pixel(int32_t x, int32_t y) { +Colour GraphicsContext::get_pixel(uint32_t x, uint32_t y) { - // Check if the pixel is within the bounds of the screen - if (0 > x || x >= m_width || 0 > y || y >= m_height) - return {0, 0, 0}; + // Check bounds + if(x >= m_width || y >= m_height) + return { 0, 0, 0 }; // Get the pixel and convert it to a colour uint32_t translated_color = get_rendered_pixel(x, mirror_y_axis ? m_height - y - 1 : y); @@ -427,7 +422,7 @@ Colour GraphicsContext::get_pixel(int32_t x, int32_t y) { * @param x The x coordinate of the pixel * @param y The y coordinate of the pixel */ -void GraphicsContext::invert_pixel(int32_t x, int32_t y) { +void GraphicsContext::invert_pixel(uint32_t x, uint32_t y) { // Get the pixel Colour colour = get_pixel(x, y); @@ -451,8 +446,8 @@ void GraphicsContext::invert_pixel(int32_t x, int32_t y) { * @param y1 The y coordinate of the final point * @param colour The colour of the line */ -void GraphicsContext::draw_line(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const Colour &colour) { - drawLine(x0, y0, x1, y1, colour_to_int(colour)); +void GraphicsContext::draw_line(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, const Colour& colour) { + draw_line(x0, y0, x1, y1, colour_to_int(colour)); } /** @@ -464,7 +459,7 @@ void GraphicsContext::draw_line(int32_t x0, int32_t y0, int32_t x1, int32_t y1, * @param y1 The y coordinate of the final point * @param colour The colour of the line */ -void GraphicsContext::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colour) { +void GraphicsContext::draw_line(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t colour) { // Store the minimum and maximum y values bool y_0_is_smaller = y0 < y1; @@ -472,54 +467,54 @@ void GraphicsContext::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, u int32_t y_max = y_0_is_smaller ? y1 : y0; //Reverse the points to draw from left to right - if (x1 < x0) { - drawLine(x1, y1, x0, y0, colour); + if(x1 < x0) { + draw_line(x1, y1, x0, y0, colour); return; } // Vertical line - if (x1 == x0) { + if(x1 == x0) { // Force the line to be within the screen - if (y_min < 0) y_min = 0; - if (y_max >= m_height) + if(y_min < 0) y_min = 0; + if(y_max >= m_height) y_max = m_height - 1; // Mirror the Y axis as directly calling put_pixel will not do this - if (mirror_y_axis) { + if(mirror_y_axis) { int32_t temp = y_max; y_max = m_height - y_min - 1; y_min = m_height - temp - 1; } // Check that the line is within the screen - if (0 > x0 || x0 >= m_width) { + if(0 > x0 || x0 >= m_width) { return; } // Draw the line - for (int32_t y = y_min; y <= y_max; ++y) - putPixel(x0, y, colour); + for(int32_t y = y_min; y <= y_max; ++y) + put_pixel(x0, y, colour); return; } // Horizontal line - if (y1 == y0) { + if(y1 == y0) { // Ensure the line is within the screen - if (x0 < 0) x0 = 0; - if (x1 >= m_width) x1 = m_width - 1; + if(x0 < 0) x0 = 0; + if(x1 >= m_width) x1 = m_width - 1; // Mirror the Y axis as directly calling put_pixel will not do this - if (mirror_y_axis) + if(mirror_y_axis) y0 = m_height - y0 - 1; // Check that the line is within the screen - if (0 > y0 || y0 >= m_height) + if(0 > y0 || y0 >= m_height) return; // Draw the line - for (int32_t x = x0; x <= x1; ++x) - putPixel(x, y0, colour); + for(int32_t x = x0; x <= x1; ++x) + put_pixel(x, y0, colour); } // If the line is not horizontal or vertical then it must be a diagonal line @@ -528,10 +523,10 @@ void GraphicsContext::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, u int slope = 1; // replace when in userland // A slope that is more horizontal should be drawn by incrementing x - if (-1 <= slope && slope <= 1) { + if(-1 <= slope && slope <= 1) { int y = y0; - for (int32_t x = x0; x <= x1; x++, y += slope) - putPixel(x, (int32_t) y, colour); + for(int32_t x = x0; x <= x1; x++, y += slope) + put_pixel(x, (int32_t) y, colour); } // A slope that is more vertical should be drawn by incrementing y @@ -540,8 +535,8 @@ void GraphicsContext::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, u slope = 1 / slope; int x = x0; - for (int32_t y = y_min; y <= y_max; x += slope, y++) - putPixel((int32_t) x, y, colour); + for(int32_t y = y_min; y <= y_max; x += slope, y++) + put_pixel((int32_t) x, y, colour); } } @@ -554,7 +549,7 @@ void GraphicsContext::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, u * @param y1 The y coordinate of the bottom right corner * @param colour The colour of the rectangle */ -void GraphicsContext::draw_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const Colour &colour) { +void GraphicsContext::draw_rectangle(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, const Colour& colour) { draw_rectangle(x0, y0, x1, y1, colour_to_int(colour)); } @@ -568,17 +563,17 @@ void GraphicsContext::draw_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t * @param y1 The y coordinate of the bottom right corner * @param colour The colour of the rectangle */ -void GraphicsContext::draw_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colour) { +void GraphicsContext::draw_rectangle(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t colour) { // Ensure x and y 0 is smaller than x and y 1 --y0; --x0; // Draw the rectangle - drawLine(x0, y0, x1, y0, colour); // Top - drawLine(x0, y1, x1, y1, colour); // Bottom - drawLine(x0, y0, x0, y1, colour); // Left - drawLine(x1, y0, x1, y1, colour); // Right + draw_line(x0, y0, x1, y0, colour); // Top + draw_line(x0, y1, x1, y1, colour); // Bottom + draw_line(x0, y0, x0, y1, colour); // Left + draw_line(x1, y0, x1, y1, colour); // Right } @@ -591,7 +586,7 @@ void GraphicsContext::draw_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t * @param y1 The y coordinate of the bottom right corner * @param colour The colour of the rectangle */ -void GraphicsContext::fill_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, const Colour &colour) { +void GraphicsContext::fill_rectangle(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, const Colour& colour) { fill_rectangle(x0, y0, x1, y1, colour_to_int(colour)); } @@ -604,38 +599,38 @@ void GraphicsContext::fill_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t * @param y1 The y coordinate of the bottom right corner * @param colour The colour of the rectangle */ -void GraphicsContext::fill_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t colour) { +void GraphicsContext::fill_rectangle(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t colour) { // Draw from left to right - if (y1 < y0) { + if(y1 < y0) { fill_rectangle(x1, y1, x0, y0, colour); return; } // Make sure the rectangle is within the height of the screen - if (y0 < 0) y0 = 0; - if (y1 > m_height) y1 = m_height; + if(y0 < 0) y0 = 0; + if(y1 > m_height) y1 = m_height; // Make sure the rectangle is within the width of the screen bool x_0_is_smaller = x0 < x1; int32_t x_min = x_0_is_smaller ? x0 : x1; int32_t x_max = x_0_is_smaller ? x1 : x0; - if (x_min < 0) x_min = 0; - if (x_max > m_width) + if(x_min < 0) x_min = 0; + if(x_max > m_width) x_max = m_width; // Mirror the Y axis as directly calling put_pixel will not do this - if (mirror_y_axis) { + if(mirror_y_axis) { int32_t temp = y1; y1 = m_height - y0 - 1; y0 = m_height - temp - 1; } // Draw the rectangle - for (int32_t y = y0; y < y1; ++y) { - for (int32_t x = x_min; x < x_max; ++x) { - putPixel(x, y, colour); + for(int32_t y = y0; y < y1; ++y) { + for(int32_t x = x_min; x < x_max; ++x) { + put_pixel(x, y, colour); } } @@ -649,7 +644,7 @@ void GraphicsContext::fill_rectangle(int32_t x0, int32_t y0, int32_t x1, int32_t * @param radius The radius of the circle * @param colour The colour of the circle */ -void GraphicsContext::draw_circle(int32_t x0, int32_t y0, int32_t radius, const Colour &colour) { +void GraphicsContext::draw_circle(uint32_t x0, uint32_t y0, uint32_t radius, const Colour& colour) { draw_circle(x0, y0, radius, colour_to_int(colour)); } @@ -661,28 +656,28 @@ void GraphicsContext::draw_circle(int32_t x0, int32_t y0, int32_t radius, const * @param radius The radius of the circle * @param colour The colour of the circle */ -void GraphicsContext::draw_circle(int32_t x0, int32_t y0, int32_t radius, uint32_t colour) { +void GraphicsContext::draw_circle(uint32_t x0, uint32_t y0, uint32_t radius, uint32_t colour) { // Make sure the circle is with in the width and height of the screen - if (x0 < 0) x0 = 0; - if (x0 > m_width) x0 = m_width; - if (y0 < 0) y0 = 0; - if (y0 > m_height) y0 = m_height; + if(x0 < 0) x0 = 0; + if(x0 > m_width) x0 = m_width; + if(y0 < 0) y0 = 0; + if(y0 > m_height) y0 = m_height; // Mirror the Y axis as directly calling put_pixel will not do this - if (mirror_y_axis) + if(mirror_y_axis) y0 = m_height - y0 - 1; // Begin drawing at the left most point of the circle and draw a line to the right most point of the circle - for (int32_t x = -radius; x <= radius; ++x) { + for(int32_t x = -radius; x <= radius; ++x) { // Draw a line from the top most point of the circle to the bottom most point of the circle - for (int32_t y = -radius; y <= radius; ++y) { + for(int32_t y = -radius; y <= radius; ++y) { // If the point is within the circle, draw it but make sure it is only part of the outline - if (x * x + y * y <= radius * radius && x * x + y * y >= (radius - 1) * (radius - 1)) - putPixel(x0 + x, y0 + y, colour); + if(x * x + y * y <= radius * radius && x * x + y * y >= (radius - 1) * (radius - 1)) + put_pixel(x0 + x, y0 + y, colour); } } @@ -697,8 +692,8 @@ void GraphicsContext::draw_circle(int32_t x0, int32_t y0, int32_t radius, uint32 * @param radius The radius of the circle * @param colour The colour of the circle */ -void GraphicsContext::fill_circle(int32_t x0, int32_t y0, int32_t radius, const Colour &colour) { - fillCircle(x0, y0, radius, colour_to_int(colour)); +void GraphicsContext::fill_circle(uint32_t x0, uint32_t y0, uint32_t radius, const Colour& colour) { + fill_circle(x0, y0, radius, colour_to_int(colour)); } @@ -710,29 +705,29 @@ void GraphicsContext::fill_circle(int32_t x0, int32_t y0, int32_t radius, const * @param radius The radius of the circle * @param colour The colour of the circle */ -void GraphicsContext::fillCircle(int32_t x0, int32_t y0, int32_t radius, uint32_t colour) { +void GraphicsContext::fill_circle(uint32_t x0, uint32_t y0, uint32_t radius, uint32_t colour) { // Make sure the circle is with in the width and height of the screen - if (x0 < 0) x0 = 0; - if (x0 > m_width) x0 = m_width; - if (y0 < 0) y0 = 0; - if (y0 > m_height) y0 = m_height; + if(x0 < 0) x0 = 0; + if(x0 > m_width) x0 = m_width; + if(y0 < 0) y0 = 0; + if(y0 > m_height) y0 = m_height; // Mirror the Y axis as directly calling put_pixel will not do this - if (mirror_y_axis) + if(mirror_y_axis) y0 = m_height - y0 - 1; // Draw the circle // Begin drawing at the left most point of the circle and draw a line to the right most point of the circle - for (int32_t x = -radius; x <= radius; ++x) { + for(int32_t x = -radius; x <= radius; ++x) { // Draw a line from the top most point of the circle to the bottom most point of the circle - for (int32_t y = -radius; y <= radius; ++y) { + for(int32_t y = -radius; y <= radius; ++y) { // Only draw the pixel if it is within the circle - if (x * x + y * y <= radius * radius) - putPixel(x0 + x, y0 + y, colour); + if(x * x + y * y <= radius * radius) + put_pixel(x0 + x, y0 + y, colour); } } } @@ -742,6 +737,6 @@ void GraphicsContext::fillCircle(int32_t x0, int32_t y0, int32_t radius, uint32_ * * @return The framebuffer address */ -uint64_t *GraphicsContext::framebuffer_address() { +uint64_t* GraphicsContext::framebuffer_address() { return m_framebuffer_address; } diff --git a/kernel/src/common/outputStream.cpp b/kernel/src/common/outputStream.cpp index 5ea43630..db674475 100644 --- a/kernel/src/common/outputStream.cpp +++ b/kernel/src/common/outputStream.cpp @@ -34,7 +34,7 @@ void OutputStream::line_feed() { /** * @brief Writes a carriage return to the output stream. */ -void OutputStream::carriageReturn() { +void OutputStream::carriage_return() { // write the text representation of a carriage return to the output stream. write_char('\r'); @@ -75,7 +75,7 @@ void OutputStream::write(const char *string_to_write) { break; case '\r': - carriageReturn(); + carriage_return(); break; case '\0': diff --git a/kernel/src/common/string.cpp b/kernel/src/common/string.cpp index 940f715b..bfd10352 100644 --- a/kernel/src/common/string.cpp +++ b/kernel/src/common/string.cpp @@ -601,7 +601,7 @@ String String::strip(char strip_char) const { stripped.copy(*this); // Search from the back for the earliest non-whitespace character - int end = m_length - 1; + size_t end = m_length - 1; while (end >= 0 && (m_string[end] == strip_char || m_string[end] == '\n' || m_string[end] == '\t')) end--; @@ -706,7 +706,7 @@ char* itoa(int base, int64_t number) { static char buffer[50] = { 0 }; int i = 49; - bool isNegative = number < 0; + bool is_negative = number < 0; // Null terminate the string buffer[i] = '\0'; @@ -721,7 +721,7 @@ char* itoa(int base, int64_t number) { for (; number && i; --i, number /= base) buffer[i] = "0123456789ABCDEF"[number % base]; - if (isNegative) { + if (is_negative) { buffer[i] = '-'; return &buffer[i]; } diff --git a/kernel/src/common/symbols.cpp b/kernel/src/common/symbols.cpp index 8f36d524..06ac84c4 100644 --- a/kernel/src/common/symbols.cpp +++ b/kernel/src/common/symbols.cpp @@ -8,48 +8,45 @@ #include -namespace MaxOS{ - - namespace common{ - - /** - * @brief Resolve an instruction pointer (rip) to a symbol name and optional offset. - * - * @param rip Instruction pointer - * @param link_base Where the kernel is linked at - * @param load_base Where the kernel is loaded at - * - * @return The symbol name - */ - const char* resolve_symbol(uintptr_t rip, uintptr_t link_base, uintptr_t load_base) - { - - // No symbols - if (KERNEL_SYMBOLS_COUNT == 0) - return nullptr; - - // Convert load to linked - uintptr_t offset = 0; - if (load_base >= link_base) - offset = load_base - link_base; - - // Get the adjusted address - uintptr_t adjusted_address = rip; - if (rip >= offset) - adjusted_address = rip - offset; - - // Binary Search for symbol - size_t left = 0; - size_t right = KERNEL_SYMBOLS_COUNT; - while (left < right) { - size_t middle = (left + right) >> 1; - if (kernel_symbols[middle].address <= adjusted_address) - left = middle + 1; - else - right = middle; - } - - return left == 0 ? nullptr : kernel_symbols[left - 1].name; + +namespace MaxOS::common { + + /** + * @brief resolve an instruction pointer (rip) to a symbol name and optional offset. + * + * @param rip Instruction pointer + * @param link_base Where the kernel is linked at + * @param load_base Where the kernel is loaded at + * + * @return The symbol name + */ + const char* resolve_symbol(uintptr_t rip, uintptr_t link_base, uintptr_t load_base) { + + // No symbols + if(KERNEL_SYMBOLS_COUNT == 0) + return nullptr; + + // Convert load to linked + uintptr_t offset = 0; + if(load_base >= link_base) + offset = load_base - link_base; + + // Get the adjusted address + uintptr_t adjusted_address = rip; + if(rip >= offset) + adjusted_address = rip - offset; + + // Binary Search for symbol + size_t left = 0; + size_t right = KERNEL_SYMBOLS_COUNT; + while(left < right) { + size_t middle = (left + right) >> 1; + if(kernel_symbols[middle].address <= adjusted_address) + left = middle + 1; + else + right = middle; } + + return left == 0 ? nullptr : kernel_symbols[left - 1].name; } -} \ No newline at end of file +} diff --git a/kernel/src/drivers/console/console.cpp b/kernel/src/drivers/console/console.cpp index 1d642537..7d8c97aa 100644 --- a/kernel/src/drivers/console/console.cpp +++ b/kernel/src/drivers/console/console.cpp @@ -23,7 +23,7 @@ Console::~Console() = default; * @return The width of the console in characters */ uint16_t Console::width() { - return 0; + return 0; } /** @@ -32,7 +32,7 @@ uint16_t Console::width() { * @return The height of the console in characters */ uint16_t Console::height() { - return 0; + return 0; } /** @@ -75,7 +75,7 @@ void Console::set_background_color(uint16_t, uint16_t, ConsoleColour) { * @return The character at the given coordinate */ char Console::get_character(uint16_t, uint16_t) { - return ' '; + return ' '; } /** @@ -86,7 +86,7 @@ char Console::get_character(uint16_t, uint16_t) { * @return The background color of the character */ ConsoleColour Console::get_foreground_color(uint16_t, uint16_t) { - return ConsoleColour::Green; + return ConsoleColour::Green; } /** @@ -97,7 +97,7 @@ ConsoleColour Console::get_foreground_color(uint16_t, uint16_t) { * @return The background color of the character */ ConsoleColour Console::get_background_color(uint16_t, uint16_t) { - return ConsoleColour::Green; + return ConsoleColour::Green; } /** @@ -111,12 +111,12 @@ ConsoleColour Console::get_background_color(uint16_t, uint16_t) { */ void Console::put_character(uint16_t x, uint16_t y, char c, ConsoleColour foreground, ConsoleColour background) { - // Set the colors of the character - set_foreground_color(x, y, foreground); - set_background_color(x, y, background); + // Set the colors of the character + set_foreground_color(x, y, foreground); + set_background_color(x, y, background); - // Put the character on the console - put_character(x, y, c); + // Put the character on the console + put_character(x, y, c); } @@ -131,9 +131,9 @@ void Console::put_character(uint16_t x, uint16_t y, char c, ConsoleColour foregr */ void Console::put_string(uint16_t x, uint16_t y, string string, ConsoleColour foreground, ConsoleColour background) { - // Print each character on the screen - for(size_t i = 0; i < string.length(); i++) - put_character(x + i, y, string[i], foreground, background); + // Print each character on the screen + for(size_t i = 0; i < string.length(); i++) + put_character(x + i, y, string[i], foreground, background); } /** @@ -141,7 +141,7 @@ void Console::put_string(uint16_t x, uint16_t y, string string, ConsoleColour fo */ void Console::scroll_up() { - scroll_up(0, 0, width(), height()); + scroll_up(0, 0, width(), height()); } /** @@ -157,14 +157,15 @@ void Console::scroll_up() { */ void Console::scroll_up(uint16_t left, uint16_t top, uint16_t width, uint16_t height, ConsoleColour foreground, ConsoleColour background, char fill) { - // Shift everything but the last line by getting what is below it - for(uint16_t y = top; y < top+height-1; y++) - for(uint32_t x = left; x < left+width; x++) - put_character(x, y, get_character(x, y + 1), get_foreground_color(x, y + 1), get_background_color(x, y + 1)); + // Shift everything but the last line by getting what is below it + for(int y = top; y < top + height - 1; y++) + for(uint32_t x = left; x < left + width; x++) + put_character(x, y, get_character(x, y + 1), get_foreground_color(x, y + 1), + get_background_color(x, y + 1)); - // Fill the last line - for(uint16_t x = left; x < left+width; x++) - put_character(x, top + height - 1, fill, foreground, background); + // Fill the last line + for(uint16_t x = left; x < left + width; x++) + put_character(x, top + height - 1, fill, foreground, background); } @@ -173,7 +174,7 @@ void Console::scroll_up(uint16_t left, uint16_t top, uint16_t width, uint16_t he */ void Console::clear() { - clear(0, 0, width(), height()); + clear(0, 0, width(), height()); } @@ -190,14 +191,14 @@ void Console::clear() { */ void Console::clear(uint16_t left, uint16_t top, uint16_t width, uint16_t height, ConsoleColour foreground, ConsoleColour background, char fill) { - // Check bounds - if ( left > this -> width() || top > this -> height() || width > this -> width() || height > this -> height() ) - return; + // Check bounds + if(left > this->width() || top > this->height() || width > this->width() || height > this->height()) + return; - // Fill the area with the character - for(uint16_t y = top; y < top + height; y++) - for(uint16_t x = left; x < left + width; x++) - put_character(x, y, fill, foreground, background); + // Fill the area with the character + for(uint16_t y = top; y < top + height; y++) + for(uint16_t x = left; x < left + width; x++) + put_character(x, y, fill, foreground, background); } @@ -209,13 +210,13 @@ void Console::clear(uint16_t left, uint16_t top, uint16_t width, uint16_t height */ void Console::invert_colors(uint16_t x, uint16_t y) { - // Get the colors of the character - ConsoleColour foreground = get_foreground_color(x, y); - ConsoleColour background = get_background_color(x, y); + // Get the colors of the character + ConsoleColour foreground = get_foreground_color(x, y); + ConsoleColour background = get_background_color(x, y); - // Set the colors of the character - set_foreground_color(x, y, background); - set_background_color(x, y, foreground); + // Set the colors of the character + set_foreground_color(x, y, background); + set_background_color(x, y, foreground); } /** @@ -227,13 +228,12 @@ void Console::invert_colors(uint16_t x, uint16_t y) { * @param width The width of the area * @param height The height of the area */ -ConsoleArea::ConsoleArea(Console *console, uint16_t left, uint16_t top, uint16_t width, uint16_t height) -: m_console(console), - m_left(left), - m_top(top), - m_width(width), - m_height(height) -{ +ConsoleArea::ConsoleArea(Console* console, uint16_t left, uint16_t top, uint16_t width, uint16_t height) + : m_console(console), + m_left(left), + m_top(top), + m_width(width), + m_height(height) { } @@ -248,20 +248,19 @@ ConsoleArea::ConsoleArea(Console *console, uint16_t left, uint16_t top, uint16_t * @param foreground The foreground color of the area * @param background The background color of the area */ -ConsoleArea::ConsoleArea(Console *console, uint16_t left, uint16_t top, uint16_t width, uint16_t height, ConsoleColour foreground, ConsoleColour background) -: m_console(console), - m_left(left), - m_top(top), - m_width(width), - m_height(height) -{ - - // Store the colours of the console - for(uint16_t y = top; y < top+height; y++) - for(uint16_t x = left; x < left+width; x++){ - console->set_foreground_color(x, y, foreground); - console->set_background_color(x, y, background); - } +ConsoleArea::ConsoleArea(Console* console, uint16_t left, uint16_t top, uint16_t width, uint16_t height, ConsoleColour foreground, ConsoleColour background) + : m_console(console), + m_left(left), + m_top(top), + m_width(width), + m_height(height) { + + // Store the colours of the console + for(uint16_t y = top; y < top + height; y++) + for(uint16_t x = left; x < left + width; x++) { + console->set_foreground_color(x, y, foreground); + console->set_background_color(x, y, background); + } } @@ -273,7 +272,7 @@ ConsoleArea::~ConsoleArea() = default; * @return The width of the console area */ uint16_t ConsoleArea::width() { - return m_width; + return m_width; } /** @@ -282,7 +281,7 @@ uint16_t ConsoleArea::width() { * @return The height of the console area */ uint16_t ConsoleArea::height() { - return m_height; + return m_height; } /** @@ -294,12 +293,12 @@ uint16_t ConsoleArea::height() { */ void ConsoleArea::put_character(uint16_t x, uint16_t y, char c) { - // Check bounds - if(x >= m_width || y >= m_height) - return; + // Check bounds + if(x >= m_width || y >= m_height) + return; - // Write to the console - m_console->put_character(m_left + x, m_top + y, c); + // Write to the console + m_console->put_character(m_left + x, m_top + y, c); } @@ -312,12 +311,12 @@ void ConsoleArea::put_character(uint16_t x, uint16_t y, char c) { */ void ConsoleArea::set_foreground_color(uint16_t x, uint16_t y, ConsoleColour foreground) { - // Make sure the coordinates are within the console area - if(x >= m_width || y >= m_height) - return; + // Make sure the coordinates are within the console area + if(x >= m_width || y >= m_height) + return; - // Set the foreground color of the character - m_console->set_foreground_color(m_left + x, m_top + y, foreground); + // Set the foreground color of the character + m_console->set_foreground_color(m_left + x, m_top + y, foreground); } @@ -330,12 +329,12 @@ void ConsoleArea::set_foreground_color(uint16_t x, uint16_t y, ConsoleColour for */ void ConsoleArea::set_background_color(uint16_t x, uint16_t y, ConsoleColour background) { - // Make sure the coordinates are within the console area - if(x >= m_width || y >= m_height) - return; + // Make sure the coordinates are within the console area + if(x >= m_width || y >= m_height) + return; - // Set the background color of the character - m_console->set_background_color(m_left + x, m_top + y, background); + // Set the background color of the character + m_console->set_background_color(m_left + x, m_top + y, background); } @@ -348,12 +347,12 @@ void ConsoleArea::set_background_color(uint16_t x, uint16_t y, ConsoleColour bac */ char ConsoleArea::get_character(uint16_t x, uint16_t y) { - // Make sure the coordinates are within the console area - if(x >= m_width || y >= m_height) - return ' '; + // Make sure the coordinates are within the console area + if(x >= m_width || y >= m_height) + return ' '; - // Return the character at the given coordinates - return m_console->get_character(m_left + x, m_top + y); + // Return the character at the given coordinates + return m_console->get_character(m_left + x, m_top + y); } /** @@ -365,12 +364,12 @@ char ConsoleArea::get_character(uint16_t x, uint16_t y) { */ ConsoleColour ConsoleArea::get_foreground_color(uint16_t x, uint16_t y) { - // Make sure the coordinates are within the console area - if(x >= m_width || y >= m_height) - return ConsoleColour::LightGrey; + // Make sure the coordinates are within the console area + if(x >= m_width || y >= m_height) + return ConsoleColour::LightGrey; - // Return the foreground color of the character at the given coordinates - return m_console->get_foreground_color(m_left + x, m_top + y); + // Return the foreground color of the character at the given coordinates + return m_console->get_foreground_color(m_left + x, m_top + y); } @@ -383,12 +382,12 @@ ConsoleColour ConsoleArea::get_foreground_color(uint16_t x, uint16_t y) { */ ConsoleColour ConsoleArea::get_background_color(uint16_t x, uint16_t y) { - // Make sure the coordinates are within the console area - if(x >= m_width || y >= m_height) - return ConsoleColour::Black; + // Make sure the coordinates are within the console area + if(x >= m_width || y >= m_height) + return ConsoleColour::Black; - // Return the background color of the character at the given coordinates - return m_console->get_background_color(m_left + x, m_top + y); + // Return the background color of the character at the given coordinates + return m_console->get_background_color(m_left + x, m_top + y); } /** @@ -396,7 +395,7 @@ ConsoleColour ConsoleArea::get_background_color(uint16_t x, uint16_t y) { */ void ConsoleArea::scroll_up() { - m_console->scroll_up(m_left, m_top, m_width, m_height); + m_console->scroll_up(m_left, m_top, m_width, m_height); } /** @@ -414,7 +413,7 @@ void ConsoleArea::scroll_up(uint16_t left, uint16_t top, uint16_t width, uint16_t height, common::ConsoleColour foreground, common::ConsoleColour background, char fill) { - m_console->scroll_up(m_left + left, m_top + top, width, height, foreground, background, fill); + m_console->scroll_up(m_left + left, m_top + top, width, height, foreground, background, fill); } @@ -422,9 +421,8 @@ void ConsoleArea::scroll_up(uint16_t left, uint16_t top, uint16_t width, * @brief Construct a new Console Stream object * @param console The console to create the stream on */ -ConsoleStream::ConsoleStream(Console *console) -: m_console(console) -{ +ConsoleStream::ConsoleStream(Console* console) + : m_console(console) { } @@ -437,69 +435,69 @@ ConsoleStream::~ConsoleStream() = default; */ void ConsoleStream::write_char(char c) { - uint16_t spaces = 0; + uint16_t spaces = 0; - // If the character placement is more than the width of the console go on a new line - if(m_cursor_x >= m_console->width() && c != '\n'){ - line_feed(); - write(" "); - } + // If the character placement is more than the width of the console go on a new line + if(m_cursor_x >= m_console->width() && c != '\n') { + line_feed(); + write(" "); + } - // Check if the character is an ANSI escape code - if(c == '\033') is_ansi = true; + // Check if the character is an ANSI escape code + if(c == '\033') is_ansi = true; - // Handle the character - switch (c) { - // New line - case '\n': - // Go to the next line, if it is more then what the console can fit then scroll - if(++m_cursor_y >= m_console->height()){ - m_console->scroll_up(); + // Handle the character + switch(c) { + // New line + case '\n': + // Go to the next line, if it is more than what the console can fit then scroll + if(++m_cursor_y >= m_console->height()) { + m_console->scroll_up(); - // Ensure there is space at the bottom to write - m_cursor_y = m_console->height()-1; - } + // Ensure there is space at the bottom to write + m_cursor_y = m_console->height() - 1; + } - // don't break here, we want to go to the next case because of the \r - [[fallthrough]]; + // don't break here, we want to go to the next case because of the \r + [[fallthrough]]; - // Carriage return - case '\r': - m_cursor_x = 0; - break; + // Carriage return + case '\r': + m_cursor_x = 0; + break; - // End of string - case '\0': - break; + // End of string + case '\0': + break; - // Backspace - case '\b': - m_cursor_x--; - break; + // Backspace + case '\b': + m_cursor_x--; + break; - // Tab - case '\t': + // Tab + case '\t': - // Pad with spaces until a tab is reached - spaces = 8 - (m_cursor_x % 8); - for(uint16_t i = 0; i < spaces; i++) - write_char(' '); - break; + // Pad with spaces until a tab is reached + spaces = 8 - (m_cursor_x % 8); + for(uint16_t i = 0; i < spaces; i++) + write_char(' '); //TODO: Recursive, dont + break; - default: - // Put the character on the console - m_console->put_character(m_cursor_x, m_cursor_y, c); + default: + // Put the character on the console + m_console->put_character(m_cursor_x, m_cursor_y, c); - // Increment the x coordinate (ANSI aren't rendered) - if(!is_ansi) - m_cursor_x++; + // Increment the x coordinate (ANSI aren't rendered) + if(!is_ansi) + m_cursor_x++; - break; + break; - } + } - // Check if the ANSI code is complete - if(c == 'm') is_ansi = false; + // Check if the ANSI code is complete + if(c == 'm') is_ansi = false; } @@ -511,7 +509,7 @@ void ConsoleStream::write_char(char c) { */ void ConsoleStream::set_cursor(uint16_t x, uint16_t y) { - // Set the x and y coordinates - m_cursor_x = x; - m_cursor_y = y; + // Set the x and y coordinates + m_cursor_x = x; + m_cursor_y = y; } diff --git a/kernel/src/drivers/console/vesaboot.cpp b/kernel/src/drivers/console/vesaboot.cpp index 0e24c4e4..7f8108d6 100644 --- a/kernel/src/drivers/console/vesaboot.cpp +++ b/kernel/src/drivers/console/vesaboot.cpp @@ -22,14 +22,13 @@ using namespace MaxOS::system; * @brief Constructs a new VESA Boot Console object, initializing the console area for text output. * @param graphics_context The graphics context to use for rendering */ -VESABootConsole::VESABootConsole(GraphicsContext *graphics_context) -: m_font((uint8_t *)AMIGA_FONT) -{ +VESABootConsole::VESABootConsole(GraphicsContext* graphics_context) + : m_font((uint8_t*) AMIGA_FONT) { // Set up Logger::INFO() << "Setting up VESA console\n"; s_graphics_context = graphics_context; - m_video_memory_meta = (uint16_t *) MemoryManager::kmalloc(width() * height() * sizeof(uint16_t)); + m_video_memory_meta = (uint16_t*) MemoryManager::kmalloc(width() * height() * sizeof(uint16_t)); // Prepare the console VESABootConsole::clear(); @@ -38,10 +37,10 @@ VESABootConsole::VESABootConsole(GraphicsContext *graphics_context) cout = new ConsoleStream(m_console_area); // Only log to the screen when debugging - #ifndef NDEBUG - Logger::active_logger()->add_log_writer(cout); - Logger::INFO() << "Console Stream set up \n"; - #endif +#ifndef NDEBUG + Logger::active_logger()->add_log_writer(cout); + Logger::INFO() << "Console Stream set up \n"; +#endif } VESABootConsole::~VESABootConsole() = default; @@ -74,7 +73,7 @@ uint16_t VESABootConsole::height() { void VESABootConsole::put_character(uint16_t x, uint16_t y, char c) { // Parse any ansi codes - if (c == '\033') { + if(c == '\033') { // Store the character ansi_code_length = 0; @@ -84,17 +83,17 @@ void VESABootConsole::put_character(uint16_t x, uint16_t y, char c) { return; } - if (ansi_code_length < 8) { + if(ansi_code_length < 8) { // Add the character to the ANSI code ansi_code[ansi_code_length++] = c; // If the ANSI code is complete - if (c == 'm') { + if(c == 'm') { ansi_code[ansi_code_length] = '\0'; ansi_code_length = -1; - if (strcmp("\033[0m", ansi_code) != 0) { + if(strcmp("\033[0m", ansi_code) != 0) { m_foreground_color = ConsoleColour::Uninitialised; m_background_color = ConsoleColour::Uninitialised; return; @@ -105,7 +104,7 @@ void VESABootConsole::put_character(uint16_t x, uint16_t y, char c) { // Set the colour bool foreground = ansi_code[4] == '3'; - if (foreground) + if(foreground) m_foreground_color = colour.to_console_colour(); else m_background_color = colour.to_console_colour(); @@ -117,7 +116,7 @@ void VESABootConsole::put_character(uint16_t x, uint16_t y, char c) { } // If the coordinates are out of bounds, return - if (x >= width() || y >= height()) + if(x >= width() || y >= height()) return; // Calculate the offset @@ -130,8 +129,8 @@ void VESABootConsole::put_character(uint16_t x, uint16_t y, char c) { char s[] = " "; s[0] = c; - Colour foreground = m_foreground_color == ConsoleColour::Uninitialised ? get_foreground_color(x, y) : Colour(m_foreground_color); - Colour background = m_background_color == ConsoleColour::Uninitialised ? get_background_color(x, y) : Colour(m_background_color); + Colour foreground = m_foreground_color == ConsoleColour::Uninitialised ? Colour(get_foreground_color(x, y)) : Colour(m_foreground_color); + Colour background = m_background_color == ConsoleColour::Uninitialised ? Colour(get_background_color(x, y)) : Colour(m_background_color); // Use the m_font to draw the character m_font.draw_text(x * 8, y * FONT_HEIGHT, foreground, background, s_graphics_context, s); @@ -147,7 +146,7 @@ void VESABootConsole::put_character(uint16_t x, uint16_t y, char c) { void VESABootConsole::set_foreground_color(uint16_t x, uint16_t y, ConsoleColour foreground) { // If the coordinates are out of bounds, return - if (x >= width() || y >= height()) + if(x >= width() || y >= height()) return; // Calculate the offset @@ -167,7 +166,7 @@ void VESABootConsole::set_foreground_color(uint16_t x, uint16_t y, ConsoleColour void VESABootConsole::set_background_color(uint16_t x, uint16_t y, ConsoleColour background) { // If the coordinates are out of bounds, return - if (x >= width() || y >= height()) + if(x >= width() || y >= height()) return; // Calculate the offset @@ -187,7 +186,7 @@ void VESABootConsole::set_background_color(uint16_t x, uint16_t y, ConsoleColour char VESABootConsole::get_character(uint16_t x, uint16_t y) { // If the coordinates are out of bounds, return - if (x >= width() || y >= height()) + if(x >= width() || y >= height()) return ' '; // Calculate the offset @@ -210,7 +209,7 @@ ConsoleColour VESABootConsole::get_foreground_color(uint16_t x, uint16_t y) { return ConsoleColour::White; // If the coordinates are out of bounds, return - if (x >= width() || y >= height()) + if(x >= width() || y >= height()) return ConsoleColour::White; // Calculate the offset @@ -233,7 +232,7 @@ ConsoleColour VESABootConsole::get_background_color(uint16_t x, uint16_t y) { return ConsoleColour::Red; // If the coordinates are out of bounds, return - if (x >= width() || y >= height()) + if(x >= width() || y >= height()) return ConsoleColour::Black; // Calculate the offset @@ -251,7 +250,7 @@ ConsoleColour VESABootConsole::get_background_color(uint16_t x, uint16_t y) { void VESABootConsole::print_logo(bool is_panic) { // Load the logo - const char *logo = is_panic ? header_data_kp : header_data; + const char* logo = is_panic ? header_data_kp : header_data; // Find the center of the screen uint32_t screen_width = s_graphics_context->width(); @@ -261,20 +260,20 @@ void VESABootConsole::print_logo(bool is_panic) { // Fill the screen with the logo colour auto col = Colour(is_panic ? ConsoleColour::Red : ConsoleColour::Black); - memset(s_graphics_context->framebuffer_address(), s_graphics_context->colour_to_int(col), screen_width * screen_height * (s_graphics_context->color_depth()/8)); + memset(s_graphics_context->framebuffer_address(), s_graphics_context->colour_to_int(col), screen_width * screen_height * (s_graphics_context->color_depth() / 8)); // Draw the logo - for (uint32_t logoY = 0; logoY < LOGO_HEIGHT; ++logoY) { - for (uint32_t logoX = 0; logoX < LOGO_WIDTH; ++logoX) { + for(uint32_t logo_y = 0; logo_y < LOGO_HEIGHT; ++logo_y) { + for(uint32_t logo_x = 0; logo_x < LOGO_WIDTH; ++logo_x) { // Get the pixel from the logo - uint8_t pixel[3] = {0}; + uint8_t pixel[3] = { 0 }; LOGO_HEADER_PIXEL(logo, pixel) // Draw the pixel - s_graphics_context->put_pixel(center_x - LOGO_WIDTH / 2 + logoX, - center_y - LOGO_HEIGHT / 2 + logoY, - common::Colour(pixel[0], pixel[1], pixel[2])); + s_graphics_context->put_pixel(center_x - LOGO_WIDTH / 2 + logo_x, + center_y - LOGO_HEIGHT / 2 + logo_y, + common::Colour(pixel[0], pixel[1], pixel[2])); } } @@ -294,13 +293,13 @@ void VESABootConsole::print_logo(bool is_panic) { * @param fill The character to fill the new line with */ void VESABootConsole::scroll_up(uint16_t left, uint16_t top, uint16_t width, - uint16_t height, - common::ConsoleColour foreground, - common::ConsoleColour background, char fill) { + uint16_t height, + common::ConsoleColour foreground, + common::ConsoleColour background, char fill) { // Get the framebuffer info - auto *framebuffer_address = (uint8_t *) s_graphics_context->framebuffer_address(); + auto* framebuffer_address = (uint8_t*) s_graphics_context->framebuffer_address(); uint64_t framebuffer_width = s_graphics_context->width(); uint64_t framebuffer_bpp = s_graphics_context->color_depth(); // in bits per pixel uint64_t bytes_per_pixel = framebuffer_bpp / 8; @@ -318,28 +317,27 @@ void VESABootConsole::scroll_up(uint16_t left, uint16_t top, uint16_t width, // Decide the colour of the pixel ConsoleColour to_set_foreground = get_foreground_color(left, top + height - 1); ConsoleColour to_set_background = get_background_color(left, top + height - 1); - Colour fill_colour = Colour(to_set_background); - uint32_t fill_value = s_graphics_context->colour_to_int(to_set_background); + uint32_t fill_value = s_graphics_context->colour_to_int(Colour(to_set_background)); // Scroll the region upward by one text line - for (uint16_t row = 0; row < region_pixel_height - line_height; row++) { - uint8_t *src = framebuffer_address + (region_pixel_y + row + line_height) * framebuffer_pitch + region_pixel_left * bytes_per_pixel; - uint8_t *dest = framebuffer_address + (region_pixel_y + row) * framebuffer_pitch + region_pixel_left * bytes_per_pixel; + for(uint16_t row = 0; row < region_pixel_height - line_height; row++) { + uint8_t* src = framebuffer_address + (region_pixel_y + row + line_height) * framebuffer_pitch + region_pixel_left * bytes_per_pixel; + uint8_t* dest = framebuffer_address + (region_pixel_y + row) * framebuffer_pitch + region_pixel_left * bytes_per_pixel; memmove(dest, src, row_bytes); } // Clear the last line of the region uint16_t clear_start_y = region_pixel_y + region_pixel_height - line_height; - for (uint16_t row = 0; row < line_height; row++) { - auto row_add = (uint32_t *) (framebuffer_address + (clear_start_y + row) * framebuffer_pitch + region_pixel_left * 4); - for (uint16_t col = 0; col < region_pixel_width; col++) { + for(uint16_t row = 0; row < line_height; row++) { + auto row_add = (uint32_t*) (framebuffer_address + (clear_start_y + row) * framebuffer_pitch + region_pixel_left * 4); + for(uint16_t col = 0; col < region_pixel_width; col++) { row_add[col] = fill_value; } } //Update any per-pixel colour metadata uint16_t text_row = top + height - 1; - for (uint16_t x = left; x < left + width; x++) { + for(uint16_t x = left; x < left + width; x++) { set_foreground_color(x, text_row, to_set_foreground); set_background_color(x, text_row, to_set_background); } @@ -348,7 +346,7 @@ void VESABootConsole::scroll_up(uint16_t left, uint16_t top, uint16_t width, /** * @brief Cleans up the boot console */ -void VESABootConsole::finish() { +void VESABootConsole::finish() const { // Done Logger::HEADER() << "MaxOS Kernel Successfully Booted\n" << ANSI_COLOURS[ANSIColour::Reset]; @@ -364,11 +362,11 @@ void VESABootConsole::finish() { void VESABootConsole::update_progress_bar(uint8_t percentage) { // Check bounds - if (percentage > 100) + if(percentage > 100) percentage = 100; // Must have a valid graphics context - if (s_graphics_context == nullptr) + if(s_graphics_context == nullptr) return; uint8_t progress_height = 15; @@ -386,19 +384,19 @@ void VESABootConsole::update_progress_bar(uint8_t percentage) { uint32_t end_y = LOGO_HEIGHT + progress_height + progress_spacing; // Draw the progress bar - for (uint32_t progress_y = start_y; progress_y < end_y; ++progress_y) { - for (uint32_t progress_x = start_x; progress_x < end_x; ++progress_x) { + for(uint32_t progress_y = start_y; progress_y < end_y; ++progress_y) { + for(uint32_t progress_x = start_x; progress_x < end_x; ++progress_x) { // Check if drawing border bool is_border = (progress_y == start_y) || (progress_y == end_y - 1) || - (progress_x == start_x) || (progress_x == end_x - 1); + (progress_x == start_x) || (progress_x == end_x - 1); // Only draw the border if it is the first time drawing it is_border = is_border && percentage == 0; // If it is not within the percentage, skip it uint32_t logo_progress_width = LOGO_WIDTH * percentage / 100; - if (progress_x > logo_progress_width && !is_border) + if(progress_x > logo_progress_width && !is_border) continue; s_graphics_context->put_pixel(right_x + progress_x, bottom_y + progress_y, Colour(0xFF, 0xFF, 0xFF)); diff --git a/kernel/src/drivers/disk/ata.cpp b/kernel/src/drivers/disk/ata.cpp index fe6a4a5c..54677821 100644 --- a/kernel/src/drivers/disk/ata.cpp +++ b/kernel/src/drivers/disk/ata.cpp @@ -82,16 +82,19 @@ bool AdvancedTechnologyAttachment::identify() { return false; } - // Read the rest of the data as a whole sector needs to be read - for (uint16_t i = 0; i < 256; ++i) - uint16_t data = m_data_port.read(); + // Read the rest of the data as a whole sector needs to be read (force the compiler to do so) + for (uint16_t i = 0; i < 256; ++i) { + volatile uint16_t data = m_data_port.read(); + (void) data; + } + // Device is present and ready return true; } /** - * @brief Read a sector from the ATA device + * @brief read a sector from the ATA device * * @param sector The sector to read * @param data_buffer The data to read into @@ -106,7 +109,7 @@ void AdvancedTechnologyAttachment::read(uint32_t sector, buffer_t* data_buffer, // Select the device (master or slave) m_device_port.write((m_is_master ? 0xE0 : 0xF0) | ((sector & 0x0F000000) >> 24)); - // Device is busy @todo yeild + // Device is busy @todo yield while ((m_command_port.read() & 0x80) != 0); // Reset the device @@ -189,17 +192,17 @@ void AdvancedTechnologyAttachment::write(uint32_t sector, buffer_t* data, size_t // Write the data to the device for (size_t i = 0; i < m_bytes_per_sector; i += 2) { - uint16_t writeData = data->read(); + uint16_t write_data = data->read(); // Place the next byte in the array if there is one if (i + 1 < count) - writeData |= (uint16_t) (data->read()) << 8; + write_data |= (uint16_t) (data->read()) << 8; - m_data_port.write(writeData); + m_data_port.write(write_data); } // Write the remaining bytes as a full sector has to be written - for (int i = count + (count % 2); i < m_bytes_per_sector; i += 2) + for (size_t i = count + (count % 2); i < m_bytes_per_sector; i += 2) m_data_port.write(0x0000); // Wait for the device to finish writing @todo YIELD diff --git a/kernel/src/drivers/disk/disk.cpp b/kernel/src/drivers/disk/disk.cpp index 90854e06..a408fa32 100644 --- a/kernel/src/drivers/disk/disk.cpp +++ b/kernel/src/drivers/disk/disk.cpp @@ -18,7 +18,7 @@ Disk::Disk() = default; Disk::~Disk() = default; /** - * @brief Read data from the disk into a buffer (max capacity 512 bytes) + * @brief read data from the disk into a buffer (max capacity 512 bytes) * * @param sector The sector to read from * @param data_buffer The buffer to read the data into @@ -31,7 +31,7 @@ void Disk::read(uint32_t sector, common::buffer_t* data_buffer) { } /** - * @brief Read data from the disk + * @brief read data from the disk * * @param sector The sector to read from * @param data_buffer The buffer to read the data into @@ -42,7 +42,7 @@ void Disk::read(uint32_t sector, buffer_t* data_buffer, size_t amount) { } /** - * @brief Write data to the disk from a buffer (max capacity 512 bytes) + * @brief write data to the disk from a buffer (max capacity 512 bytes) * * @param sector The sector to write to * @param data The buffer to write the data from @@ -55,7 +55,7 @@ void Disk::write(uint32_t sector, common::buffer_t* data) { } /** - * @brief Write data to the disk + * @brief write data to the disk * * @param sector The sector to write to * @param data The buffer to write the data into diff --git a/kernel/src/drivers/driver.cpp b/kernel/src/drivers/driver.cpp index d59e11ea..17ba40d4 100644 --- a/kernel/src/drivers/driver.cpp +++ b/kernel/src/drivers/driver.cpp @@ -189,17 +189,17 @@ uint32_t DriverManager::reset_devices() { Logger::INFO() << "Resetting Devices \n"; - uint32_t resetWaitTime = 0; + uint32_t reset_wait_time = 0; for (auto &driver: m_drivers) { // Reset the driver - uint32_t waitTime = driver->reset(); + uint32_t wait_time = driver->reset(); // If the wait time is longer than the current longest wait time, set it as the new longest wait time - if (waitTime > resetWaitTime) - resetWaitTime = waitTime; + if (wait_time > reset_wait_time) + reset_wait_time = wait_time; } - return resetWaitTime; + return reset_wait_time; } /** diff --git a/kernel/src/drivers/ethernet/amd_am79c973.cpp b/kernel/src/drivers/ethernet/amd_am79c973.cpp index 8db674a9..31e18f01 100644 --- a/kernel/src/drivers/ethernet/amd_am79c973.cpp +++ b/kernel/src/drivers/ethernet/amd_am79c973.cpp @@ -23,95 +23,95 @@ using namespace MaxOS::hardwarecommunication; * @brief Constructs a new AMD_AM79C973 Ethernet driver, reads the MAC address and sets up the initialisation block and buffer descriptors * @param dev The PCI device descriptor for this device */ -AMD_AM79C973::AMD_AM79C973(PCIDeviceDescriptor *dev) -: InterruptHandler(0x20 + dev -> interrupt), - MACAddress0Port(dev ->port_base), - MACAddress2Port(dev ->port_base + 0x02), - MACAddress4Port(dev ->port_base + 0x04), - registerDataPort(dev ->port_base + 0x10), - registerAddressPort(dev ->port_base + 0x12), - busControlRegisterDataPort(dev ->port_base + 0x16), - resetPort(dev ->port_base + 0x14), - initBlock(), - sendBuffers(), - recvBuffers() -{ - // No active buffer at the start - currentSendBuffer = 0; - currentRecvBuffer = 0; - - //Not active or initialised - active = false; - initDone = false; +AMD_AM79C973::AMD_AM79C973(PCIDeviceDescriptor* dev) +: InterruptHandler(0x20 + dev->interrupt), +mac_address_0_port(dev->port_base), +mac_address_2_port(dev->port_base + 0x02), +mac_address_4_port(dev->port_base + 0x04), +register_data_port(dev->port_base + 0x10), +register_address_port(dev->port_base + 0x12), +bus_control_register_data_port(dev->port_base + 0x16), +reset_port(dev->port_base + 0x14), +init_block(), +send_buffers(), +recv_buffers() { + // No active buffer at the start + current_send_buffer = 0; + current_recv_buffer = 0; + + //Not active or initialised + active = false; + init_done = false; ///@todo move all this to initilise() - // Get the MAC addresses (split up in little endian order) - uint64_t MAC0 = MACAddress0Port.read() % 256; - uint64_t MAC1 = MACAddress0Port.read() / 256; - uint64_t MAC2 = MACAddress2Port.read() % 256; - uint64_t MAC3 = MACAddress2Port.read() / 256; - uint64_t MAC4 = MACAddress4Port.read() % 256; - uint64_t MAC5 = MACAddress4Port.read() / 256; - - // Combine MAC addresses into one 48 bit number - ownMAC = MAC5 << 40 - | MAC4 << 32 - | MAC3 << 24 - | MAC2 << 16 - | MAC1 << 8 - | MAC0; - - // Set the device to 32 bit mode - registerAddressPort.write(20); // Tell device to write to register 20 - busControlRegisterDataPort.write(0x102); // write desired data - - // Reset the stop bit (tell device it's not supposed to be reset now) - registerAddressPort.write(0); // Tell device to write to register 0 - registerDataPort.write(0x04); // write desired data - - // Set the initialization block - initBlock.mode = 0x0000; // Promiscuous mode = false ( promiscuous mode tells it to receive all packets, not just broadcasts and those for its own MAC address) - initBlock.reserved1 = 0; // Reserved - initBlock.numSendBuffers = 3; // Means 8 because 2^8 (number of bits used) - initBlock.reserved2 = 0; // Reserved - initBlock.numRecvBuffers = 3; // Means 8 because 2^8 (number of bits used) - initBlock.physicalAddress = ownMAC; // Set the physical address to the MAC address - initBlock.reserved3 = 0; // Reserved - initBlock.logicalAddress = 0; // None for now - - // Set Buffer descriptors memory - sendBufferDescr = (BufferDescriptor*)(MemoryManager::kmalloc((sizeof(BufferDescriptor) * 8) + 15)); // Allocate memory for 8 buffer descriptors - initBlock.sendBufferDescrAddress = (uint64_t)sendBufferDescr; - - recvBufferDescr = (BufferDescriptor*)(MemoryManager::kmalloc((sizeof(BufferDescriptor) * 8) + 15)); // Allocate memory for 8 buffer descriptors - initBlock.recvBufferDescrAddress = (uint64_t)recvBufferDescr; - - for(uint8_t i = 0; i < 8; i++) - { - - // Send buffer descriptors - sendBufferDescr[i].address = (((uint64_t)&sendBuffers[i]) + 15 ) & ~(uint32_t)0xF; // Same as above - sendBufferDescr[i].flags = 0x7FF // Length of descriptor - | 0xF000; // Set it to send buffer - sendBufferDescr[i].flags2 = 0; // "Flags2" shows whether an error occurred while sending and should therefore be set to 0 by the drive - sendBufferDescr[i].avail = 0; // IF it is in use - - // Receive - recvBufferDescr[i].address = (((uint64_t)&recvBuffers[i]) + 15 ) & ~(uint32_t)0xF; // Same as above - recvBufferDescr[i].flags = 0xF7FF // Length of descriptor (This 0xF7FF is what was causing the problem, it used to be 0x7FF) - | 0x80000000; // Set it to receive buffer - recvBufferDescr[i].flags2 = 0; // "Flags2" shows whether an error occurred while sending and should therefore be set to 0 by the drive - recvBufferDescr[i].avail = 0; // IF it is in use - } - - // Move initialization block into device - registerAddressPort.write(1); // Tell device to write to register 1 - registerDataPort.write((uint64_t)(&initBlock) & - 0xFFFF); // write address data - registerAddressPort.write(2); // Tell device to write to register 2 - registerDataPort.write(((uint64_t)(&initBlock) >> 16) & - 0xFFFF); // write shifted address data + // Get the MAC addresses (split up in little endian order) + uint64_t mac_0 = mac_address_0_port.read() % 256; + uint64_t mac_1 = mac_address_0_port.read() / 256; + uint64_t mac_2 = mac_address_2_port.read() % 256; + uint64_t mac_3 = mac_address_2_port.read() / 256; + uint64_t mac_4 = mac_address_4_port.read() % 256; + uint64_t mac_5 = mac_address_4_port.read() / 256; + + // Combine MAC addresses into one 48 bit number + own_mac = mac_5 << 40 + | mac_4 << 32 + | mac_3 << 24 + | mac_2 << 16 + | mac_1 << 8 + | mac_0; + + // Set the device to 32 bit mode + register_address_port.write(20); // Tell device to write to register 20 + bus_control_register_data_port.write(0x102); // write desired data + + // Reset the stop bit (tell device it's not supposed to be reset now) + register_address_port.write(0); // Tell device to write to register 0 + register_data_port.write(0x04); // write desired data + + // Set the initialization block + init_block.mode = 0x0000; // Promiscuous mode = false ( promiscuous mode tells it to receive all packets, not just broadcasts and those for its own MAC address) + init_block.reserved1 = 0; // Reserved + init_block.num_send_buffers = 3; // Means 8 because 2^8 (number of bits used) + init_block.reserved2 = 0; // Reserved + init_block.num_recv_buffers = 3; // Means 8 because 2^8 (number of bits used) + init_block.physical_address = own_mac; // Set the physical address to the MAC address + init_block.reserved3 = 0; // Reserved + init_block.logical_address = 0; // None for now + + // Set Buffer descriptors memory + send_buffer_descr = (BufferDescriptor*) (MemoryManager::kmalloc((sizeof(BufferDescriptor) * 8) + 15)); // Allocate memory for 8 buffer descriptors + init_block.send_buffer_descr_address = (uint64_t) send_buffer_descr; + + recv_buffer_descr = (BufferDescriptor*) (MemoryManager::kmalloc((sizeof(BufferDescriptor) * 8) + 15)); // Allocate memory for 8 buffer descriptors + init_block.recv_buffer_descr_address = (uint64_t) recv_buffer_descr; + + for(uint8_t i = 0; i < 8; i++) { + + // Send buffer descriptors + send_buffer_descr[i].address = (((uint64_t) &send_buffers[i]) + 15) & ~(uint32_t) 0xF; // Same as above + send_buffer_descr[i].flags = + 0x7FF // Length of descriptor + | 0xF000; // Set it to send buffer + send_buffer_descr[i].flags2 = 0; // "Flags2" shows whether an error occurred while sending and should therefore be set to 0 by the drive + send_buffer_descr[i].avail = 0; // IF it is in use + + // Receive + recv_buffer_descr[i].address = (((uint64_t) &recv_buffers[i]) + 15) & ~(uint32_t) 0xF; // Same as above + recv_buffer_descr[i].flags = + 0xF7FF // Length of descriptor (This 0xF7FF is what was causing the problem, it used to be 0x7FF) + | 0x80000000; // Set it to receive buffer + recv_buffer_descr[i].flags2 = 0; // "Flags2" shows whether an error occurred while sending and should therefore be set to 0 by the drive + recv_buffer_descr[i].avail = 0; // IF it is in use + } + + // Move initialization block into device + register_address_port.write(1); // Tell device to write to register 1 + register_data_port.write((uint64_t) (&init_block) & + 0xFFFF); // write address data + register_address_port.write(2); // Tell device to write to register 2 + register_data_port.write(((uint64_t) (&init_block) >> 16) & + 0xFFFF); // write shifted address data } @@ -119,32 +119,30 @@ AMD_AM79C973::AMD_AM79C973(PCIDeviceDescriptor *dev) AMD_AM79C973::~AMD_AM79C973() = default; - /** * @brief This function activates the device and starts it (Runs when the driver-manger calls activateAll()) * * @todo Re-implement this class */ -void AMD_AM79C973::activate() -{ - - return; +void AMD_AM79C973::activate() { - initDone = false; // Set initDone to false - registerAddressPort.write(0); // Tell device to write to register 0 - registerDataPort.write(0x41); // Enable Interrupts and start the device - while(!initDone); // Wait for initDone to be set to true + init_done = false; // Set initDone to false + register_address_port.write(0); // Tell device to write to register 0 + register_data_port.write(0x41); // Enable Interrupts and start the device + while(!init_done); // Wait for initDone to be set to true - registerAddressPort.write(4); // Tell device to read from register 4 - uint32_t temp = registerDataPort.read(); // Get current data + register_address_port.write(4); // Tell device to read from register 4 + uint32_t temp = register_data_port.read(); // Get current data - registerAddressPort.write(4); // Tell device to write to register 4 - registerDataPort.write(temp | 0xC00); // Bitwise OR function on data (This automatically enlarges packets smaller than 64 bytes to that size and removes some relatively superfluous information from received packets.) + register_address_port.write(4); // Tell device to write to register 4 + register_data_port.write(temp | + 0xC00); // Bitwise OR function on data (This automatically enlarges packets smaller than 64 bytes to that size and removes some relatively superfluous information from received packets.) - registerAddressPort.write(0); // Tell device to write to register 0 - registerDataPort.write(0x42); // Tell device that it is initialised and can begin operating + register_address_port.write(0); // Tell device to write to register 0 + register_data_port.write( + 0x42); // Tell device that it is initialised and can begin operating - active = true; // Set active to true + active = true; // Set active to true } /** @@ -154,45 +152,44 @@ void AMD_AM79C973::activate() */ uint32_t AMD_AM79C973::reset() { - resetPort.read(); - resetPort.write(0); - return 10; // 10 means wait for 10ms + reset_port.read(); + reset_port.write(0); + return 10; // 10 means wait for 10ms } - /** * @brief This function handles the interrupt for the device * */ void AMD_AM79C973::handle_interrupt() { - // Similar to PIC, data needs to be read when an interrupt is sent, or it hangs - registerAddressPort.write(0); // Tell device to read from register 0 - uint32_t temp = registerDataPort.read(); // Get current data + // Similar to PIC, data needs to be read when an interrupt is sent, or it hangs + register_address_port.write(0); // Tell device to read from register 0 + uint32_t temp = register_data_port.read(); // Get current data - // Note: Cant be switch case as multiple errors can occur at the same time + // Note: Cant be switch case as multiple errors can occur at the same time - // Errors - if((temp & 0x8000) == 0x8000) - Logger::WARNING() << "AMD am79c973 ERROR: "; - if((temp & 0x2000) == 0x2000) - Logger::WARNING() << "COLLISION ERROR\n"; - if((temp & 0x1000) == 0x1000) - Logger::WARNING() << "MISSED FRAME\n"; - if((temp & 0x0800) == 0x0800) - Logger::WARNING() << "MEMORY ERROR\n"; + // Errors + if((temp & 0x8000) == 0x8000) + Logger::WARNING() << "AMD am79c973 ERROR: "; + if((temp & 0x2000) == 0x2000) + Logger::WARNING() << "COLLISION ERROR\n"; + if((temp & 0x1000) == 0x1000) + Logger::WARNING() << "MISSED FRAME\n"; + if((temp & 0x0800) == 0x0800) + Logger::WARNING() << "MEMORY ERROR\n"; - // Responses - if((temp & 0x0400) == 0x0400) FetchDataReceived(); - if((temp & 0x0200) == 0x0200) FetchDataSent(); - if((temp & 0x0100) == 0x0100) initDone = true;// + // Responses + if((temp & 0x0400) == 0x0400) fetch_data_received(); + if((temp & 0x0200) == 0x0200) fetch_data_sent(); + if((temp & 0x0100) == 0x0100) init_done = true;// - // Reply that it was received - registerAddressPort.write(0); // Tell device to write to register 0 - registerDataPort.write(temp); // Tell device that the interrupt was received + // Reply that it was received + register_address_port.write(0); // Tell device to write to register 0 + register_data_port.write(temp); // Tell device that the interrupt was received } @@ -208,81 +205,87 @@ void AMD_AM79C973::handle_interrupt() { * @param buffer The buffer to send * @param size The size of the buffer */ -void AMD_AM79C973::DoSend(uint8_t *buffer, uint32_t size) { +void AMD_AM79C973::do_send(uint8_t* buffer, uint32_t size) { - while(!active); + while(!active); - int sendDescriptor = currentSendBuffer; // Get where data has been written to - currentSendBuffer = (currentSendBuffer + 1) % 8; // Move send buffer to next send buffer (div by 8 so that it is cycled) (this allows for data to be sent from different m_tasks in parallel) + int send_descriptor = current_send_buffer; // Get where data has been written to + current_send_buffer = (current_send_buffer + 1) % + 8; // Move send buffer to next send buffer (div by 8 so that it is cycled) (this allows for data to be sent from different m_tasks in parallel) - if(size > 1518){ // If attempt to send more than 1518 bytes at once it will be too large - size = 1518; // Discard all data after that (Generally if data is bigger than that at driver level then a higher up network layer must have made a mistake) + if(size > + 1518) { // If attempt to send more than 1518 bytes at once it will be too large + size = 1518; // Discard all data after that (Generally if data is bigger than that at driver level then a higher up network layer must have made a mistake) - } + } - // What this loop does is copy the information passed as the parameter buffer (src) to the send buffer in the ram (dst) which the card will then use to send the data - for (uint8_t *src = buffer + size -1, // Set src pointer to the end of the data that is being sent - *dst = (uint8_t*)(sendBufferDescr[sendDescriptor].address + size -1); // Take the buffer that has been selected - src >= buffer; // While there is still information in the buffer that hasn't been written to src - src--,dst-- // Move 2 pointers to the end of the buffers - ) - { - *dst = *src; // Copy data from source buffer to destination buffer - } + // What this loop does is copy the information passed as the parameter buffer (src) to the send buffer in the ram (dst) which the card will then use to send the data + for(uint8_t* src = buffer + size - + 1, // Set src pointer to the end of the data that is being sent + * dst = (uint8_t*) (send_buffer_descr[send_descriptor].address + size - + 1); // Take the buffer that has been selected + src >= + buffer; // While there is still information in the buffer that hasn't been written to src + src--, dst-- // Move 2 pointers to the end of the buffers + ) { + *dst = *src; // Copy data from source buffer to destination buffer + } - sendBufferDescr[sendDescriptor].avail = 0; // Set that this buffer is in use - sendBufferDescr[sendDescriptor].flags2 = 0; // Clear any previous error messages - sendBufferDescr[sendDescriptor].flags = 0x8300F000 // Encode the size of what is being sent - | ((uint16_t)((-size) & 0xFFF)); + send_buffer_descr[send_descriptor].avail = 0; // Set that this buffer is in use + send_buffer_descr[send_descriptor].flags2 = 0; // Clear any previous error messages + send_buffer_descr[send_descriptor].flags = 0x8300F000 // Encode the size of what is being sent + | ((uint16_t) ((-size) & 0xFFF)); - registerAddressPort.write(0); // Tell device to write to register 0 - registerDataPort.write( - 0x48); // Tell device to send the data currently in the buffer + register_address_port.write(0); // Tell device to write to register 0 + register_data_port.write( + 0x48); // Tell device to send the data currently in the buffer } -void AMD_AM79C973::FetchDataReceived() -{ - - for(;(recvBufferDescr[currentRecvBuffer].flags & 0x80000000) == 0; currentRecvBuffer = (currentRecvBuffer+1)%8) //Loop through all the buffers - { - if(!(recvBufferDescr[currentRecvBuffer].flags & 0x40000000) //Check if there is an error - && (recvBufferDescr[currentRecvBuffer].flags & 0x03000000) == 0x03000000) //Check start and end bits of the packet - { - uint32_t size = recvBufferDescr[currentRecvBuffer].flags2 & 0xFFF; //Get the size of the packet - if (size > 64) //If the size is the size of ethernet 2 frame - size -= 4; //remove the checksum - - auto* buffer = (uint8_t*)(recvBufferDescr[currentRecvBuffer].address); //Get the buffer - FireDataReceived(buffer, size); //Pass data to handler - } - - recvBufferDescr[currentRecvBuffer].flags2 = 0; //write that the data has been read and can now be used again - recvBufferDescr[currentRecvBuffer].flags = 0x8000F7FF; //Clear the buffer - } +void AMD_AM79C973::fetch_data_received() { + + for(; (recv_buffer_descr[current_recv_buffer].flags & 0x80000000) == 0; current_recv_buffer = + (current_recv_buffer + 1) % + 8) //Loop through all the buffers + { + if(!(recv_buffer_descr[current_recv_buffer].flags & 0x40000000) //Check if there is an error + && (recv_buffer_descr[current_recv_buffer].flags & 0x03000000) == + 0x03000000) //Check start and end bits of the packet + { + uint32_t size = recv_buffer_descr[current_recv_buffer].flags2 & 0xFFF; //Get the size of the packet + if(size > + 64) //If the size is the size of ethernet 2 frame + size -= 4; //remove the checksum + + auto* buffer = (uint8_t*) (recv_buffer_descr[current_recv_buffer].address); //Get the buffer + fire_data_received(buffer, size); //Pass data to handler + } + + recv_buffer_descr[current_recv_buffer].flags2 = 0; //write that the data has been read and can now be used again + recv_buffer_descr[current_recv_buffer].flags = 0x8000F7FF; //Clear the buffer + } } -void AMD_AM79C973::FetchDataSent() -{ +void AMD_AM79C973::fetch_data_sent() { - /* - for(;(recvBufferDescr[currentRecvBuffer].flags & 0x80000000) == 0; currentRecvBuffer = (currentRecvBuffer+1)%8) - { - if(!(recvBufferDescr[currentRecvBuffer].flags & 0x40000000) - && (recvBufferDescr[currentRecvBuffer].flags & 0x03000000) == 0x03000000) - { - uint32_t size = recvBufferDescr[currentRecvBuffer].flags2 & 0xFFF; - if (size > 64) - size -= 4; + /* + for(;(recvBufferDescr[currentRecvBuffer].flags & 0x80000000) == 0; currentRecvBuffer = (currentRecvBuffer+1)%8) + { + if(!(recvBufferDescr[currentRecvBuffer].flags & 0x40000000) + && (recvBufferDescr[currentRecvBuffer].flags & 0x03000000) == 0x03000000) + { + uint32_t size = recvBufferDescr[currentRecvBuffer].flags2 & 0xFFF; + if (size > 64) + size -= 4; - uint8_t* buffer = (uint8_t*)(recvBufferDescr[currentRecvBuffer].address); - FireDataSent(buffer, size); - } + uint8_t* buffer = (uint8_t*)(recvBufferDescr[currentRecvBuffer].address); + FireDataSent(buffer, size); + } - recvBufferDescr[currentRecvBuffer].flags2 = 0; - recvBufferDescr[currentRecvBuffer].flags = 0x8000F7FF; - } - */ + recvBufferDescr[currentRecvBuffer].flags2 = 0; + recvBufferDescr[currentRecvBuffer].flags = 0x8000F7FF; + } + */ } @@ -292,9 +295,9 @@ void AMD_AM79C973::FetchDataSent() * * @return The MAC address */ -uint64_t AMD_AM79C973::GetMediaAccessControlAddress() { - while(ownMAC == 0); - return ownMAC; +uint64_t AMD_AM79C973::get_media_access_control_address() { + while(own_mac == 0); + return own_mac; } void AMD_AM79C973::deactivate() { @@ -302,11 +305,11 @@ void AMD_AM79C973::deactivate() { } string AMD_AM79C973::vendor_name() { - return "AMD"; + return "AMD"; } string AMD_AM79C973::device_name() { - return "PCnet-Fast III (Am79C973)"; + return "PCnet-Fast III (Am79C973)"; } diff --git a/kernel/src/drivers/ethernet/ethernet.cpp b/kernel/src/drivers/ethernet/ethernet.cpp index 36404e40..409a39e5 100644 --- a/kernel/src/drivers/ethernet/ethernet.cpp +++ b/kernel/src/drivers/ethernet/ethernet.cpp @@ -26,7 +26,7 @@ EthernetDriverEventHandler::~EthernetDriverEventHandler() = default; * @param size The size of the buffer * @return True if the data should be sent back, false otherwise */ -bool EthernetDriverEventHandler::DataReceived(uint8_t* buffer, uint32_t size) { +bool EthernetDriverEventHandler::data_received(uint8_t* buffer, uint32_t size) { return false; } @@ -36,7 +36,7 @@ bool EthernetDriverEventHandler::DataReceived(uint8_t* buffer, uint32_t size) { * @param buffer The buffer to handle * @param size The size of the buffer */ -void EthernetDriverEventHandler::BeforeSend(uint8_t* buffer, uint32_t size) { +void EthernetDriverEventHandler::before_send(uint8_t* buffer, uint32_t size) { } /** @@ -45,7 +45,7 @@ void EthernetDriverEventHandler::BeforeSend(uint8_t* buffer, uint32_t size) { * @param buffer The buffer to handle * @param size The size of the buffer */ -void EthernetDriverEventHandler::DataSent(uint8_t* buffer, uint32_t size) { +void EthernetDriverEventHandler::data_sent(uint8_t* buffer, uint32_t size) { } /** @@ -59,16 +59,16 @@ Event* EthernetDriverEventHandler::on_event(Eventtype) { case EthernetDriverEvents::BEFORE_SEND: - BeforeSend(((BeforeSendEvent*) event)->buffer, ((BeforeSendEvent*) event)->size); + before_send(((BeforeSendEvent*) event)->buffer, ((BeforeSendEvent*) event)->size); break; case EthernetDriverEvents::DATA_SENT: - DataSent(((DataSentEvent*) event)->buffer, ((DataSentEvent*) event)->size); + data_sent(((DataSentEvent*) event)->buffer, ((DataSentEvent*) event)->size); break; case EthernetDriverEvents::DATA_RECEIVED: - event->return_value.boolValue = DataReceived(((DataReceivedEvent*) event)->buffer, - ((DataReceivedEvent*) event)->size); + event->return_value.bool_value = data_received(((DataReceivedEvent*) event)->buffer, + ((DataReceivedEvent*) event)->size); break; default: @@ -86,31 +86,31 @@ EthernetDriver::~EthernetDriver() = default; * * @return the MAC address */ -MediaAccessControlAddress EthernetDriver::GetMediaAccessControlAddress() { +MediaAccessControlAddress EthernetDriver::get_media_access_control_address() { return 0; } /** - * @brief Send data to the network via the driver backend + * @brief send data to the network via the driver backend * * @param buffer The buffer to send * @param size The size of the buffer */ -void EthernetDriver::Send(uint8_t* buffer, uint32_t size) { +void EthernetDriver::send(uint8_t* buffer, uint32_t size) { // Raise the event raise_event(new BeforeSendEvent(buffer, size)); - DoSend(buffer, size); + do_send(buffer, size); } /** - * @brief (Device Side) Send the data + * @brief (Device Side) send the data * * @param buffer The buffer to handle * @param size The size of the buffer */ -void EthernetDriver::DoSend(uint8_t* buffer, uint32_t size) { +void EthernetDriver::do_send(uint8_t* buffer, uint32_t size) { } /** @@ -119,7 +119,7 @@ void EthernetDriver::DoSend(uint8_t* buffer, uint32_t size) { * @param buffer The buffer to handle * @param size The size of the buffer */ -void EthernetDriver::FireDataReceived(uint8_t* buffer, uint32_t size) { +void EthernetDriver::fire_data_received(uint8_t* buffer, uint32_t size) { // Raise the event Vector*> values = @@ -129,8 +129,8 @@ void EthernetDriver::FireDataReceived(uint8_t* buffer, uint32_t size) { for (auto &value : values) { switch (value->type) { case EthernetDriverEvents::DATA_RECEIVED: - if (value->return_value.boolValue) - Send(buffer, size); + if (value->return_value.bool_value) + send(buffer, size); break; default: @@ -140,12 +140,12 @@ void EthernetDriver::FireDataReceived(uint8_t* buffer, uint32_t size) { } /** - * @brief Send data + * @brief send data * * @param buffer The buffer to send * @param size The size of the buffer */ -void EthernetDriver::FireDataSent(uint8_t* buffer, uint32_t size) { +void EthernetDriver::fire_data_sent(uint8_t* buffer, uint32_t size) { raise_event(new DataSentEvent(buffer, size)); } @@ -162,7 +162,7 @@ void EthernetDriver::FireDataSent(uint8_t* buffer, uint32_t size) { * @param digit6 The last digit * @return The MAC address */ -MediaAccessControlAddress EthernetDriver::CreateMediaAccessControlAddress(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4, uint8_t digit5, uint8_t digit6) { +MediaAccessControlAddress EthernetDriver::create_media_access_control_address(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4, uint8_t digit5, uint8_t digit6) { return // digit6 is the most significant byte (uint64_t) digit6 << 40 | (uint64_t) digit5 << 32 @@ -203,7 +203,7 @@ DataReceivedEvent::~DataReceivedEvent() = default; /** - * @brief Construct a new Before Send Event object + * @brief Construct a new Before send Event object * * @param buffer The buffer to send * @param size The size of the buffer diff --git a/kernel/src/drivers/ethernet/intel_i217.cpp b/kernel/src/drivers/ethernet/intel_i217.cpp index 7651d96d..db2ddf67 100644 --- a/kernel/src/drivers/ethernet/intel_i217.cpp +++ b/kernel/src/drivers/ethernet/intel_i217.cpp @@ -28,56 +28,54 @@ using namespace memory; /** * @brief Constructs a new Intel I217 Ethernet driver. Gets the MAC address and clears the receive descriptor array * - * @param deviceDescriptor The PCI device descriptor for this device + * @param device_descriptor The PCI device descriptor for this device */ -IntelI217::IntelI217(PCIDeviceDescriptor *deviceDescriptor) -: InterruptHandler(0x20 + deviceDescriptor->interrupt) -{ +IntelI217::IntelI217(PCIDeviceDescriptor* device_descriptor) + : InterruptHandler(0x20 + device_descriptor->interrupt) { - //Set the registers - controlRegister = 0x0000; - statusRegister = 0x0008; - epromRegister = 0x0014; - controlExtRegister = 0x0018; - interruptMaskRegister = 0x00D0; + //Set the registers + control_register = 0x0000; + status_register = 0x0008; + eprom_register = 0x0014; + control_ext_register = 0x0018; + interrupt_mask_register = 0x00D0; - receiveControlRegister = 0x0100; - receiveDescriptorLowRegister = 0x2800; - receiveDescriptorHighRegister = 0x2804; - receiveDescriptorLengthRegister = 0x2808; - receiveDescriptorHeadRegister = 0x2810; - receiveDescriptorTailRegister = 0x2818; + receive_control_register = 0x0100; + receive_descriptor_low_register = 0x2800; + receive_descriptor_high_register = 0x2804; + receive_descriptor_length_register = 0x2808; + receive_descriptor_head_register = 0x2810; + receive_descriptor_tail_register = 0x2818; - sendControlRegister = 0x0400; - sendDescriptorLowRegister = 0x3800; - sendDescriptorHighRegister = 0x3804; - sendDescriptorLengthRegister = 0x3808; - sendDescriptorHeadRegister = 0x3810; - sendDescriptorTailRegister = 0x3818; + send_control_register = 0x0400; + send_descriptor_low_register = 0x3800; + send_descriptor_high_register = 0x3804; + send_descriptor_length_register = 0x3808; + send_descriptor_head_register = 0x3810; + send_descriptor_tail_register = 0x3818; - // Get BAR0 type, io_base address and MMIO base address - bar_type = 1; // deviceDescriptor -> has_memory_base ? 0 : 1; @todo Fix memory mapping from PCI as it is unable to get MAC from memory - portBase = deviceDescriptor ->port_base; - //TODO: memBase = deviceDescriptor -> memory_base; + // Get BAR0 type, io_base address and MMIO base address + bar_type = 1; // deviceDescriptor -> has_memory_base ? 0 : 1; @todo Fix memory mapping from PCI as it is unable to get MAC from memory + port_base = device_descriptor->port_base; + //TODO: memBase = deviceDescriptor -> memory_base; - initDone = false; - active = false; + init_done = false; + active = false; - //Clear eprom - epromPresent = false; + // Clear eprom + eprom_present = detect_ee_prom(); - //Detect eprom - detectEEProm (); - if (readMACAddress()){ - ownMAC = CreateMediaAccessControlAddress(macAddress[0], macAddress[1], macAddress[2], macAddress[3], macAddress[4], macAddress[5]); + if (read_mac_address()) { + own_mac = create_media_access_control_address(mac_address[0], mac_address[1], mac_address[2], mac_address[3], + mac_address[4], mac_address[5]); - }else{ - ASSERT(false, "ERROR, INIT FAILED, MAC ADDRESS NOT FOUND"); - } + } else { + ASSERT(false, "ERROR, INIT FAILED, MAC ADDRESS NOT FOUND"); + } - for(int i = 0; i < 0x80; i++) //Loop through all the registers - Write(0x5200 + i*4, 0); //Clear the receive descriptor array + for (int i = 0; i < 0x80; i++) //Loop through all the registers + write(0x5200 + i * 4, 0); //Clear the receive descriptor array @@ -87,311 +85,319 @@ IntelI217::IntelI217(PCIDeviceDescriptor *deviceDescriptor) IntelI217::~IntelI217() = default; -void IntelI217::Write(uint16_t address, uint32_t data) const { +void IntelI217::write(uint16_t address, uint32_t data) const { - //Note: These Ports/MemIO cant be init in the constructor like they normally would as it depends on wether the device is using IO or MemIO, and checking that in every function would be messy + //Note: These Ports/MemIO cant be init in the constructor like they normally would as it depends on wether the device is using IO or MemIO, and checking that in every function would be messy - if(bar_type == 0) { // If the base address register is memory mapped + if (bar_type == 0) { // If the base address register is memory mapped - MemIO32Bit dataMem(memBase + address); // Create a 32-bit memory class at the address - dataMem.write(data); // write the data to the memory address + MemIO32Bit data_mem(mem_base + address); // Create a 32-bit memory class at the address + data_mem.write(data); // write the data to the memory address - } else { + } else { - Port32Bit commandPort(portBase); // Create a 32 bit port at the address - Port32Bit dataPort(portBase + 4); // Create a 32 bit port at the address + 4 + Port32Bit command_port(port_base); // Create a 32 bit port at the address + Port32Bit data_port(port_base + 4); // Create a 32 bit port at the address + 4 - commandPort.write(address); // write the address to the command port - dataPort.write(data); // write the data to the data port + command_port.write(address); // write the address to the command port + data_port.write(data); // write the data to the data port - } + } } -uint32_t IntelI217::Read(uint16_t address) const { +uint32_t IntelI217::read(uint16_t address) const { - //Note: These Ports/MemIO cant be init in the constructor like they normally would as it depends on wether the device is using IO or MemIO, and checking that in every function would be messy - if(bar_type == 0) { // If the base address register is memory mapped + //Note: These Ports/MemIO cant be init in the constructor like they normally would as it depends on wether the device is using IO or MemIO, and checking that in every function would be messy + if (bar_type == 0) { // If the base address register is memory mapped - MemIO32Bit dataMem(memBase + address); // Create a 32-bit memory class at the address - return dataMem.read(); // read the data from the memory address + MemIO32Bit data_mem(mem_base + address); // Create a 32-bit memory class at the address + return data_mem.read(); // read the data from the memory address - } else{ + } else { - Port32Bit commandPort(portBase); // Create a 32 bit port at the address - Port32Bit dataPort(portBase + 4); // Create a 32 bit port at the address + 4 + Port32Bit command_port(port_base); // Create a 32 bit port at the address + Port32Bit data_port(port_base + 4); // Create a 32 bit port at the address + 4 - commandPort.write(address); // write the address to the command port - return dataPort.read(); // read the data from the data port + command_port.write(address); // write the address to the command port + return data_port.read(); // read the data from the data port - } + } } -bool IntelI217::detectEEProm() { +bool IntelI217::detect_ee_prom() { - uint32_t val = 0; // The value to be returned - Write(epromRegister, 0x1); // Set the register to read the EEProm + uint32_t val = 0; // The value to be returned + write(eprom_register, 0x1); // Set the register to read the EEProm - for(int i = 0; i < 1000 && !epromPresent; i++) //Loop 1000 times or until the EEProm is detected - { - val = Read( 0x0014); // read the register + for (int i = 0; i < 1000; i++) //Loop 1000 times or until the EEProm is detected + { + val = read(0x0014); // read the register - if(val & 0x10) // If the EEProm is detected - epromPresent = true; - else // If the EEProm is not detected - epromPresent = false; - } - return epromPresent; -} + if (val & 0x10) + return true; -uint32_t IntelI217::eepromRead( uint8_t addr) -{ - uint16_t data = 0; // The data to be returned - uint32_t tmp = 0; // A temporary variable - if ( epromPresent) // If the EEProm is detected - { - Write( epromRegister, (1) | ((uint32_t)(addr) << 8) ); // write the address to the register - while( !((tmp = Read(epromRegister)) & (1 << 4)) ); // Wait for the EEProm to be ready - } - else - { - Write( epromRegister, (1) | ((uint32_t)(addr) << 2) ); // write the address to the register - while( !((tmp = Read(epromRegister)) & (1 << 1)) ); // Wait for the EEProm to be ready - } - data = (uint16_t)((tmp >> 16) & 0xFFFF); // Get the data from the register - return data; // Return the data + } + return false; } -bool IntelI217::readMACAddress() { - if ( epromPresent) //If the EPROM exists - { - uint32_t temp; - - temp = eepromRead(0); //read the m_first_memory_chunk 16 bits of the MAC address - macAddress[0] = temp &0xff; //Get the m_first_memory_chunk 8 bits of the MAC address - macAddress[1] = temp >> 8; //Get the second 8 bits of the MAC address - - temp = eepromRead( 1); //read the second 16 bits of the MAC address - macAddress[2] = temp &0xff; //Get the third 8 bits of the MAC address - macAddress[3] = temp >> 8; //Get the fourth 8 bits of the MAC address - - temp = eepromRead( 2); //read the third 16 bits of the MAC address - macAddress[4] = temp &0xff; //Get the fifth 8 bits of the MAC address - macAddress[5] = temp >> 8; //Get the sixth 8 bits of the MAC address - } - else //If there is no eprom then read from memory - { - - - auto * mem_base_mac_8 = (uint8_t *) (memBase+0x5400); //Get the base address of the MAC address - auto * mem_base_mac_32 = (uint32_t *) (memBase+0x5400); //Get the base address of the MAC address - - if ( mem_base_mac_32[0] != 0 ) - { - for(int i = 0; i < 6; i++) //Loop through the MAC address - macAddress[i] = mem_base_mac_8[i]; //Get the MAC address +uint32_t IntelI217::eeprom_read(uint8_t addr) { + uint16_t data = 0; // The data to be returned + uint32_t tmp = 0; // A temporary variable + if (eprom_present) // If the EEProm is detected + { + write(eprom_register, (1) | ((uint32_t) (addr) << 8)); // write the address to the register + while (!((tmp = read(eprom_register)) & (1 << 4))); // Wait for the EEProm to be ready + } else { + write(eprom_register, (1) | ((uint32_t) (addr) << 2)); // write the address to the register + while (!((tmp = read(eprom_register)) & (1 << 1))); // Wait for the EEProm to be ready + } + data = (uint16_t) ((tmp >> 16) & 0xFFFF); // Get the data from the register + return data; // Return the data +} - } - else return false; - } - return true; +bool IntelI217::read_mac_address() { + if (eprom_present) //If the EPROM exists + { + uint32_t temp; + + temp = eeprom_read( + 0); //read the m_first_memory_chunk 16 bits of the MAC address + mac_address[0] = temp & + 0xff; //Get the m_first_memory_chunk 8 bits of the MAC address + mac_address[1] = + temp >> 8; //Get the second 8 bits of the MAC address + + temp = eeprom_read( + 1); //read the second 16 bits of the MAC address + mac_address[2] = + temp & 0xff; //Get the third 8 bits of the MAC address + mac_address[3] = + temp >> 8; //Get the fourth 8 bits of the MAC address + + temp = eeprom_read( + 2); //read the third 16 bits of the MAC address + mac_address[4] = + temp & 0xff; //Get the fifth 8 bits of the MAC address + mac_address[5] = + temp >> 8; //Get the sixth 8 bits of the MAC address + } else //If there is no eprom then read from memory + { + + + auto* mem_base_mac_8 = (uint8_t*) (mem_base + + 0x5400); //Get the base address of the MAC address + auto* mem_base_mac_32 = (uint32_t*) (mem_base + 0x5400); //Get the base address of the MAC address + + if (mem_base_mac_32[0] != 0) { + for (int i = 0; i < 6; i++) //Loop through the MAC address + mac_address[i] = mem_base_mac_8[i]; //Get the MAC address + + } else return false; + } + return true; } -void IntelI217::receiveInit() { +void IntelI217::receive_init() { - uint8_t * ptr; //A pointer to the memory - receive_descriptor_t*descs; //A pointer to the receive descriptors - ptr = (uint8_t *)(MemoryManager::kmalloc(sizeof(receive_descriptor_t)*32 + 16)); //Allocate memory for the receive descriptors - descs = (receive_descriptor_t*)ptr; //Set the pointer to the receive descriptors + uint8_t* ptr; //A pointer to the memory + receive_descriptor_t* descs; //A pointer to the receive descriptors + ptr = (uint8_t*) (MemoryManager::kmalloc( + sizeof(receive_descriptor_t) * 32 + 16)); //Allocate memory for the receive descriptors + descs = (receive_descriptor_t*) ptr; //Set the pointer to the receive descriptors - for(int i = 0; i < 32; i++) - { - receiveDsrctrs[i] = (receive_descriptor_t*)((uint8_t *)descs + i*16); - receiveDsrctrs[i] -> bufferAddress = (uint64_t)(uint8_t *)(MemoryManager::kmalloc(8192 + 16)); - receiveDsrctrs[i] -> status = 0; - } + for (int i = 0; i < 32; i++) { + receive_dsrctrs[i] = (receive_descriptor_t*) ((uint8_t*) descs + i * 16); + receive_dsrctrs[i]->buffer_address = (uint64_t) (uint8_t*) (MemoryManager::kmalloc(8192 + 16)); + receive_dsrctrs[i]->status = 0; + } - //write the send descriptor list address to the register - Write(sendDescriptorLowRegister, (uint32_t)((uint64_t)ptr >> 32) ); - Write(sendDescriptorHighRegister, (uint32_t)((uint64_t)ptr & 0xFFFFFFFF)); + //write the send descriptor list address to the register + write(send_descriptor_low_register, (uint32_t) ((uint64_t) ptr >> 32)); + write(send_descriptor_high_register, (uint32_t) ((uint64_t) ptr & 0xFFFFFFFF)); - //write the receive descriptor list address to the register - Write(receiveDescriptorLowRegister, (uint64_t)ptr); - Write(receiveDescriptorHighRegister, 0); + //write the receive descriptor list address to the register + write(receive_descriptor_low_register, (uint64_t) ptr); + write(receive_descriptor_high_register, 0); - //Set the receive descriptor list length - Write(receiveDescriptorLengthRegister, 32 * 16); + //Set the receive descriptor list length + write(receive_descriptor_length_register, 32 * 16); - Write(receiveDescriptorHeadRegister, 0); //Set the head to 0 - Write(receiveDescriptorTailRegister, 32-1); //Set the tail to 32-1 + write(receive_descriptor_head_register, + 0); //Set the head to 0 + write(receive_descriptor_tail_register, + 32 - 1); //Set the tail to 32-1 - currentReceiveBuffer = 0; //Set the current receive buffer to 0 + current_receive_buffer = 0; //Set the current receive buffer to 0 - Write(receiveControlRegister, (1 << 1) // Receiver Enable - | (1 << 2) // Store Bad Packets - | (1 << 3) // Uni cast Promiscuous Enabled - | (1 << 4) // Multicast Promiscuous Enabled - | (0 << 6) // No Loop back - | (0 << 8) // Free Buffer Threshold is 1/2 of RDLEN - | (1 << 15) // Broadcast Accept Mode - | (1 << 26) // Strip Ethernet CRC - | buffer8192 - ); + write(receive_control_register, (1 << 1) // Receiver Enable + | (1 << 2) // Store Bad Packets + | (1 << 3) // Uni cast Promiscuous Enabled + | (1 << 4) // Multicast Promiscuous Enabled + | (0 << 6) // No Loop back + | (0 << 8) // Free Buffer Threshold is 1/2 of RDLEN + | (1 << 15) // Broadcast Accept Mode + | (1 << 26) // Strip Ethernet CRC + | buffer8192 + ); + + delete ptr; } -void IntelI217::sendInit() { +void IntelI217::send_init() { - uint8_t * ptr; //A pointer to the memory + uint8_t* ptr; //A pointer to the memory send_descriptor_t* descs; //A pointer to the send descriptors - ptr = (uint8_t *)(MemoryManager::kmalloc(sizeof(send_descriptor_t)*8 + 16)); //Allocate memory for the send descriptors - descs = (send_descriptor_t*)ptr; //Set the pointer to the send descriptors + ptr = (uint8_t*) (MemoryManager::kmalloc( + sizeof(send_descriptor_t) * 8 + 16)); //Allocate memory for the send descriptors + descs = (send_descriptor_t*) ptr; //Set the pointer to the send descriptors + + for (int i = 0; i < 8; i++) { + send_dsrctrs[i] = (send_descriptor_t*) ((uint8_t*) descs + i * 16); + send_dsrctrs[i]->buffer_address = 0; + send_dsrctrs[i]->cmd = 0; + send_dsrctrs[i]->status = (1 << 0); // Descriptor Done + } - for(int i = 0; i < 8; i++) - { - sendDsrctrs[i] = (send_descriptor_t*)((uint8_t*)descs + i*16); - sendDsrctrs[i] -> bufferAddress = 0; - sendDsrctrs[i] -> cmd = 0; - sendDsrctrs[i] -> status = (1 << 0); // Descriptor Done - } + //write the send descriptor list address to the register + write(send_descriptor_high_register, (uint32_t) ((uint64_t) ptr >> 32)); + write(send_descriptor_low_register, (uint32_t) ((uint64_t) ptr & 0xFFFFFFFF)); - //write the send descriptor list address to the register - Write(sendDescriptorHighRegister, (uint32_t)((uint64_t)ptr >> 32) ); - Write(sendDescriptorLowRegister, (uint32_t)((uint64_t)ptr & 0xFFFFFFFF)); + //now setup total length of descriptors + write(send_descriptor_length_register, 8 * 16); - //now setup total length of descriptors - Write(sendDescriptorLengthRegister, 8 * 16); + //setup numbers + write(send_descriptor_head_register, 0); + write(send_descriptor_tail_register, 0); - //setup numbers - Write( sendDescriptorHeadRegister, 0); - Write( sendDescriptorTailRegister, 0); + current_send_buffer = 0; - currentSendBuffer = 0; + write(send_control_register, (1 << 1) // Transmit Enable + | (1 << 3) // Pad Short Packets + | (15 << 4) // Collision Threshold + | (64 << 12) // Collision Distance + | (1 << 24) // Re-transmit on Late Collision + ); - Write(sendControlRegister, (1 << 1) // Transmit Enable - | (1 << 3) // Pad Short Packets - | (15 << 4) // Collision Threshold - | (64 << 12) // Collision Distance - | (1 << 24) // Re-transmit on Late Collision - ); + // In the case of I217 (id = 0x0410) and 82577LM (id = 0x10EA) packets will not be sent if the TCTRL is not configured using the following bits. + // write(sendControlRegister, 0b0110000000000111111000011111010); + //write(0x0410, 0x0060200A); - // In the case of I217 (id = 0x0410) and 82577LM (id = 0x10EA) packets will not be sent if the TCTRL is not configured using the following bits. - // write(sendControlRegister, 0b0110000000000111111000011111010); - //write(0x0410, 0x0060200A); + delete ptr; } void IntelI217::activate() { - //Enable interrupts - Write(interruptMaskRegister ,0x1F6DC); //Enable all interrupts - Write(interruptMaskRegister ,0xff & ~4); //Enable all interrupts except link status change - Read(0xc0); //Clear all interrupts + //Enable interrupts + write(interrupt_mask_register, 0x1F6DC); //Enable all interrupts + write(interrupt_mask_register, 0xff & ~4); //Enable all interrupts except link status change + read(0xc0); //Clear all interrupts - //while (!initDone); //Wait for the init to be done + //while (!initDone); //Wait for the init to be done - //Initialise the send and receive descriptors - receiveInit(); - sendInit(); + //Initialise the send and receive descriptors + receive_init(); + send_init(); - active = true; // Set active to true + active = true; // Set active to true } void IntelI217::handle_interrupt() { - Write(interruptMaskRegister, 0x1); //Clear the interrupt or it will hang - uint32_t temp = Read(0xc0); //read the interrupt status register + write(interrupt_mask_register, 0x1); //Clear the interrupt or it will hang + uint32_t temp = read(0xc0); //read the interrupt status register - // if(temp & 0x04) - // m_driver_message_stream-> write("INTEL i217 START LINK");//initDone = true; - // - // if(temp & 0x10) - // m_driver_message_stream-> write("INTEL i217 GOOD THRESHOLD"); + // if(temp & 0x04) + // m_driver_message_stream-> write("INTEL i217 START LINK");//initDone = true; + // + // if(temp & 0x10) + // m_driver_message_stream-> write("INTEL i217 GOOD THRESHOLD"); - if(temp & 0x80) FetchDataReceived(); + if (temp & 0x80) fetch_data_received(); } -void IntelI217::FetchDataReceived() { +void IntelI217::fetch_data_received() { - uint16_t old_cur; + uint16_t old_cur; - while((receiveDsrctrs[currentReceiveBuffer] -> status & 0x1)) - { - auto *buffer = (uint8_t *)receiveDsrctrs[currentReceiveBuffer] -> bufferAddress; - uint16_t size = receiveDsrctrs[currentReceiveBuffer] -> length; + while ((receive_dsrctrs[current_receive_buffer]->status & 0x1)) { + auto* buffer = (uint8_t*) receive_dsrctrs[current_receive_buffer]->buffer_address; + uint16_t size = receive_dsrctrs[current_receive_buffer]->length; - if(size > 64){ // If the size is the size of ethernet 2 frame - size -= 4; // remove the checksum - } + if (size > 64) { // If the size is the size of ethernet 2 frame + size -= 4; // remove the checksum + } - FireDataReceived(buffer, size); //Pass data to handler + fire_data_received(buffer, size); //Pass data to handler - receiveDsrctrs[currentReceiveBuffer]->status = 0; + receive_dsrctrs[current_receive_buffer]->status = 0; - old_cur = currentReceiveBuffer; //Save the current receive buffer - currentReceiveBuffer = (currentReceiveBuffer + 1) % 32; //Increment the current receive buffer + old_cur = current_receive_buffer; //Save the current receive buffer + current_receive_buffer = (current_receive_buffer + 1) % 32; //Increment the current receive buffer - Write(receiveDescriptorTailRegister, old_cur ); //write the old current receive buffer to the tail register - } + write(receive_descriptor_tail_register, old_cur); //write the old current receive buffer to the tail register + } } -void IntelI217::DoSend(uint8_t* buffer, uint32_t size) { +void IntelI217::do_send(uint8_t* buffer, uint32_t size) { - while(!active); + while (!active); - //Put params into send buffer - sendDsrctrs[currentSendBuffer] -> bufferAddress = (uint64_t)buffer; - sendDsrctrs[currentSendBuffer] -> length = size; + //Put params into send buffer + send_dsrctrs[current_send_buffer]->buffer_address = (uint64_t) buffer; + send_dsrctrs[current_send_buffer]->length = size; - //Set the commands - sendDsrctrs[currentSendBuffer] -> cmd = (1 << 0) // End of Packet - | (1 << 1) // Insert FCS - | (1 << 3) // Report Status - ; + //Set the commands + send_dsrctrs[current_send_buffer]->cmd = (1 << 0) // End of Packet + | (1 << 1) // Insert FCS + | (1 << 3) // Report Status + ; - sendDsrctrs[currentSendBuffer] -> status = 0; + send_dsrctrs[current_send_buffer]->status = 0; - uint8_t old_cur = currentSendBuffer; //Save the current send buffer - currentSendBuffer = (currentSendBuffer + 1) % 8; //Increment the current send buffer - Write(sendDescriptorTailRegister, currentSendBuffer); //write the current send buffer to the tail register + uint8_t old_cur = current_send_buffer; //Save the current send buffer + current_send_buffer = (current_send_buffer + 1) % 8; //Increment the current send buffer + write(send_descriptor_tail_register, current_send_buffer); //write the current send buffer to the tail register - //Wait for the packet to be sent - while(!(sendDsrctrs[old_cur]->status & 0xff)); + //Wait for the packet to be sent + while (!(send_dsrctrs[old_cur]->status & 0xff)); } -uint64_t IntelI217::GetMediaAccessControlAddress() { - while(ownMAC == 0); - return ownMAC; +uint64_t IntelI217::get_media_access_control_address() { + while (own_mac == 0); + return own_mac; } uint32_t IntelI217::reset() { - return Driver::reset(); + return Driver::reset(); } void IntelI217::deactivate() { - Driver::deactivate(); + Driver::deactivate(); } string IntelI217::vendor_name() { - return "Intel"; + return "Intel"; } string IntelI217::device_name() { - return "E1000 (i217)"; + return "E1000 (i217)"; } diff --git a/kernel/src/drivers/ethernet/rawdatahandler.cpp b/kernel/src/drivers/ethernet/rawdatahandler.cpp index 228b4c17..c754124b 100644 --- a/kernel/src/drivers/ethernet/rawdatahandler.cpp +++ b/kernel/src/drivers/ethernet/rawdatahandler.cpp @@ -23,7 +23,7 @@ RawDataHandler::~RawDataHandler() = default; * @param size Size of the raw data in bytes * @return True if the data was handled, false otherwise */ -bool RawDataHandler::HandleRawData(uint8_t* data, uint32_t size) +bool RawDataHandler::handle_raw_data(uint8_t* data, uint32_t size) { return false; } \ No newline at end of file diff --git a/kernel/src/drivers/peripherals/keyboard.cpp b/kernel/src/drivers/peripherals/keyboard.cpp index a99e60f4..b7c53c80 100644 --- a/kernel/src/drivers/peripherals/keyboard.cpp +++ b/kernel/src/drivers/peripherals/keyboard.cpp @@ -24,7 +24,7 @@ KeyboardEventHandler::~KeyboardEventHandler() = default; * @param key_down_code The keycode of the key that was pressed * @param key_down_state The state of the keyboard when the key was pressed */ -void KeyboardEventHandler::on_key_down(KeyCode key_down_code, KeyboardState key_down_state) { +void KeyboardEventHandler::on_key_down(KeyCode key_down_code, const KeyboardState& key_down_state) { } /** @@ -33,7 +33,7 @@ void KeyboardEventHandler::on_key_down(KeyCode key_down_code, KeyboardState key_ * @param key_up_code The keycode of the key that was released * @param key_up_state The state of the keyboard when the key was released */ -void KeyboardEventHandler::on_key_up(KeyCode key_up_code, KeyboardState key_up_state) { +void KeyboardEventHandler::on_key_up(KeyCode key_up_code, const KeyboardState& key_up_state) { } /** @@ -656,13 +656,13 @@ void KeyboardInterpreterEN_US::on_stream_read(uint8_t scan_code) { /** * @brief Constructor for the KeyDownEvent class * - * @param keyCode The keycode of the key that was pressed - * @param keyboardState The state of the keyboard when the key was pressed + * @param key_code The keycode of the key that was pressed + * @param keyboard_state The state of the keyboard when the key was pressed */ -KeyDownEvent::KeyDownEvent(KeyCode keyCode, const KeyboardState &keyboardState) +KeyDownEvent::KeyDownEvent(KeyCode key_code, const KeyboardState &keyboard_state) : Event(KeyboardEvents::KEYDOWN), - key_code(keyCode), - keyboard_state(keyboardState) + key_code(key_code), + keyboard_state(keyboard_state) { } diff --git a/kernel/src/drivers/peripherals/mouse.cpp b/kernel/src/drivers/peripherals/mouse.cpp index 01a00374..f81b6257 100644 --- a/kernel/src/drivers/peripherals/mouse.cpp +++ b/kernel/src/drivers/peripherals/mouse.cpp @@ -22,20 +22,20 @@ MouseEventHandler::MouseEventHandler() = default; * @param event The event that was triggered * @return The event that was triggered with the modified data */ -Event *MouseEventHandler::on_event(Event *event) { - switch (event->type) { +Event* MouseEventHandler::on_event(Event* event) { + switch(event->type) { case MouseEvents::MOVE: - this->on_mouse_move_event(((MouseMoveEvent *) event)->x, - ((MouseMoveEvent *) event)->y); + this->on_mouse_move_event(((MouseMoveEvent*) event)->x, + ((MouseMoveEvent*) event)->y); break; case MouseEvents::DOWN: - this->on_mouse_down_event(((MouseDownEvent *) event)->button); + this->on_mouse_down_event(((MouseDownEvent*) event)->button); break; case MouseEvents::UP: - this->on_mouse_up_event(((MouseUpEvent *) event)->button); + this->on_mouse_up_event(((MouseUpEvent*) event)->button); break; } @@ -77,10 +77,9 @@ MouseEventHandler::~MouseEventHandler() = default; * @brief Constructs a new MouseDriver object and registers it as an interrupt handler for interrupt 0x2C */ MouseDriver::MouseDriver() -: InterruptHandler(0x2C, 0xC, 0x28), - data_port(0x60), - command_port(0x64) -{ + : InterruptHandler(0x2C, 0xC, 0x28), + data_port(0x60), + command_port(0x64) { } @@ -115,7 +114,7 @@ void MouseDriver::handle_interrupt() { // Check if there is data to handle uint8_t status = command_port.read(); - if (!(status & 0x20)) + if(!(status & 0x20)) return; // Read the data @@ -123,23 +122,23 @@ void MouseDriver::handle_interrupt() { m_offset = (m_offset + 1) % 3; // If the mouse data transmission is incomplete (3rd piece of data isn't through) - if (m_offset != 0) + if(m_offset != 0) return; // If the mouse is moved (y-axis is inverted) - if (m_buffer[1] != 0 || m_buffer[2] != 0) + if(m_buffer[1] != 0 || m_buffer[2] != 0) raise_event(new MouseMoveEvent(m_buffer[1], -m_buffer[2])); // Handle button presses - for (int i = 0; i < 3; ++i) { + for(int i = 0; i < 3; ++i) { // This button is still in the same state - if ((m_buffer[0] & (0x1 << i)) == (m_buttons & (0x1 << i))) + if((m_buffer[0] & (0x1 << i)) == (m_buttons & (0x1 << i))) continue; // Pass to handlers bool is_pressed = (m_buttons & (0x1 << i)) != 0; - if (is_pressed) + if(is_pressed) raise_event(new MouseDownEvent(m_buffer[i])); else raise_event(new MouseUpEvent(m_buffer[i])); @@ -163,9 +162,8 @@ string MouseDriver::device_name() { * @param button The button that was released */ MouseUpEvent::MouseUpEvent(uint8_t button) -: Event(MouseEvents::UP), - button(button) -{ + : Event(MouseEvents::UP), + button(button) { } @@ -177,9 +175,8 @@ MouseUpEvent::~MouseUpEvent() = default; * @param button The button that was pressed */ MouseDownEvent::MouseDownEvent(uint8_t button) -: Event(MouseEvents::DOWN), - button(button) -{ + : Event(MouseEvents::DOWN), + button(button) { } MouseDownEvent::~MouseDownEvent() = default; @@ -191,10 +188,9 @@ MouseDownEvent::~MouseDownEvent() = default; * @param y The amount the mouse moved in the y direction */ MouseMoveEvent::MouseMoveEvent(int8_t x, int8_t y) -: Event(MouseEvents::MOVE), - x(x), - y(y) -{ + : Event(MouseEvents::MOVE), + x(x), + y(y) { } MouseMoveEvent::~MouseMoveEvent() = default; \ No newline at end of file diff --git a/kernel/src/drivers/video/vga.cpp b/kernel/src/drivers/video/vga.cpp index cabe5b2f..064a88ba 100644 --- a/kernel/src/drivers/video/vga.cpp +++ b/kernel/src/drivers/video/vga.cpp @@ -147,10 +147,10 @@ uint8_t *VideoGraphicsArray::get_frame_buffer_segment() { //read data from index number 6 m_graphics_controller_index_port.write(0x06); - uint8_t segmentNumber = + uint8_t segment_number = m_graphics_controller_data_port.read() & (3 << 2); //Shift by 2 as only interested in bits 3 & 4 (& 3 so all the other bits are removed) - switch (segmentNumber) { + switch (segment_number) { default: case 0 << 2: return (uint8_t *) nullptr; diff --git a/kernel/src/filesystem/filesystem.cpp b/kernel/src/filesystem/filesystem.cpp index 8282f1a8..54f8bde5 100644 --- a/kernel/src/filesystem/filesystem.cpp +++ b/kernel/src/filesystem/filesystem.cpp @@ -18,7 +18,7 @@ File::File() = default; File::~File() = default; /** - * @brief Write data to the file + * @brief write data to the file * * @param data The byte buffer to write * @param amount The amount of data to write @@ -27,7 +27,7 @@ void File::write(buffer_t* data, size_t amount) { } /** - * @brief Read data from the file + * @brief read data from the file * * @param data The byte buffer to read into * @param amount The amount of data to read @@ -70,7 +70,7 @@ void File::seek(SeekType seek_type, size_t offset) { * * @return The current position in the file */ -uint32_t File::position() { +uint32_t File::position() const { return m_offset; } @@ -88,7 +88,7 @@ string File::name() { * * @return The size of the file (in bytes) */ -size_t File::size() { +size_t File::size() const { return m_size; } @@ -110,7 +110,7 @@ Directory::~Directory() { } /** - * @brief Read the directory from the disk + * @brief read the directory from the disk */ void Directory::read_from_disk() { diff --git a/kernel/src/filesystem/format/ext2.cpp b/kernel/src/filesystem/format/ext2.cpp index 8efb7a79..c4c37e59 100644 --- a/kernel/src/filesystem/format/ext2.cpp +++ b/kernel/src/filesystem/format/ext2.cpp @@ -25,8 +25,10 @@ using namespace MaxOS::drivers::clock; * @todo Should lock per file and not expose volume lock */ Ext2Volume::Ext2Volume(drivers::disk::Disk* disk, lba_t partition_offset) - : disk(disk), - partition_offset(partition_offset) { +: disk(disk), + partition_offset(partition_offset), + superblock({}) +{ // Read superblock buffer_t superblock_buffer(&superblock, 1024); @@ -37,7 +39,7 @@ Ext2Volume::Ext2Volume(drivers::disk::Disk* disk, lba_t partition_offset) ASSERT(superblock.signature == 0xEF53, "Ext2 Filesystem doesnt have a valid signature\n"); // Version 0 has constant inode info - if (superblock.version_major < 1) { + if(superblock.version_major < 1) { superblock.first_inode = 11; superblock.inode_size = 128; } @@ -56,11 +58,11 @@ Ext2Volume::Ext2Volume(drivers::disk::Disk* disk, lba_t partition_offset) uint32_t bgdt_lba = partition_offset + block_group_descriptor_table_block * sectors_per_block; uint32_t sectors_to_read = (block_group_descriptor_table_size + block_size - 1) / block_size * sectors_per_block; buffer_t bg_buffer(sectors_to_read * 512); - for (uint32_t i = 0; i < sectors_to_read; ++i) + for(uint32_t i = 0; i < sectors_to_read; ++i) disk->read(bgdt_lba + i, &bg_buffer, 512); // Store the block groups - for (uint32_t i = 0; i < total_block_groups; ++i) { + for(uint32_t i = 0; i < total_block_groups; ++i) { block_groups[i] = new block_group_descriptor_t; memcpy(block_groups[i], bg_buffer.raw() + i * sizeof(block_group_descriptor_t), sizeof(block_group_descriptor_t)); @@ -70,12 +72,12 @@ Ext2Volume::Ext2Volume(drivers::disk::Disk* disk, lba_t partition_offset) Ext2Volume::~Ext2Volume() = default; /** - * @brief Write a single block from a buffer into onto the disk + * @brief write a single block from a buffer into onto the disk * * @param block_num The block to update * @param buffer The buffer to read from */ -void Ext2Volume::write_block(uint32_t block_num, buffer_t* buffer) { +void Ext2Volume::write_block(uint32_t block_num, buffer_t* buffer) const { // Ensure the buffer is in the right format buffer->set_offset(0); @@ -83,21 +85,21 @@ void Ext2Volume::write_block(uint32_t block_num, buffer_t* buffer) { buffer->update_offset = true; // Read each sector of the block - for (size_t i = 0; i < sectors_per_block; ++i) + for(size_t i = 0; i < sectors_per_block; ++i) disk->write(partition_offset + block_num * sectors_per_block + i, buffer, 512); // Reset buffer buffer->set_offset(0); buffer->update_offset = old; -}; +} /** - * @brief Write an inode to the filesystem + * @brief write an inode to the filesystem * * @param inode_num The inode index * @param inode The inode to read from */ -void Ext2Volume::write_inode(uint32_t inode_num, inode_t* inode) { +void Ext2Volume::write_inode(uint32_t inode_num, inode_t* inode) const { // Locate the inode uint32_t group = (inode_num - 1) / superblock.inodes_per_group; @@ -130,7 +132,7 @@ void Ext2Volume::read_block(uint32_t block_num, buffer_t* buffer) const { buffer->set_offset(0); // Read each sector of the block - for (size_t i = 0; i < sectors_per_block; ++i) + for(size_t i = 0; i < sectors_per_block; ++i) disk->read(partition_offset + block_num * sectors_per_block + i, buffer, 512); // Reset buffer @@ -139,7 +141,7 @@ void Ext2Volume::read_block(uint32_t block_num, buffer_t* buffer) const { } /** - * @brief Read an inode from the filesystem + * @brief read an inode from the filesystem * * @param inode_num The inode index * @return The inode read @@ -186,34 +188,34 @@ uint32_t Ext2Volume::allocate_block() { Vector Ext2Volume::allocate_blocks(uint32_t amount) { // No blocks to allocate - if (!amount) + if(!amount) return { 1, 0 }; // Find the block group with enough free blocks block_group_descriptor_t* block_group = block_groups[0]; - for (uint32_t bg_index = 0; bg_index < total_block_groups; block_group = block_groups[++bg_index]) - if (block_group->free_blocks >= amount) + for(uint32_t bg_index = 0; bg_index < total_block_groups; block_group = block_groups[++bg_index]) + if(block_group->free_blocks >= amount) return allocate_group_blocks(bg_index, amount); // No block group can contain the block so split across multiple Vector result { }; - while (amount > 0) { + while(amount > 0) { // Find the block group with most free blocks block_group = block_groups[0]; uint32_t bg_index = 0; - for (; bg_index < total_block_groups; ++bg_index) - if (block_groups[bg_index]->free_blocks > block_group->free_blocks) + for(; bg_index < total_block_groups; ++bg_index) + if(block_groups[bg_index]->free_blocks > block_group->free_blocks) block_group = block_groups[bg_index]; // No space - if (block_group->free_blocks == 0) + if(block_group->free_blocks == 0) return { 1, 0 }; // Allocate the remaining blocks auto allocated = allocate_group_blocks(bg_index, 1); amount -= allocated.size(); - for (auto block : allocated) + for(auto block : allocated) result.push_back(block); } @@ -231,7 +233,7 @@ common::Vector Ext2Volume::allocate_group_blocks(uint32_t block_group, // Ensure enough space block_group_descriptor_t* descriptor = block_groups[block_group]; - if (amount > descriptor->free_blocks) + if(amount > descriptor->free_blocks) return { 1, 0 }; // Prepare @@ -244,10 +246,10 @@ common::Vector Ext2Volume::allocate_group_blocks(uint32_t block_group, read_block(descriptor->block_usage_bitmap, &bitmap); // Allocate the blocks - for (uint32_t i = 0; i < superblock.blocks_per_group; ++i) { + for(uint32_t i = 0; i < superblock.blocks_per_group; ++i) { // Block is already used - if ((bitmap.raw()[i / 8] & (1u << (i % 8))) != 0) + if((bitmap.raw()[i / 8] & (1u << (i % 8))) != 0) continue; // Mark as used @@ -262,7 +264,7 @@ common::Vector Ext2Volume::allocate_group_blocks(uint32_t block_group, // All done amount--; - if (!amount) + if(!amount) break; } @@ -293,10 +295,10 @@ void Ext2Volume::free_group_blocks(uint32_t block_group, uint32_t amount, uint32 start -= (block_group * superblock.blocks_per_group + superblock.starting_block); // Free the blocks - for (uint32_t i = start; i < start + amount; ++i) { + for(uint32_t i = start; i < start + amount; ++i) { // Block is already free (shouldn't happen) - if ((bitmap.raw()[i / 8] & (1u << (i % 8))) == 0) + if((bitmap.raw()[i / 8] & (1u << (i % 8))) == 0) continue; // Mark as free @@ -325,12 +327,12 @@ void Ext2Volume::write_back_block_groups() const { // Copy the block groups into the buffer buffer_t bg_buffer(sectors_to_write * 512); - for (uint32_t i = 0; i < total_block_groups; ++i) + for(uint32_t i = 0; i < total_block_groups; ++i) bg_buffer.copy_from(block_groups[i], sizeof(block_group_descriptor_t)); // Write the buffer to disk bg_buffer.set_offset(0); - for (uint32_t i = 0; i < sectors_to_write; ++i) + for(uint32_t i = 0; i < sectors_to_write; ++i) disk->write(bgdt_lba + i, &bg_buffer, 512); } @@ -372,8 +374,8 @@ uint32_t Ext2Volume::create_inode(bool is_directory) { // Find the block group with enough free inodes block_group_descriptor_t* block_group = block_groups[0]; uint32_t bg_index = 0; - for (; bg_index < total_block_groups; block_group = block_groups[++bg_index]) - if (block_group->free_inodes >= 1) + for(; bg_index < total_block_groups; block_group = block_groups[++bg_index]) + if(block_group->free_inodes >= 1) break; // Read bitmap @@ -382,14 +384,14 @@ uint32_t Ext2Volume::create_inode(bool is_directory) { // First group contains reserved inodes uint32_t inode_index = 0; - if (bg_index == 0 && superblock.first_inode > 1) + if(bg_index == 0 && superblock.first_inode > 1) inode_index = superblock.first_inode - 1; // Find a free inode - for (; inode_index < superblock.inodes_per_group; ++inode_index) { + for(; inode_index < superblock.inodes_per_group; ++inode_index) { // Block is already used - if ((bitmap.raw()[inode_index / 8] & (1u << (inode_index % 8))) != 0) + if((bitmap.raw()[inode_index / 8] & (1u << (inode_index % 8))) != 0) continue; // Mark as used @@ -441,7 +443,7 @@ void Ext2Volume::free_inode(uint32_t inode) { // First group contains reserved inodes uint32_t inode_index = (inode - 1) % superblock.inodes_per_group; - if (bg_index == 0 && (inode_index < (superblock.first_inode - 1))) + if(bg_index == 0 && (inode_index < (superblock.first_inode - 1))) return; // Mark as used @@ -462,7 +464,7 @@ void Ext2Volume::free_inode(uint32_t inode) { void Ext2Volume::free_blocks(const common::Vector& blocks) { // No blocks to free - if (blocks.empty()) + if(blocks.empty()) return; uint32_t start = blocks[0]; @@ -470,14 +472,14 @@ void Ext2Volume::free_blocks(const common::Vector& blocks) { uint32_t amount = 1; // Free each adjacent set of blocks - for (auto& block : blocks) { + for(auto& block : blocks) { // First is already accounted for - if (block == start) + if(block == start) continue; // Is this block adjacent - if ((previous + 1) == block) { + if((previous + 1) == block) { previous = block; amount += 1; continue; @@ -510,8 +512,8 @@ InodeHandler::InodeHandler(Ext2Volume* volume, uint32_t inode_index) inode(m_volume->read_inode(inode_number)) { // Read the block pointers - for (uint32_t direct_pointer = 0; direct_pointer < 12; ++direct_pointer) - if (inode.block_pointers[direct_pointer]) + for(uint32_t direct_pointer = 0; direct_pointer < 12; ++direct_pointer) + if(inode.block_pointers[direct_pointer]) block_cache.push_back(inode.block_pointers[direct_pointer]); buffer_t buffer(m_volume->block_size); @@ -521,7 +523,7 @@ InodeHandler::InodeHandler(Ext2Volume* volume, uint32_t inode_index) } /** - * @brief Read the size upper and lower into a single size_t + * @brief read the size upper and lower into a single size_t * @return The size of the inode data (not the inode itself) */ size_t InodeHandler::size() const { @@ -529,7 +531,7 @@ size_t InodeHandler::size() const { } /** - * @brief Store the size of the inode data. (does not write to disk) + * @brief store the size of the inode data. (does not write to disk) * @param size The new size */ void InodeHandler::set_size(size_t size) { @@ -549,7 +551,7 @@ void InodeHandler::set_size(size_t size) { void InodeHandler::parse_indirect(uint32_t level, uint32_t block, buffer_t* buffer) { // Invalid - if (block == 0) + if(block == 0) return; // Read the block @@ -557,15 +559,15 @@ void InodeHandler::parse_indirect(uint32_t level, uint32_t block, buffer_t* buff auto* pointers = (uint32_t*) (buffer->raw()); // Parse the pointers - for (size_t i = 0; i < m_volume->pointers_per_block; ++i) { + for(size_t i = 0; i < m_volume->pointers_per_block; ++i) { uint32_t pointer = pointers[i]; // Invaild - if (pointer == 0) + if(pointer == 0) break; // Has indirect sub entries - if (level > 1) { + if(level > 1) { parse_indirect(level - 1, pointer, buffer); continue; } @@ -587,11 +589,11 @@ void InodeHandler::write_indirect(uint32_t level, uint32_t& block, size_t& index // Nothing left to write size_t remaining = block_cache.size() - index; - if (remaining == 0 || index >= block_cache.size()) + if(remaining == 0 || index >= block_cache.size()) return; // Level hasn't been set yet - if (block == 0) + if(block == 0) block = m_volume->allocate_block(); // Allocate a local buffer for this recursion level @@ -600,14 +602,14 @@ void InodeHandler::write_indirect(uint32_t level, uint32_t& block, size_t& index auto* pointers = (uint32_t*) buffer.raw(); // Write the pointers - for (size_t i = 0; i < m_volume->pointers_per_block; ++i) { + for(size_t i = 0; i < m_volume->pointers_per_block; ++i) { // Invalid - if (index >= block_cache.size()) + if(index >= block_cache.size()) break; // Has indirect - if (level > 1) { + if(level > 1) { write_indirect(level - 1, pointers[i], index); continue; } @@ -629,15 +631,15 @@ void InodeHandler::store_blocks(Vector const& blocks) { Logger::DEBUG() << "STORING BLOCKS\n"; // Store in cache - for (auto block : blocks) + for(auto block : blocks) block_cache.push_back(block); // Direct blocks - for (uint32_t i = 0; i < 12; ++i) + for(uint32_t i = 0; i < 12; ++i) inode.block_pointers[i] = i < block_cache.size() ? block_cache[i] : 0; // No need to do any indirects - if (block_cache.size() < 12) + if(block_cache.size() < 12) return; // Setup Recursive blocks @@ -645,7 +647,7 @@ void InodeHandler::store_blocks(Vector const& blocks) { // Write the blocks uint32_t indirect_blocks[3] = { inode.l1_indirect, inode.l2_indirect, inode.l3_indirect }; - for (int i = 0; i < 3; ++i) { + for(int i = 0; i < 3; ++i) { // Have to use temp because of packed field uint32_t temp = indirect_blocks[i]; @@ -673,7 +675,7 @@ void InodeHandler::store_blocks(Vector const& blocks) { size_t InodeHandler::grow(size_t amount, bool flush) { // Nothing to grow - if (amount <= 0) + if(amount <= 0) return size(); // Allocate new blocks @@ -683,7 +685,7 @@ size_t InodeHandler::grow(size_t amount, bool flush) { // Save the changes store_blocks(blocks); set_size(size() + amount); - if (flush) + if(flush) save(); return size() + amount; @@ -731,7 +733,7 @@ Ext2File::Ext2File(Ext2Volume* volume, uint32_t inode, string const& name) } /** - * @brief Write data to the file (at the current seek position, updated to be += amount) + * @brief write data to the file (at the current seek position, updated to be += amount) * * @param data The byte buffer to write * @param amount The amount of data to write @@ -739,7 +741,7 @@ Ext2File::Ext2File(Ext2Volume* volume, uint32_t inode, string const& name) void Ext2File::write(buffer_t* data, size_t amount) { // Nothing to write - if (amount == 0) + if(amount == 0) return; // Prepare for writing @@ -748,7 +750,7 @@ void Ext2File::write(buffer_t* data, size_t amount) { buffer_t buffer(block_size); // Expand the file - if (m_offset + amount > m_size) + if(m_offset + amount > m_size) m_size = m_inode.grow((m_offset + amount) - m_size, false); // Save the updated metadata @@ -762,7 +764,7 @@ void Ext2File::write(buffer_t* data, size_t amount) { // Write each block size_t current_block = block_start; size_t written = 0; - while (written < amount) { + while(written < amount) { // Read the block uint32_t block = m_inode.block_cache[current_block++]; @@ -785,7 +787,7 @@ void Ext2File::write(buffer_t* data, size_t amount) { } /** -* @brief Read data from the file (at the current seek position, updated to be += amount) +* @brief read data from the file (at the current seek position, updated to be += amount) * * @param data The byte buffer to read into * @param amount The amount of data to read @@ -793,7 +795,7 @@ void Ext2File::write(buffer_t* data, size_t amount) { void Ext2File::read(buffer_t* data, size_t amount) { // Nothing to read - if (m_size == 0 || amount == 0) + if(m_size == 0 || amount == 0) return; // Prepare for reading @@ -802,7 +804,7 @@ void Ext2File::read(buffer_t* data, size_t amount) { buffer_t buffer(block_size); // Force bounds - if (m_offset + amount > m_size) + if(m_offset + amount > m_size) amount = m_size - m_offset; // Convert bytes to blocks @@ -812,7 +814,7 @@ void Ext2File::read(buffer_t* data, size_t amount) { // Read each block size_t current_block = block_start; size_t read = 0; - while (read < amount) { + while(read < amount) { // Read the block uint32_t block = m_inode.block_cache[current_block++]; @@ -856,19 +858,19 @@ Ext2Directory::Ext2Directory(Ext2Volume* volume, uint32_t inode, const string& n } /** - * @brief Store all entries from a buffer and convert to File or Directory objects + * @brief store all entries from a buffer and convert to File or Directory objects */ void Ext2Directory::parse_block(buffer_t* buffer) { size_t offset = 0; - while (offset < m_volume->block_size) { + while(offset < m_volume->block_size) { // Read the entry auto* entry = (directory_entry_t*) (buffer->raw() + offset); m_entries.push_back(*entry); // Not valid - if (entry->inode == 0 || entry->name_length == 0) + if(entry->inode == 0 || entry->name_length == 0) break; // Parse @@ -877,7 +879,7 @@ void Ext2Directory::parse_block(buffer_t* buffer) { uint32_t inode = entry->inode; // Create the object - switch ((EntryType) entry->type) { + switch((EntryType) entry->type) { case EntryType::FILE: m_files.push_back(new Ext2File(m_volume, inode, filename)); @@ -909,18 +911,18 @@ void Ext2Directory::remove_entry(string const& name, bool is_directory, bool cle // Find the entry uint32_t index = 0; directory_entry_t* entry = nullptr; - for (; index < m_entries.size(); ++index) - if (m_entry_names[index] == name) { + for(; index < m_entries.size(); ++index) + if(m_entry_names[index] == name) { entry = &m_entries[index]; break; } // No entry found - if (!entry || entry->type != (uint8_t) (is_directory ? EntryType::DIRECTORY : EntryType::FILE)) + if(!entry || entry->type != (uint8_t) (is_directory ? EntryType::DIRECTORY : EntryType::FILE)) return; // Clear the inode - if (clear) { + if(clear) { InodeHandler inode(m_volume, entry->inode); inode.free(); } @@ -941,9 +943,9 @@ void Ext2Directory::remove_entry(string const& name, bool is_directory, bool cle void Ext2Directory::rename_entry(string const& old_name, string const& new_name, bool is_directory) { // Change the name - for (uint32_t i = 0; i < m_entry_names.size(); ++i) - if (m_entry_names[i] == old_name && - m_entries[i].type == (uint8_t) (is_directory ? EntryType::DIRECTORY : EntryType::FILE)) + for(uint32_t i = 0; i < m_entry_names.size(); ++i) + if(m_entry_names[i] == old_name && + m_entries[i].type == (uint8_t) (is_directory ? EntryType::DIRECTORY : EntryType::FILE)) m_entry_names[i] = new_name; // Save the change @@ -952,7 +954,7 @@ void Ext2Directory::rename_entry(string const& old_name, string const& new_name, } /** - * @brief Read the directory from the inode on the disk + * @brief read the directory from the inode on the disk */ void Ext2Directory::read_from_disk() { @@ -961,21 +963,20 @@ void Ext2Directory::read_from_disk() { m_entry_names.clear(); // Clear the old files & Directories - for (auto& file : m_files) + for(auto& file : m_files) delete file; m_files.clear(); - for (auto& directory : m_subdirectories) + for(auto& directory : m_subdirectories) delete directory; m_subdirectories.clear(); // Read the direct blocks (cant use for( : )) buffer_t buffer(m_volume->block_size); - for (uint32_t i = 0; i < m_inode.block_cache.size(); ++i) { - uint32_t block_pointer = m_inode.block_cache[i]; + for(unsigned int block_pointer : m_inode.block_cache) { // Invalid block - if (block_pointer == 0) + if(block_pointer == 0) break; // Parse the block @@ -987,13 +988,13 @@ void Ext2Directory::read_from_disk() { } /** - * @brief Write all directory entries to the disk (expands the directory blocks if needed) + * @brief write all directory entries to the disk (expands the directory blocks if needed) */ void Ext2Directory::write_entries() { // Calculate the size needed to store the entries and the null entry size_t size_required = sizeof(directory_entry_t); - for (uint32_t i = 0; i < m_entries.size(); ++i) { + for(uint32_t i = 0; i < m_entries.size(); ++i) { size_t size = sizeof(directory_entry_t) + m_entry_names[i].length() + 1; size += (size % 4) ? 4 - size % 4 : 0; size_required += size; @@ -1001,7 +1002,7 @@ void Ext2Directory::write_entries() { // Expand the directory size_t blocks_required = m_volume->bytes_to_blocks(size_required); - if (blocks_required > m_inode.block_cache.size()) + if(blocks_required > m_inode.block_cache.size()) m_inode.grow((blocks_required - m_inode.block_cache.size()) * m_volume->block_size, false); // Prepare for writing @@ -1018,7 +1019,7 @@ void Ext2Directory::write_entries() { // Write each entry size_t current_block = 0; size_t buffer_offset = 0; - for (uint32_t i = 0; i < m_entries.size(); ++i) { + for(uint32_t i = 0; i < m_entries.size(); ++i) { // Get the current entry directory_entry_t& entry = m_entries[i]; @@ -1030,7 +1031,7 @@ void Ext2Directory::write_entries() { entry.size += (entry.size % 4) ? 4 - (entry.size % 4) : 0; // Entry needs to be stored in the next block - if (entry.size + buffer_offset > block_size) { + if(entry.size + buffer_offset > block_size) { m_volume->write_block(m_inode.block_cache[current_block], &buffer); buffer.clear(); current_block++; @@ -1038,7 +1039,7 @@ void Ext2Directory::write_entries() { } // If it is the last entry it takes up the rest of the block - if (i == m_entries.size() - 1) + if(i == m_entries.size() - 1) entry.size = block_size - buffer_offset; // Copy the entry and the name @@ -1054,6 +1055,14 @@ void Ext2Directory::write_entries() { m_volume->ext2_lock.unlock(); } +/** + * @brief Create a new directory entry and save it to disk + * + * @param name The name of the entry + * @param inode The inode number to use (0 to create a new inode) + * @param is_directory True if the entry is a directory, false if it is a file + * @return The created directory entry + */ directory_entry_t Ext2Directory::create_entry(const string& name, uint32_t inode, bool is_directory) { // Create the inode @@ -1081,8 +1090,8 @@ directory_entry_t Ext2Directory::create_entry(const string& name, uint32_t inode File* Ext2Directory::create_file(string const& name) { // Check if the file already exists - for (auto& file : m_files) - if (file->name() == name) + for(auto& file : m_files) + if(file->name() == name) return nullptr; // Create the file @@ -1119,8 +1128,8 @@ void Ext2Directory::rename_file(string const& old_name, string const& new_name) Directory* Ext2Directory::create_subdirectory(string const& name) { // Check if the directory already exists - for (auto& subdirectory : m_subdirectories) - if (subdirectory->name() == name) + for(auto& subdirectory : m_subdirectories) + if(subdirectory->name() == name) return nullptr; // Store the directory diff --git a/kernel/src/filesystem/format/fat32.cpp b/kernel/src/filesystem/format/fat32.cpp index 50e0dc16..6eb545c5 100644 --- a/kernel/src/filesystem/format/fat32.cpp +++ b/kernel/src/filesystem/format/fat32.cpp @@ -24,29 +24,29 @@ using namespace MaxOS::memory; * @param partition_offset The offset of the partition on the disk */ Fat32Volume::Fat32Volume(Disk* disk, uint32_t partition_offset) -: disk(disk) -{ + : disk(disk) { // Read the BIOS parameter block buffer_t bpb_buffer(&bpb, sizeof(bpb32_t)); disk->read(partition_offset, &bpb_buffer); // Parse the FAT info - uint32_t total_data_sectors = bpb.total_sectors_32 - (bpb.reserved_sectors + (bpb.table_copies * bpb.table_size_32)); - fat_total_clusters = total_data_sectors / bpb.sectors_per_cluster; - fat_lba = partition_offset + bpb.reserved_sectors; - fat_copies = bpb.table_copies; - fat_info_lba = partition_offset + bpb.fat_info; - data_lba = fat_lba + (bpb.table_copies * bpb.table_size_32); - root_lba = data_lba + bpb.sectors_per_cluster * (bpb.root_cluster - 2); + uint32_t total_data_sectors = + bpb.total_sectors_32 - (bpb.reserved_sectors + (bpb.table_copies * bpb.table_size_32)); + fat_total_clusters = total_data_sectors / bpb.sectors_per_cluster; + fat_lba = partition_offset + bpb.reserved_sectors; + fat_copies = bpb.table_copies; + fat_info_lba = partition_offset + bpb.fat_info; + data_lba = fat_lba + (bpb.table_copies * bpb.table_size_32); + root_lba = data_lba + bpb.sectors_per_cluster * (bpb.root_cluster - 2); // Read the fs info buffer_t fs_buffer(&fsinfo, sizeof(fs_info_t)); disk->read(fat_info_lba, &fs_buffer); // Validate the fat information - if (fsinfo.lead_signature != 0x41615252 || fsinfo.structure_signature != 0x61417272 || - fsinfo.trail_signature != 0xAA550000) { + if(fsinfo.lead_signature != 0x41615252 || fsinfo.structure_signature != 0x61417272 || + fsinfo.trail_signature != 0xAA550000) { Logger::ERROR() << "Invalid FAT32 filesystem information TODO: Handle this\n"; return; } @@ -62,7 +62,7 @@ Fat32Volume::~Fat32Volume() = default; * * @todo The auto entry = uint32_t* '&' is weird, fix it */ -lba_t Fat32Volume::next_cluster(lba_t cluster) { +lba_t Fat32Volume::next_cluster(lba_t cluster) const { // Get the location in the FAT table lba_t offset = cluster * sizeof(uint32_t); @@ -74,7 +74,7 @@ lba_t Fat32Volume::next_cluster(lba_t cluster) { disk->read(sector, &fat); // Get the next cluster info (mask the upper 4 bits) - auto entry = (uint32_t *) (&(fat.raw()[entry_index])); + auto entry = (uint32_t*) (&(fat.raw()[entry_index])); return *entry & 0x0FFFFFFF; } @@ -87,12 +87,12 @@ lba_t Fat32Volume::next_cluster(lba_t cluster) { * * @todo when in userspace: For performance cache fat entirely, cache file data, cache cluster chains */ -uint32_t Fat32Volume::set_next_cluster(uint32_t cluster, uint32_t next_cluster) { +uint32_t Fat32Volume::set_next_cluster(uint32_t cluster, uint32_t next_cluster) const { // Get the location in the FAT table lba_t offset = cluster * sizeof(uint32_t); - for (uint32_t i = 0; i < fat_copies; ++i) { + for(uint32_t i = 0; i < fat_copies; ++i) { lba_t sector = (fat_lba + i * bpb.table_size_32) + (offset / bpb.bytes_per_sector); uint32_t entry_index = offset % bpb.bytes_per_sector; @@ -102,7 +102,7 @@ uint32_t Fat32Volume::set_next_cluster(uint32_t cluster, uint32_t next_cluster) disk->read(sector, &fat); // Set the next cluster info (mask the upper 4 bits) - auto entry = (uint32_t *) (&(fat.raw()[entry_index])); + auto entry = (uint32_t*) (&(fat.raw()[entry_index])); *entry = next_cluster & 0x0FFFFFFF; disk->write(sector, &fat); @@ -116,16 +116,16 @@ uint32_t Fat32Volume::set_next_cluster(uint32_t cluster, uint32_t next_cluster) * * @return The first free cluster in the FAT table */ -uint32_t Fat32Volume::find_free_cluster() { +uint32_t Fat32Volume::find_free_cluster() const { // Get the first free cluster - for (uint32_t start = fsinfo.next_free_cluster; start < fat_total_clusters + 1; start++) - if (next_cluster(start) == 0) + for(uint32_t start = fsinfo.next_free_cluster; start < fat_total_clusters + 1; start++) + if(next_cluster(start) == 0) return start; // Check any clusters before the first free cluster - for (uint32_t start = 2; start < fsinfo.next_free_cluster; start++) - if (next_cluster(start) == 0) + for(uint32_t start = 2; start < fsinfo.next_free_cluster; start++) + if(next_cluster(start) == 0) return start; ASSERT(false, "No free clusters found in the FAT table"); @@ -154,11 +154,11 @@ uint32_t Fat32Volume::allocate_cluster(uint32_t cluster) { uint32_t Fat32Volume::allocate_cluster(uint32_t cluster, size_t amount) { // Make sure within bounds - if (cluster > fat_total_clusters || cluster + amount > fat_total_clusters) + if(cluster > fat_total_clusters || cluster + amount > fat_total_clusters) return 0; // Go through allocating the clusters - for (size_t i = 0; i < amount; i++) { + for(size_t i = 0; i < amount; i++) { uint32_t next_cluster = find_free_cluster(); // Update the fsinfo @@ -166,7 +166,7 @@ uint32_t Fat32Volume::allocate_cluster(uint32_t cluster, size_t amount) { fsinfo.free_cluster_count -= 1; // If there is an existing chain it needs to be updated - if (cluster != 0) + if(cluster != 0) set_next_cluster(cluster, next_cluster); cluster = next_cluster; @@ -176,9 +176,8 @@ uint32_t Fat32Volume::allocate_cluster(uint32_t cluster, size_t amount) { buffer_t fs_info_buffer(&fsinfo, sizeof(fs_info_t)); disk->write(fat_info_lba, &fs_info_buffer); - // Finish the chin + // Finish the chain set_next_cluster(cluster, (uint32_t) ClusterState::END_OF_CHAIN); - uint32_t next = next_cluster(cluster); return cluster; } @@ -203,11 +202,11 @@ void Fat32Volume::free_cluster(lba_t cluster) { void Fat32Volume::free_cluster(uint32_t cluster, size_t amount) { // Make sure within bounds - if (cluster < 2 || cluster > fat_total_clusters || cluster + amount > fat_total_clusters) + if(cluster < 2 || cluster > fat_total_clusters || cluster + amount > fat_total_clusters) return; // Go through freeing the clusters - for (size_t i = 0; i < amount; i++) { + for(size_t i = 0; i < amount; i++) { // Find the next cluster before it is removed from the chain uint32_t next_in_chain = next_cluster(cluster); @@ -237,12 +236,11 @@ void Fat32Volume::free_cluster(uint32_t cluster, size_t amount) { * @param info The directory entry information that describes this file * @param name The name of the file */ -Fat32File::Fat32File(Fat32Volume* volume, Fat32Directory *parent, dir_entry_t *info, const string &name) -: m_volume(volume), - m_parent_directory(parent), - m_entry(info), - m_first_cluster((info->first_cluster_high << 16) | info->first_cluster_low) -{ +Fat32File::Fat32File(Fat32Volume* volume, Fat32Directory* parent, dir_entry_t* info, const string& name) + : m_volume(volume), + m_parent_directory(parent), + m_entry(info), + m_first_cluster((info->first_cluster_high << 16) | info->first_cluster_low) { m_name = name; m_size = info->size; @@ -252,14 +250,14 @@ Fat32File::Fat32File(Fat32Volume* volume, Fat32Directory *parent, dir_entry_t *i Fat32File::~Fat32File() = default; /** - * @brief Write data to the file (at the current seek position, updated to be += amount) + * @brief write data to the file (at the current seek position, updated to be += amount) * * @param data The byte buffer to write * @param amount The amount of data to write * * @todo When in userspace: save timestamps */ -void Fat32File::write(buffer_t *data, size_t amount) { +void Fat32File::write(buffer_t* data, size_t amount) { size_t buffer_space = m_volume->bpb.bytes_per_sector * m_volume->bpb.sectors_per_cluster; buffer_t buffer(buffer_space); @@ -270,29 +268,29 @@ void Fat32File::write(buffer_t *data, size_t amount) { uint32_t last = m_first_cluster; // Read the file - for (uint32_t cluster = last; - cluster != (uint32_t) ClusterState::END_OF_CHAIN; cluster = m_volume->next_cluster(cluster)) { + for(uint32_t cluster = last; + cluster != (uint32_t) ClusterState::END_OF_CHAIN; cluster = m_volume->next_cluster(cluster)) { last = cluster; // No cluster to read from (blank file) - if (cluster == 0) + if(cluster == 0) break; // Skip clusters before the offset - if ((current_offset + buffer_space) < m_offset) { + if((current_offset + buffer_space) < m_offset) { current_offset += buffer_space; continue; } // Read each sector in the cluster (prevent overwriting the data) lba_t lba = m_volume->data_lba + (cluster - 2) * m_volume->bpb.sectors_per_cluster; - for (size_t sector = 0; sector < m_volume->bpb.sectors_per_cluster; sector++) + for(size_t sector = 0; sector < m_volume->bpb.sectors_per_cluster; sector++) m_volume->disk->read(lba + sector, &buffer, m_volume->bpb.bytes_per_sector); buffer.set_offset(0); // If the offset is in the middle of the cluster size_t buffer_offset = 0; - if (m_offset > current_offset) + if(m_offset > current_offset) buffer_offset = m_offset - current_offset; // Calculate how many bytes are being copied (read from cluster at offset? @@ -300,7 +298,7 @@ void Fat32File::write(buffer_t *data, size_t amount) { size_t cluster_remaining_bytes = buffer_space - buffer_offset; size_t data_remaining_bytes = amount - bytes_written; size_t bytes_to_copy = (cluster_remaining_bytes < data_remaining_bytes) ? cluster_remaining_bytes - : data_remaining_bytes; + : data_remaining_bytes; bytes_to_copy = (bytes_to_copy > buffer_space) ? buffer_space : bytes_to_copy; // Update the data @@ -310,18 +308,18 @@ void Fat32File::write(buffer_t *data, size_t amount) { buffer.set_offset(0); // Write the data back to the disk - for (size_t sector = 0; sector < m_volume->bpb.sectors_per_cluster; sector++) + for(size_t sector = 0; sector < m_volume->bpb.sectors_per_cluster; sector++) m_volume->disk->write(lba + sector, &buffer, m_volume->bpb.bytes_per_sector); } // Extend the file - while (bytes_written < amount) { + while(bytes_written < amount) { // Allocate a new cluster uint32_t new_cluster = m_volume->allocate_cluster(last); - if (new_cluster == 0) + if(new_cluster == 0) break; - if (last == 0) + if(last == 0) m_first_cluster = new_cluster; // Update the data @@ -333,7 +331,7 @@ void Fat32File::write(buffer_t *data, size_t amount) { // Write the data back to the disk lba_t lba = m_volume->data_lba + (new_cluster - 2) * m_volume->bpb.sectors_per_cluster; - for (size_t sector = 0; sector < m_volume->bpb.sectors_per_cluster; sector++) + for(size_t sector = 0; sector < m_volume->bpb.sectors_per_cluster; sector++) m_volume->disk->write(lba + sector, &buffer, m_volume->bpb.bytes_per_sector); // Go to the next cluster @@ -342,7 +340,7 @@ void Fat32File::write(buffer_t *data, size_t amount) { // Update file size m_offset += bytes_written; - if (m_offset > m_size) + if(m_offset > m_size) m_size = m_offset; // Update entry info @@ -355,12 +353,12 @@ void Fat32File::write(buffer_t *data, size_t amount) { } /** - * @brief Read data from the file (at the current seek position, updated to be += amount) + * @brief read data from the file (at the current seek position, updated to be += amount) * * @param data The byte buffer to read into * @param amount The amount of data to read */ -void Fat32File::read(buffer_t *data, size_t amount) { +void Fat32File::read(buffer_t* data, size_t amount) { size_t buffer_space = m_volume->bpb.bytes_per_sector * m_volume->bpb.sectors_per_cluster; buffer_t buffer(buffer_space); buffer.clear(); @@ -369,31 +367,31 @@ void Fat32File::read(buffer_t *data, size_t amount) { uint64_t bytes_read = 0; // Read the file - for (uint32_t cluster = m_first_cluster; - cluster != (uint32_t) ClusterState::END_OF_CHAIN; cluster = m_volume->next_cluster(cluster)) { + for(uint32_t cluster = m_first_cluster; + cluster != (uint32_t) ClusterState::END_OF_CHAIN; cluster = m_volume->next_cluster(cluster)) { // Skip clusters before the offset - if ((current_offset + buffer_space) < m_offset) { + if((current_offset + buffer_space) < m_offset) { current_offset += buffer_space; continue; } // Read each sector in the cluster lba_t lba = m_volume->data_lba + (cluster - 2) * m_volume->bpb.sectors_per_cluster; - for (size_t sector = 0; sector < m_volume->bpb.sectors_per_cluster; sector++) + for(size_t sector = 0; sector < m_volume->bpb.sectors_per_cluster; sector++) m_volume->disk->read(lba + sector, &buffer, m_volume->bpb.bytes_per_sector); buffer.set_offset(0); // If the offset is in the middle of the cluster size_t buffer_offset = 0; - if (m_offset > current_offset) + if(m_offset > current_offset) buffer_offset = m_offset - current_offset; // Calculate how many bytes are being copied (read from cluster at offset? or read part of cluster?) size_t cluster_remaining_bytes = buffer_space - buffer_offset; size_t data_remaining_bytes = amount - bytes_read; size_t bytes_to_copy = (cluster_remaining_bytes < data_remaining_bytes) ? cluster_remaining_bytes - : data_remaining_bytes; + : data_remaining_bytes; bytes_to_copy = (bytes_to_copy > buffer_space) ? buffer_space : bytes_to_copy; // Read the data @@ -402,7 +400,7 @@ void Fat32File::read(buffer_t *data, size_t amount) { current_offset += buffer_space; // Dont read more than needed - if (bytes_read >= amount) + if(bytes_read >= amount) break; } @@ -423,10 +421,9 @@ void Fat32File::flush() { * @param cluster The cluster of the directory * @param name The name of the directory */ -Fat32Directory::Fat32Directory(Fat32Volume *volume, uint32_t cluster, const string &name) -: m_volume(volume), - m_first_cluster(cluster) -{ +Fat32Directory::Fat32Directory(Fat32Volume* volume, uint32_t cluster, const string& name) + : m_volume(volume), + m_first_cluster(cluster) { m_name = name; } @@ -439,58 +436,58 @@ Fat32Directory::~Fat32Directory() = default; * @param is_directory True if the entry is a directory, false if it is a file * @return The cluster of the new entry */ -dir_entry_t *Fat32Directory::create_entry(const string &name, bool is_directory) { +dir_entry_t* Fat32Directory::create_entry(const string& name, bool is_directory) { // Allocate a cluster for the new entry uint32_t cluster = m_volume->allocate_cluster(0); - if (cluster == 0) + if(cluster == 0) return nullptr; // Store the name Vector lfn_entries = to_long_filenames(name); char short_name[8]; char short_extension[3]; - for (size_t i = 0; i < 8; i++) + for(size_t i = 0; i < 8; i++) short_name[i] = (i < name.length()) ? name[i] : ' '; - for (size_t i = 0; i < 3; i++) + for(size_t i = 0; i < 3; i++) short_extension[i] = (8 + i < name.length()) ? name[8 + i] : ' '; // Create the directory entry - dir_entry_t entry = {}; + dir_entry_t entry = { }; memcpy(entry.name, short_name, sizeof(short_name)); memcpy(entry.extension, short_extension, sizeof(short_extension)); entry.attributes = is_directory ? (uint8_t) DirectoryEntryAttributes::DIRECTORY - : (uint8_t) DirectoryEntryAttributes::ARCHIVE; + : (uint8_t) DirectoryEntryAttributes::ARCHIVE; entry.first_cluster_high = (cluster >> 16) & 0xFFFF; entry.first_cluster_low = cluster & 0xFFFF; // Find free space for the new entry and the name size_t entries_needed = 1 + lfn_entries.size(); int entry_index = find_free_entries(entries_needed); - if (entry_index == -1) + if(entry_index == -1) entry_index = expand_directory(entries_needed); // Store the entries in the cache - for (size_t i = 0; i < entries_needed; i++) - m_entries[entry_index + i] = i == 0 ? entry : *(dir_entry_t *) &lfn_entries[i - 1]; + for(size_t i = 0; i < entries_needed; i++) + m_entries[entry_index + i] = i == 0 ? entry : *(dir_entry_t*) &lfn_entries[i - 1]; // Write the long file name entries - for (int index = entry_index + lfn_entries.size() - 1; index >= entry_index; index--) + for(size_t index = entry_index + lfn_entries.size() - 1; index >= entry_index; index--) update_entry_on_disk(index); // Creating the file is done - if (!is_directory) + if(!is_directory) return &m_entries[entry_index]; // Create the "." in the directory - dir_entry_t current_dir_entry = {}; + dir_entry_t current_dir_entry = { }; memcpy(current_dir_entry.name, ".", 1); current_dir_entry.attributes = 0x10; current_dir_entry.first_cluster_high = (cluster >> 16) & 0xFFFF; current_dir_entry.first_cluster_low = cluster & 0xFFFF; // Create the ".." in the directory - dir_entry_t parent_dir_entry = {}; + dir_entry_t parent_dir_entry = { }; memcpy(parent_dir_entry.name, "..", 2); parent_dir_entry.attributes = 0x10; parent_dir_entry.first_cluster_high = (m_first_cluster >> 16) & 0xFFFF; @@ -513,33 +510,32 @@ dir_entry_t *Fat32Directory::create_entry(const string &name, bool is_directory) * @brief Remove an entry from the directory * * @param cluster The cluster of the entry to remove - * @param name The name of the entry to remove */ -void Fat32Directory::remove_entry(uint32_t cluster, const string &name) { +void Fat32Directory::remove_entry(uint32_t cluster) { // Find the entry in the directory - int entry = entry_index(cluster); - if (entry == -1) + int64_t entry = entry_index(cluster); + if(entry == -1) return; // Find any long file name entries that belong to this entry - int delete_entry_index = entry; - while (delete_entry_index > 0 && - m_entries[delete_entry_index - 1].attributes == (uint8_t) DirectoryEntryAttributes::LONG_NAME) + int64_t delete_entry_index = entry; + while(delete_entry_index > 0 && + m_entries[delete_entry_index - 1].attributes == (uint8_t) DirectoryEntryAttributes::LONG_NAME) delete_entry_index--; // Mark the entries as free - for (int i = delete_entry_index; i < entry; i++) + for(int64_t i = delete_entry_index; i < entry; i++) m_entries[i].name[0] = (uint8_t) DirectoryEntryType::FREE; // Update the entries on the disk - for (int i = delete_entry_index; i <= entry; i++) + for(int64_t i = delete_entry_index; i <= entry; i++) update_entry_on_disk(i); // Count the number of clusters in the chain size_t cluster_count = 0; - for (uint32_t next_cluster = cluster; - next_cluster < (lba_t) ClusterState::BAD; next_cluster = m_volume->next_cluster(next_cluster)) + for(uint32_t next_cluster = cluster; + next_cluster < (lba_t) ClusterState::BAD; next_cluster = m_volume->next_cluster(next_cluster)) cluster_count++; // Free all the clusters in the chain @@ -547,7 +543,7 @@ void Fat32Directory::remove_entry(uint32_t cluster, const string &name) { } /** - * @brief Read all of the directory entries for each cluster in this directory + * @brief read all of the directory entries for each cluster in this directory */ void Fat32Directory::read_all_entries() { m_entries.clear(); @@ -557,8 +553,8 @@ void Fat32Directory::read_all_entries() { buffer.clear(); // Read the directory - for (uint32_t cluster = m_first_cluster; - cluster != (uint32_t) ClusterState::END_OF_CHAIN; cluster = m_volume->next_cluster(cluster)) { + for(uint32_t cluster = m_first_cluster; + cluster != (uint32_t) ClusterState::END_OF_CHAIN; cluster = m_volume->next_cluster(cluster)) { // Cache info to prevent re-traversing the chain m_last_cluster = cluster; @@ -566,18 +562,18 @@ void Fat32Directory::read_all_entries() { // Read each sector in the cluster lba_t lba = m_volume->data_lba + (cluster - 2) * m_volume->bpb.sectors_per_cluster; - for (size_t sector = 0; sector < m_volume->bpb.sectors_per_cluster; sector++) + for(size_t sector = 0; sector < m_volume->bpb.sectors_per_cluster; sector++) m_volume->disk->read(lba + sector, &buffer, m_volume->bpb.bytes_per_sector); // Parse the directory entries (each entry is 32 bytes) - for (size_t entry_offset = 0; entry_offset < buffer_space; entry_offset += 32) { + for(size_t entry_offset = 0; entry_offset < buffer_space; entry_offset += 32) { // Store the entry - auto entry = (dir_entry_t *) &(buffer.raw()[entry_offset]); + auto entry = (dir_entry_t*) &(buffer.raw()[entry_offset]); m_entries.push_back(*entry); // Check if the entry is the end of the directory - if (entry->name[0] == (uint8_t) DirectoryEntryType::LAST) + if(entry->name[0] == (uint8_t) DirectoryEntryType::LAST) return; } @@ -590,11 +586,11 @@ void Fat32Directory::read_all_entries() { * * @param entry The entry to write */ -void Fat32Directory::save_entry_to_disk(DirectoryEntry *entry) { +void Fat32Directory::save_entry_to_disk(DirectoryEntry* entry) { int index = 0; - for (auto &m_entry: m_entries) { - if (&m_entry == entry) + for(auto& m_entry : m_entries) { + if(&m_entry == entry) break; index++; } @@ -606,7 +602,7 @@ void Fat32Directory::save_entry_to_disk(DirectoryEntry *entry) { * @brief Save the directory entry at the given index to the disk * @param index The index of the entry to update */ -void Fat32Directory::update_entry_on_disk(int index) { +void Fat32Directory::update_entry_on_disk(size_t index) { // Get the entry auto entry = m_entries[index]; @@ -619,8 +615,8 @@ void Fat32Directory::update_entry_on_disk(int index) { // Find which cluster has the entry uint32_t cluster = m_first_cluster; - for (uint32_t offset_remaining = entry_offset; - offset_remaining >= bytes_per_sector; offset_remaining -= bytes_per_sector) + for(uint32_t offset_remaining = entry_offset; + offset_remaining >= bytes_per_sector; offset_remaining -= bytes_per_sector) cluster = m_volume->next_cluster(cluster); // Read the full sector into a buffer @@ -642,25 +638,25 @@ void Fat32Directory::update_entry_on_disk(int index) { uint32_t Fat32Directory::entry_index(lba_t cluster) { uint32_t entry_index = 0; - for (; entry_index < m_entries.size(); entry_index++) { - auto &entry = m_entries[entry_index]; + for(; entry_index < m_entries.size(); entry_index++) { + auto& entry = m_entries[entry_index]; // End of directory means no more entries - if (entry.name[0] == (uint8_t) DirectoryEntryType::LAST) + if(entry.name[0] == (uint8_t) DirectoryEntryType::LAST) return -1; // Skip free entries - if (entry.name[0] == (uint8_t) DirectoryEntryType::FREE) + if(entry.name[0] == (uint8_t) DirectoryEntryType::FREE) continue; // Check if the entry is the one uint32_t start_cluster = (entry.first_cluster_high << 16) | entry.first_cluster_low; - if (start_cluster == cluster) + if(start_cluster == cluster) break; } // Make sure the entry is valid - if (entry_index >= m_entries.size()) + if(entry_index >= m_entries.size()) return -1; return entry_index; @@ -674,16 +670,16 @@ uint32_t Fat32Directory::entry_index(lba_t cluster) { * * @return The index of the first free entry or -1 if cant find that many free entries */ -int Fat32Directory::find_free_entries(size_t amount) { +int64_t Fat32Directory::find_free_entries(size_t amount) { - for (uint32_t entry_index = 0; entry_index < m_entries.size(); entry_index++) { + for(uint32_t entry_index = 0; entry_index < m_entries.size(); entry_index++) { // Check if there are enough free entries in a row bool found = true; - for (size_t j = 0; j < amount; j++) - if (m_entries[entry_index + j].name[0] != (uint8_t)DirectoryEntryType::FREE) + for(size_t j = 0; j < amount; j++) + if(m_entries[entry_index + j].name[0] != (uint8_t) DirectoryEntryType::FREE) found = false; - if (found) + if(found) return entry_index; } @@ -704,13 +700,13 @@ int Fat32Directory::find_free_entries(size_t amount) { int Fat32Directory::expand_directory(size_t amount) { // Remove the old end of directory marker - int free_start = m_entries.size() - 1; + int64_t free_start = m_entries.size() - 1; ASSERT(m_entries[free_start].name[0] == (uint8_t) DirectoryEntryType::LAST, "Last entry is not marked"); m_entries[free_start].name[0] = (uint8_t) DirectoryEntryType::FREE; // Count how many free entries there is before the end - for (int i = free_start; i >= 0; --i) { - if (m_entries[i].name[0] == (char) DirectoryEntryType::FREE) + for(int64_t i = free_start; i >= 0; --i) { + if(m_entries[i].name[0] == (uint8_t) DirectoryEntryType::FREE) free_start = i; else break; @@ -720,23 +716,23 @@ int Fat32Directory::expand_directory(size_t amount) { uint32_t found = m_entries.size() - free_start; uint32_t needed_entries = amount + 1; uint32_t additional_entries = 0; - if (needed_entries > found) + if(needed_entries > found) additional_entries = needed_entries - found; // Find the length of the current cluster chain uint32_t total_entries = m_entries.size() + additional_entries; uint32_t total_clusters = (total_entries * sizeof(dir_entry_t)) / - (m_volume->bpb.bytes_per_sector * m_volume->bpb.sectors_per_cluster); + (m_volume->bpb.bytes_per_sector * m_volume->bpb.sectors_per_cluster); // Expand the cluster chain if needed - if (total_clusters > m_current_cluster_length) { + if(total_clusters > m_current_cluster_length) { m_volume->allocate_cluster(m_last_cluster, total_clusters - m_current_cluster_length); m_current_cluster_length = total_clusters; } // Expand the directory to fit the remaining entries - for (uint32_t i = 0; i < additional_entries; ++i) { - dir_entry_t free = {}; + for(uint32_t i = 0; i < additional_entries; ++i) { + dir_entry_t free = { }; free.name[0] = (uint8_t) DirectoryEntryType::FREE; m_entries.push_back(free); } @@ -761,7 +757,7 @@ Vector Fat32Directory::to_long_filenames(string name) { Vector lfn_entries; // Create the long file name entries (in reverse order) - for (size_t i = lfn_count; i-- > 0; ) { + for(size_t i = lfn_count; i-- > 0;) { // Create the long file name entry long_file_name_entry_t lfn_entry; @@ -771,20 +767,20 @@ Vector Fat32Directory::to_long_filenames(string name) { lfn_entry.checksum = 0; // If it is the last entry, set the last bit - if (i == lfn_entries.size() - 1) + if(i == lfn_entries.size() - 1) lfn_entry.order |= 0x40; // Set the name - for (int j = 0; j < 13; j++) { + for(int j = 0; j < 13; j++) { // Get the character info (0xFFFF if out of bounds) size_t char_index = i * 13 + j; char c = (char_index < name.length()) ? name[char_index] : 0xFFFF; // Set the character in the entry - if (j < 5) + if(j < 5) lfn_entry.name1[j] = c; - else if (j < 11) + else if(j < 11) lfn_entry.name2[j - 5] = c; else lfn_entry.name3[j - 11] = c; @@ -803,23 +799,23 @@ Vector Fat32Directory::to_long_filenames(string name) { * * @return The parsed entry prepended to the current string */ -string Fat32Directory::parse_long_filename(long_file_name_entry_t *entry, const string ¤t) { +string Fat32Directory::parse_long_filename(long_file_name_entry_t* entry, const string& current) { // Extract the long name from each part (in reverse order) string current_long_name = ""; - for (int i = 0; i < 13; i++) { + for(int i = 0; i < 13; i++) { // Get the character (in utf8 encoding) char c; - if (i < 5) + if(i < 5) c = entry->name1[i] & 0xFF; - else if (i < 11) + else if(i < 11) c = entry->name2[i - 5] & 0xFF; else c = entry->name3[i - 11] & 0xFF; // Padding / invalid or end of string - if (c == (char) 0xFF || c == '\0') + if(c == (char) 0xFF || c == '\0') break; // Add to the start as the entries are stored in reverse @@ -832,11 +828,11 @@ string Fat32Directory::parse_long_filename(long_file_name_entry_t *entry, const void Fat32Directory::read_from_disk() { - for (auto &file: m_files) + for(auto& file : m_files) delete file; m_files.clear(); - for (auto &directory: m_subdirectories) + for(auto& directory : m_subdirectories) delete directory; m_subdirectories.clear(); @@ -845,17 +841,17 @@ void Fat32Directory::read_from_disk() { // Parse the entries string long_name = ""; - for (auto &entry: m_entries) { + for(auto& entry : m_entries) { // Skip free entries and volume labels - if (entry.name[0] == (uint8_t) DirectoryEntryType::FREE - || entry.attributes == (uint8_t) DirectoryEntryAttributes::FREE - || entry.attributes == (uint8_t) DirectoryEntryAttributes::VOLUME_ID) + if(entry.name[0] == (uint8_t) DirectoryEntryType::FREE + || entry.attributes == (uint8_t) DirectoryEntryAttributes::FREE + || entry.attributes == (uint8_t) DirectoryEntryAttributes::VOLUME_ID) continue; // Extract the long name - if (entry.attributes == (uint8_t) DirectoryEntryAttributes::LONG_NAME) { - long_name = parse_long_filename((long_file_name_entry_t *) &entry, long_name); + if(entry.attributes == (uint8_t) DirectoryEntryAttributes::LONG_NAME) { + long_name = parse_long_filename((long_file_name_entry_t*) &entry, long_name); continue; } @@ -863,11 +859,11 @@ void Fat32Directory::read_from_disk() { // Get the name of the entry string name = long_name; - if (long_name == "") { + if(long_name == "") { name = string(entry.name, 8); // Add the extension - if (!is_directory) + if(!is_directory) name = name.strip() + "." + string(entry.extension, 3); } @@ -877,7 +873,7 @@ void Fat32Directory::read_from_disk() { uint32_t start_cluster = (entry.first_cluster_high << 16) | entry.first_cluster_low; // Store the file or directory - if (is_directory) + if(is_directory) m_subdirectories.push_back(new Fat32Directory(m_volume, start_cluster, name.strip())); else m_files.push_back(new Fat32File(m_volume, this, &entry, name)); @@ -891,15 +887,15 @@ void Fat32Directory::read_from_disk() { * @param name The name of the file to create * @return The new file object or null if it could not be created */ -File *Fat32Directory::create_file(const string &name) { +File* Fat32Directory::create_file(const string& name) { // Check if the file already exists - for (auto &file: m_files) - if (file->name() == name) + for(auto& file : m_files) + if(file->name() == name) return nullptr; // Check if the name is too long - if (name.length() > MAX_NAME_LENGTH) + if(name.length() > MAX_NAME_LENGTH) return nullptr; // Create the file @@ -913,14 +909,14 @@ File *Fat32Directory::create_file(const string &name) { * * @param name The name of the file to delete */ -void Fat32Directory::remove_file(const string &name) { +void Fat32Directory::remove_file(const string& name) { // Find the file if it exists - for (auto &file: m_files) - if (file->name() == name) { + for(auto& file : m_files) + if(file->name() == name) { // Remove the file from the directory m_files.erase(file); - remove_entry(((Fat32File *) file)->first_cluster(), name); + remove_entry(((Fat32File*) file)->first_cluster()); // Delete the file reference delete file; @@ -934,15 +930,15 @@ void Fat32Directory::remove_file(const string &name) { * @param name The name of the directory to create * @return The new directory object or null if it could not be created */ -Directory *Fat32Directory::create_subdirectory(const string &name) { +Directory* Fat32Directory::create_subdirectory(const string& name) { // Check if the directory already exists - for (auto &subdirectory: m_subdirectories) - if (subdirectory->name() == name) + for(auto& subdirectory : m_subdirectories) + if(subdirectory->name() == name) return nullptr; // Check if the name is too long - if (name.length() > MAX_NAME_LENGTH) + if(name.length() > MAX_NAME_LENGTH) return nullptr; // Create the directory @@ -960,23 +956,23 @@ Directory *Fat32Directory::create_subdirectory(const string &name) { * * @param name The name of the entry to remove */ -void Fat32Directory::remove_subdirectory(const string &name) { +void Fat32Directory::remove_subdirectory(const string& name) { // Find the directory if it exists - for (auto &subdirectory: m_subdirectories) { - if (subdirectory->name() != name) + for(auto& subdirectory : m_subdirectories) { + if(subdirectory->name() != name) continue; // Remove all the files in the directory - for (auto &file: subdirectory->files()) + for(auto& file : subdirectory->files()) subdirectory->remove_file(file->name()); // Remove all the subdirectories in the directory - for (auto &subdirectory: subdirectory->subdirectories()) - subdirectory->remove_subdirectory(subdirectory->name()); + for(auto& child_dir : subdirectory->subdirectories()) + child_dir->remove_subdirectory(child_dir->name()); // Remove the entry m_subdirectories.erase(subdirectory); - remove_entry(((Fat32Directory *) subdirectory)->first_cluster(), name); + remove_entry(((Fat32Directory*) subdirectory)->first_cluster()); // Delete the directory delete subdirectory; @@ -990,9 +986,8 @@ void Fat32Directory::remove_subdirectory(const string &name) { * @param disk The disk to mount the filesystem from * @param partition_offset The partition offset on the disk */ -Fat32FileSystem::Fat32FileSystem(Disk *disk, uint32_t partition_offset) -: m_volume(disk, partition_offset) -{ +Fat32FileSystem::Fat32FileSystem(Disk* disk, uint32_t partition_offset) + : m_volume(disk, partition_offset) { // Create the root directory m_root_directory = new Fat32Directory(&m_volume, m_volume.bpb.root_cluster, "/"); diff --git a/kernel/src/filesystem/path.cpp b/kernel/src/filesystem/path.cpp index 3036956f..4f049c0f 100644 --- a/kernel/src/filesystem/path.cpp +++ b/kernel/src/filesystem/path.cpp @@ -18,7 +18,7 @@ using namespace MaxOS::filesystem; * @param path The path to check * @return True if the path is valid, false otherwise */ -bool Path::valid(string path) { +bool Path::valid(const string& path) { // Must not be empty if (path.length() == 0) @@ -51,7 +51,7 @@ bool Path::is_file(const string& path) { * @param path The path to get the file name from * @return The file name or the original path if it does not exist */ -string Path::file_name(string path) { +string Path::file_name(const string& path) { // Find the last / int last_slash = -1; @@ -74,7 +74,7 @@ string Path::file_name(string path) { * @param path The path to get the file extension from * @return The file extension or the original path if it does not exist */ -string Path::file_extension(string path) { +string Path::file_extension(const string& path) { // Find the last . int last_dot = -1; @@ -98,7 +98,7 @@ string Path::file_extension(string path) { * @param path The path to get the file path from * @return The file path or the original path if it does not exist */ -string Path::file_path(string path) { +string Path::file_path(const string& path) { // Try to find the last / int last_slash = -1; @@ -122,7 +122,7 @@ string Path::file_path(string path) { * @param path The path to get the top directory from * @return The top directory or the original path if it does not exist */ -string Path::top_directory(string path) { +string Path::top_directory(const string& path) { // Find the first / int first_slash = -1; @@ -145,7 +145,7 @@ string Path::top_directory(string path) { * @param path The path to either the file or the directory * @return */ -string Path::parent_directory(string path) { +string Path::parent_directory(const string& path) { // Find the last / int last_slash = -1; @@ -167,7 +167,7 @@ string Path::parent_directory(string path) { * @param path The path * @return The new path, direct from root */ -string Path::absolute_path(string path) { +string Path::absolute_path(const string& path) { // Split the path into components auto components = path.split("/"); @@ -205,7 +205,7 @@ string Path::absolute_path(string path) { * @param extended What to add to the base path (if its from root, "/", then it will just return this) * @return The joint path */ -string Path::join_path(string base, string extended) { +string Path::join_path(const string& base, const string& extended) { // The new path is from root if(extended[0] == '/') diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp index 0c1ebb3c..a5737dbb 100644 --- a/kernel/src/filesystem/vfs.cpp +++ b/kernel/src/filesystem/vfs.cpp @@ -404,7 +404,7 @@ void VirtualFileSystem::delete_directory(Directory* parent, Directory* directory } // Delete the directory from the bottom of the tree - for (int i = to_delete.size() - 1; i >= 0; --i) { + for (uint32_t i = to_delete.size() - 1; i >= 0; --i) { // Get the parent and child const auto ¤t = to_delete[i]; diff --git a/kernel/src/filesystem/vfsresource.cpp b/kernel/src/filesystem/vfsresource.cpp index 41a1b83e..6971f689 100644 --- a/kernel/src/filesystem/vfsresource.cpp +++ b/kernel/src/filesystem/vfsresource.cpp @@ -31,7 +31,7 @@ FileResource::FileResource(string const& name, size_t flags, processes::resource FileResource::~FileResource() = default; /** - * @brief Read from a file resource + * @brief read from a file resource * * @param buffer The buffer to read into * @param size The number of bytes to read @@ -70,7 +70,7 @@ int FileResource::read(void* buffer, size_t size, size_t flags) { } /** - * @brief Write to a file resource + * @brief write to a file resource * * @param buffer The buffer to write from * @param size The number of bytes to write @@ -220,7 +220,7 @@ size_t DirectoryResource::entries_size() const { } /** - * @brief Read from a directory resource + * @brief read from a directory resource * * @param buffer The buffer to read into * @param size The number of bytes to read @@ -252,7 +252,7 @@ int DirectoryResource::read(void* buffer, size_t size, size_t flags) { } /** - * @brief Write to a directory resource + * @brief write to a directory resource * * @param buffer The buffer to write from * @param size The number of bytes to write diff --git a/kernel/src/gui/desktop.cpp b/kernel/src/gui/desktop.cpp index f4108b74..006b84ee 100644 --- a/kernel/src/gui/desktop.cpp +++ b/kernel/src/gui/desktop.cpp @@ -23,11 +23,10 @@ using namespace MaxOS::drivers::peripherals; * @param gc The graphics context to use */ Desktop::Desktop(GraphicsContext* gc) -: CompositeWidget(0, 0, gc->width(), gc->height()), - MouseEventHandler(), - m_graphics_context(gc), - colour(Colour(0xA8, 0xA8, 0xA8)) -{ + : CompositeWidget(0, 0, gc->width(), gc->height()), + MouseEventHandler(), + m_graphics_context(gc), + colour(Colour(0xA8, 0xA8, 0xA8)) { // Set the mouse m_position to the center of the screen m_mouse_x = gc->width() / 2; @@ -50,7 +49,7 @@ Desktop::~Desktop() = default; void Desktop::set_focus(Widget* widget) { // If there is a widget in focus then send a focus lost event to it - if (this->m_focussed_widget != nullptr) + if(this->m_focussed_widget != nullptr) this->m_focussed_widget->on_focus_lost(); // Focus the new widget and send a focus event to it @@ -78,12 +77,12 @@ void Desktop::bring_to_front(Widget* front_widget) { void Desktop::invert_mouse_cursor() { // Draw the horizontal line - for (int32_t x = m_mouse_x - 3; x <= m_mouse_x + 3; ++x) { + for(uint32_t x = m_mouse_x - 3; x <= m_mouse_x + 3; ++x) { m_graphics_context->invert_pixel(x, m_mouse_y); } // Draw the vertical line - for (int32_t y = m_mouse_y - 3; y <= m_mouse_y + 3; ++y) { + for(uint32_t y = m_mouse_y - 3; y <= m_mouse_y + 3; ++y) { m_graphics_context->invert_pixel(m_mouse_x, y); } } @@ -95,22 +94,21 @@ void Desktop::invert_mouse_cursor() { * @param start The start of the invalid areas * @param stop The end of the invalid areas */ -void Desktop::internal_invalidate(common::Rectangle& area, Vector>::iterator start, - Vector>::iterator stop) { +void Desktop::internal_invalidate(common::Rectangle& area, Vector>::iterator start, Vector>::iterator stop) { // Loop through the invalid rectangles - for (Vector>::iterator invaild_rect = start; invaild_rect != stop; invaild_rect++) { + for(Vector>::iterator invaild_rect = start; invaild_rect != stop; invaild_rect++) { // Check if the area intersects with the invalid rectangle - if (!area.intersects(*invaild_rect)) + if(!area.intersects(*invaild_rect)) continue; // Get the parts of the area that are covered by the invalid rectangle - Vector> coveredAreas = area.subtract(*invaild_rect); + Vector> covered_areas = area.subtract(*invaild_rect); // Invalidate the covered areas - for (auto& coveredArea: coveredAreas) - internal_invalidate(coveredArea, invaild_rect + 1, stop); + for(auto& covered_area : covered_areas) + internal_invalidate(covered_area, invaild_rect + 1, stop); // The entire area will be invalidated by now return; @@ -118,10 +116,10 @@ void Desktop::internal_invalidate(common::Rectangle& area, Vector>::iterator vectorPosition = m_invalid_areas.push_back(area); + Vector>::iterator vector_position = m_invalid_areas.push_back(area); // If the m_position is the last item then the invalidation buffer is full - if (vectorPosition == m_invalid_areas.end()) { + if(vector_position == m_invalid_areas.end()) { // Invalidate the entire desktop m_invalid_areas.clear(); @@ -139,13 +137,13 @@ void Desktop::internal_invalidate(common::Rectangle& area, Vector& area) { // Calculate the rectangle - int32_t topCornerX = area.left; - int32_t topCornerY = area.top; - int32_t bottomCornerX = area.left + area.width; - int32_t bottomCornerY = area.top + area.height; + int32_t top_corner_x = area.left; + int32_t top_corner_y = area.top; + int32_t bottom_corner_x = area.left + area.width; + int32_t bottom_corner_y = area.top + area.height; // Draw the background, a rectangle the size of the desktop of the given colour - gc->fill_rectangle(topCornerX, topCornerY, bottomCornerX, bottomCornerY, colour); + gc->fill_rectangle(top_corner_x, top_corner_y, bottom_corner_x, bottom_corner_y, colour); } /** @@ -156,17 +154,17 @@ void Desktop::draw_self(common::GraphicsContext* gc, common::Rectangle& void Desktop::add_child(Widget* child_widget) { // Check if the new widget is under the mouse - bool underMouse = child_widget->contains_coordinate(m_mouse_x, m_mouse_y); + bool under_mouse = child_widget->contains_coordinate(m_mouse_x, m_mouse_y); // If the mouse is over the widget then send a mouse leave event to the child widget as it is no longer under the mouse - if (underMouse) + if(under_mouse) CompositeWidget::on_mouse_leave_widget(m_mouse_x, m_mouse_y); // Add the widget to the desktop CompositeWidget::add_child(child_widget); // If the mouse is over the new widget then send a mouse enter event to the child widget - if (underMouse) + if(under_mouse) CompositeWidget::on_mouse_enter_widget(m_mouse_x, m_mouse_y); } @@ -178,19 +176,19 @@ void Desktop::add_child(Widget* child_widget) { void Desktop::on_time(common::Time const&) { // Check if anything is invalid and needs to be redrawn - if (m_invalid_areas.empty()) + if(m_invalid_areas.empty()) return; // Erase the mouse cursor invert_mouse_cursor(); // Loop through the invalid areas - while (!m_invalid_areas.empty()) { + while(!m_invalid_areas.empty()) { // Redraw the m_first_memory_chunk area - Rectangle invalidArea = *(m_invalid_areas.begin()); + Rectangle invalid_area = *(m_invalid_areas.begin()); m_invalid_areas.pop_front(); - draw(m_graphics_context, invalidArea); + draw(m_graphics_context, invalid_area); } @@ -221,30 +219,28 @@ void Desktop::invalidate(Rectangle& area) { void Desktop::on_mouse_move_event(int8_t x, int8_t y) { // Calculate the m_position of the mouse on the desktop - Rectangle desktopPosition = position(); - int32_t newMouseX = m_mouse_x + x; - int32_t newMouseY = m_mouse_y + y; + Rectangle desktop_position = position(); + uint32_t new_mouse_x = m_mouse_x + x; + uint32_t new_mouse_y = m_mouse_y + y; // Restrain the mouse to the desktop - if (newMouseX < 0) newMouseX = 0; - if (newMouseY < 0) newMouseY = 0; - if (newMouseX > desktopPosition.width) newMouseX = desktopPosition.width - 1; - if (newMouseY > desktopPosition.height) newMouseY = desktopPosition.height - 1; + if(new_mouse_x > desktop_position.width) new_mouse_x = desktop_position.width - 1; + if(new_mouse_y > desktop_position.height) new_mouse_y = desktop_position.height - 1; // Remove the old cursor from the screen as it will be redrawn in the new m_position invert_mouse_cursor(); // If a widget is being dragged then pass the event to it - if (m_dragged_widget != nullptr) - m_dragged_widget->on_mouse_move_event(newMouseX - m_mouse_x, newMouseY - m_mouse_y); + if(m_dragged_widget != nullptr) + m_dragged_widget->on_mouse_move_event(new_mouse_x - m_mouse_x, new_mouse_y - m_mouse_y); // Handle the mouse moving event (pass it to the widget that the mouse is over) - CompositeWidget::on_mouse_move_widget(m_mouse_x, m_mouse_y, newMouseX, - newMouseY); + CompositeWidget::on_mouse_move_widget(m_mouse_x, m_mouse_y, new_mouse_x, + new_mouse_y); // Update the mouse m_position - m_mouse_x = newMouseX; - m_mouse_y = newMouseY; + m_mouse_x = new_mouse_x; + m_mouse_y = new_mouse_y; // Draw the new cursor invert_mouse_cursor(); @@ -277,24 +273,24 @@ void Desktop::on_mouse_up_event(uint8_t button) { /** * @brief When a key is pressed pass the event to the widget that is currently focussed - * @param keyDownCode The key that was pressed - * @param keyDownState The state of the keyboard + * @param key_down_code The key that was pressed + * @param key_down_state The state of the keyboard */ -void Desktop::on_key_down(KeyCode keyDownCode, KeyboardState keyDownState) { +void Desktop::on_key_down(KeyCode key_down_code, const KeyboardState& key_down_state) { // Pass the event to the widget that is in focus - if (m_focussed_widget != nullptr) - m_focussed_widget->on_key_down(keyDownCode, keyDownState); + if(m_focussed_widget != nullptr) + m_focussed_widget->on_key_down(key_down_code, key_down_state); } /** * @brief When a key is pressed pass the event to the widget that is currently focussed - * @param keyUpCode The key that was pressed - * @param keyUpState The state of the keyboard + * @param key_up_code The key that was pressed + * @param key_up_state The state of the keyboard */ -void Desktop::on_key_up(KeyCode keyUpCode, KeyboardState keyUpState) { +void Desktop::on_key_up(KeyCode key_up_code, const KeyboardState& key_up_state) { // Pass the event to the widget that is in focus - if (m_focussed_widget != nullptr) - m_focussed_widget->on_key_up(keyUpCode, keyUpState); + if(m_focussed_widget != nullptr) + m_focussed_widget->on_key_up(key_up_code, key_up_state); } \ No newline at end of file diff --git a/kernel/src/gui/font.cpp b/kernel/src/gui/font.cpp index 189a5440..546007fb 100644 --- a/kernel/src/gui/font.cpp +++ b/kernel/src/gui/font.cpp @@ -22,7 +22,7 @@ using namespace MaxOS::gui; Font::Font(const uint8_t* font_data) { // Store the font data - for (int i = 0; i < 2048; ++i) { + for(int i = 0; i < 2048; ++i) { m_font8x8[i] = font_data[i]; } } @@ -39,8 +39,8 @@ Font::~Font() = default; * @param text The text to draw */ void Font::draw_text(int32_t x, int32_t y, common::Colour foreground_colour, - common::Colour background_colour, - common::GraphicsContext* context, string text) { + common::Colour background_colour, + common::GraphicsContext* context, string text) { // Calculate the rectangle of the text int32_t top = 0; @@ -65,67 +65,67 @@ void Font::draw_text(int32_t x, int32_t y, common::Colour foreground_colour, * @param background_colour The background colour * @param context The graphics context to draw the text on * @param text The text to draw - * @param limitArea The area of the text to draw + * @param limit_area The area of the text to draw */ void Font::draw_text(int32_t x, int32_t y, common::Colour foreground_colour, - common::Colour background_colour, - common::GraphicsContext* context, string text, - common::Rectangle limitArea) { + common::Colour background_colour, + common::GraphicsContext* context, string text, + common::Rectangle limit_area) { // Convert the colours uint32_t foreground = context->colour_to_int(foreground_colour); uint32_t background = context->colour_to_int(background_colour); // Ensure the area is within the actual area of the text - if (limitArea.top < 0) { - limitArea.height += limitArea.top; - limitArea.top = 0; + if(limit_area.top < 0) { + limit_area.height += limit_area.top; + limit_area.top = 0; } - if (limitArea.left < 0) { - limitArea.width += limitArea.left; - limitArea.left = 0; + if(limit_area.left < 0) { + limit_area.width += limit_area.left; + limit_area.left = 0; } // Clamp the height and width max - if (limitArea.top + limitArea.height > (int) get_text_height(text)) - limitArea.height = get_text_height(text) - limitArea.top; + if(limit_area.top + limit_area.height > (int) get_text_height(text)) + limit_area.height = get_text_height(text) - limit_area.top; - if (limitArea.left + limitArea.width > (int) get_text_width(text)) - limitArea.width = get_text_width(text) - limitArea.left; + if(limit_area.left + limit_area.width > (int) get_text_width(text)) + limit_area.width = get_text_width(text) - limit_area.left; // Calculate limits - int32_t xLimit = limitArea.left + limitArea.width; - int32_t yLimit = limitArea.top + limitArea.height; + int32_t x_limit = limit_area.left + limit_area.width; + int32_t y_limit = limit_area.top + limit_area.height; // Draw the text from top to bottom - for (int yBitMapOffset = limitArea.top; yBitMapOffset < yLimit; yBitMapOffset++) { - for (int xBitMapOffset = limitArea.left; xBitMapOffset < xLimit; ++xBitMapOffset) { + for(int y_bit_map_offset = limit_area.top; y_bit_map_offset < y_limit; y_bit_map_offset++) { + for(int x_bit_map_offset = limit_area.left; x_bit_map_offset < x_limit; ++x_bit_map_offset) { // If the y is the middle then add a strikethrough - if (is_strikethrough && yBitMapOffset == yLimit / 2) { + if(is_strikethrough && y_bit_map_offset == y_limit / 2) { // Draw the pixel - context->putPixel(x + xBitMapOffset, y + yBitMapOffset, foreground); + context->put_pixel(x + x_bit_map_offset, y + y_bit_map_offset, foreground); continue; } // If the y is the bottom then add an underline - if (is_underlined && yBitMapOffset == yLimit - 1) { + if(is_underlined && y_bit_map_offset == y_limit - 1) { // Draw the pixel - context->putPixel(x + xBitMapOffset, y + yBitMapOffset, foreground); + context->put_pixel(x + x_bit_map_offset, y + y_bit_map_offset, foreground); continue; } // Get the character - uint8_t character = text[xBitMapOffset / 8]; + uint8_t character = text[x_bit_map_offset / 8]; // Check if this pixel is set or not - bool set = m_font8x8[(uint16_t) character * 8 + yBitMapOffset] & (128 >> (xBitMapOffset % 8)); + bool set = m_font8x8[(uint16_t) character * 8 + y_bit_map_offset] & (128 >> (x_bit_map_offset % 8)); // Draw the pixel - context->putPixel(x + xBitMapOffset, y + yBitMapOffset, set ? foreground : background); + context->put_pixel(x + x_bit_map_offset, y + y_bit_map_offset, set ? foreground : background); } } @@ -137,7 +137,7 @@ void Font::draw_text(int32_t x, int32_t y, common::Colour foreground_colour, * @param text The text to get the height of * @return The height of the text */ -int32_t Font::get_text_height(string text) { +size_t Font::get_text_height(string text) { return 8; @@ -149,7 +149,7 @@ int32_t Font::get_text_height(string text) { * @param text The text to get the width of * @return The width of the text */ -int32_t Font::get_text_width(string text) { +size_t Font::get_text_width(string text) { return text.length() * 8; } diff --git a/kernel/src/gui/widget.cpp b/kernel/src/gui/widget.cpp index 0920ce47..d921160e 100644 --- a/kernel/src/gui/widget.cpp +++ b/kernel/src/gui/widget.cpp @@ -58,10 +58,10 @@ void Widget::invalidate() { Coordinates coordinates = absolute_coordinates(Coordinates(0, 0)); // Create a rectangle with the absolute coordinates and the size of the widget - Rectangle invalidArea = Rectangle(coordinates.first, coordinates.second, m_position.width, m_position.height); + Rectangle invalid_area = Rectangle(coordinates.first, coordinates.second, m_position.width, m_position.height); // Invalidate the area - invalidate(invalidArea); + invalidate(invalid_area); } @@ -410,20 +410,20 @@ void CompositeWidget::add_child(Widget* child) { /** * @brief Passes the event to the child that the mouse is over. (Event handling should be done by the derived class) * - * @param toX The x coordinate of the mouse - * @param toY The y coordinate of the mouse + * @param to_x The x coordinate of the mouse + * @param to_y The y coordinate of the mouse */ -void CompositeWidget::on_mouse_enter_widget(uint32_t toX, uint32_t toY) { +void CompositeWidget::on_mouse_enter_widget(uint32_t to_x, uint32_t to_y) { for (auto& child_widget: m_children) { // Check if the mouse is in the child Rectangle child_area = child_widget->position(); - if (child_area.contains(toX, toY)) { + if (child_area.contains(to_x, to_y)) { // Get the position of the mouse relative to the child - uint32_t child_x = toX - child_area.left; - uint32_t child_y = toY - child_area.top; + uint32_t child_x = to_x - child_area.left; + uint32_t child_y = to_y - child_area.top; // Call the child's on_mouse_enter_widget function child_widget->on_mouse_enter_widget(child_x, child_y); @@ -437,20 +437,20 @@ void CompositeWidget::on_mouse_enter_widget(uint32_t toX, uint32_t toY) { /** * @brief Passes the event to the child that the mouse is over. (Event handling should be done by the derived class) * - * @param fromX The x coordinate of the mouse - * @param fromY The y coordinate of the mouse + * @param from_x The x coordinate of the mouse + * @param from_y The y coordinate of the mouse */ -void CompositeWidget::on_mouse_leave_widget(uint32_t fromX, uint32_t fromY) { +void CompositeWidget::on_mouse_leave_widget(uint32_t from_x, uint32_t from_y) { for (auto& child_widget: m_children) { // Check if the mouse is in the child Rectangle child_area = child_widget->position(); - if (child_area.contains(fromX, fromY)) { + if (child_area.contains(from_x, from_y)) { // Get the position of the mouse relative to the child - uint32_t child_x = fromX - child_area.left; - uint32_t child_y = fromY - child_area.top; + uint32_t child_x = from_x - child_area.left; + uint32_t child_y = from_y - child_area.top; // Call the child's on_mouse_leave_widget function child_widget->on_mouse_leave_widget(child_x, child_y); @@ -464,12 +464,12 @@ void CompositeWidget::on_mouse_leave_widget(uint32_t fromX, uint32_t fromY) { /** * @brief Passes the event to the child that the mouse is over, also generates a leave/enter event for children * - * @param fromX The x coordinate of the mouse - * @param fromY The y coordinate of the mouse - * @param toX The x coordinate of the mouse - * @param toY The y coordinate of the mouse + * @param from_x The x coordinate of the mouse + * @param from_y The y coordinate of the mouse + * @param to_x The x coordinate of the mouse + * @param to_y The y coordinate of the mouse */ -void CompositeWidget::on_mouse_move_widget(uint32_t fromX, uint32_t fromY, uint32_t toX, uint32_t toY) { +void CompositeWidget::on_mouse_move_widget(uint32_t from_x, uint32_t from_y, uint32_t to_x, uint32_t to_y) { Widget* left_child = nullptr; Widget* entered_child = nullptr; @@ -478,8 +478,8 @@ void CompositeWidget::on_mouse_move_widget(uint32_t fromX, uint32_t fromY, uint3 // Check if the mouse is in the child Rectangle child_area = child_widget->position(); - bool mouse_in_from = child_area.contains(fromX, fromY); - bool mouse_in_to = child_area.contains(toX, toY); + bool mouse_in_from = child_area.contains(from_x, from_y); + bool mouse_in_to = child_area.contains(to_x, to_y); // If the mouse started in the child if (mouse_in_from) { @@ -491,7 +491,7 @@ void CompositeWidget::on_mouse_move_widget(uint32_t fromX, uint32_t fromY, uint3 } // Mouse still in the child - child_widget->on_mouse_move_widget(fromX, fromY, toX, toY); + child_widget->on_mouse_move_widget(from_x, from_y, to_x, to_y); } else { @@ -502,10 +502,10 @@ void CompositeWidget::on_mouse_move_widget(uint32_t fromX, uint32_t fromY, uint3 // Pass the events to the child if (left_child != nullptr) - left_child->on_mouse_leave_widget(fromX, fromY); + left_child->on_mouse_leave_widget(from_x, from_y); if (entered_child != nullptr) - entered_child->on_mouse_enter_widget(toX, toY); + entered_child->on_mouse_enter_widget(to_x, to_y); } } diff --git a/kernel/src/gui/widgets/button.cpp b/kernel/src/gui/widgets/button.cpp index 88119fcc..d87c3723 100644 --- a/kernel/src/gui/widgets/button.cpp +++ b/kernel/src/gui/widgets/button.cpp @@ -93,12 +93,12 @@ void Button::draw(GraphicsContext* gc, Rectangle& area) { Widget::draw(gc, area); // Get the absolute m_position of the button - Coordinates buttonCoordinates = absolute_coordinates(Coordinates(0, 0)); - Rectangle buttonPosition = position(); + Coordinates button_coordinates = absolute_coordinates(Coordinates(0, 0)); + Rectangle button_position = position(); // Get the x and y m_position of the button - int32_t x = buttonCoordinates.first; - int32_t y = buttonCoordinates.second; + int32_t x = button_coordinates.first; + int32_t y = button_coordinates.second; // Draw the background for the button gc->fill_rectangle(x + area.left, y + area.top, x + area.left + area.width, @@ -107,7 +107,7 @@ void Button::draw(GraphicsContext* gc, Rectangle& area) { // Draw the border // Top Border - if (area.intersects(Rectangle(0, 0, buttonPosition.width, 1))) { + if (area.intersects(Rectangle(0, 0, button_position.width, 1))) { // Start in the top left corner of the button and end in the top right corner gc->draw_line(x + area.left, y, x + area.left + area.width - 1, y, @@ -115,7 +115,7 @@ void Button::draw(GraphicsContext* gc, Rectangle& area) { } // Left Border - if (area.intersects(Rectangle(0, 0, 1, buttonPosition.height))) { + if (area.intersects(Rectangle(0, 0, 1, button_position.height))) { // Start in the top left corner and end in the bottom left corner gc->draw_line(x, y + area.top, x, y + area.top + area.height - 1, @@ -123,27 +123,27 @@ void Button::draw(GraphicsContext* gc, Rectangle& area) { } // Right Border - if (area.intersects(Rectangle(0, buttonPosition.height - 1, buttonPosition.width, 1))) { + if (area.intersects(Rectangle(0, button_position.height - 1, button_position.width, 1))) { // Start in the top right corner and end in the bottom right corner - gc->draw_line(x + area.left, y + buttonPosition.height - 1, + gc->draw_line(x + area.left, y + button_position.height - 1, x + area.left + area.width - 1, - y + buttonPosition.height - 1, border_colour); + y + button_position.height - 1, border_colour); } // Bottom Border - if (area.intersects(Rectangle(buttonPosition.width - 1, 0, 1, buttonPosition.height))) { + if (area.intersects(Rectangle(button_position.width - 1, 0, 1, button_position.height))) { // Start in the bottom left corner and end in the bottom right corner - gc->draw_line(x + buttonPosition.width - 1, y + area.top, - x + buttonPosition.width - 1, + gc->draw_line(x + button_position.width - 1, y + area.top, + x + button_position.width - 1, y + area.top + area.height - 1, border_colour); } // Draw the text - common::Rectangle textArea(area.left - 1, area.top - 1, area.width, area.height); + common::Rectangle text_area(area.left - 1, area.top - 1, area.width, area.height); font.draw_text(x + 1, y + 1, foreground_colour, background_colour, gc, text, - textArea); + text_area); } diff --git a/kernel/src/gui/widgets/inputbox.cpp b/kernel/src/gui/widgets/inputbox.cpp index 3eec10a9..81f43441 100644 --- a/kernel/src/gui/widgets/inputbox.cpp +++ b/kernel/src/gui/widgets/inputbox.cpp @@ -39,7 +39,7 @@ Event* InputBoxEventHandler::on_event(Event* eve /** * @brief Event triggered when the text in the input box is changed */ -void InputBoxEventHandler::on_input_box_text_changed(string) { +void InputBoxEventHandler::on_input_box_text_changed(const string& text) { } @@ -98,7 +98,7 @@ void InputBox::draw(GraphicsContext* gc, Rectangle& area) { // Get the absolute m_position of the input box Coordinates inputBoxCoordinates = absolute_coordinates(Coordinates(0, 0)); - Rectangle inputBoxPosition = position(); + Rectangle input_box_position = position(); // Get the x and y m_position of the input box int32_t x = inputBoxCoordinates.first; @@ -111,7 +111,7 @@ void InputBox::draw(GraphicsContext* gc, Rectangle& area) { // Draw the border // Top Border - if (area.intersects(Rectangle(0, 0, inputBoxPosition.width, 1))) { + if (area.intersects(Rectangle(0, 0, input_box_position.width, 1))) { // Start in the top left corner of the button and end in the top right corner gc->draw_line(x + area.left, y, x + area.left + area.width - 1, y, @@ -119,7 +119,7 @@ void InputBox::draw(GraphicsContext* gc, Rectangle& area) { } // Left Border - if (area.intersects(Rectangle(0, 0, 1, inputBoxPosition.height))) { + if (area.intersects(Rectangle(0, 0, 1, input_box_position.height))) { // Start in the top left corner and end in the bottom left corner gc->draw_line(x, y + area.top, x, y + area.top + area.height - 1, @@ -127,26 +127,26 @@ void InputBox::draw(GraphicsContext* gc, Rectangle& area) { } // Right Border - if (area.intersects(Rectangle(0, inputBoxPosition.height - 1, inputBoxPosition.width, 1))) { + if (area.intersects(Rectangle(0, input_box_position.height - 1, input_box_position.width, 1))) { // Start in the top right corner and end in the bottom right corner - gc->draw_line(x + area.left, y + inputBoxPosition.height - 1, + gc->draw_line(x + area.left, y + input_box_position.height - 1, x + area.left + area.width - 1, - y + inputBoxPosition.height - 1, border_colour); + y + input_box_position.height - 1, border_colour); } // Bottom Border - if (area.intersects(Rectangle(inputBoxPosition.width - 1, 0, 1, inputBoxPosition.height))) { + if (area.intersects(Rectangle(input_box_position.width - 1, 0, 1, input_box_position.height))) { // Start in the bottom left corner and end in the bottom right corner - gc->draw_line(x + inputBoxPosition.width - 1, y + area.top, - x + inputBoxPosition.width - 1, + gc->draw_line(x + input_box_position.width - 1, y + area.top, + x + input_box_position.width - 1, y + area.top + area.height - 1, border_colour); } // Draw the text - common::Rectangle textArea(area.left - 1, area.top - 1, area.width, area.height); - font.draw_text(x + 1, y + 1, foreground_colour, background_colour, gc, m_widget_text, textArea); + common::Rectangle text_area(area.left - 1, area.top - 1, area.width, area.height); + font.draw_text(x + 1, y + 1, foreground_colour, background_colour, gc, m_widget_text, text_area); } /** @@ -175,7 +175,7 @@ void InputBox::on_focus_lost() { * @param key_down_code The key being pressed * @param key_down_state The state of the key being pressed */ -void InputBox::on_key_down(KeyCode key_down_code, KeyboardState key_down_state) { +void InputBox::on_key_down(KeyCode key_down_code, const KeyboardState& key_down_state) { // Handle the key press switch (key_down_code) { @@ -234,7 +234,7 @@ void InputBox::on_key_down(KeyCode key_down_code, KeyboardState key_down_state) // Insert the new character m_widget_text[cursor_position + 1] = m_widget_text[cursor_position]; - m_widget_text[cursor_position] = (uint8_t) key_down_code; + m_widget_text[cursor_position] = (char)key_down_code; cursor_position++; } else { diff --git a/kernel/src/gui/widgets/text.cpp b/kernel/src/gui/widgets/text.cpp index 7e6047fa..c713ee48 100644 --- a/kernel/src/gui/widgets/text.cpp +++ b/kernel/src/gui/widgets/text.cpp @@ -49,7 +49,7 @@ void Text::draw(GraphicsContext* gc, Rectangle& area) { // Get the absolute m_position of the text Coordinates textCoordinates = absolute_coordinates(Coordinates(0, 0)); - Rectangle textPosition = position(); + Rectangle text_position = position(); // Get the x and y m_position of the text int32_t x = textCoordinates.first; diff --git a/kernel/src/gui/window.cpp b/kernel/src/gui/window.cpp index 5d131ce1..002ca1d8 100644 --- a/kernel/src/gui/window.cpp +++ b/kernel/src/gui/window.cpp @@ -57,12 +57,12 @@ Window::Window(int32_t left, int32_t top, uint32_t width, uint32_t height, const /** * @brief Construct a new Window object that contains a specific widget with a title. The window sizes itself to fit the widget. * - * @param containedWidget The widget to contain within the window + * @param contained_widget The widget to contain within the window * @param title_text The text to display in the title bar of the window */ -Window::Window(Widget* containedWidget, const string& title_text) -: CompositeWidget(0, 0, containedWidget->position().width + 2 * 5 + 2, containedWidget->position().height + 2 * 5 + 10 + 2), - m_title(0, -(10 + 5) + 2, containedWidget->position().width, 10 + 5 - 3, title_text), +Window::Window(Widget* contained_widget, const string& title_text) +: CompositeWidget(0, 0, contained_widget->position().width + 2 * 5 + 2, contained_widget->position().height + 2 * 5 + 10 + 2), + m_title(0, -(10 + 5) + 2, contained_widget->position().width, 10 + 5 - 3, title_text), m_mover(this), m_resizer_top(this), m_resizer_bottom(this), @@ -87,7 +87,7 @@ Window::Window(Widget* containedWidget, const string& title_text) // Add the title to the window Window::add_child(&m_title); - Window::add_child(containedWidget); + Window::add_child(contained_widget); } Window::~Window() = default; @@ -155,14 +155,14 @@ void Window::draw_self(common::GraphicsContext* gc, common::Rectangle& // Get the positioning of the window Coordinates window_absolute_position = CompositeWidget::absolute_coordinates(Coordinates(0, 0)); - Rectangle windowPosition = this->position(); + Rectangle window_position = this->position(); int32_t window_x = window_absolute_position.first; int32_t window_y = window_absolute_position.second; // Create an area for the window contents Rectangle window_contents_area(frame_thickness, frame_thickness + title_bar_height, - windowPosition.width - 2 * frame_thickness, - windowPosition.height - 2 * frame_thickness - title_bar_height); + window_position.width - 2 * frame_thickness, + window_position.height - 2 * frame_thickness - title_bar_height); // Draw the window contents if they are in the area to draw if (window_contents_area.intersects(area)) { @@ -173,7 +173,7 @@ void Window::draw_self(common::GraphicsContext* gc, common::Rectangle& } // Draw the frame if it is in the area to draw - Rectangle window_frame_top_area(frame_thickness, 0, windowPosition.width - 2 * frame_thickness, + Rectangle window_frame_top_area(frame_thickness, 0, window_position.width - 2 * frame_thickness, frame_thickness + title_bar_height); if (window_frame_top_area.intersects(area)) { Rectangle frame_drawable = window_frame_top_area.intersection(area); @@ -183,8 +183,8 @@ void Window::draw_self(common::GraphicsContext* gc, common::Rectangle& } // Draw the bottom of the window frame - Rectangle window_frame_bottom_area(frame_thickness, windowPosition.height - frame_thickness, - windowPosition.width - 2 * frame_thickness, frame_thickness); + Rectangle window_frame_bottom_area(frame_thickness, window_position.height - frame_thickness, + window_position.width - 2 * frame_thickness, frame_thickness); if (window_frame_bottom_area.intersects(area)) { Rectangle bottom_drawable = window_frame_bottom_area.intersection(area); gc->fill_rectangle(window_x + bottom_drawable.left, window_y + bottom_drawable.top, @@ -193,7 +193,7 @@ void Window::draw_self(common::GraphicsContext* gc, common::Rectangle& } // Draw the left of the window frame - Rectangle window_frame_left_area(0, 0, frame_thickness, windowPosition.height); + Rectangle window_frame_left_area(0, 0, frame_thickness, window_position.height); if (window_frame_left_area.intersects(area)) { Rectangle left_drawable = window_frame_left_area.intersection(area); gc->fill_rectangle(window_x + left_drawable.left, window_y + left_drawable.top, @@ -202,8 +202,8 @@ void Window::draw_self(common::GraphicsContext* gc, common::Rectangle& } // Draw the right of the window frame - Rectangle window_frame_right_area(windowPosition.width - frame_thickness, 0, frame_thickness, - windowPosition.height); + Rectangle window_frame_right_area(window_position.width - frame_thickness, 0, frame_thickness, + window_position.height); if (window_frame_right_area.intersects(area)) { Rectangle right_drawable = window_frame_right_area.intersection(area); gc->fill_rectangle(window_x + right_drawable.left, window_y + right_drawable.top, @@ -223,9 +223,9 @@ void Window::add_child(Widget* child) { if (child != nullptr) { // Change the position of the child to be inside the window contents - Rectangle childPosition = child->position(); - child->move(childPosition.left + frame_thickness + 1, - childPosition.top + frame_thickness + title_bar_height + 1); + Rectangle child_position = child->position(); + child->move(child_position.left + frame_thickness + 1, + child_position.top + frame_thickness + title_bar_height + 1); } diff --git a/kernel/src/hardwarecommunication/acpi.cpp b/kernel/src/hardwarecommunication/acpi.cpp index 8e93a27c..8d13c8ac 100644 --- a/kernel/src/hardwarecommunication/acpi.cpp +++ b/kernel/src/hardwarecommunication/acpi.cpp @@ -15,11 +15,13 @@ using namespace MaxOS::memory; using namespace MaxOS::common; /** - * @brief Construct a new Advanced Configuration And Power Interface object. Maps the ACPI headers and tables into the higher half. + * @brief Construct a new Advanced Configuration And Power Interface object. Maps the ACPI headers and tables into the + * higher half. * * @param multiboot The multiboot information structure to get the ACPI information from */ -AdvancedConfigurationAndPowerInterface::AdvancedConfigurationAndPowerInterface(system::Multiboot* multiboot) { +AdvancedConfigurationAndPowerInterface::AdvancedConfigurationAndPowerInterface(system::Multiboot* multiboot) +: m_header(nullptr) { Logger::INFO() << "Setting up ACPI\n"; @@ -30,7 +32,7 @@ AdvancedConfigurationAndPowerInterface::AdvancedConfigurationAndPowerInterface(s m_using_new_acpi = multiboot->old_acpi() == nullptr; Logger::DEBUG() << "CPU Supports " << (m_using_new_acpi ? "New" : "Old") << " ACPI\n"; - if (m_using_new_acpi) + if(m_using_new_acpi) m_rsdp2 = (RSDPDescriptor2*) (multiboot->new_acpi() + 1); else m_rsdp = (RSDPDescriptor*) (multiboot->old_acpi() + 1); @@ -39,13 +41,14 @@ AdvancedConfigurationAndPowerInterface::AdvancedConfigurationAndPowerInterface(s uint64_t physical_address = m_using_new_acpi ? m_rsdp2->xsdt_address : m_rsdp->rsdt_address; void* virtual_address = map_descriptor(physical_address); ASSERT(virtual_address != nullptr, "Failed to map ACPI table"); - Logger::DEBUG() << "XSDT/RSDT: physical: 0x" << physical_address << ", virtual: 0x" << (uint64_t)virtual_address << "\n"; + Logger::DEBUG() << "XSDT/RSDT: physical: 0x" << physical_address << ", virtual: 0x" << (uint64_t) virtual_address + << "\n"; // Load - if (m_using_new_acpi) - m_xsdt = (XSDT*)virtual_address; + if(m_using_new_acpi) + m_xsdt = (XSDT*) virtual_address; else - m_rsdt = (RSDT*)virtual_address; + m_rsdt = (RSDT*) virtual_address; // Map the Tables Logger::DEBUG() << "Mapping ACPI Tables\n"; @@ -65,7 +68,7 @@ AdvancedConfigurationAndPowerInterface::~AdvancedConfigurationAndPowerInterface( void AdvancedConfigurationAndPowerInterface::map_tables(uint8_t pointer_size) { size_t entries = (m_header->length - sizeof(ACPISDTHeader)) / pointer_size; - for (uint32_t i = 0; i < entries; i++) { + for(uint32_t i = 0; i < entries; i++) { // Get the address (aligned to page) auto address = (uint64_t) (m_using_new_acpi ? m_xsdt->pointers[i] : get_rsdt_pointer(i)); @@ -88,11 +91,11 @@ virtual_address_t* AdvancedConfigurationAndPowerInterface::map_descriptor(uint64 // Map that page virtual_address_t* virtual_address = PhysicalMemoryManager::to_io_region(page); - PhysicalMemoryManager::s_current_manager -> map((physical_address_t*)page, virtual_address, PRESENT | WRITE); - PhysicalMemoryManager::s_current_manager -> reserve(page); + PhysicalMemoryManager::s_current_manager->map((physical_address_t*) page, virtual_address, PRESENT | WRITE); + PhysicalMemoryManager::s_current_manager->reserve(page); // Read the length - m_header = (ACPISDTHeader*)((uint8_t*)virtual_address + offset); + m_header = (ACPISDTHeader*) ((uint8_t*) virtual_address + offset); ASSERT(m_header->length >= sizeof(ACPISDTHeader), "ACPI table too short"); // Where to stop looping @@ -100,10 +103,10 @@ virtual_address_t* AdvancedConfigurationAndPowerInterface::map_descriptor(uint64 end = PhysicalMemoryManager::align_direct_to_page(end); // Map the remaining pages - for (uint64_t page_i = page + PAGE_SIZE; page_i <= end; page_i += PAGE_SIZE) { + for(uint64_t page_i = page + PAGE_SIZE; page_i <= end; page_i += PAGE_SIZE) { virtual_address_t* virtual_i = PhysicalMemoryManager::to_io_region(page_i); - PhysicalMemoryManager::s_current_manager -> map((physical_address_t*)page_i, virtual_i, PRESENT | WRITE); + PhysicalMemoryManager::s_current_manager->map((physical_address_t*) page_i, virtual_i, PRESENT | WRITE); PhysicalMemoryManager::s_current_manager->reserve(page_i); } @@ -119,7 +122,7 @@ virtual_address_t* AdvancedConfigurationAndPowerInterface::map_descriptor(uint64 * @todo UBSan issue: type mismatch so using memcpy as a workaround */ uint64_t AdvancedConfigurationAndPowerInterface::get_rsdt_pointer(size_t index) { - uint8_t* raw = (uint8_t*) m_rsdt; + auto raw = (uint8_t*) m_rsdt; size_t offset = sizeof(ACPISDTHeader) + index * sizeof(uint32_t); // Ensure offset is within mapped header length (optional but safe) @@ -144,7 +147,7 @@ bool AdvancedConfigurationAndPowerInterface::validate(const char* descriptor, si uint32_t sum = 0; // Calculate the checksum - for (uint32_t i = 0; i < length; i++) + for(uint32_t i = 0; i < length; i++) sum += ((char*) descriptor)[i]; // Check if the checksum is valid @@ -161,10 +164,10 @@ ACPISDTHeader* AdvancedConfigurationAndPowerInterface::find(char const* signatur // Get the number of entries size_t entries = (m_header->length - sizeof(ACPISDTHeader)) / sizeof(uint32_t); - if (m_using_new_acpi) entries = (m_header->length - sizeof(ACPISDTHeader)) / sizeof(uint64_t); + if(m_using_new_acpi) entries = (m_header->length - sizeof(ACPISDTHeader)) / sizeof(uint64_t); // Loop through all the entries - for (size_t i = 0; i < entries; ++i) { + for(size_t i = 0; i < entries; ++i) { // Get the entry auto* header = (ACPISDTHeader*) (m_using_new_acpi ? m_xsdt->pointers[i] : get_rsdt_pointer(i)); @@ -173,7 +176,7 @@ ACPISDTHeader* AdvancedConfigurationAndPowerInterface::find(char const* signatur header = (ACPISDTHeader*) PhysicalMemoryManager::to_io_region((uint64_t) header); // Check if the signature matches - if (strncmp(header->signature, signature, 4)) + if(strncmp(header->signature, signature, 4)) return header; } @@ -194,7 +197,7 @@ bool AdvancedConfigurationAndPowerInterface::valid_checksum() { // Calculate the checksum uint8_t sum = 0; - for (uint32_t i = 0; i < length; i++) + for(uint32_t i = 0; i < length; i++) sum += check[i]; return sum == 0; diff --git a/kernel/src/hardwarecommunication/apic.cpp b/kernel/src/hardwarecommunication/apic.cpp index dbd6ce75..1c0bb893 100644 --- a/kernel/src/hardwarecommunication/apic.cpp +++ b/kernel/src/hardwarecommunication/apic.cpp @@ -68,7 +68,7 @@ LocalAPIC::LocalAPIC() { LocalAPIC::~LocalAPIC() = default; /** - * @brief Read a value from the apic register using the MSR or memory I/O depending on the local apic version + * @brief read a value from the apic register using the MSR or memory I/O depending on the local apic version * * @param reg The register to read * @return The value of the register @@ -83,7 +83,7 @@ uint32_t LocalAPIC::read(uint32_t reg) const { } /** - * @brief Write a value to the apic register using the MSR or memory I/O depending on the local apic version + * @brief write a value to the apic register using the MSR or memory I/O depending on the local apic version * * @param reg The register to write to * @param value The value to write @@ -123,12 +123,12 @@ void LocalAPIC::send_eoi() const { } /** - * @brief Send the init IPI to another apic + * @brief send the init IPI to another apic * * @param apic_id The id of the apic to send to * @param assert Is this an assert code (drive / release the signal) */ -void LocalAPIC::send_init(uint8_t apic_id, bool assert) { +void LocalAPIC::send_init(uint8_t apic_id, bool assert) const { uint32_t icr_low = 0; @@ -162,12 +162,12 @@ void LocalAPIC::send_init(uint8_t apic_id, bool assert) { } /** - * @brief Send the start up IPI to another apic + * @brief send the start up IPI to another apic * * @param apic_id The apic to send it to * @param vector Where to start executing */ -void LocalAPIC::send_startup(uint8_t apic_id, uint8_t vector) { +void LocalAPIC::send_startup(uint8_t apic_id, uint8_t vector) const { if (!m_x2apic) { @@ -289,7 +289,7 @@ MADTEntry* IOAPIC::get_madt_item(MADT_TYPE type, uint8_t index) { } /** - * @brief Read a value from a IO Apic register + * @brief read a value from a IO Apic register * * @param reg The register to read from * @return The value at the register @@ -304,7 +304,7 @@ uint32_t IOAPIC::read(uint32_t reg) const { } /** - * @brief Write a value to an IO Apic register + * @brief write a value to an IO Apic register * * @param reg The register to write to * @param value The value to set the register to @@ -319,12 +319,12 @@ void IOAPIC::write(uint32_t reg, uint32_t value) const { } /** - * @brief Read a redirect entry into a buffer + * @brief read a redirect entry into a buffer * * @param index The index of the entry * @param entry The buffer to read into */ -void IOAPIC::read_redirect(uint8_t index, RedirectionEntry* entry) { +void IOAPIC::read_redirect(uint8_t index, RedirectionEntry* entry) const { // Check bounds if (index < 0x10 || index > 0x3F) @@ -337,12 +337,12 @@ void IOAPIC::read_redirect(uint8_t index, RedirectionEntry* entry) { } /** - * @brief Write a redirect entry from a buffer + * @brief write a redirect entry from a buffer * * @param index The index of the entry * @param entry The buffer to write into */ -void IOAPIC::write_redirect(uint8_t index, RedirectionEntry* entry) { +void IOAPIC::write_redirect(uint8_t index, RedirectionEntry* entry) const { // Check bounds if (index < 0x10 || index > 0x3F) diff --git a/kernel/src/hardwarecommunication/interrupts.cpp b/kernel/src/hardwarecommunication/interrupts.cpp index 0fb978f6..5bd7c2e1 100644 --- a/kernel/src/hardwarecommunication/interrupts.cpp +++ b/kernel/src/hardwarecommunication/interrupts.cpp @@ -203,8 +203,7 @@ void InterruptManager::activate() { Logger::INFO() << "Activating Interrupts \n"; // Deactivate the current (old) interrupt manager - if (s_active_interrupt_manager != nullptr) - s_active_interrupt_manager->deactivate(); + InterruptManager::deactivate(); // Set the current interrupt manager and start interrupts s_active_interrupt_manager = this; diff --git a/kernel/src/hardwarecommunication/pci.cpp b/kernel/src/hardwarecommunication/pci.cpp index cbdb2c9e..7f6e8519 100644 --- a/kernel/src/hardwarecommunication/pci.cpp +++ b/kernel/src/hardwarecommunication/pci.cpp @@ -178,33 +178,33 @@ void PCIController::select_drivers(DriverSelectorEventHandler* handler) { for (int bus = 0; bus < 8; ++bus) { for (int device = 0; device < 32; ++device) { - int numFunctions = (device_has_functions(bus, device)) ? 8 : 1; + int num_functions = (device_has_functions(bus, device)) ? 8 : 1; - for (int function = 0; function < numFunctions; ++function) { + for (int function = 0; function < num_functions; ++function) { // Get the device descriptor, if the vendor id is 0x0000 or 0xFFFF, the device is not present/ready - PCIDeviceDescriptor deviceDescriptor = get_device_descriptor(bus, device, - function); - if (deviceDescriptor.vendor_id == 0x0000 || deviceDescriptor.vendor_id == 0x0001 || - deviceDescriptor.vendor_id == 0xFFFF) + PCIDeviceDescriptor device_descriptor = get_device_descriptor(bus, device, + function); + if (device_descriptor.vendor_id == 0x0000 || device_descriptor.vendor_id == 0x0001 || + device_descriptor.vendor_id == 0xFFFF) continue; // Get the earliest port number - for (int barNum = 5; barNum >= 0; barNum--) { - BaseAddressRegister bar = get_base_address_register(bus, device, function, barNum); + for (int bar_num = 5; bar_num >= 0; bar_num--) { + BaseAddressRegister bar = get_base_address_register(bus, device, function, bar_num); if (bar.address && (bar.type == BARType::InputOutput)) - deviceDescriptor.port_base = (uint64_t) bar.address; + device_descriptor.port_base = (uint64_t) bar.address; } - Logger::DEBUG() << "DEVICE FOUND: " << deviceDescriptor.get_type() << " - "; + Logger::DEBUG() << "DEVICE FOUND: " << device_descriptor.get_type() << " - "; // Select the driver and print information about the device - Driver* driver = get_driver(deviceDescriptor); + Driver* driver = get_driver(device_descriptor); if (driver != nullptr) { handler->on_driver_selected(driver); Logger::Out() << driver->vendor_name() << " " << driver->device_name(); } else { - list_known_device(deviceDescriptor); + list_known_device(device_descriptor); } Logger::Out() << "\n"; @@ -440,8 +440,8 @@ BaseAddressRegister PCIController::get_base_address_register(uint16_t bus, uint1 BaseAddressRegister result{}; // Only types 0x00 (normal devices) and 0x01 (PCI-to-PCI bridges) are supported: - uint32_t headerType = read(bus, device, function, 0x0E); - if (headerType & 0x3F) + uint32_t header_type = read(bus, device, function, 0x0E); + if (header_type & 0x3F) return result; // read the base address register diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp index 910ad30d..52b2fc2b 100644 --- a/kernel/src/kernel.cpp +++ b/kernel/src/kernel.cpp @@ -6,7 +6,7 @@ * @author Max Tyson */ -#include +#include #include #include #include @@ -43,10 +43,10 @@ extern "C" uint8_t core_boot_info[]; ///< The boot info structure for the /** * @brief The main entry point for secondary cores. Sets up the core and waits to be scheduled. */ -extern "C" [[noreturn]] void core_main(){ +extern "C" [[noreturn]] void core_main() { - auto info = (core_boot_info_t*)(core_boot_info); - info -> activated = true; + auto info = (core_boot_info_t*) (core_boot_info); + info->activated = true; auto core = CPU::executing_core(); // Make sure the correct core is being setup @@ -54,11 +54,11 @@ extern "C" [[noreturn]] void core_main(){ Logger::DEBUG() << "Core " << core->id << " now in higher half \n"; // Set up the core - core -> init(); + core->init(); asm("sti"); // Wait to be scheduled - while (true) + while(true) asm("nop"); } @@ -84,7 +84,7 @@ extern "C" [[noreturn]] void kernel_main(unsigned long addr, unsigned long magic Logger::HEADER() << "Stage {1.1}: Memory Initialisation\n"; PhysicalMemoryManager pmm(&multiboot); VirtualMemoryManager vmm; - MemoryManager memoryManager(&vmm); + MemoryManager memory_manager(&vmm); Logger::HEADER() << "Stage {1.2}: Console Initialisation\n"; VideoElectronicsStandardsAssociation vesa(multiboot.framebuffer()); @@ -115,14 +115,14 @@ extern "C" [[noreturn]] void kernel_main(unsigned long addr, unsigned long magic GlobalScheduler::activate(); // Idle loop (read Idle.md) - while (true) + while(true) asm("hlt"); } /** * @todo Kernel configuration (debug/release) - * @todo Clean up warnings * @todo Test suite of common functions & other statics (paths) * @todo Thread storage (when clib) + * @todo Once kernel done, turn into mono repo and seperate components */ \ No newline at end of file diff --git a/kernel/src/memory/memorymanagement.cpp b/kernel/src/memory/memorymanagement.cpp index 1e0b0654..789bc0c0 100644 --- a/kernel/src/memory/memorymanagement.cpp +++ b/kernel/src/memory/memorymanagement.cpp @@ -20,17 +20,16 @@ using namespace MaxOS::system; * @param vmm The virtual memory manager to use, if nullptr a new one will be created */ MemoryManager::MemoryManager(VirtualMemoryManager* vmm) -: m_virtual_memory_manager(vmm) -{ +: m_virtual_memory_manager(vmm) { // Create the VMM if not provided - if (m_virtual_memory_manager == nullptr) + if(m_virtual_memory_manager == nullptr) m_virtual_memory_manager = new VirtualMemoryManager(); // Enable the memory manager switch_active_memory_manager(this); - // Setup the first chunk of memory + // Set up the first chunk of memory this->m_first_memory_chunk = (MemoryChunk*) m_virtual_memory_manager->allocate(PAGE_SIZE + sizeof(MemoryChunk), 0); m_first_memory_chunk->allocated = false; m_first_memory_chunk->prev = nullptr; @@ -39,7 +38,7 @@ MemoryManager::MemoryManager(VirtualMemoryManager* vmm) m_last_memory_chunk = m_first_memory_chunk; // First memory manager is the kernel memory manager - if (s_kernel_memory_manager == nullptr) + if(s_kernel_memory_manager == nullptr) s_kernel_memory_manager = this; } @@ -50,15 +49,15 @@ MemoryManager::MemoryManager(VirtualMemoryManager* vmm) MemoryManager::~MemoryManager() { // Free the VMM (if this is not the kernel memory manager) - if (m_virtual_memory_manager != nullptr && s_current_memory_manager != s_kernel_memory_manager) + if(m_virtual_memory_manager != nullptr && s_current_memory_manager != s_kernel_memory_manager) delete m_virtual_memory_manager; // Remove the kernel reference to this - if (s_kernel_memory_manager == this) + if(s_kernel_memory_manager == this) s_kernel_memory_manager = nullptr; // Remove the active reference to this - if (s_current_memory_manager == this) + if(s_current_memory_manager == this) s_current_memory_manager = nullptr; } @@ -71,7 +70,7 @@ MemoryManager::~MemoryManager() { void* MemoryManager::malloc(size_t size) { // Make sure there is somthing to do the allocation - if (s_current_memory_manager == nullptr) + if(s_current_memory_manager == nullptr) return nullptr; return s_current_memory_manager->handle_malloc(size); @@ -86,7 +85,7 @@ void* MemoryManager::malloc(size_t size) { void* MemoryManager::kmalloc(size_t size) { // Make sure there is a kernel memory manager - if (s_kernel_memory_manager == nullptr) + if(s_kernel_memory_manager == nullptr) return nullptr; return s_kernel_memory_manager->handle_malloc(size); @@ -103,24 +102,24 @@ void* MemoryManager::handle_malloc(size_t size) { MemoryChunk* result = nullptr; // Nothing to allocate - if (size == 0) + if(size == 0) return nullptr; // Add room to store the chunk information size = align(size + sizeof(MemoryChunk)); // Find the next free chunk that is big enough - for (MemoryChunk* chunk = m_first_memory_chunk; chunk != nullptr && result == nullptr; chunk = chunk->next) { - if (chunk->size > size && !chunk->allocated) + for(MemoryChunk* chunk = m_first_memory_chunk; chunk != nullptr && result == nullptr; chunk = chunk->next) { + if(chunk->size > size && !chunk->allocated) result = chunk; } // If there is no free chunk then make more room - if (result == nullptr) + if(result == nullptr) result = expand_heap(size); // If there is not left over space to store extra chunks there is no need to split the chunk - if (result->size < size + sizeof(MemoryChunk) + 1) { + if(result->size < size + sizeof(MemoryChunk) + 1) { result->allocated = true; void* p = (void*) (((size_t) result) + sizeof(MemoryChunk)); return p; @@ -135,7 +134,7 @@ void* MemoryManager::handle_malloc(size_t size) { // Add to the linked list extra->next = result->next; - if (extra->next != nullptr) + if(extra->next != nullptr) extra->next->prev = extra; // Requested chunk is now allocated exactly to the size requested and points to the free (split) block of memory that @@ -145,7 +144,7 @@ void* MemoryManager::handle_malloc(size_t size) { result->next = extra; // Update the last memory chunk if necessary - if (result == m_last_memory_chunk) + if(result == m_last_memory_chunk) m_last_memory_chunk = extra; return (void*) (((size_t) result) + sizeof(MemoryChunk)); @@ -159,7 +158,7 @@ void* MemoryManager::handle_malloc(size_t size) { void MemoryManager::free(void* pointer) { // Make sure there is a memory manager - if (s_current_memory_manager == nullptr) + if(s_current_memory_manager == nullptr) return; s_current_memory_manager->handle_free(pointer); @@ -173,7 +172,7 @@ void MemoryManager::free(void* pointer) { void MemoryManager::kfree(void* pointer) { // Make sure there is a kernel memory manager - if (s_kernel_memory_manager == nullptr) + if(s_kernel_memory_manager == nullptr) return; s_kernel_memory_manager->handle_free(pointer); @@ -187,11 +186,11 @@ void MemoryManager::kfree(void* pointer) { void MemoryManager::handle_free(void* pointer) { // Cant free unallocated memory - if (pointer == nullptr) + if(pointer == nullptr) return; // Check bounds - if ((uint64_t) pointer < (uint64_t) m_first_memory_chunk || (uint64_t) pointer > (uint64_t) m_last_memory_chunk) + if((uint64_t) pointer < (uint64_t) m_first_memory_chunk || (uint64_t) pointer > (uint64_t) m_last_memory_chunk) return; // Get the chunk information from the pointer @@ -199,14 +198,14 @@ void MemoryManager::handle_free(void* pointer) { chunk->allocated = false; // If there is a free chunk before this chunk then merge them - if (chunk->prev != nullptr && !chunk->prev->allocated) { + if(chunk->prev != nullptr && !chunk->prev->allocated) { // Grow the chunk behind this one so that it now contains the freed one chunk->prev->size += chunk->size + sizeof(MemoryChunk); chunk->prev->next = chunk->next; // The chunk in front of the freed one now needs to point to the merged chunk - if (chunk->next != nullptr) + if(chunk->next != nullptr) chunk->next->prev = chunk->prev; // Freed chunk doesn't exist anymore so now working with the merged chunk @@ -215,7 +214,7 @@ void MemoryManager::handle_free(void* pointer) { } // If there is a free chunk after this chunk then merge them - if (chunk->next != nullptr && !chunk->next->allocated) { + if(chunk->next != nullptr && !chunk->next->allocated) { // Grow this chunk so that it now contains the free chunk in front of the old (now freed) one chunk->size += chunk->next->size + sizeof(MemoryChunk); @@ -223,7 +222,7 @@ void MemoryManager::handle_free(void* pointer) { // Now that this chunk contains the next one, it has to point to the one in front of what has just been merged // and that has to point to this chunk->next = chunk->next->next; - if (chunk->next != nullptr) + if(chunk->next != nullptr) chunk->next->prev = chunk; } @@ -242,7 +241,7 @@ MemoryChunk* MemoryManager::expand_heap(size_t size) { ASSERT(chunk != nullptr, "Out of memory - kernel cannot allocate any more memory"); // Handled by assert, but just in case - if (chunk == nullptr) + if(chunk == nullptr) return nullptr; // Set the chunk's properties @@ -257,7 +256,7 @@ MemoryChunk* MemoryManager::expand_heap(size_t size) { // If it is possible to merge the new chunk with the previous chunk then do so (note: this happens if the // previous chunk is free but cant contain the size required) - if (!chunk->prev->allocated) + if(!chunk->prev->allocated) free((void*) ((size_t) chunk + sizeof(MemoryChunk))); return chunk; @@ -268,13 +267,13 @@ MemoryChunk* MemoryManager::expand_heap(size_t size) { * * @return The amount of memory used */ -int MemoryManager::memory_used() { +size_t MemoryManager::memory_used() { - int result = 0; + size_t result = 0; // Loop through all the chunks and add up the size of the allocated chunks - for (MemoryChunk* chunk = m_first_memory_chunk; chunk != nullptr; chunk = chunk->next) - if (chunk->allocated) + for(MemoryChunk* chunk = m_first_memory_chunk; chunk != nullptr; chunk = chunk->next) + if(chunk->allocated) result += chunk->size; return result; @@ -300,7 +299,7 @@ size_t MemoryManager::align(size_t size) { void MemoryManager::switch_active_memory_manager(MemoryManager* manager) { // Make sure there is a manager - if (manager == nullptr) + if(manager == nullptr) return; // Switch the address space @@ -344,7 +343,7 @@ void* operator new(size_t size) throw() { void* operator new[](size_t size) throw() { // Handle the memory allocation - return MaxOS::memory::MemoryManager::kmalloc(size); + return MaxOS::memory::MemoryManager::kmalloc(size); } /** diff --git a/kernel/src/memory/physical.cpp b/kernel/src/memory/physical.cpp index 19e69dc8..56a4a7fc 100644 --- a/kernel/src/memory/physical.cpp +++ b/kernel/src/memory/physical.cpp @@ -30,13 +30,14 @@ extern uint64_t _kernel_physical_end; ///< The physical address where the kern */ PhysicalMemoryManager::PhysicalMemoryManager(Multiboot* multiboot) : m_kernel_end((uint64_t) &_kernel_physical_end), - m_multiboot(multiboot), - m_pml4_root_address((uint64_t*) p4_table), - m_pml4_root((pte_t*) p4_table) -{ +m_multiboot(multiboot), +m_pml4_root_address((uint64_t*) p4_table), +m_pml4_root((pte_t*) p4_table) { Logger::INFO() << "Setting up Physical Memory Manager\n"; - Logger::DEBUG() << "Kernel Memory: kernel_end = 0x" << (uint64_t) &_kernel_end << ", kernel_size = 0x" << (uint64_t) &_kernel_size << ", kernel_physical_end = 0x" << (uint64_t) &_kernel_physical_end << "\n"; + Logger::DEBUG() << "Kernel Memory: kernel_end = 0x" << (uint64_t) &_kernel_end << ", kernel_size = 0x" + << (uint64_t) &_kernel_size << ", kernel_physical_end = 0x" << (uint64_t) &_kernel_physical_end + << "\n"; m_kernel_start_page = align_up_to_page((size_t) &_kernel_physical_end + PAGE_SIZE, PAGE_SIZE); // Set up the current manager @@ -45,12 +46,15 @@ PhysicalMemoryManager::PhysicalMemoryManager(Multiboot* multiboot) s_current_manager = this; m_nx_allowed = CPU::check_nx(); - // Find a region of memory available to be used - m_mmap_tag = m_multiboot->mmap(); - for (multiboot_mmap_entry *entry = m_mmap_tag->entries; (multiboot_uint8_t *)entry < (multiboot_uint8_t *)m_mmap_tag + m_mmap_tag->size; entry = (multiboot_mmap_entry *)((unsigned long)entry + m_mmap_tag->entry_size)) { + // Find a region of memory available to be used + m_mmap_tag = m_multiboot->mmap(); + for(multiboot_mmap_entry* entry = m_mmap_tag->entries; (multiboot_uint8_t*) entry < + (multiboot_uint8_t*) m_mmap_tag + + m_mmap_tag->size; entry = (multiboot_mmap_entry*) ( + (unsigned long) entry + m_mmap_tag->entry_size)) { // Skip if the region is not free or there is not enough space - if (entry->type != MULTIBOOT_MEMORY_AVAILABLE) + if(entry->type != MULTIBOOT_MEMORY_AVAILABLE) continue; // Store the entry. (note: don't break here as it is desired to find the last usable entry as that is normally biggest) @@ -61,12 +65,16 @@ PhysicalMemoryManager::PhysicalMemoryManager(Multiboot* multiboot) m_memory_size = (m_mmap->addr + m_mmap->len); m_bitmap_size = m_memory_size / PAGE_SIZE + 1; m_total_entries = m_bitmap_size / ROW_BITS + 1; - Logger::DEBUG() << "Memory Info: size = " << (int) (m_memory_size / 1024 / 1024) << "mb, bitmap size = 0x" << (uint64_t) m_bitmap_size << ", total entries = " << (int) m_total_entries << ", page size = 0x" << (uint64_t) PAGE_SIZE << "\n"; + Logger::DEBUG() << "Memory Info: size = " << (int) (m_memory_size / 1024 / 1024) << "mb, bitmap size = 0x" + << (uint64_t) m_bitmap_size << ", total entries = " << (int) m_total_entries << ", page size = 0x" + << (uint64_t) PAGE_SIZE << "\n"; // Map the physical memory into the virtual memory - Logger::DEBUG() << "Mapping from 0x0 to 0x" << (uint64_t) (m_mmap->addr + m_mmap->len) << " to higher half direct map at offset 0x" << HIGHER_HALF_DIRECT_MAP << "\n"; - for (uint64_t physical_address = 0; physical_address < (m_mmap->addr + m_mmap->len); physical_address += PAGE_SIZE) - map((physical_address_t*) physical_address, (virtual_address_t*) (HIGHER_HALF_DIRECT_MAP + physical_address), PRESENT | WRITE); + Logger::DEBUG() << "Mapping from 0x0 to 0x" << (uint64_t) (m_mmap->addr + m_mmap->len) + << " to higher half direct map at offset 0x" << HIGHER_HALF_DIRECT_MAP << "\n"; + for(uint64_t physical_address = 0; physical_address < (m_mmap->addr + m_mmap->len); physical_address += PAGE_SIZE) + map((physical_address_t*) physical_address, (virtual_address_t*) (HIGHER_HALF_DIRECT_MAP + physical_address), + PRESENT | WRITE); // Kernel Setup initialise_bit_map(); @@ -88,14 +96,14 @@ PhysicalMemoryManager::~PhysicalMemoryManager() = default; void PhysicalMemoryManager::reserve_kernel_regions(Multiboot* multiboot) { // Reserve the pages used by the higher half mapping - reserve((uint64_t)m_mmap->addr, m_setup_frames * PAGE_SIZE, "HHDM"); + reserve((uint64_t) m_mmap->addr, m_setup_frames * PAGE_SIZE, "HHDM"); // Reserve the area for the bitmap reserve((uint64_t) from_dm_region((uint64_t) m_bit_map), m_bitmap_size / 8, "Bitmap"); // Calculate how much space the kernel takes up uint32_t kernel_entries = (m_kernel_start_page / PAGE_SIZE) + 1; - if ((((uint32_t) (m_kernel_start_page)) % PAGE_SIZE) != 0) + if((((uint32_t) (m_kernel_start_page)) % PAGE_SIZE) != 0) kernel_entries += 1; // Reserve the kernel entries @@ -103,23 +111,28 @@ void PhysicalMemoryManager::reserve_kernel_regions(Multiboot* multiboot) { // Reserve the area for the mmap uint64_t mem_end = m_mmap->addr + m_mmap->len; - for (multiboot_mmap_entry* entry = m_mmap_tag->entries; (multiboot_uint8_t*) entry < (multiboot_uint8_t*) m_mmap_tag + m_mmap_tag->size; entry = (multiboot_mmap_entry*) ((unsigned long) entry + m_mmap_tag->entry_size)) { + for(multiboot_mmap_entry* entry = m_mmap_tag->entries; (multiboot_uint8_t*) entry < + (multiboot_uint8_t*) m_mmap_tag + + m_mmap_tag->size; entry = (multiboot_mmap_entry*) ( + (unsigned long) entry + m_mmap_tag->entry_size)) { // Dont reserve free regions - if (entry->type <= MULTIBOOT_MEMORY_AVAILABLE) + if(entry->type <= MULTIBOOT_MEMORY_AVAILABLE) continue; // Don't reserve the memory being managed by pmm - if (entry->addr >= mem_end) + if(entry->addr >= mem_end) continue; reserve(entry->addr, entry->len, "MMap"); } // Reserve the area for each multiboot module - for (multiboot_tag* tag = multiboot->start_tag(); tag->type != MULTIBOOT_TAG_TYPE_END; tag = (struct multiboot_tag*) ((multiboot_uint8_t*) tag + ((tag->size + 7) & ~7))) { + for(multiboot_tag* tag = multiboot->start_tag(); + tag->type != MULTIBOOT_TAG_TYPE_END; tag = (struct multiboot_tag*) ((multiboot_uint8_t*) tag + + ((tag->size + 7) & ~7))) { - if (tag->type != MULTIBOOT_TAG_TYPE_MODULE) + if(tag->type != MULTIBOOT_TAG_TYPE_MODULE) continue; // Reserve the module's address @@ -128,8 +141,8 @@ void PhysicalMemoryManager::reserve_kernel_regions(Multiboot* multiboot) { } // Reserve all the tags - auto end_tag = (multiboot_tag*)to_higher_region(multiboot->end_address); - auto start_tag = (uint64_t)to_lower_region((uintptr_t)multiboot->start_tag()); + auto end_tag = (multiboot_tag*) to_higher_region(multiboot->end_address); + auto start_tag = (uint64_t) to_lower_region((uintptr_t) multiboot->start_tag()); size_t tags_size = multiboot->end_address - start_tag + ((end_tag->size + 7) & ~7); reserve(start_tag, tags_size, "Tags"); } @@ -191,10 +204,10 @@ void* PhysicalMemoryManager::allocate_frame() { // If not initialised, cant use the bitmap or higher half mapped physical memory so use leftover kernel memory already // mapped in loader.s - if (!m_initialised) { + if(!m_initialised) { // Use frames at the start of the mmap free - void* address = (void*)m_mmap->addr + (m_setup_frames * PAGE_SIZE); + void* address = (void*) ((uintptr_t) m_mmap->addr + (m_setup_frames * PAGE_SIZE)); m_setup_frames++; m_lock.unlock(); @@ -204,16 +217,16 @@ void* PhysicalMemoryManager::allocate_frame() { // Check if there are enough frames ASSERT(m_used_frames < m_bitmap_size, "No more frames available\n"); - for (uint32_t row = 0; row < m_total_entries; ++row) { + for(uint32_t row = 0; row < m_total_entries; ++row) { // If the row is full continue - if (m_bit_map[row] == 0xFFFFFFFFFFFFFFF) + if(m_bit_map[row] == 0xFFFFFFFFFFFFFFF) continue; - for (uint32_t column = 0; column < ROW_BITS; ++column) { + for(uint32_t column = 0; column < ROW_BITS; ++column) { // Entry isn't free - if (m_bit_map[row] & (1ULL << column)) + if(m_bit_map[row] & (1ULL << column)) continue; // Mark the frame as used @@ -269,34 +282,34 @@ void* PhysicalMemoryManager::allocate_area(uint64_t start_address, size_t size) uint32_t start_column = 0; size_t adjacent_frames = 0; - for (uint32_t row = 0; row < m_total_entries; ++row) { + for(uint32_t row = 0; row < m_total_entries; ++row) { // Skip full rows - if (m_bit_map[row] == 0xFFFFFFFFFFFFFFF) + if(m_bit_map[row] == 0xFFFFFFFFFFFFFFF) continue; - for (uint32_t column = 0; column < ROW_BITS; ++column) { + for(uint32_t column = 0; column < ROW_BITS; ++column) { // Not enough adjacent frames - if (m_bit_map[row] & (1ULL << column)) { + if(m_bit_map[row] & (1ULL << column)) { adjacent_frames = 0; continue; } // Store the address of the first frame in set of adjacent ones - if (adjacent_frames == 0) { + if(adjacent_frames == 0) { start_row = row; start_column = column; } // Make sure there are enough frames in a row found adjacent_frames++; - if (adjacent_frames != frame_count) + if(adjacent_frames != frame_count) continue; // Mark the frames as used m_used_frames += frame_count; - for (uint32_t i = 0; i < frame_count; ++i) { + for(uint32_t i = 0; i < frame_count; ++i) { // Get the location of the bit uint32_t index = start_row + (start_column + i) / ROW_BITS; @@ -335,7 +348,7 @@ void PhysicalMemoryManager::free_area(uint64_t start_address, size_t size) { uint64_t frame_address = start_address / PAGE_SIZE; // Check bounds - if (frame_address >= m_bitmap_size) + if(frame_address >= m_bitmap_size) return; // Wait until other threads have finished other memory operations @@ -343,7 +356,7 @@ void PhysicalMemoryManager::free_area(uint64_t start_address, size_t size) { // Mark the frames as not used m_used_frames -= frame_count; - for (uint32_t i = 0; i < frame_count; ++i) + for(uint32_t i = 0; i < frame_count; ++i) m_bit_map[(frame_address + i) / ROW_BITS] &= ~(1 << ((frame_address + i) % ROW_BITS)); m_lock.unlock(); @@ -374,7 +387,7 @@ pml_t* PhysicalMemoryManager::get_higher_half_table(uint64_t index, uint64_t ind pml_t* PhysicalMemoryManager::get_or_create_table(pml_t* table, size_t index, size_t flags) { // Table is already created so just find the entry - if (table->entries[index].present) + if(table->entries[index].present) return (pml_t*) to_dm_region(physical_address_of_entry(&table->entries[index])); // Create the table @@ -401,10 +414,10 @@ pml_t* PhysicalMemoryManager::get_or_create_table(pml_t* table, size_t index, si */ pml_t* PhysicalMemoryManager::get_and_create_table(pml_t* parent_table, uint64_t table_index, pml_t* table) { - // Table already created so dont need to do anything + // Table already created so don't need to do anything /// Note: this is where it differs when not having pmm init done as cant find the entry (direct map not setup) thus /// requiring get_higher_half_table() to be passed in as the *table arg by the caller - if (parent_table->entries[table_index].present) + if(parent_table->entries[table_index].present) return table; // Create the table @@ -431,7 +444,7 @@ pte_t* PhysicalMemoryManager::get_entry(virtual_address_t* virtual_address, pml_ // Kernel memory must be in the higher half size_t flags = PRESENT | WRITE; - if (!in_higher_region((uint64_t) virtual_address)) + if(!in_higher_region((uint64_t) virtual_address)) flags |= USER; uint16_t pml4_index = PML4_GET_INDEX((uint64_t) virtual_address); @@ -444,7 +457,7 @@ pte_t* PhysicalMemoryManager::get_entry(virtual_address_t* virtual_address, pml_ pml_t* pt_table = nullptr; // If it is before initialization then cant rely on the direct map - if (!m_initialised) { + if(!m_initialised) { pdpr_table = get_and_create_table(pml4_table, pml4_index, get_higher_half_table(pml4_index)); pd_table = get_and_create_table(pdpr_table, pdpr_index, get_higher_half_table(pdpr_index, pml4_index)); pt_table = get_and_create_table(pd_table, pd_index, get_higher_half_table(pd_index, pdpr_index, pml4_index)); @@ -498,12 +511,12 @@ virtual_address_t* PhysicalMemoryManager::map(physical_address_t* physical_addre virtual_address_t* PhysicalMemoryManager::map(physical_address_t* physical_address, virtual_address_t* virtual_address, size_t flags, uint64_t* pml4_table) { // If it is in a lower region then assume it is the user space - if (!in_higher_region((uint64_t) virtual_address)) + if(!in_higher_region((uint64_t) virtual_address)) flags |= USER; // If the entry already exists then the mapping is already done pte_t* pte = get_entry(virtual_address, (pml_t*) pml4_table); - if (pte->present) + if(pte->present) return virtual_address; // Map the physical address to the virtual address @@ -539,8 +552,8 @@ virtual_address_t* PhysicalMemoryManager::map(virtual_address_t* virtual_address void PhysicalMemoryManager::map_area(virtual_address_t* virtual_address_start, size_t length, size_t flags) { // Map the required frames - for (size_t i = 0; i < size_to_frames(length); ++i) - map(virtual_address_start + (i * PAGE_SIZE), flags); + for(size_t i = 0; i < size_to_frames(length); ++i) + map((virtual_address_t*) ((uintptr_t) virtual_address_start + (i * PAGE_SIZE)), flags); } @@ -555,8 +568,9 @@ void PhysicalMemoryManager::map_area(virtual_address_t* virtual_address_start, s void PhysicalMemoryManager::map_area(physical_address_t* physical_address_start, virtual_address_t* virtual_address_start, size_t length, size_t flags) { // Map the required frames - for (size_t i = 0; i < size_to_frames(length); ++i) - map(physical_address_start + (i * PAGE_SIZE), virtual_address_start + (i * PAGE_SIZE), flags); + for(size_t i = 0; i < size_to_frames(length); ++i) + map((virtual_address_t*) ((uintptr_t) physical_address_start + (i * PAGE_SIZE)), + (virtual_address_t*) ((uintptr_t) virtual_address_start + (i * PAGE_SIZE)), flags); } /** @@ -594,7 +608,7 @@ void PhysicalMemoryManager::unmap(virtual_address_t* virtual_address, uint64_t* pte_t* pte = get_entry(virtual_address, (pml_t*) pml4_root); // Make sure the address is actually mapped - if (!pte->present) + if(!pte->present) return; // Unmap the entry @@ -613,8 +627,8 @@ void PhysicalMemoryManager::unmap(virtual_address_t* virtual_address, uint64_t* void PhysicalMemoryManager::unmap_area(virtual_address_t* virtual_address_start, size_t length) { // Unmap the required frames - for (size_t i = 0; i < size_to_frames(length); ++i) - unmap(virtual_address_start + (i * PAGE_SIZE)); + for(size_t i = 0; i < size_to_frames(length); ++i) + unmap((virtual_address_t*) ((uintptr_t) virtual_address_start + (i * PAGE_SIZE))); } /** @@ -625,7 +639,7 @@ void PhysicalMemoryManager::unmap_area(virtual_address_t* virtual_address_start, void PhysicalMemoryManager::clean_page_table(uint64_t* table) { // Null the table (prevents false mappings when re-using frames) - for (int i = 0; i < 512; i++) + for(int i = 0; i < 512; i++) table[i] = 0x00l; } @@ -641,21 +655,21 @@ void PhysicalMemoryManager::clean_page_table(uint64_t* table) { pte_t PhysicalMemoryManager::create_page_table_entry(uintptr_t address, size_t flags) const { pte_t page = (pte_t) { - .present = (flags & PRESENT) != 0, - .write = (flags & WRITE) != 0, - .user = (flags & USER) != 0, - .write_through = (flags & WRITE_THROUGH) != 0, - .cache_disabled = (flags & CACHE_DISABLED) != 0, - .accessed = (flags & ACCESSED) != 0, - .dirty = (flags & DIRTY) != 0, - .huge_page = (flags & HUGE_PAGE) != 0, - .global = (flags & GLOBAL) != 0, - .available = 0, - .physical_address = address >> 12, + .present = (flags & PRESENT) != 0, + .write = (flags & WRITE) != 0, + .user = (flags & USER) != 0, + .write_through = (flags & WRITE_THROUGH) != 0, + .cache_disabled = (flags & CACHE_DISABLED) != 0, + .accessed = (flags & ACCESSED) != 0, + .dirty = (flags & DIRTY) != 0, + .huge_page = (flags & HUGE_PAGE) != 0, + .global = (flags & GLOBAL) != 0, + .available = 0, + .physical_address = address >> 12, }; // Set the NX bit if it is allowed - if (m_nx_allowed && (flags & NO_EXECUTE)) { + if(m_nx_allowed && (flags & NO_EXECUTE)) { auto page_raw = (uint64_t) &page; page_raw |= NO_EXECUTE; page = *(pte_t*) page_raw; @@ -675,17 +689,20 @@ void PhysicalMemoryManager::initialise_bit_map() { uint64_t limit = m_kernel_start_page; // Find a region for the bitmap to handle - for (multiboot_mmap_entry* entry = m_mmap_tag->entries; (multiboot_uint8_t*) entry < (multiboot_uint8_t*) m_mmap_tag + m_mmap_tag->size; entry = (multiboot_mmap_entry*) ((unsigned long) entry + m_mmap_tag->entry_size)) { + for(multiboot_mmap_entry* entry = m_mmap_tag->entries; (multiboot_uint8_t*) entry < + (multiboot_uint8_t*) m_mmap_tag + + m_mmap_tag->size; entry = (multiboot_mmap_entry*) ( + (unsigned long) entry + m_mmap_tag->entry_size)) { // Cant use a non-free entry or an entry past limit (ie don't user higher addresses that will be overridden later) - if (entry->type != MULTIBOOT_MEMORY_AVAILABLE || entry->len > limit) + if(entry->type != MULTIBOOT_MEMORY_AVAILABLE || entry->len > limit) continue; size_t space = entry->len; size_t offset = 0; // Determine how much of the region is below the limit and adjust the starting point to there - if (entry->addr < limit) { + if(entry->addr < limit) { offset = limit - entry->addr; space -= offset; } @@ -702,10 +719,12 @@ void PhysicalMemoryManager::initialise_bit_map() { ASSERT(m_bit_map != nullptr, "No space for the bitmap (no region)\n"); // Clear the bitmap (mark all as free) - for (uint32_t i = 0; i < m_total_entries; ++i) + for(uint32_t i = 0; i < m_total_entries; ++i) m_bit_map[i] = 0; - Logger::DEBUG() << "Bitmap: location: 0x" << (uint64_t) m_bit_map << " - 0x" << (uint64_t) (m_bit_map + m_bitmap_size / 8) << " (range of 0x" << (uint64_t) m_bitmap_size / 8 << ")\n"; + Logger::DEBUG() << "Bitmap: location: 0x" << (uint64_t) m_bit_map << " - 0x" + << (uint64_t) (m_bit_map + m_bitmap_size / 8) << " (range of 0x" << (uint64_t) m_bitmap_size / 8 + << ")\n"; } @@ -771,7 +790,8 @@ void PhysicalMemoryManager::reserve(uint64_t address, size_t size, const char* t // Cant reserve virtual addresses (ensure the address is physical) ASSERT(address < m_memory_size, "Attempt to reserve address bigger then the memory can contain: 0x%x\n", address); - ASSERT(address + size < m_memory_size, "Attempt to reserve region bigger then the memory can contain: 0x%x-0x%x\n", address, address+size); + ASSERT(address + size < m_memory_size, "Attempt to reserve region bigger then the memory can contain: 0x%x-0x%x\n", + address, address + size); // Wait to be able to reserve m_lock.lock(); @@ -787,7 +807,7 @@ void PhysicalMemoryManager::reserve(uint64_t address, size_t size, const char* t uint64_t frame_index = aligned_address / PAGE_SIZE; // Mark all as used - for (size_t i = 0; i < page_count; ++i) + for(size_t i = 0; i < page_count; ++i) m_bit_map[(frame_index + i) / ROW_BITS] |= (1ULL << ((frame_index + i) % ROW_BITS)); // Update the used frames @@ -795,7 +815,8 @@ void PhysicalMemoryManager::reserve(uint64_t address, size_t size, const char* t // Clear the lock m_lock.unlock(); - Logger::DEBUG() << "Reserved Address for "<< type << ": 0x" << aligned_address << " - 0x" << aligned_address + size << " (length of 0x" << size << ")\n"; + Logger::DEBUG() << "Reserved Address for " << type << ": 0x" << aligned_address << " - 0x" << aligned_address + size + << " (length of 0x" << size << ")\n"; } /** @@ -810,7 +831,7 @@ physical_address_t* PhysicalMemoryManager::get_physical_address(virtual_address_ pte_t* entry = get_entry(virtual_address, (pml_t*) pml4_root); // Cant get a physical address if its inst free - if (!entry->present) + if(!entry->present) return nullptr; return (physical_address_t*) physical_address_of_entry(entry); @@ -828,7 +849,7 @@ void PhysicalMemoryManager::change_page_flags(virtual_address_t* virtual_address pte_t* entry = get_entry(virtual_address, (pml_t*) pml4_root); // Cant edit a non-present entry (will page fault) - if (!entry->present) + if(!entry->present) return; *entry = create_page_table_entry(physical_address_of_entry(entry), flags); @@ -848,7 +869,8 @@ void PhysicalMemoryManager::change_page_flags(virtual_address_t* virtual_address */ bool PhysicalMemoryManager::is_mapped(uintptr_t physical_address, uintptr_t virtual_address, uint64_t* pml4_root) { - return get_physical_address((virtual_address_t*) virtual_address, pml4_root) == (physical_address_t*) physical_address; + return get_physical_address((virtual_address_t*) virtual_address, pml4_root) == + (physical_address_t*) physical_address; } @@ -861,7 +883,7 @@ bool PhysicalMemoryManager::is_mapped(uintptr_t physical_address, uintptr_t virt void* PhysicalMemoryManager::to_higher_region(uintptr_t physical_address) { // If it's in the lower half then add the offset - if (physical_address < HIGHER_HALF_KERNEL_OFFSET) + if(physical_address < HIGHER_HALF_KERNEL_OFFSET) return (void*) (physical_address + HIGHER_HALF_KERNEL_OFFSET); // Must be in the higher half @@ -877,7 +899,7 @@ void* PhysicalMemoryManager::to_higher_region(uintptr_t physical_address) { void* PhysicalMemoryManager::to_lower_region(uintptr_t virtual_address) { // If it's in the lower half then add the offset - if (virtual_address > HIGHER_HALF_KERNEL_OFFSET) + if(virtual_address > HIGHER_HALF_KERNEL_OFFSET) return (void*) (virtual_address - HIGHER_HALF_KERNEL_OFFSET); // Must be in the lower half @@ -892,7 +914,7 @@ void* PhysicalMemoryManager::to_lower_region(uintptr_t virtual_address) { */ void* PhysicalMemoryManager::to_io_region(uintptr_t physical_address) { - if (physical_address < HIGHER_HALF_MEM_OFFSET) + if(physical_address < HIGHER_HALF_MEM_OFFSET) return (void*) (physical_address + HIGHER_HALF_MEM_OFFSET); // Must be in the higher half @@ -907,7 +929,7 @@ void* PhysicalMemoryManager::to_io_region(uintptr_t physical_address) { */ void* PhysicalMemoryManager::to_dm_region(uintptr_t physical_address) { - if (physical_address < HIGHER_HALF_OFFSET) + if(physical_address < HIGHER_HALF_OFFSET) return (void*) (physical_address + HIGHER_HALF_DIRECT_MAP); // Must be in the higher half @@ -922,7 +944,7 @@ void* PhysicalMemoryManager::to_dm_region(uintptr_t physical_address) { */ void* PhysicalMemoryManager::from_dm_region(uintptr_t virtual_address) { - if (virtual_address > HIGHER_HALF_DIRECT_MAP) + if(virtual_address > HIGHER_HALF_DIRECT_MAP) return (void*) (virtual_address - HIGHER_HALF_DIRECT_MAP); // Must be in the lower half diff --git a/kernel/src/net/arp.cpp b/kernel/src/net/arp.cpp index 9a317599..8706dfa6 100644 --- a/kernel/src/net/arp.cpp +++ b/kernel/src/net/arp.cpp @@ -18,16 +18,15 @@ using namespace MaxOS::drivers::ethernet; /** * @brief Constructs an AddressResolutionProtocol handler. * - * @param ethernetFrameHandler The Ethernet frame handler to use. - * @param internetProtocolHandler The Internet protocol handler to use. - * @param errorMessages The output stream to use for error messages. + * @param ethernet_frame_handler The Ethernet frame handler to use. + * @param internet_protocol_handler The Internet protocol handler to use. + * @param error_messages The output stream to use for error messages. */ -net::AddressResolutionProtocol::AddressResolutionProtocol(EthernetFrameHandler* ethernetFrameHandler, InternetProtocolHandler* internetProtocolHandler, OutputStream* errorMessages) -: EthernetFramePayloadHandler(ethernetFrameHandler, 0x0806), - IPV4AddressResolver(internetProtocolHandler) -{ - this->internetProtocolHandler = internetProtocolHandler; - this->errorMessages = errorMessages; +net::AddressResolutionProtocol::AddressResolutionProtocol(EthernetFrameHandler* ethernet_frame_handler, InternetProtocolHandler* internet_protocol_handler, OutputStream* error_messages) + : EthernetFramePayloadHandler(ethernet_frame_handler, 0x0806), + IPV4AddressResolver(internet_protocol_handler) { + this->internet_protocol_handler = internet_protocol_handler; + this->error_messages = error_messages; } net::AddressResolutionProtocol::~AddressResolutionProtocol() = default; @@ -35,54 +34,54 @@ net::AddressResolutionProtocol::~AddressResolutionProtocol() = default; /** * @brief Called when an ARP packet is received. * - * @param etherframePayload The payload of the ARP packet. + * @param ethernetframePayload The payload of the ARP packet. * @param size The size of the ARP packet. * @return True if the device should send a response, false otherwise. */ -bool AddressResolutionProtocol::handleEthernetframePayload(uint8_t* etherframePayload, uint32_t size) { +bool AddressResolutionProtocol::handle_ethernetframe_payload(uint8_t* ethernetframePayload, uint32_t size) { - //Check if the size is correct - if(size < sizeof(ARPMessage)) - return false; + //Check if the size is correct + if (size < sizeof(ARPMessage)) + return false; - //Convert the payload to an ARP message - ARPMessage* arpMessage = (ARPMessage*)etherframePayload; + //Convert the payload to an ARP message + auto* arp_message = (ARPMessage*) ethernetframePayload; - //Check if the message hardware type is Ethernet (BigEndian) - if(arpMessage -> hardwareType == 0x100){ + //Check if the message hardware type is Ethernet (BigEndian) + if (arp_message->hardware_type == 0x100) { - if(arpMessage -> protocol == 0x0008 //Check if the protocol is IPv4 (BigEndian) - && arpMessage -> hardwareAddressSize == 6 - && arpMessage -> protocolAddressSize == 4 - && arpMessage -> dstIP == internetProtocolHandler -> GetInternetProtocolAddress()) - { + if (arp_message->protocol == 0x0008 //Check if the protocol is IPv4 (BigEndian) + && arp_message->hardware_address_size == 6 + && arp_message->protocol_address_size == 4 + && arp_message->dst_ip == internet_protocol_handler->get_internet_protocol_address()) { - switch (arpMessage -> command) { - //Request - case 0x0100: - arpMessage -> command = 0x0200; //Set the command to reply - arpMessage -> dstMAC = arpMessage -> srcMAC; //Set the destination MAC to the source MAC - arpMessage -> dstIP = arpMessage -> srcIP; //Set the destination IP to the source IP - arpMessage -> srcMAC = internetProtocolHandler -> GetMediaAccessControlAddress(); //Set the source MAC to this MAC - arpMessage -> srcIP = internetProtocolHandler -> GetInternetProtocolAddress(); //Set the source IP to this IP - return true; + switch (arp_message->command) { + //Request + case 0x0100: + arp_message->command = 0x0200; //Set the command to reply + arp_message->dst_mac = arp_message->src_mac; //Set the destination MAC to the source MAC + arp_message->dst_ip = arp_message->src_ip; //Set the destination IP to the source IP + arp_message->src_mac = internet_protocol_handler->get_media_access_control_address(); //Set the source MAC to this MAC + arp_message->src_ip = internet_protocol_handler->get_internet_protocol_address(); //Set the source IP to this IP + return true; - //Response - case 0x0200: - addressCache.insert((InternetProtocolAddress)arpMessage -> srcIP, (MediaAccessControlAddress)arpMessage -> srcMAC); //Insert the MAC address into the cache - break; + //Response + case 0x0200: + address_cache.insert((InternetProtocolAddress) arp_message->src_ip, + (MediaAccessControlAddress) arp_message->src_mac); //Insert the MAC address into the cache + break; - default: - break; + default: + break; - } + } - } + } - } + } - //By default, don't send anything back - return false; + //By default, don't send anything back + return false; } @@ -93,26 +92,26 @@ bool AddressResolutionProtocol::handleEthernetframePayload(uint8_t* etherframePa * * @param address The IP address in BigEndian. */ -void AddressResolutionProtocol::RequestMACAddress(InternetProtocolAddress address) { +void AddressResolutionProtocol::request_mac_address(InternetProtocolAddress address) { - //When a MAC address is requested, instantiate a new ARP message block on the stack - ARPMessage arpMessage = {}; + //When a MAC address is requested, instantiate a new ARP message block on the stack + ARPMessage arp_message = { }; - //Set the message's values - arpMessage.hardwareType = 0x0100; //Ethernet, encoded in BigEndian - arpMessage.protocol = 0x0008; //IPv4, encoded in BigEndian - arpMessage.hardwareAddressSize = 6; //MAC address size - arpMessage.protocolAddressSize = 4; //IPv4 address size - arpMessage.command = 0x0100; //Request, encoded in BigEndian + //Set the message's values + arp_message.hardware_type = 0x0100; //Ethernet, encoded in BigEndian + arp_message.protocol = 0x0008; //IPv4, encoded in BigEndian + arp_message.hardware_address_size = 6; //MAC address size + arp_message.protocol_address_size = 4; //IPv4 address size + arp_message.command = 0x0100; //Request, encoded in BigEndian - //Set the message's source and destination - arpMessage.srcMAC = frameHandler -> getMAC(); //Set the source MAC address to the backend's MAC address - arpMessage.srcIP = internetProtocolHandler -> GetInternetProtocolAddress(); //Set the source IP address to the backend's IP address - arpMessage.dstMAC = 0xFFFFFFFFFFFF; //Set the destination MAC address to broadcast - arpMessage.dstIP = address; //Set the destination IP address to the requested IP address + //Set the message's source and destination + arp_message.src_mac = frame_handler->get_mac(); //Set the source MAC address to the backend's MAC address + arp_message.src_ip = internet_protocol_handler->get_internet_protocol_address(); //Set the source IP address to the backend's IP address + arp_message.dst_mac = 0xFFFFFFFFFFFF; //Set the destination MAC address to broadcast + arp_message.dst_ip = address; //Set the destination IP address to the requested IP address - //Send the message - this -> Send(arpMessage.dstMAC, (uint8_t*)&arpMessage, sizeof(ARPMessage)); + //Send the message + this->send(arp_message.dst_mac, (uint8_t*) &arp_message, sizeof(ARPMessage)); } @@ -126,32 +125,33 @@ void AddressResolutionProtocol::RequestMACAddress(InternetProtocolAddress addres * * @todo Should have a timeout in case the address cannot be resolved and avoid infinite loops */ -MediaAccessControlAddress AddressResolutionProtocol::Resolve(InternetProtocolAddress address) { +MediaAccessControlAddress AddressResolutionProtocol::resolve(InternetProtocolAddress address) { - volatile Map::iterator cacheIterator = addressCache.find(address); //Check if the MAC address is in the cache + volatile Map::iterator cache_iterator = address_cache.find( + address); //Check if the MAC address is in the cache - //If not, request it - if(addressCache.end() == cacheIterator){ - RequestMACAddress(address); - } + //If not, request it + if (address_cache.end() == cache_iterator) { + request_mac_address(address); + } - //This isn't safe because the MAC address might not be in the cache yet or the machine may not be connected to the network (possible infinite loop) //TODO: TIMEOUT - while (cacheIterator == addressCache.end()) { //Wait until the MAC address is found - cacheIterator = addressCache.find(address); - } + //This isn't safe because the MAC address might not be in the cache yet or the machine may not be connected to the network (possible infinite loop) //TODO: TIMEOUT + while (cache_iterator == address_cache.end()) { //Wait until the MAC address is found + cache_iterator = address_cache.find(address); + } - //Return the MAC address + //Return the MAC address - return cacheIterator -> second; + return cache_iterator->second; } /** - * @brief Store a mapping of an IP address to a MAC address. + * @brief store a mapping of an IP address to a MAC address. * - * @param internetProtocolAddress The IP address. - * @param mediaAccessControlAddress The MAC address. + * @param internet_protocol_address The IP address. + * @param media_access_control_address The MAC address. */ -void AddressResolutionProtocol::Store(InternetProtocolAddress internetProtocolAddress, MediaAccessControlAddress mediaAccessControlAddress) { - addressCache.insert(internetProtocolAddress, mediaAccessControlAddress); +void AddressResolutionProtocol::store(InternetProtocolAddress internet_protocol_address, drivers::ethernet::MediaAccessControlAddress media_access_control_address) { + address_cache.insert(internet_protocol_address, media_access_control_address); } diff --git a/kernel/src/net/ethernetframe.cpp b/kernel/src/net/ethernetframe.cpp index d3cc0906..20a02363 100644 --- a/kernel/src/net/ethernetframe.cpp +++ b/kernel/src/net/ethernetframe.cpp @@ -18,14 +18,14 @@ using namespace MaxOS::memory; /** * @brief Construct a new Ether Frame Payload Handler object * - * @param frameHandler the handler for the ethernet frame - * @param handledType the type of the protocol, which will be handled by this handler + * @param frame_handler the handler for the ethernet frame + * @param handled_type the type of the protocol, which will be handled by this handler */ -EthernetFramePayloadHandler::EthernetFramePayloadHandler(EthernetFrameHandler* frameHandler, uint16_t handledType) { +EthernetFramePayloadHandler::EthernetFramePayloadHandler(EthernetFrameHandler* frame_handler, uint16_t handled_type) { - this -> handledType = handledType; - this -> frameHandler = frameHandler; - frameHandler->connectHandler(this); + this->handled_type = handled_type; + this->frame_handler = frame_handler; + frame_handler->connect_handler(this); } @@ -40,44 +40,43 @@ EthernetFramePayloadHandler::~EthernetFramePayloadHandler() = default; /** * @brief Handle the received ethernet frame payload * - * @param ethernetframePayload the payload of the ethernet frame + * @param ethernetframe_payload the payload of the ethernet frame * @param size the size of the payload * * @return True if the data is to be sent back, false otherwise */ -bool EthernetFramePayloadHandler::handleEthernetframePayload(uint8_t* ethernetframePayload, uint32_t size) { +bool EthernetFramePayloadHandler::handle_ethernetframe_payload(uint8_t* ethernetframe_payload, uint32_t size) { - //By default, don't handle it, will be handled in the override - return false; + //By default, don't handle it, will be handled in the override + return false; } /** - * @brief Send an packet via the backend driver + * @brief send an packet via the backend driver * * @param destination the destination MAC address * @param data the data to send * @param size the size of the payload */ -void EthernetFramePayloadHandler::Send(uint64_t destination, uint8_t *data, uint32_t size) { +void EthernetFramePayloadHandler::send(uint64_t destination, uint8_t* data, uint32_t size) { - frameHandler -> sendEthernetFrame (destination, handledType, data, size); + frame_handler->send_ethernet_frame(destination, handled_type, data, size); } /** * @brief Construct a new Ether Frame Handler object * * @param driver The backend ethernet driver - * @param errorMessages The output stream for error messages + * @param error_messages The output stream for error messages */ -EthernetFrameHandler::EthernetFrameHandler(EthernetDriver* driver, OutputStream* errorMessages) -: EthernetDriverEventHandler() -{ +EthernetFrameHandler::EthernetFrameHandler(EthernetDriver* driver, OutputStream* error_messages) + : EthernetDriverEventHandler() { - this -> ethernetDriver = driver; - this -> errorMessages = errorMessages; + this->ethernet_driver = driver; + this->error_messages = error_messages; - driver->connect_event_handler(this); + driver->connect_event_handler(this); } @@ -88,8 +87,8 @@ EthernetFrameHandler::~EthernetFrameHandler() = default; * * @return MediaAccessControlAddress The MAC address */ -drivers::ethernet::MediaAccessControlAddress EthernetFrameHandler::getMAC() { - return ethernetDriver -> GetMediaAccessControlAddress(); +drivers::ethernet::MediaAccessControlAddress EthernetFrameHandler::get_mac() { + return ethernet_driver->get_media_access_control_address(); } @@ -102,106 +101,107 @@ drivers::ethernet::MediaAccessControlAddress EthernetFrameHandler::getMAC() { * * @todo Future debugging me: the override is not being called in derived classes */ -bool EthernetFrameHandler::DataReceived(uint8_t* buffer, uint32_t size) { +bool EthernetFrameHandler::data_received(uint8_t* buffer, uint32_t size) { - errorMessages -> write("EFH: Data received\n"); + error_messages->write("EFH: Data received\n"); - //Check if the size is big enough to contain an ethernet frame - if(size < sizeof(EthernetFrameHeader)) - return false; + //Check if the size is big enough to contain an ethernet frame + if(size < sizeof(EthernetFrameHeader)) + return false; - //Convert to struct for easier use - auto* frame = (EthernetFrameHeader*)buffer; - bool sendBack = false; + //Convert to struct for easier use + auto* frame = (EthernetFrameHeader*) buffer; + bool send_back = false; - //Only handle if it is for this device - if(frame->destinationMAC == 0xFFFFFFFFFFFF //If it is a broadcast - || frame->destinationMAC == ethernetDriver -> GetMediaAccessControlAddress()) //If it is for this device - { + //Only handle if it is for this device + if(frame->destination_mac == 0xFFFFFFFFFFFF //If it is a broadcast + || frame->destination_mac == ethernet_driver->get_media_access_control_address()) //If it is for this device + { - // Find the handler for the protocol - Map::iterator handlerIterator = frameHandlers.find(frame->type); + // Find the handler for the protocol + Map::iterator handler_iterator = frame_handlers.find(frame->type); - // If the handler is found - if(handlerIterator != frameHandlers.end()) { + // If the handler is found + if(handler_iterator != frame_handlers.end()) { - //Handle the data - errorMessages -> write("EFH: Handling ethernet frame payload\n"); - sendBack = handlerIterator->second->handleEthernetframePayload(buffer + sizeof(EthernetFrameHeader), size - sizeof(EthernetFrameHeader)); - errorMessages -> write("..DONE\n"); + //Handle the data + error_messages->write("EFH: Handling ethernet frame payload\n"); + send_back = handler_iterator->second->handle_ethernetframe_payload(buffer + sizeof(EthernetFrameHeader), + size - sizeof(EthernetFrameHeader)); + error_messages->write("..DONE\n"); - } else { + } else { - //If the handler is not found, print an error message - errorMessages -> write("EFH: Unhandled ethernet frame type 0x"); - errorMessages->write_hex(frame->type); - errorMessages -> write("\n"); + //If the handler is not found, print an error message + error_messages->write("EFH: Unhandled ethernet frame type 0x"); + error_messages->write_hex(frame->type); + error_messages->write("\n"); - } - } + } + } - //If the data is to be sent back again - if(sendBack){ + //If the data is to be sent back again + if(send_back) { - errorMessages -> write("EFH: Sending back\n"); + error_messages->write("EFH: Sending back\n"); - frame -> destinationMAC = frame -> sourceMAC; //Set the new destination to be the device the data was received from - frame -> sourceMAC = ethernetDriver->GetMediaAccessControlAddress(); //Set the new source to be this device's MAC address + frame->destination_mac = frame->source_mac; //Set the new destination to be the device the data was received from + frame->source_mac = ethernet_driver->get_media_access_control_address(); //Set the new source to be this device's MAC address - } + } - //Return if the data is to be sent back - return sendBack; + //Return if the data is to be sent back + return send_back; } /** - * @brief Connect a handler to the frame handler + * @brief connect a handler to the frame handler * * @param handler The handler to connect */ -void EthernetFrameHandler::connectHandler(EthernetFramePayloadHandler *handler) { +void EthernetFrameHandler::connect_handler(EthernetFramePayloadHandler* handler) { - // Convert the protocol type to big endian - uint16_t frameType_BE = ((handler->handledType >> 8) & 0xFF) | ((handler->handledType << 8) & 0xFF00); + // Convert the protocol type to big endian + uint16_t frame_type_be = ((handler->handled_type >> 8) & 0xFF) | ((handler->handled_type << 8) & 0xFF00); - // Add the handler to the list - frameHandlers.insert(frameType_BE, handler); + // Add the handler to the list + frame_handlers.insert(frame_type_be, handler); } /** - * @brief Send an packet via the backend driver + * @brief send an packet via the backend driver * - * @param destinationMAC the destination MAC address - * @param frameType the type of the protocol + * @param destination_mac the destination MAC address + * @param frame_type the type of the protocol * @param data the data to send * @param size the size of the payload */ -void EthernetFrameHandler::sendEthernetFrame(uint64_t destinationMAC, uint16_t frameType, uint8_t* data, uint32_t size) { +void EthernetFrameHandler::send_ethernet_frame(uint64_t destination_mac, uint16_t frame_type, uint8_t* data, uint32_t size) { - errorMessages->write("EFH: Sending frame..."); + error_messages->write("EFH: Sending frame..."); - //Allocate memory for the buffer - auto* buffer = (uint8_t*)MemoryManager::kmalloc(size + sizeof(EthernetFrameHeader)); - auto* frame = (EthernetFrameHeader*)buffer; + //Allocate memory for the buffer + auto* buffer = (uint8_t*) MemoryManager::kmalloc(size + sizeof(EthernetFrameHeader)); + auto* frame = (EthernetFrameHeader*) buffer; - //Put data in the header - frame -> destinationMAC = destinationMAC; - frame -> sourceMAC = ethernetDriver -> GetMediaAccessControlAddress(); - frame -> type = (frameType >> 8) | (frameType << 8); //Convert to big endian + //Put data in the header + frame->destination_mac = destination_mac; + frame->source_mac = ethernet_driver->get_media_access_control_address(); + frame->type = (frame_type >> 8) | (frame_type << 8); //Convert to big endian - //Copy the data - for(uint8_t *src = data + size - 1, *dst = buffer+sizeof(EthernetFrameHeader)+size-1; src >= data; --src, --dst) - *dst = *src; + //Copy the data + for(uint8_t* src = data + size - 1, * dst = buffer + sizeof(EthernetFrameHeader) + size - 1; src >= data; --src, --dst) + *dst = *src; - //Send the data - ethernetDriver -> Send(buffer, size + sizeof(EthernetFrameHeader)); + //Send the data + ethernet_driver->send(buffer, size + sizeof(EthernetFrameHeader)); - errorMessages->write("Done\n"); + error_messages->write("Done\n"); - //Free the buffer - MemoryManager::kfree(buffer); + //Free the buffer + MemoryManager::kfree(buffer); } diff --git a/kernel/src/net/icmp.cpp b/kernel/src/net/icmp.cpp index bfd9b583..890c6f0b 100644 --- a/kernel/src/net/icmp.cpp +++ b/kernel/src/net/icmp.cpp @@ -15,13 +15,13 @@ using namespace MaxOS::net; /** * @brief Constructs an InternetControlMessageProtocol handler. * - * @param internetProtocolHandler The Internet protocol handler to use. - * @param errorMessages The output stream to use for error messages. + * @param internet_protocol_handler The Internet protocol handler to use. + * @param error_messages The output stream to use for error messages. */ -InternetControlMessageProtocol::InternetControlMessageProtocol(InternetProtocolHandler *internetProtocolHandler, OutputStream* errorMessages) -: IPV4PayloadHandler(internetProtocolHandler, 0x01) +InternetControlMessageProtocol::InternetControlMessageProtocol(InternetProtocolHandler *internet_protocol_handler, OutputStream* error_messages) +: IPV4PayloadHandler(internet_protocol_handler, 0x01) { - this -> errorMessages = errorMessages; + this -> error_messages = error_messages; } @@ -30,9 +30,9 @@ InternetControlMessageProtocol::~InternetControlMessageProtocol() = default; /** * @brief Called by the InternetProtocolProvider when a new packet has arrived * - * @param srcIP_BE The source IP address of the packet - * @param dstIP_BE The destination IP address of the packet - * @param payloadData The payload of the packet + * @param src_ip_be The source IP address of the packet + * @param dst_ip_be The destination IP address of the packet + * @param payload_data The payload of the packet * @param size The size of the payload * @return True if the packet is to be sent back to the sender, false otherwise @@ -40,13 +40,13 @@ InternetControlMessageProtocol::~InternetControlMessageProtocol() = default; * @todo Reply to ping requests * @todo Implement the rest of the ICMP messages */ -bool InternetControlMessageProtocol::handleInternetProtocolPayload(InternetProtocolAddress srcIP_BE, - InternetProtocolAddress dstIP_BE, - uint8_t *payloadData, - uint32_t size) +bool InternetControlMessageProtocol::handle_internet_protocol_payload(net::InternetProtocolAddress src_ip_be, + net::InternetProtocolAddress dst_ip_be, + uint8_t *payload_data, + uint32_t size) { - errorMessages -> write("ICMP received a packet\n"); + error_messages -> write("ICMP received a packet\n"); // Check if the size is at least the size of the header if(size < sizeof(ICMPHeader)){ @@ -54,7 +54,7 @@ bool InternetControlMessageProtocol::handleInternetProtocolPayload(InternetProto } // Cast the payload to the ICMP header - auto* icmp = (ICMPHeader*)payloadData; + auto* icmp = (ICMPHeader*)payload_data; switch (icmp -> type) { @@ -66,7 +66,7 @@ bool InternetControlMessageProtocol::handleInternetProtocolPayload(InternetProto // Create a response icmp -> type = 0; // Echo reply icmp -> checksum = 0; // Reset the checksum - icmp -> checksum = InternetProtocolHandler::Checksum((uint16_t *)&icmp, sizeof(ICMPHeader)); // Calculate the checksum + icmp -> checksum = InternetProtocolHandler::checksum((uint16_t*) &icmp, sizeof(ICMPHeader)); // Calculate the checksum return true; //Send data back @@ -81,9 +81,9 @@ bool InternetControlMessageProtocol::handleInternetProtocolPayload(InternetProto * * @param ip_be The IP address to send the request to */ -void InternetControlMessageProtocol::RequestEchoReply(uint32_t ip_be) { +void InternetControlMessageProtocol::request_echo_reply(uint32_t ip_be) { - errorMessages -> write("ICMP: Sending echo request\n"); + error_messages -> write("ICMP: Sending echo request\n"); ICMPHeader icmp = {}; icmp.type = 8; // Echo request @@ -91,9 +91,9 @@ void InternetControlMessageProtocol::RequestEchoReply(uint32_t ip_be) { icmp.checksum = 0; // Checksum must be 0 to calculate it icmp.data = 0x69420; // Data - icmp.checksum = InternetProtocolHandler::Checksum((uint16_t *)&icmp, sizeof(ICMPHeader)); + icmp.checksum = InternetProtocolHandler::checksum((uint16_t*) &icmp, sizeof(ICMPHeader)); - Send(ip_be, (uint8_t *)&icmp, sizeof(ICMPHeader)); + send(ip_be, (uint8_t*) &icmp, sizeof(ICMPHeader)); - errorMessages -> write("ICMP: Echo request sent\n"); + error_messages -> write("ICMP: Echo request sent\n"); } diff --git a/kernel/src/net/ipv4.cpp b/kernel/src/net/ipv4.cpp index f1f8367a..7e0e0ee4 100644 --- a/kernel/src/net/ipv4.cpp +++ b/kernel/src/net/ipv4.cpp @@ -17,17 +17,15 @@ using namespace MaxOS::drivers::ethernet; /** * @brief Construct a new IPV4 Address Resolver object and register it with the Internet Protocol Handler - * @param internetProtocolHandler The Internet Protocol Handler to register with + * @param internet_protocol_handler The Internet Protocol Handler to register with */ -IPV4AddressResolver::IPV4AddressResolver(InternetProtocolHandler *internetProtocolHandler) -{ +IPV4AddressResolver::IPV4AddressResolver(InternetProtocolHandler* internet_protocol_handler) { - internetProtocolHandler -> RegisterIPV4AddressResolver(this); + internet_protocol_handler->register_ipv_4_address_resolver(this); } - IPV4AddressResolver::~IPV4AddressResolver() = default; /** @@ -36,8 +34,8 @@ IPV4AddressResolver::~IPV4AddressResolver() = default; * @param address The IP address to turn into a MAC address. * @return The MAC address. */ -MediaAccessControlAddress IPV4AddressResolver::Resolve(InternetProtocolAddress address) { - return 0xFFFFFFFFFFFF; +MediaAccessControlAddress IPV4AddressResolver::resolve(InternetProtocolAddress address) { + return 0xFFFFFFFFFFFF; } /** @@ -46,24 +44,24 @@ MediaAccessControlAddress IPV4AddressResolver::Resolve(InternetProtocolAddress a * @param internetProtocolAddress The IP address. * @param mediaAccessControlAddress The MAC address. */ -void IPV4AddressResolver::Store(InternetProtocolAddress, MediaAccessControlAddress) { +void IPV4AddressResolver::store(InternetProtocolAddress, drivers::ethernet::MediaAccessControlAddress) { } /** * @brief Construct a new IPV4 Payload Handler object and register it with the Internet Protocol Handler * - * @param internetProtocolHandler The Internet Protocol Handler to register with + * @param internet_protocol_handler The Internet Protocol Handler to register with * @param protocol The IP protocol to handle */ -IPV4PayloadHandler::IPV4PayloadHandler(InternetProtocolHandler* internetProtocolHandler, uint8_t protocol) { +IPV4PayloadHandler::IPV4PayloadHandler(InternetProtocolHandler* internet_protocol_handler, uint8_t protocol) { - // Store vars - this -> internetProtocolHandler = internetProtocolHandler; - this -> ipProtocol = protocol; + // Store vars + this->internet_protocol_handler = internet_protocol_handler; + this->ip_protocol = protocol; - //Register handler - internetProtocolHandler ->connectIPV4PayloadHandler(this); + //Register handler + internet_protocol_handler->connect_ipv_4_payload_handler(this); } @@ -72,31 +70,31 @@ IPV4PayloadHandler::~IPV4PayloadHandler() = default; /** * @brief Called when an IP packet is received. (Deafult, does nothing, overide for use) * - * @param srcIP_BE The source IP address. - * @param dstIP_BE The destination IP address. - * @param internetprotocolPayload The payload of the IP packet. + * @param src_ip_be The source IP address. + * @param dst_ip_be The destination IP address. + * @param internetprotocol_payload The payload of the IP packet. * @param size The size of the IP packet. * @return True if the packet was handled, false otherwise. */ -bool IPV4PayloadHandler::handleInternetProtocolPayload(net::InternetProtocolAddress srcIP_BE, - net::InternetProtocolAddress dstIP_BE, - uint8_t * internetprotocolPayload, - uint32_t size) { - return false; +bool IPV4PayloadHandler::handle_internet_protocol_payload(net::InternetProtocolAddress src_ip_be, + net::InternetProtocolAddress dst_ip_be, + uint8_t* internetprotocol_payload, + uint32_t size) { + return false; } /** * @brief Sends an IP packet. * - * @param destinationIP The destination IP address. - * @param payloadData The payload of the IP packet. + * @param destination_ip The destination IP address. + * @param payload_data The payload of the IP packet. * @param size The size of the IP packet. */ -void IPV4PayloadHandler::Send(InternetProtocolAddress destinationIP, uint8_t *payloadData, uint32_t size) { +void IPV4PayloadHandler::send(InternetProtocolAddress destination_ip, uint8_t* payload_data, uint32_t size) { - //Pass to backend - internetProtocolHandler -> sendInternetProtocolPacket(destinationIP, ipProtocol, payloadData, size); + //Pass to backend + internet_protocol_handler->send_internet_protocol_packet(destination_ip, ip_protocol, payload_data, size); } @@ -104,19 +102,18 @@ void IPV4PayloadHandler::Send(InternetProtocolAddress destinationIP, uint8_t *pa * @brief Construct a new Internet Protocol Handler object * * @param backend The backend Ethernet frame handler. - * @param ownInternetProtocolAddress The IP address of this device. - * @param defaultGatewayInternetProtocolAddress The IP address of the default gateway. - * @param subnetMask The subnet mask. - * @param errorMessages Where to write error messages. + * @param own_internet_protocol_address The IP address of this device. + * @param default_gateway_internet_protocol_address The IP address of the default gateway. + * @param subnet_mask The subnet mask. + * @param error_messages Where to write error messages. */ -InternetProtocolHandler::InternetProtocolHandler(EthernetFrameHandler *backend, InternetProtocolAddress ownInternetProtocolAddress, InternetProtocolAddress defaultGatewayInternetProtocolAddress, SubnetMask subnetMask, OutputStream* errorMessages) - : EthernetFramePayloadHandler(backend, 0x0800) -{ - //Store vars - this -> ownInternetProtocolAddress = ownInternetProtocolAddress; - this -> defaultGatewayInternetProtocolAddress = defaultGatewayInternetProtocolAddress; - this -> subnetMask = subnetMask; - this -> errorMessages = errorMessages; +InternetProtocolHandler::InternetProtocolHandler(EthernetFrameHandler* backend, InternetProtocolAddress own_internet_protocol_address, InternetProtocolAddress default_gateway_internet_protocol_address, SubnetMask subnet_mask, OutputStream* error_messages) +: EthernetFramePayloadHandler(backend, 0x0800) { + //Store vars + this->own_internet_protocol_address = own_internet_protocol_address; + this->default_gateway_internet_protocol_address = default_gateway_internet_protocol_address; + this->subnet_mask = subnet_mask; + this->error_messages = error_messages; } InternetProtocolHandler::~InternetProtocolHandler() = default; @@ -124,132 +121,151 @@ InternetProtocolHandler::~InternetProtocolHandler() = default; /** * @brief Called when an IP packet is received. * - * @param ethernetframePayload The payload of the IP packet. + * @param ethernetframe_payload The payload of the IP packet. * @param size The size of the IP packet. * @return True if the packet is to be sent back, false otherwise. * * @todo Set the identifier when sending packets back */ -bool InternetProtocolHandler::handleEthernetframePayload(uint8_t* ethernetframePayload, uint32_t size){ +bool InternetProtocolHandler::handle_ethernetframe_payload(uint8_t* ethernetframe_payload, uint32_t size) { - errorMessages ->write("IP: Handling packet\n"); + error_messages->write("IP: Handling packet\n"); - //Check if the size is big enough to contain an ethernet frame - if(size < sizeof(IPV4Header)) - return false; + //Check if the size is big enough to contain an ethernet frame + if(size < sizeof(IPV4Header)) + return false; - //Convert to struct for easier use - auto* ipMessage = (IPV4Header*)ethernetframePayload; - bool sendBack = false; + //Convert to struct for easier use + auto* ip_message = (IPV4Header*) ethernetframe_payload; + bool send_back = false; - //Only handle if it is for this device - if(ipMessage -> destinationIP == GetInternetProtocolAddress()) - { - uint32_t length = ipMessage -> totalLength; //Get length of the message - if(length > size) //Check if the length is bigger than the size of the message - length = size; //If so, set length to size (this stops heartbleed attacks as it will not read past the end of the message, which the attacker could have filled with data) + //Only handle if it is for this device + if(ip_message->destination_ip == get_internet_protocol_address()) { + uint32_t length = ip_message->total_length; //Get length of the message + if(length > + size) //Check if the length is bigger than the size of the message + length = size; //If so, set length to size (this stops heartbleed attacks as it will not read past the end of the message, which the attacker could have filled with data) - // Get the handler for the protocol - Map::iterator handlerIterator = IPV4PayloadHandlers.find(ipMessage -> protocol); - if(handlerIterator != IPV4PayloadHandlers.end()) { - IPV4PayloadHandler* handler = handlerIterator -> second; - if(handler != nullptr) { - sendBack = handler -> handleInternetProtocolPayload(ipMessage -> sourceIP, ipMessage -> destinationIP, ethernetframePayload + sizeof(IPV4Header), length - sizeof(IPV4Header)); - } - } + // Get the handler for the protocol + Map::iterator handler_iterator = ipv_4_payload_handlers.find(ip_message->protocol); + if(handler_iterator != ipv_4_payload_handlers.end()) { + IPV4PayloadHandler* handler = handler_iterator->second; + if(handler != nullptr) { + send_back = handler->handle_internet_protocol_payload(ip_message->source_ip, ip_message->destination_ip, + ethernetframe_payload + sizeof(IPV4Header), + length - sizeof(IPV4Header)); + } + } - } + } - //If the data is to be sent back again - if(sendBack){ + //If the data is to be sent back again + if(send_back) { - //Swap source and destination - uint32_t temp = ipMessage -> destinationIP; //Store destination IP - ipMessage -> destinationIP = ipMessage -> sourceIP; //Set destination IP to source IP - ipMessage -> sourceIP = temp; //Set source IP to destination IP + //Swap source and destination + uint32_t temp = ip_message->destination_ip; //Store destination IP + ip_message->destination_ip = ip_message->source_ip; //Set destination IP to source IP + ip_message->source_ip = temp; //Set source IP to destination IP - ipMessage -> timeToLive = 0x40; //Reset TTL - ipMessage -> checksum = Checksum((uint16_t*)ipMessage, 4 * ipMessage -> headerLength); //Reset checksum as the source and destination IP have changed so has the time to live and therefore there is a different header + ip_message->time_to_live = 0x40; //Reset TTL + ip_message->checksum = checksum((uint16_t*) ip_message, 4 * + ip_message->header_length); //Reset checksum as the source and destination IP have changed so has the time to live and therefore there is a different header - } + } - errorMessages ->write("IP: Handled packet\n"); - return sendBack; + error_messages->write("IP: Handled packet\n"); + return send_back; } /** * @brief Sends an IP packet. * - * @param dstIP_BE The destination IP address. + * @param dst_ip_be The destination IP address. * @param protocol The protocol of the IP packet. * @param data The payload of the IP packet. * @param size The size of the IP packet. */ -void InternetProtocolHandler::sendInternetProtocolPacket(uint32_t dstIP_BE, uint8_t protocol, const uint8_t *data, uint32_t size) { - - auto* buffer = (uint8_t*)MemoryManager::kmalloc(sizeof(IPV4Header) + size); //Allocate memory for the message - auto *message = (IPV4Header*)buffer; //Convert to struct for easier use - - message -> version = 4; //Set version - message -> headerLength = sizeof(IPV4Header)/4; //Set header length - message -> typeOfService = 0; //Set type of service (not private) - - message -> totalLength = size + sizeof(IPV4Header); //Set total length - message -> totalLength = ((message -> totalLength & 0xFF00) >> 8) // Convert to big endian (Swap bytes) - | ((message -> totalLength & 0x00FF) << 8); // Convert to big endian (Swap bytes) - - message -> identifier = 0x100; //Set identification TODO: do properly - message -> flagsAndOffset = 0x0040; //Set flags/offset, 0x40 because we are not fragmenting (TODO: doesnt work for packets bigger than 1500 bytes) - - message -> timeToLive = 0x40; //Set time to live - message -> protocol = protocol; //Set protocol - - message -> destinationIP = dstIP_BE; //Set destination IP - message -> sourceIP = GetInternetProtocolAddress(); //Set source IP - - message -> checksum = 0; //Set checksum to 0, init with 0 as checksum funct will also add this value - message -> checksum = Checksum((uint16_t*)message, sizeof(IPV4Header)); //Calculate checksum - - //Copy data - uint8_t* data_buffer = buffer + sizeof(IPV4Header); //Get pointer to the data - for(uint32_t i = 0; i < size; i++) //Loop through data - data_buffer[i] = data[i]; //Copy data - - //Check if the destination is on the same subnet, The if condition determines if the destination device is on the same Local network as the source device . and if they are not on the same local network then we resolve the ip address of the gateway . - InternetProtocolAddress route = dstIP_BE; //Set route to destination IP by default - if((dstIP_BE & subnetMask) != (ownInternetProtocolAddress & subnetMask)) //Check if the destination is on the same subnet - route = defaultGatewayInternetProtocolAddress; //If not, set route to gateway IP - //Print debug info - uint32_t MAC = resolver ->Resolve(route); - - //Send message - frameHandler -> sendEthernetFrame(MAC, this -> handledType, buffer, size + sizeof(IPV4Header)); //Send message - MemoryManager::kfree(buffer); //Free memory +void InternetProtocolHandler::send_internet_protocol_packet(uint32_t dst_ip_be, uint8_t protocol, const uint8_t* data, uint32_t size) { + + auto* buffer = (uint8_t*) MemoryManager::kmalloc( + sizeof(IPV4Header) + size); //Allocate memory for the message + auto* message = (IPV4Header*) buffer; //Convert to struct for easier use + + message->version = 4; //Set version + message->header_length = sizeof(IPV4Header) / + 4; //Set header length + message->type_of_service = 0; //Set type of service (not private) + + message->total_length = size + + sizeof(IPV4Header); //Set total length + message->total_length = ((message->total_length & 0xFF00) + >> 8) // Convert to big endian (Swap bytes) + | ((message->total_length & 0x00FF) + << 8); // Convert to big endian (Swap bytes) + + message->identifier = 0x100; //Set identification TODO: do properly + message->flags_and_offset = 0x0040; //Set flags/offset, 0x40 because we are not fragmenting (TODO: doesnt work for packets bigger than 1500 bytes) + + message->time_to_live = 0x40; //Set time to live + message->protocol = protocol; //Set protocol + + message->destination_ip = dst_ip_be; //Set destination IP + message->source_ip = get_internet_protocol_address(); //Set source IP + + message->checksum = 0; //Set checksum to 0, init with 0 as checksum funct will also add this value + message->checksum = checksum((uint16_t*) message, + sizeof(IPV4Header)); //Calculate checksum + + //Copy data + uint8_t* data_buffer = buffer + + sizeof(IPV4Header); //Get pointer to the data + for(uint32_t i = 0; i < + size; i++) //Loop through data + data_buffer[i] = data[i]; //Copy data + + //Check if the destination is on the same subnet, The if condition determines if the destination device is on the same Local network as the source device . and if they are not on the same local network then we resolve the ip address of the gateway . + InternetProtocolAddress route = dst_ip_be; //Set route to destination IP by default + if((dst_ip_be & subnet_mask) != (own_internet_protocol_address & + subnet_mask)) //Check if the destination is on the same subnet + route = default_gateway_internet_protocol_address; //If not, set route to gateway IP + //Print debug info + uint32_t mac = resolver->resolve(route); + + //Send message + frame_handler->send_ethernet_frame(mac, this->handled_type, buffer, size + sizeof(IPV4Header)); //Send message + MemoryManager::kfree( + buffer); //Free memory } /** * @brief Creates a checksum for the given data. * * @param data The data to create a checksum for. - * @param lengthInBytes The length of the data in bytes. + * @param length_in_bytes The length of the data in bytes. * @return The checksum. */ -uint16_t InternetProtocolHandler::Checksum(const uint16_t *data, uint32_t lengthInBytes) { +uint16_t InternetProtocolHandler::checksum(const uint16_t* data, uint32_t length_in_bytes) { - uint32_t temp = 0; //Init sum + uint32_t temp = 0; //Init sum - for(uint32_t i = 0; i < lengthInBytes/2; i++) //Loop through data (/2 bc bytes) - temp += ((data[i] & 0xFF00) >> 8) | ((data[i] & 0x00FF) << 8); //Add data to sum in big endian + for(uint32_t i = 0; i < length_in_bytes / + 2; i++) //Loop through data (/2 bc bytes) + temp += ((data[i] & 0xFF00) >> 8) | + ((data[i] & 0x00FF) << 8); //Add data to sum in big endian - if(lengthInBytes % 2) //If there is an odd number of bytes - temp += ((uint16_t)((char*)data)[lengthInBytes-1]) << 8; //Add the last byte to the sum + if(length_in_bytes % + 2) //If there is an odd number of bytes + temp += ((uint16_t) ((char*) data)[length_in_bytes - 1]) + << 8; //Add the last byte to the sum - while(temp & 0xFFFF0000) //While there is a carry - temp = (temp & 0xFFFF) + (temp >> 16); //Add the carry to the sum + while(temp & + 0xFFFF0000) //While there is a carry + temp = (temp & 0xFFFF) + + (temp >> 16); //Add the carry to the sum - return ((~temp & 0xFF00) >> 8) | ((~temp & 0x00FF) << 8); + return ((~temp & 0xFF00) >> 8) | ((~temp & 0x00FF) << 8); } /** @@ -257,9 +273,9 @@ uint16_t InternetProtocolHandler::Checksum(const uint16_t *data, uint32_t length * * @param resolver The resolver to register. */ -void InternetProtocolHandler::RegisterIPV4AddressResolver(IPV4AddressResolver *resolver) { +void InternetProtocolHandler::register_ipv_4_address_resolver(IPV4AddressResolver* ipv4_resolver) { - this -> resolver = resolver; + this->resolver = ipv4_resolver; } @@ -273,12 +289,12 @@ void InternetProtocolHandler::RegisterIPV4AddressResolver(IPV4AddressResolver *r * * @return The created IP address. */ -InternetProtocolAddress InternetProtocolHandler::CreateInternetProtocolAddress(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4) { - InternetProtocolAddress result = digit4; - result = (result << 8) | digit3; - result = (result << 8) | digit2; - result = (result << 8) | digit1; - return result; +InternetProtocolAddress InternetProtocolHandler::create_internet_protocol_address(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4) { + InternetProtocolAddress result = digit4; + result = (result << 8) | digit3; + result = (result << 8) | digit2; + result = (result << 8) | digit1; + return result; } /** @@ -287,24 +303,24 @@ InternetProtocolAddress InternetProtocolHandler::CreateInternetProtocolAddress(u * @param address The string representation of the IP address. * @return The parsed IP address. */ -InternetProtocolAddress InternetProtocolHandler::Parse(string address) { - uint8_t digits[4]; +InternetProtocolAddress InternetProtocolHandler::parse(string address) { + uint8_t digits[4]; - uint8_t currentDigit = 0; - for(unsigned char & digit : digits) - digit = 0; + uint8_t current_digit = 0; + for(unsigned char& digit : digits) + digit = 0; - for(size_t i = 0; i < address.length(); i++) { - if(address[i] == '.') { - currentDigit++; - continue; - } + for(size_t i = 0; i < address.length(); i++) { + if(address[i] == '.') { + current_digit++; + continue; + } - digits[currentDigit] *= 10; - digits[currentDigit] += address[i] - '0'; - } + digits[current_digit] *= 10; + digits[current_digit] += address[i] - '0'; + } - return CreateInternetProtocolAddress(digits[0], digits[1], digits[2], digits[3]); + return create_internet_protocol_address(digits[0], digits[1], digits[2], digits[3]); } /** @@ -317,8 +333,8 @@ InternetProtocolAddress InternetProtocolHandler::Parse(string address) { * * @return The created subnet mask. */ -SubnetMask InternetProtocolHandler::CreateSubnetMask(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4) { - return (SubnetMask)CreateInternetProtocolAddress(digit1, digit2, digit3, digit4); +SubnetMask InternetProtocolHandler::create_subnet_mask(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4) { + return (SubnetMask) create_internet_protocol_address(digit1, digit2, digit3, digit4); } /** @@ -326,8 +342,8 @@ SubnetMask InternetProtocolHandler::CreateSubnetMask(uint8_t digit1, uint8_t dig * * @return The IP address. */ -InternetProtocolAddress InternetProtocolHandler::GetInternetProtocolAddress() const { - return ownInternetProtocolAddress; +InternetProtocolAddress InternetProtocolHandler::get_internet_protocol_address() const { + return own_internet_protocol_address; } /** @@ -335,15 +351,15 @@ InternetProtocolAddress InternetProtocolHandler::GetInternetProtocolAddress() co * * @return The MAC address. */ -MediaAccessControlAddress InternetProtocolHandler::GetMediaAccessControlAddress() { - return frameHandler -> getMAC(); +MediaAccessControlAddress InternetProtocolHandler::get_media_access_control_address() { + return frame_handler->get_mac(); } /** * @brief Connects an IP protocol payload handler. * - * @param IPV4PayloadHandler The payload handler to connect. + * @param ipv_4_payload_handler The payload handler to connect. */ -void InternetProtocolHandler::connectIPV4PayloadHandler( IPV4PayloadHandler *IPV4PayloadHandler) { - IPV4PayloadHandlers.insert(IPV4PayloadHandler -> ipProtocol, IPV4PayloadHandler); +void InternetProtocolHandler::connect_ipv_4_payload_handler(IPV4PayloadHandler* ipv_4_payload_handler) { + ipv_4_payload_handlers.insert(ipv_4_payload_handler->ip_protocol, ipv_4_payload_handler); } diff --git a/kernel/src/net/tcp.cpp b/kernel/src/net/tcp.cpp index 4bab91a1..76c83586 100644 --- a/kernel/src/net/tcp.cpp +++ b/kernel/src/net/tcp.cpp @@ -19,7 +19,7 @@ using namespace MaxOS::memory; TCPPayloadHandler::TCPPayloadHandler() = default; -TCPPayloadHandler::~TCPPayloadHandler()= default; +TCPPayloadHandler::~TCPPayloadHandler() = default; /** * @brief Handle TCP data received on the socket @@ -28,7 +28,7 @@ TCPPayloadHandler::~TCPPayloadHandler()= default; * @param data The data received * @param size The size of the data in bytes */ -void TCPPayloadHandler::handleTransmissionControlProtocolPayload(TCPSocket* socket, uint8_t* data, uint16_t size) { +void TCPPayloadHandler::handle_transmission_control_protocol_payload(TCPSocket* socket, uint8_t* data, uint16_t size) { } @@ -37,7 +37,7 @@ void TCPPayloadHandler::handleTransmissionControlProtocolPayload(TCPSocket* sock * * @param socket The socket that was connected */ -void TCPPayloadHandler::Connected(TCPSocket* socket) { +void TCPPayloadHandler::connected(TCPSocket* socket) { } @@ -46,7 +46,7 @@ void TCPPayloadHandler::Connected(TCPSocket* socket) { * * @param socket The socket that was disconnected */ -void TCPPayloadHandler::Disconnected(TCPSocket* socket) { +void TCPPayloadHandler::disconnected(TCPSocket* socket) { } @@ -58,17 +58,17 @@ void TCPPayloadHandler::Disconnected(TCPSocket* socket) { */ Event* TCPPayloadHandler::on_event(Event* event) { - switch (event->type) { + switch(event->type) { case TCPPayloadHandlerEvents::CONNECTED: - Connected(((ConnectedEvent*) event)->socket); + connected(((ConnectedEvent*) event)->socket); break; case TCPPayloadHandlerEvents::DISCONNECTED: - Disconnected(((DisconnectedEvent*) event)->socket); + disconnected(((DisconnectedEvent*) event)->socket); break; case TCPPayloadHandlerEvents::DATA_RECEIVED: - handleTransmissionControlProtocolPayload(((DataReceivedEvent*) event)->socket, - ((DataReceivedEvent*) event)->data, - ((DataReceivedEvent*) event)->size); + handle_transmission_control_protocol_payload(((DataReceivedEvent*) event)->socket, + ((DataReceivedEvent*) event)->data, + ((DataReceivedEvent*) event)->size); break; } @@ -78,11 +78,11 @@ Event* TCPPayloadHandler::on_event(EventtransmissionControlProtocolHandler = transmissionControlProtocolHandler; + this->transmission_control_protocol_handler = transmission_control_protocol_handler; //Closed as default state = TCPSocketState::CLOSED; @@ -97,7 +97,7 @@ TCPSocket::~TCPSocket() = default; * @param size The size of the data * @return True if the connection is to be terminated after hadnling or false if not */ -bool TCPSocket::handleTransmissionControlProtocolPayload(uint8_t* data, uint16_t size) { +bool TCPSocket::handle_transmission_control_protocol_payload(uint8_t* data, uint16_t size) { auto* event = new DataReceivedEvent(this, data, size); raise_event(event); MemoryManager::kfree(event); @@ -105,32 +105,32 @@ bool TCPSocket::handleTransmissionControlProtocolPayload(uint8_t* data, uint16_t } /** - * @brief Send data over the socket + * @brief send data over the socket * * @param data The data to send * @param size The size of the data */ -void TCPSocket::Send(uint8_t* data, uint16_t size) { +void TCPSocket::send(uint8_t* data, uint16_t size) { //Wait for the socket to be connected - while (state != TCPSocketState::ESTABLISHED); + while(state != TCPSocketState::ESTABLISHED); //Pass the data to the backend - transmissionControlProtocolHandler->sendTransmissionControlProtocolPacket(this, data, size, - (uint16_t) TCPFlag::PSH | - (uint16_t) TCPFlag::ACK); + transmission_control_protocol_handler->send_transmission_control_protocol_packet(this, data, size, + (uint16_t) TCPFlag::PSH | + (uint16_t) TCPFlag::ACK); } /** - * @brief Disconnect the socket + * @brief disconnect the socket */ -void TCPSocket::Disconnect() { - transmissionControlProtocolHandler->Disconnect(this); +void TCPSocket::disconnect() { + transmission_control_protocol_handler->disconnect(this); } /** * @brief Raise the disconnected event */ -void TCPSocket::Disconnected() { +void TCPSocket::disconnected() { auto* event = new DisconnectedEvent(this); raise_event(event); MemoryManager::kfree(event); @@ -140,7 +140,7 @@ void TCPSocket::Disconnected() { /** * @brief Raise the connected event */ -void TCPSocket::Connected() { +void TCPSocket::connected() { auto* event = new ConnectedEvent(this); raise_event(event); MemoryManager::kfree(event); @@ -149,17 +149,17 @@ void TCPSocket::Connected() { ///__Handler__/// -TransmissionControlProtocolPort TransmissionControlProtocolHandler::freePorts = 0x8000; +TransmissionControlProtocolPort TransmissionControlProtocolHandler::free_ports = 0x8000; /** * @brief Construct a new Transmission Control Protocol Handler object * - * @param internetProtocolHandler The Internet protocol handler - * @param errorMessages Where to write error messages + * @param internet_protocol_handler The Internet protocol handler + * @param error_messages Where to write error messages */ -TransmissionControlProtocolHandler::TransmissionControlProtocolHandler(MaxOS::net::InternetProtocolHandler* internetProtocolHandler, OutputStream* errorMessages) - : IPV4PayloadHandler(internetProtocolHandler, 0x06) { - this->errorMessages = errorMessages; +TransmissionControlProtocolHandler::TransmissionControlProtocolHandler(MaxOS::net::InternetProtocolHandler* internet_protocol_handler, OutputStream* error_messages) + : IPV4PayloadHandler(internet_protocol_handler, 0x06) { + this->error_messages = error_messages; } @@ -171,7 +171,7 @@ TransmissionControlProtocolHandler::~TransmissionControlProtocolHandler() = defa * @param x The 32-bit integer to convert * @return The big-endian formatted integer */ -uint32_t bigEndian32(uint32_t x) { +uint32_t big_endian_32(uint32_t x) { return ((x & 0xFF000000) >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) @@ -184,7 +184,7 @@ uint32_t bigEndian32(uint32_t x) { * @param x The 16-bit integer to convert * @return The big-endian formatted integer */ -uint32_t bigEndian16(uint16_t x) { +uint32_t big_endian_16(uint16_t x) { return ((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8); } @@ -192,58 +192,58 @@ uint32_t bigEndian16(uint16_t x) { /** * @brief Handle the TCP message (provider end) * - * @param sourceIP The source IP address - * @param destinationIP The destination IP address - * @param payloadData The payload + * @param source_ip The source IP address + * @param destination_ip The destination IP address + * @param payload_data The payload * @param size The size of the payload * @return True if data is to be sent back or false if not */ -bool TransmissionControlProtocolHandler::handleInternetProtocolPayload(InternetProtocolAddress sourceIP, InternetProtocolAddress destinationIP, uint8_t* payloadData, uint32_t size) { +bool TransmissionControlProtocolHandler::handle_internet_protocol_payload(net::InternetProtocolAddress source_ip, net::InternetProtocolAddress destination_ip, uint8_t* payload_data, uint32_t size) { - errorMessages->write("TCP: Handling TCP message\n"); + error_messages->write("TCP: Handling TCP message\n"); //Check if the size is too small - if (size < 13) { + if(size < 13) { return false; } // If it's smaller than the header, return - if (size < 4 * payloadData[12] / 16) // The lower 4 bits of the 13th byte is the header length + if(size < 4 * payload_data[12] / 16) // The lower 4 bits of the 13th byte is the header length { return false; } //Get the header - auto* msg = (TCPHeader*) payloadData; + auto* msg = (TCPHeader*) payload_data; //Get the connection values (convert to host endian) - uint16_t localPort = bigEndian16(msg->dstPort); - uint16_t remotePort = bigEndian16(msg->srcPort); + uint16_t local_port = big_endian_16(msg->dst_port); + uint16_t remote_port = big_endian_16(msg->src_port); //Create the socket TCPSocket* socket = nullptr; - for (auto ¤tSocket : sockets) { - if (currentSocket->localPort == - localPort //Check if the local port is the same as the destination port - && currentSocket->localIP == - destinationIP //Check if the local IP is the same as the destination IP - && currentSocket->state == - TCPSocketState::LISTEN //Check if the socket is in the LISTEN state - && (((msg->flags) & ((uint16_t) TCPFlag::SYN | (uint16_t) TCPFlag::ACK)) == - (uint16_t) TCPFlag::SYN)) //Check if the SYN flag is set (allow for acknoweldgement) + for(auto& current_socket : sockets) { + if(current_socket->local_port == + local_port //Check if the local port is the same as the destination port + && current_socket->local_ip == + destination_ip //Check if the local IP is the same as the destination IP + && current_socket->state == + TCPSocketState::LISTEN //Check if the socket is in the LISTEN state + && (((msg->flags) & ((uint16_t) TCPFlag::SYN | (uint16_t) TCPFlag::ACK)) == + (uint16_t) TCPFlag::SYN)) //Check if the SYN flag is set (allow for acknoweldgement) { - socket = currentSocket; - } else if (currentSocket->localPort == - localPort //Check if the local port is the same as the destination port - && currentSocket->localIP == - destinationIP //Check if the local IP is the same as the destination IP - && currentSocket->remotePort == - remotePort //Check if the remote port is the same as the source port - && currentSocket->remoteIP == - destinationIP) //Check if the remote IP is the same as the source IP + socket = current_socket; + } else if(current_socket->local_port == + local_port //Check if the local port is the same as the destination port + && current_socket->local_ip == + destination_ip //Check if the local IP is the same as the destination IP + && current_socket->remotePort == + remote_port //Check if the remote port is the same as the source port + && current_socket->remote_ip == + destination_ip) //Check if the remote IP is the same as the source IP { - socket = currentSocket; + socket = current_socket; } } @@ -251,14 +251,14 @@ bool TransmissionControlProtocolHandler::handleInternetProtocolPayload(InternetP bool reset = false; //Check if the socket is found and if the socket wants to reset - if (socket != nullptr && msg->flags & (uint16_t) TCPFlag::RST) { + if(socket != nullptr && msg->flags & (uint16_t) TCPFlag::RST) { socket->state = TCPSocketState::CLOSED; - socket->Disconnected(); + socket->disconnected(); } //Check if the socket is found and if the socket is not closed - if (socket != nullptr && socket->state != TCPSocketState::CLOSED) { - switch ((msg->flags) & ((uint16_t) TCPFlag::SYN | (uint16_t) TCPFlag::ACK | (uint16_t) TCPFlag::FIN)) { + if(socket != nullptr && socket->state != TCPSocketState::CLOSED) { + switch((msg->flags) & ((uint16_t) TCPFlag::SYN | (uint16_t) TCPFlag::ACK | (uint16_t) TCPFlag::FIN)) { /* * Example for explanation: * socket -> state = SYN_RECEIVED; //The state of the socket, e.g. recieved, or established. This is used to know how to handle the socket @@ -272,26 +272,26 @@ bool TransmissionControlProtocolHandler::handleInternetProtocolPayload(InternetP */ case (uint16_t) TCPFlag::SYN: - if (socket->state == TCPSocketState::LISTEN) { + if(socket->state == TCPSocketState::LISTEN) { socket->state = TCPSocketState::SYN_RECEIVED; - socket->remotePort = msg->srcPort; - socket->remoteIP = sourceIP; - socket->acknowledgementNumber = bigEndian32(msg->sequenceNumber) + 1; - socket->sequenceNumber = 0xbeefcafe; - sendTransmissionControlProtocolPacket(socket, nullptr, 0, - (uint16_t) TCPFlag::SYN | (uint16_t) TCPFlag::ACK); - socket->sequenceNumber++; + socket->remotePort = msg->src_port; + socket->remote_ip = source_ip; + socket->acknowledgement_number = big_endian_32(msg->sequence_number) + 1; + socket->sequence_number = 0xbeefcafe; + send_transmission_control_protocol_packet(socket, nullptr, 0, + (uint16_t) TCPFlag::SYN | (uint16_t) TCPFlag::ACK); + socket->sequence_number++; } else reset = true; break; case (uint16_t) TCPFlag::SYN | (uint16_t) TCPFlag::ACK: - if (socket->state == TCPSocketState::SYN_SENT) { + if(socket->state == TCPSocketState::SYN_SENT) { socket->state = TCPSocketState::ESTABLISHED; - socket->acknowledgementNumber = bigEndian32(msg->sequenceNumber) + 1; - socket->sequenceNumber++; - sendTransmissionControlProtocolPacket(socket, nullptr, 0, (uint16_t) TCPFlag::ACK); + socket->acknowledgement_number = big_endian_32(msg->sequence_number) + 1; + socket->sequence_number++; + send_transmission_control_protocol_packet(socket, nullptr, 0, (uint16_t) TCPFlag::ACK); } else reset = true; break; @@ -305,39 +305,39 @@ bool TransmissionControlProtocolHandler::handleInternetProtocolPayload(InternetP case (uint16_t) TCPFlag::FIN: case (uint16_t) TCPFlag::FIN | (uint16_t) TCPFlag::ACK: - if (socket->state == TCPSocketState::ESTABLISHED) { + if(socket->state == TCPSocketState::ESTABLISHED) { socket->state = TCPSocketState::CLOSE_WAIT; - socket->acknowledgementNumber++; - sendTransmissionControlProtocolPacket(socket, nullptr, 0, (uint16_t) TCPFlag::ACK); - sendTransmissionControlProtocolPacket(socket, nullptr, 0, - (uint16_t) TCPFlag::FIN | (uint16_t) TCPFlag::ACK); - socket->Disconnected(); - } else if (socket->state == TCPSocketState::CLOSE_WAIT) { + socket->acknowledgement_number++; + send_transmission_control_protocol_packet(socket, nullptr, 0, (uint16_t) TCPFlag::ACK); + send_transmission_control_protocol_packet(socket, nullptr, 0, + (uint16_t) TCPFlag::FIN | (uint16_t) TCPFlag::ACK); + socket->disconnected(); + } else if(socket->state == TCPSocketState::CLOSE_WAIT) { socket->state = TCPSocketState::CLOSED; - } else if (socket->state == TCPSocketState::FIN_WAIT1 || socket->state == TCPSocketState::FIN_WAIT2) { + } else if(socket->state == TCPSocketState::FIN_WAIT1 || socket->state == TCPSocketState::FIN_WAIT2) { socket->state = TCPSocketState::CLOSED; - socket->acknowledgementNumber++; - sendTransmissionControlProtocolPacket(socket, nullptr, 0, (uint16_t) TCPFlag::ACK); - socket->Disconnected(); + socket->acknowledgement_number++; + send_transmission_control_protocol_packet(socket, nullptr, 0, (uint16_t) TCPFlag::ACK); + socket->disconnected(); } else reset = true; break; case (uint16_t) TCPFlag::ACK: - if (socket->state == TCPSocketState::SYN_RECEIVED) { + if(socket->state == TCPSocketState::SYN_RECEIVED) { socket->state = TCPSocketState::ESTABLISHED; - socket->Connected(); + socket->connected(); return false; - } else if (socket->state == TCPSocketState::FIN_WAIT1) { + } else if(socket->state == TCPSocketState::FIN_WAIT1) { socket->state = TCPSocketState::FIN_WAIT2; return false; - } else if (socket->state == TCPSocketState::CLOSE_WAIT) { + } else if(socket->state == TCPSocketState::CLOSE_WAIT) { socket->state = TCPSocketState::CLOSED; break; } - if (msg->flags == (uint16_t) TCPFlag::ACK) + if(msg->flags == (uint16_t) TCPFlag::ACK) break; // no break, because of piggybacking @@ -345,23 +345,24 @@ bool TransmissionControlProtocolHandler::handleInternetProtocolPayload(InternetP default: - //By default handle the data + // By default, handle the data - if (bigEndian32(msg->sequenceNumber) == socket->acknowledgementNumber) { + if(big_endian_32(msg->sequence_number) == socket->acknowledgement_number) { - reset = !(socket->handleTransmissionControlProtocolPayload(payloadData + msg->headerSize32 * 4, - size - msg->headerSize32 * 4)); - if (!reset) { + reset = !(socket->handle_transmission_control_protocol_payload( + payload_data + msg->header_size_32 * 4, + size - msg->header_size_32 * 4)); + if(!reset) { uint32_t x = 0; //The number of bytes to send back - for (uint32_t i = msg->headerSize32 * 4; - i < size; i++) //Loop through the data - if (payloadData[i] != - 0) //Check if the data is not 0 + for(uint32_t i = msg->header_size_32 * 4; + i < size; i++) //Loop through the data + if(payload_data[i] != + 0) //Check if the data is not 0 x = i; //Set the number of bytes to send back to the current index - socket->acknowledgementNumber += x - msg->headerSize32 * 4 + - 1; //Increment the acknowledgement number by the number of bytes to send back - sendTransmissionControlProtocolPacket(socket, nullptr, 0, - (uint16_t) TCPFlag::ACK); //Send the acknowledgement + socket->acknowledgement_number += x - msg->header_size_32 * 4 + + 1; //Increment the acknowledgement number by the number of bytes to send back + send_transmission_control_protocol_packet(socket, nullptr, 0, + (uint16_t) TCPFlag::ACK); //Send the acknowledgement } } else { // data in wrong order @@ -372,32 +373,33 @@ bool TransmissionControlProtocolHandler::handleInternetProtocolPayload(InternetP } - if (reset) //If the socket is to be reset + if(reset) //If the socket is to be reset { - if (socket != - nullptr) //If the socket exists then send a reset flag + if(socket != + nullptr) //If the socket exists then send a reset flag { - sendTransmissionControlProtocolPacket(socket, nullptr, 0, (uint16_t) TCPFlag::RST); + send_transmission_control_protocol_packet(socket, nullptr, 0, (uint16_t) TCPFlag::RST); } else //If it doesn't exist then create a new socket and send a reset flag { TCPSocket new_socket(this); //Create a new socket - new_socket.remotePort = msg->srcPort; //Set the remote port - new_socket.remoteIP = sourceIP; //Set the remote IP - new_socket.localPort = msg->dstPort; //Set the local port - new_socket.localIP = destinationIP; //Set the local IP - new_socket.sequenceNumber = bigEndian32(msg->acknowledgementNumber); //Set the sequence number - new_socket.acknowledgementNumber = - bigEndian32(msg->sequenceNumber) + 1; //Set the acknowledgement number - sendTransmissionControlProtocolPacket(&new_socket, nullptr, 0, - (uint16_t) TCPFlag::RST); //Send the reset flag + new_socket.remotePort = msg->src_port; //Set the remote port + new_socket.remote_ip = source_ip; //Set the remote IP + new_socket.local_port = msg->dst_port; //Set the local port + new_socket.local_ip = destination_ip; //Set the local IP + new_socket.sequence_number = big_endian_32( + msg->acknowledgement_number); //Set the sequence number + new_socket.acknowledgement_number = + big_endian_32(msg->sequence_number) + 1; //Set the acknowledgement number + send_transmission_control_protocol_packet(&new_socket, nullptr, 0, + (uint16_t) TCPFlag::RST); //Send the reset flag } } - errorMessages->write("TCP: Handled packet\n"); + error_messages->write("TCP: Handled packet\n"); - if (socket != nullptr && socket->state == - TCPSocketState::CLOSED) //If the socket is closed then remove it from the list + if(socket != nullptr && socket->state == + TCPSocketState::CLOSED) //If the socket is closed then remove it from the list { sockets.erase(socket); return true; @@ -408,20 +410,20 @@ bool TransmissionControlProtocolHandler::handleInternetProtocolPayload(InternetP } /** - * @brief Send a packet (Throught the provider) + * @brief send a packet (Throught the provider) * * @param socket The socket to send the packet from * @param data The data to send * @param size The size of the data * @param flags The flags to send */ -void TransmissionControlProtocolHandler::sendTransmissionControlProtocolPacket(TCPSocket* socket, const uint8_t* data, uint16_t size, uint16_t flags) { +void TransmissionControlProtocolHandler::send_transmission_control_protocol_packet(TCPSocket* socket, const uint8_t* data, uint16_t size, uint16_t flags) { //Get the total size of the packet and the packet with the pseudo header - uint16_t totalLength = size + sizeof(TCPHeader); - uint16_t lengthInclPHdr = totalLength + sizeof(TCPPseudoHeader); + uint16_t total_length = size + sizeof(TCPHeader); + uint16_t length_incl_p_hdr = total_length + sizeof(TCPPseudoHeader); //Create a buffer for the packet - auto* buffer = (uint8_t*) MemoryManager::kmalloc(lengthInclPHdr); + auto* buffer = (uint8_t*) MemoryManager::kmalloc(length_incl_p_hdr); uint8_t* buffer2 = buffer + sizeof(TCPHeader) + sizeof(TCPPseudoHeader); @@ -430,91 +432,91 @@ void TransmissionControlProtocolHandler::sendTransmissionControlProtocolPacket(T auto* msg = (TCPHeader*) (buffer + sizeof(TCPPseudoHeader)); //Size is translated into 32bit - msg->headerSize32 = sizeof(TCPHeader) / 4; + msg->header_size_32 = sizeof(TCPHeader) / 4; //Set the ports - msg->srcPort = bigEndian16(socket->localPort); - msg->dstPort = bigEndian16(socket->remotePort); + msg->src_port = big_endian_16(socket->local_port); + msg->dst_port = big_endian_16(socket->remotePort); //Set TCP related data - msg->acknowledgementNumber = bigEndian32(socket->acknowledgementNumber); - msg->sequenceNumber = bigEndian32(socket->sequenceNumber); + msg->acknowledgement_number = big_endian_32(socket->acknowledgement_number); + msg->sequence_number = big_endian_32(socket->sequence_number); msg->reserved = 0; msg->flags = flags; - msg->windowSize = 0xFFFF; - msg->urgentPtr = 0; + msg->window_size = 0xFFFF; + msg->urgent_ptr = 0; //Through the options allow for the MSS to be set msg->options = ((flags & (uint16_t) TCPFlag::SYN) != 0) ? 0xB4050402 : 0; //Increase the sequence number - socket->sequenceNumber += size; + socket->sequence_number += size; // Check if the data is not null - if (data != nullptr) { + if(data != nullptr) { //Copy the data into the buffer - for (int i = 0; i < size; i++) + for(int i = 0; i < size; i++) buffer2[i] = data[i]; } //Set the pseudo header - phdr->srcIP = socket->localIP; - phdr->dstIP = socket->remoteIP; + phdr->src_ip = socket->local_ip; + phdr->dst_ip = socket->remote_ip; phdr->protocol = 0x0600; - phdr->totalLength = ((totalLength & 0x00FF) << 8) | ((totalLength & 0xFF00) >> 8); + phdr->total_length = ((total_length & 0x00FF) << 8) | ((total_length & 0xFF00) >> 8); //Calculate the checksum msg->checksum = 0; - msg->checksum = InternetProtocolHandler::Checksum((uint16_t*) buffer, lengthInclPHdr); + msg->checksum = InternetProtocolHandler::checksum((uint16_t*) buffer, length_incl_p_hdr); //Send and then free the data - Send(socket->remoteIP, (uint8_t*) msg, totalLength); + send(socket->remote_ip, (uint8_t*) msg, total_length); MemoryManager::kfree(buffer); } /** - * @brief Connect to a remote host through the TCP protocol + * @brief connect to a remote host through the TCP protocol * @param ip The IP of the remote host * @param port The port of the remote host * @return The socket that is connected to the remote host, 0 if it failed */ -TCPSocket* TransmissionControlProtocolHandler::Connect(InternetProtocolAddress ip, TransmissionControlProtocolPort port) { +TCPSocket* TransmissionControlProtocolHandler::connect(InternetProtocolAddress ip, TransmissionControlProtocolPort port) { //Create a new socket auto* socket = (TCPSocket*) MemoryManager::kmalloc( sizeof(TCPSocket)); //If there is space for the socket - if (socket != nullptr) { + if(socket != nullptr) { //Set the socket new(socket) TCPSocket(this); //Set local and remote addresses socket->remotePort = port; - socket->remoteIP = ip; - socket->localPort = freePorts++; - socket->localIP = internetProtocolHandler->GetInternetProtocolAddress(); + socket->remote_ip = ip; + socket->local_port = free_ports++; + socket->local_ip = internet_protocol_handler->get_internet_protocol_address(); //Convert into big endian socket->remotePort = ((socket->remotePort & 0xFF00) >> 8) | ((socket->remotePort & 0x00FF) << 8); - socket->localPort = ((socket->localPort & 0xFF00) >> 8) | ((socket->localPort & 0x00FF) << 8); + socket->local_port = ((socket->local_port & 0xFF00) >> 8) | ((socket->local_port & 0x00FF) << 8); //Set the socket into the socket array and then set its state sockets.push_back(socket); socket->state = TCPSocketState::SYN_SENT; //Dummy sequence number - socket->sequenceNumber = 0xbeefcafe; + socket->sequence_number = 0xbeefcafe; //Send a sync packet - sendTransmissionControlProtocolPacket(socket, nullptr, 0, (uint16_t) TCPFlag::SYN); + send_transmission_control_protocol_packet(socket, nullptr, 0, (uint16_t) TCPFlag::SYN); } return socket; } /** - * @brief Connect to a remote host through the TCP protocol + * @brief connect to a remote host through the TCP protocol * * @param address The address to connect to in the form "IP:PORT" * @@ -522,7 +524,7 @@ TCPSocket* TransmissionControlProtocolHandler::Connect(InternetProtocolAddress i * * @todo Implement string parsing for address */ -TCPSocket* TransmissionControlProtocolHandler::Connect(const string &address) { +TCPSocket* TransmissionControlProtocolHandler::connect(const string& address) { return nullptr; } @@ -532,12 +534,12 @@ TCPSocket* TransmissionControlProtocolHandler::Connect(const string &address) { * * @param socket The socket to disconnect */ -void TransmissionControlProtocolHandler::Disconnect(TCPSocket* socket) { +void TransmissionControlProtocolHandler::disconnect(TCPSocket* socket) { socket->state = TCPSocketState::FIN_WAIT1; //Begin fin wait sequence - sendTransmissionControlProtocolPacket(socket, nullptr, 0, (uint16_t) TCPFlag::FIN + - (uint16_t) TCPFlag::ACK); //Send FIN|ACK packet - socket->sequenceNumber++; //Increase the sequence number + send_transmission_control_protocol_packet(socket, nullptr, 0, (uint16_t) TCPFlag::FIN + + (uint16_t) TCPFlag::ACK); //Send FIN|ACK packet + socket->sequence_number++; //Increase the sequence number } /** @@ -546,20 +548,20 @@ void TransmissionControlProtocolHandler::Disconnect(TCPSocket* socket) { * @param port The port to listen on * @return The socket that will handle the connection */ -TCPSocket* TransmissionControlProtocolHandler::Listen(uint16_t port) { +TCPSocket* TransmissionControlProtocolHandler::listen(uint16_t port) { //Create a new socket auto* socket = (TCPSocket*) MemoryManager::kmalloc( sizeof(TCPSocket)); //If there is space for the socket - if (socket != nullptr) { + if(socket != nullptr) { //Set the socket new(socket) TCPSocket(this); //Configure the socket socket->state = TCPSocketState::LISTEN; - socket->localIP = internetProtocolHandler->GetInternetProtocolAddress(); - socket->localPort = ((port & 0xFF00) >> 8) | ((port & 0x00FF) << 8); + socket->local_ip = internet_protocol_handler->get_internet_protocol_address(); + socket->local_port = ((port & 0xFF00) >> 8) | ((port & 0x00FF) << 8); //Add the socket to the socket array sockets.push_back(socket); @@ -571,12 +573,12 @@ TCPSocket* TransmissionControlProtocolHandler::Listen(uint16_t port) { /** - * @brief Bind a data handler to this socket + * @brief bind a data handler to this socket * * @param socket The socket to bind the handler to * @param handler The handler to bind */ -void TransmissionControlProtocolHandler::Bind(TCPSocket* socket, TCPPayloadHandler* handler) { +void TransmissionControlProtocolHandler::bind(TCPSocket* socket, TCPPayloadHandler* handler) { socket->connect_event_handler(handler); } @@ -599,7 +601,7 @@ DataReceivedEvent::DataReceivedEvent(TCPSocket* socket, uint8_t* data, uint16_t DataReceivedEvent::~DataReceivedEvent() = default; /** - * @brief Construct a new Connected Event object + * @brief Construct a new connected Event object * * @param socket The socket that is connected */ @@ -611,7 +613,7 @@ ConnectedEvent::ConnectedEvent(TCPSocket* socket) ConnectedEvent::~ConnectedEvent() = default; /** - * @brief Construct a new Disconnected Event object + * @brief Construct a new disconnected Event object * * @param socket The socket that is disconnected */ diff --git a/kernel/src/net/udp.cpp b/kernel/src/net/udp.cpp index 7c76ac68..78311fbc 100644 --- a/kernel/src/net/udp.cpp +++ b/kernel/src/net/udp.cpp @@ -26,7 +26,7 @@ UDPPayloadHandler::~UDPPayloadHandler() = default; * @param data The data received * @param size The size of the data received */ -void UDPPayloadHandler::handleUserDatagramProtocolMessage(UDPSocket* socket, uint8_t* data, uint16_t size) { +void UDPPayloadHandler::handle_user_datagram_protocol_message(UDPSocket* socket, uint8_t* data, uint16_t size) { } @@ -40,7 +40,9 @@ Event* UDPPayloadHandler::on_event(Event *event) { switch (event -> type) { case UDPEvents::DATA_RECEIVED: - handleUserDatagramProtocolMessage(((UDPDataReceivedEvent*)event) -> socket, ((UDPDataReceivedEvent*)event) -> data, ((UDPDataReceivedEvent*)event) -> size); + handle_user_datagram_protocol_message(((UDPDataReceivedEvent*) event)->socket, + ((UDPDataReceivedEvent*) event)->data, + ((UDPDataReceivedEvent*) event)->size); break; default: break; @@ -67,7 +69,7 @@ UDPSocket::~UDPSocket() = default; * @param data The data received * @param size The size of the data received */ -void UDPSocket::handleUserDatagramProtocolPayload(uint8_t *data, uint16_t size) { +void UDPSocket::handle_user_datagram_protocol_payload(uint8_t *data, uint16_t size) { // Create the event auto* event = new UDPDataReceivedEvent(this, data, size); @@ -77,40 +79,40 @@ void UDPSocket::handleUserDatagramProtocolPayload(uint8_t *data, uint16_t size) } /** - * @brief Send data through the UDP socket + * @brief send data through the UDP socket * * @param data The data to send * @param size The size of the data */ -void UDPSocket::Send(uint8_t *data, uint16_t size) { +void UDPSocket::send(uint8_t *data, uint16_t size) { - userDatagramProtocolHandler -> Send(this, data, size); + user_datagram_protocol_handler->send(this, data, size); } /** - * @brief Disconnect the UDP socket + * @brief disconnect the UDP socket */ -void UDPSocket::Disconnect() { +void UDPSocket::disconnect() { - userDatagramProtocolHandler ->Disconnect(this); + user_datagram_protocol_handler->disconnect(this); } ///__Provider__ -UserDatagramProtocolPort UserDatagramProtocolHandler::freePorts = 0x8000; +UserDatagramProtocolPort UserDatagramProtocolHandler::free_ports = 0x8000; /** * @brief Construct a new User Datagram Protocol Handler object * - * @param internetProtocolHandler The Internet protocol handler - * @param errorMessages Where to write error messages + * @param internet_protocol_handler The Internet protocol handler + * @param error_messages Where to write error messages */ -UserDatagramProtocolHandler::UserDatagramProtocolHandler(InternetProtocolHandler* internetProtocolHandler, OutputStream* errorMessages) -: IPV4PayloadHandler(internetProtocolHandler, 0x11) //0x11 is the UDP protocol number +UserDatagramProtocolHandler::UserDatagramProtocolHandler(InternetProtocolHandler* internet_protocol_handler, OutputStream* error_messages) +: IPV4PayloadHandler(internet_protocol_handler, 0x11) //0x11 is the UDP protocol number { - this -> errorMessages = errorMessages; + this -> errorMessages = error_messages; } UserDatagramProtocolHandler::~UserDatagramProtocolHandler() = default; @@ -118,13 +120,13 @@ UserDatagramProtocolHandler::~UserDatagramProtocolHandler() = default; /** * @brief Handle the recivement of an UDP packet * - * @param sourceIP The source IP address in big endian - * @param destinationIP The destination IP address in big endian - * @param payloadData The UDP payload + * @param source_ip The source IP address in big endian + * @param destination_ip The destination IP address in big endian + * @param payload_data The UDP payload * @param size The size of the UDP payload * @return True if the packet is to be sent back to the sender */ -bool UserDatagramProtocolHandler::handleInternetProtocolPayload(InternetProtocolAddress sourceIP, InternetProtocolAddress destinationIP, uint8_t* payloadData, uint32_t size) { +bool UserDatagramProtocolHandler::handle_internet_protocol_payload(net::InternetProtocolAddress source_ip, net::InternetProtocolAddress destination_ip, uint8_t* payload_data, uint32_t size) { //Check the size if(size < sizeof(UDPHeader)) { @@ -132,36 +134,37 @@ bool UserDatagramProtocolHandler::handleInternetProtocolPayload(InternetProtocol } //Get the header - auto* header = (UDPHeader*)payloadData; + auto* header = (UDPHeader*)payload_data; //Set the local and remote ports - uint16_t localPort = header -> destinationPort; - uint16_t remotePort = header -> sourcePort; + uint16_t local_port = header -> destination_port; + uint16_t remote_port = header -> source_port; UDPSocket* socket = nullptr; //The socket that will be used - for(auto & currentSocket : sockets) { - if(currentSocket->localPort == localPort //If the local port (header dst, our port) is the same as the local port of the socket - && currentSocket->localIP == destinationIP //If the local IP (packet dst, our IP) is the same as the local IP of the socket - && currentSocket->listening) //If the socket is listening + for(auto & current_socket : sockets) { + if(current_socket->local_port == local_port //If the local port (header dst, our port) is the same as the local port of the socket + && current_socket->local_ip == destination_ip //If the local IP (packet dst, our IP) is the same as the local IP of the socket + && current_socket->listening) //If the socket is listening { - socket = currentSocket; //Set the socket to the socket that is being checked + socket = current_socket; //Set the socket to the socket that is being checked socket->listening = false; //Set the socket to not listening, as it is now in use - socket->remotePort = remotePort; //Set the remote port of the socket to the remote port of the packet - socket->remoteIP = sourceIP; //Set the remote IP of the socket to the remote IP of the packet + socket->remote_port = remote_port; //Set the remote port of the socket to the remote port of the packet + socket->remote_ip = source_ip; //Set the remote IP of the socket to the remote IP of the packet - }else if(currentSocket->localPort == localPort //If the local port (header dst, our port) is the same as the local port of the socket - && currentSocket->localIP == destinationIP //If the local IP (packet dst, our IP) is the same as the local IP of the socket - && currentSocket->remotePort == remotePort //If the remote port (header src, their port) is the same as the remote port of the socket - && currentSocket->remoteIP == sourceIP) //If the remote IP (packet src, their IP) is the same as the remote IP of the socket + }else if(current_socket->local_port == local_port //If the local port (header dst, our port) is the same as the local port of the socket + && current_socket->local_ip == destination_ip //If the local IP (packet dst, our IP) is the same as the local IP of the socket + && current_socket->remote_port == remote_port //If the remote port (header src, their port) is the same as the remote port of the socket + && current_socket->remote_ip == source_ip) //If the remote IP (packet src, their IP) is the same as the remote IP of the socket { - socket = currentSocket; //Set the socket to the current socket + socket = current_socket; //Set the socket to the current socket } } if(socket != nullptr) { //If the socket is not null then pass the data to the socket - socket->handleUserDatagramProtocolPayload(payloadData + sizeof(UDPHeader), size - sizeof(UDPHeader)); + socket->handle_user_datagram_protocol_payload(payload_data + sizeof(UDPHeader), + size - sizeof(UDPHeader)); } //UDP doesn't send back packets, so always return false @@ -175,7 +178,7 @@ bool UserDatagramProtocolHandler::handleInternetProtocolPayload(InternetProtocol * @param port The remote port * @return The socket that was connected */ -UDPSocket *UserDatagramProtocolHandler::Connect(uint32_t ip, uint16_t port) { +UDPSocket *UserDatagramProtocolHandler::connect(uint32_t ip, uint16_t port) { auto* socket = (UDPSocket*)MemoryManager::kmalloc(sizeof(UDPSocket)); //Allocate memory for the socket @@ -185,11 +188,11 @@ UDPSocket *UserDatagramProtocolHandler::Connect(uint32_t ip, uint16_t port) { new (socket) UDPSocket(); //Create the socket //Configure the socket - socket -> remotePort = port; //Port to that application wants to connect to - socket -> remoteIP = ip; //IP to that application wants to connect to - socket -> localPort = freePorts++; //Port that we will use to connect to the remote application (note, local port doesnt have to be the same as remote) - socket -> localIP = internetProtocolHandler -> GetInternetProtocolAddress(); //IP that we will use to connect to the remote application - socket -> userDatagramProtocolHandler = this; //Set the UDP handler + socket -> remote_port = port; //Port to that application wants to connect to + socket -> remote_ip = ip; //IP to that application wants to connect to + socket -> local_port = free_ports++; //Port that we will use to connect to the remote application (note, local port doesnt have to be the same as remote) + socket -> local_ip = internet_protocol_handler->get_internet_protocol_address(); //IP that we will use to connect to the remote application + socket -> user_datagram_protocol_handler = this; //Set the UDP handler sockets.push_back(socket); //Add the socket to the list of sockets } @@ -205,7 +208,7 @@ UDPSocket *UserDatagramProtocolHandler::Connect(uint32_t ip, uint16_t port) { * * @todo Implement string parsing to extract IP and port */ -UDPSocket *UserDatagramProtocolHandler::Connect(const string& address) { +UDPSocket *UserDatagramProtocolHandler::connect(const string& address) { return nullptr; } @@ -216,7 +219,7 @@ UDPSocket *UserDatagramProtocolHandler::Connect(const string& address) { * @param port The port to listen on * @return The socket that is listening */ -UDPSocket *UserDatagramProtocolHandler::Listen(uint16_t port) { +UDPSocket *UserDatagramProtocolHandler::listen(uint16_t port) { auto* socket = (UDPSocket*)MemoryManager::kmalloc(sizeof(UDPSocket)); //Allocate memory for the socket @@ -226,9 +229,9 @@ UDPSocket *UserDatagramProtocolHandler::Listen(uint16_t port) { //Configure the socket socket -> listening = true; //Set the socket to listening - socket -> localPort = port; //Port that we will use to connect to the remote application (note, local port doesnt have to be the same as remote) - socket -> localIP = internetProtocolHandler -> GetInternetProtocolAddress(); //IP that we will use to connect to the remote application - socket -> userDatagramProtocolHandler = this; //Set the UDP handler + socket -> local_port = port; //Port that we will use to connect to the remote application (note, local port doesnt have to be the same as remote) + socket -> local_ip = internet_protocol_handler->get_internet_protocol_address(); //IP that we will use to connect to the remote application + socket -> user_datagram_protocol_handler = this; //Set the UDP handler sockets.push_back(socket); //Add the socket to the list of sockets } @@ -242,13 +245,13 @@ UDPSocket *UserDatagramProtocolHandler::Listen(uint16_t port) { * * @param socket The socket to disconnect */ -void UserDatagramProtocolHandler::Disconnect(UDPSocket *socket) { +void UserDatagramProtocolHandler::disconnect(UDPSocket *socket) { - for(Vector::iterator currentSocket = sockets.begin(); currentSocket != sockets.end(); currentSocket++) { - if((*currentSocket) == socket) //If the socket is the same as the socket that is being checked + for(Vector::iterator current_socket = sockets.begin(); current_socket != sockets.end(); current_socket++) { + if((*current_socket) == socket) //If the socket is the same as the socket that is being checked { - sockets.erase(currentSocket); //Remove the socket from the list of sockets + sockets.erase(current_socket); //Remove the socket from the list of sockets MemoryManager::kfree(socket); //Free the socket break; //Break out of the loop } @@ -263,22 +266,22 @@ void UserDatagramProtocolHandler::Disconnect(UDPSocket *socket) { * @param data The data to send * @param size The size of the data */ -void UserDatagramProtocolHandler::Send(UDPSocket *socket, const uint8_t *data, uint16_t size) { +void UserDatagramProtocolHandler::send(UDPSocket *socket, const uint8_t *data, uint16_t size) { - uint16_t totalSize = sizeof(UDPHeader) + size; //Get the total size of the packet - auto* buffer = (uint8_t*)MemoryManager::kmalloc(totalSize); //Allocate memory for the packet + uint16_t total_size = sizeof(UDPHeader) + size; //Get the total size of the packet + auto* buffer = (uint8_t*)MemoryManager::kmalloc(total_size); //Allocate memory for the packet uint8_t* buffer2 = buffer + sizeof(UDPHeader); //Get the buffer that will be used to store the data auto* header = (UDPHeader*)buffer; //Create the header of the packet //Set the header - header -> sourcePort = socket -> localPort; //Set the source port to the local port of the socket (this is the port that the packet will be sent from) - header -> destinationPort = socket -> remotePort; //Set the destination port to the remote port of the socket (this is the port that the packet will be sent to) - header -> length = ((totalSize & 0x00FF) << 8) | ((totalSize & 0xFF00) >> 8); //Set the length of the packet + header -> source_port = socket -> local_port; //Set the source port to the local port of the socket (this is the port that the packet will be sent from) + header -> destination_port = socket -> remote_port; //Set the destination port to the remote port of the socket (this is the port that the packet will be sent to) + header -> length = ((total_size & 0x00FF) << 8) | ((total_size & 0xFF00) >> 8); //Set the length of the packet // Convert the ports into big endian - header -> sourcePort = ((header -> sourcePort & 0x00FF) << 8) | ((header -> sourcePort & 0xFF00) >> 8); - header -> destinationPort = ((header -> destinationPort & 0x00FF) << 8) | ((header -> destinationPort & 0xFF00) >> 8); + header -> source_port = ((header -> source_port & 0x00FF) << 8) | ((header -> source_port & 0xFF00) >> 8); + header -> destination_port = ((header -> destination_port & 0x00FF) << 8) | ((header -> destination_port & 0xFF00) >> 8); //Copy the data to the buffer for (int i = 0; i < size; ++i) { //Loop through the data @@ -289,7 +292,7 @@ void UserDatagramProtocolHandler::Send(UDPSocket *socket, const uint8_t *data, u header -> checksum = 0; //Set the checksum to 0, this is becuase UDP doesnt have to have a checksum //Send the packet - IPV4PayloadHandler::Send(socket->remoteIP, buffer, totalSize); + IPV4PayloadHandler::send(socket->remote_ip, buffer, total_size); //Free the buffer MemoryManager::kfree(buffer); @@ -300,11 +303,11 @@ void UserDatagramProtocolHandler::Send(UDPSocket *socket, const uint8_t *data, u * @brief Binds a handler to the socket * * @param socket The socket to bind the handler to - * @param UDPPayloadHandler The handler to bind + * @param udp_payload_handler The handler to bind */ -void UserDatagramProtocolHandler::Bind(UDPSocket *socket, UDPPayloadHandler *UDPPayloadHandler) { +void UserDatagramProtocolHandler::bind(UDPSocket *socket, UDPPayloadHandler *udp_payload_handler) { - socket->m_handlers.push_back(UDPPayloadHandler); //Set the handler of the socket to the handler that was passed in + socket->m_handlers.push_back(udp_payload_handler); //Set the handler of the socket to the handler that was passed in } diff --git a/kernel/src/processes/resource.cpp b/kernel/src/processes/resource.cpp index eddb745b..83852e40 100644 --- a/kernel/src/processes/resource.cpp +++ b/kernel/src/processes/resource.cpp @@ -47,7 +47,7 @@ void Resource::close(size_t flags) { } /** - * @brief Read a certain amount of bytes from a resource + * @brief read a certain amount of bytes from a resource * * @param buffer The buffer to read into * @param size How many bytes to read @@ -59,7 +59,7 @@ int Resource::read(void* buffer, size_t size, size_t flags) { } /** - * @brief Write a certain amount of bytes to a resource + * @brief write a certain amount of bytes to a resource * * @param buffer The buffer to read from * @param size How many bytes to write diff --git a/kernel/src/processes/scheduler.cpp b/kernel/src/processes/scheduler.cpp index 3acff77b..d5dc8a84 100644 --- a/kernel/src/processes/scheduler.cpp +++ b/kernel/src/processes/scheduler.cpp @@ -265,7 +265,7 @@ system::cpu_status_t* GlobalScheduler::force_remove_process(Process* process) { // Get the core running the process if(!s_instance) - return 0; + return nullptr; auto core = s_instance -> m_core_pids[process->pid()]; return CPU::cores[core]->scheduler->force_remove_process(process); @@ -626,7 +626,7 @@ cpu_status_t* Scheduler::force_remove_process(Process* process) { for (auto thread: process->threads()) { // Remove the thread from the scheduler - int index = m_threads.find(thread) - m_threads.begin(); + size_t index = m_threads.find(thread) - m_threads.begin(); m_threads.erase(m_threads.begin() + index); // Delete the thread diff --git a/kernel/src/system/cpu.cpp b/kernel/src/system/cpu.cpp index 482b745c..9dfa0e7f 100644 --- a/kernel/src/system/cpu.cpp +++ b/kernel/src/system/cpu.cpp @@ -140,7 +140,7 @@ void Core::init_tss() { uint8_t base_3 = (base >> 24) & 0xFF; uint32_t base_4 = (base >> 32) & 0xFFFFFFFF; - uint16_t limit_low = (uint16_t)(sizeof(tss) - 1); + auto limit_low = (uint16_t)(sizeof(tss) - 1); // Flags: 1 - Type = 0x9, Descriptor Privilege Level = 0, Present = 1, 2 - Available = 0, Granularity = 0 uint8_t flags_1 = 0x89; @@ -506,7 +506,7 @@ cpu_status_t* CPU::prepare_for_panic(cpu_status_t* status, const string& msg) { Logger::ERROR() << "CPU Panicked (i " << (int)status->interrupt_number << ") in process " << process->name.c_str() << " at 0x" << status->rip << " - killing process\n"; Logger::ERROR() << msg; panic_lock.unlock(); - return GlobalScheduler::system_scheduler()->force_remove_process(process); + return GlobalScheduler::force_remove_process(process); } // Otherwise occurred whilst the kernel was doing something for the process @@ -524,7 +524,7 @@ cpu_status_t* CPU::prepare_for_panic(cpu_status_t* status, const string& msg) { * * @todo Support for x2apic */ -void CPU::find_cores() { +void CPU::find_cores() const { // Now that memory is set up the vector can be used cores.reserve(1); diff --git a/kernel/src/system/multiboot.cpp b/kernel/src/system/multiboot.cpp index 1d068683..eb424be9 100644 --- a/kernel/src/system/multiboot.cpp +++ b/kernel/src/system/multiboot.cpp @@ -151,7 +151,7 @@ multiboot_tag_new_acpi* Multiboot::new_acpi() { * @param address The address to check * @return True if the address is reserved */ -bool Multiboot::is_reserved(multiboot_uint64_t address) { +bool Multiboot::is_reserved(multiboot_uint64_t address) const { // Loop through the tags checking if the address is reserved for (multiboot_tag* tag = start_tag(); tag->type != MULTIBOOT_TAG_TYPE_END; tag = (struct multiboot_tag*) ((multiboot_uint8_t*) tag + ((tag->size + 7) & ~7))) { diff --git a/libraries/syscore/include/filesystem/directory.h b/libraries/syscore/include/filesystem/directory.h index 8df9d749..96e99f3a 100644 --- a/libraries/syscore/include/filesystem/directory.h +++ b/libraries/syscore/include/filesystem/directory.h @@ -5,16 +5,16 @@ #ifndef SYSCORE_FILESYSTEM_DIRECTORY_H #define SYSCORE_FILESYSTEM_DIRECTORY_H -#include -#include +#include +#include #include #include -namespace syscore{ - namespace filesystem{ +namespace syscore { + namespace filesystem { - enum class DirectoryFlags{ + enum class DirectoryFlags { READ_ENTRIES, READ_ENTRIES_SIZE, WRITE_NAME, @@ -24,19 +24,19 @@ namespace syscore{ WRITE_REMOVE_DIR }; - typedef struct EntryInformation{ + typedef struct EntryInformation { size_t entry_length; size_t size; bool is_file; char name[]; } entry_information_t; - uint64_t open_directory(const char* path); - void rename_directory(uint64_t handle, const char* name); - void close_directory(uint64_t handle); + uint64_t open_directory(const char* path); + void rename_directory(uint64_t handle, const char* name); + void close_directory(uint64_t handle); size_t directory_entries_size(uint64_t handle); - void directory_entries(uint64_t handle, void* buffer, size_t size); + void directory_entries(uint64_t handle, void* buffer, size_t size); void new_file(uint64_t handle, const char* name); void new_directory(uint64_t handle, const char* name); diff --git a/libraries/syscore/include/filesystem/file.h b/libraries/syscore/include/filesystem/file.h index 52f35b94..c532f9dc 100644 --- a/libraries/syscore/include/filesystem/file.h +++ b/libraries/syscore/include/filesystem/file.h @@ -5,42 +5,42 @@ #ifndef SYSCORE_FILESYSTEM_FILE_H #define SYSCORE_FILESYSTEM_FILE_H -#include -#include +#include +#include #include #include -namespace syscore{ - namespace filesystem{ - - enum class FileFlags{ - DEFAULT, - READ_SIZE, - READ_OFFSET, - WRITE_SEEK_SET, - WRITE_SEEK_CUR, - WRITE_SEEK_END, - WRITE_NAME, - }; - - enum class SeekType{ - SET, - CURRENT, - END - }; - - uint64_t open_file(const char* path); - void close_file(uint64_t handle); - - size_t file_size(uint64_t handle); - size_t file_offset(uint64_t handle); - - size_t file_read(uint64_t handle, void* buffer, size_t size); - size_t file_write(uint64_t handle, void* buffer, size_t size); - - void rename_file(uint64_t handle, const char* name); - void seek_file(uint64_t handle, size_t position, SeekType seek_type); - } + +namespace syscore::filesystem { + + enum class FileFlags { + DEFAULT, + READ_SIZE, + READ_OFFSET, + WRITE_SEEK_SET, + WRITE_SEEK_CUR, + WRITE_SEEK_END, + WRITE_NAME, + }; + + enum class SeekType { + SET, + CURRENT, + END + }; + + uint64_t open_file(const char* path); + void close_file(uint64_t handle); + + size_t file_size(uint64_t handle); + size_t file_offset(uint64_t handle); + + size_t file_read(uint64_t handle, void* buffer, size_t size); + size_t file_write(uint64_t handle, void* buffer, size_t size); + + void rename_file(uint64_t handle, const char* name); + void seek_file(uint64_t handle, size_t position, SeekType seek_type); } + #endif //SYSCORE_FILESYSTEM_FILE_H diff --git a/libraries/syscore/include/ipc/messages.h b/libraries/syscore/include/ipc/messages.h index cf42e5f1..fda28067 100644 --- a/libraries/syscore/include/ipc/messages.h +++ b/libraries/syscore/include/ipc/messages.h @@ -5,23 +5,20 @@ #ifndef SYSCORE_IPC_MESSAGES_H #define SYSCORE_IPC_MESSAGES_H -#include -#include +#include +#include #include -namespace syscore{ - namespace ipc{ - uint64_t create_endpoint(const char* name); - uint64_t open_endpoint(const char* name); - void close_endpoint(uint64_t endpoint); - - void send_message(uint64_t endpoint, void* buffer, size_t size); - void read_message(uint64_t endpoint, void* buffer, size_t size); - } -} +namespace syscore::ipc { + uint64_t create_endpoint(const char* name); + uint64_t open_endpoint(const char* name); + void close_endpoint(uint64_t endpoint); + void send_message(uint64_t endpoint, void* buffer, size_t size); + void read_message(uint64_t endpoint, void* buffer, size_t size); +} -#endif //IPC_MESSAGES_H +#endif //SYSCORE_IPC_MESSAGES_H diff --git a/libraries/syscore/include/ipc/sharedmemory.h b/libraries/syscore/include/ipc/sharedmemory.h index 3953517a..7fddb42b 100644 --- a/libraries/syscore/include/ipc/sharedmemory.h +++ b/libraries/syscore/include/ipc/sharedmemory.h @@ -5,17 +5,17 @@ #ifndef SYSCORE_IPC_SHAREDMEMORY_H #define SYSCORE_IPC_SHAREDMEMORY_H -#include -#include +#include +#include #include -namespace syscore { - namespace ipc { - void* create_shared_memory(const char* name, size_t size); +namespace syscore::ipc { - void* open_shared_memory(const char* name); - } + void* create_shared_memory(const char* name, size_t size); + + void* open_shared_memory(const char* name); } + #endif //SYSCORE_IPC_SHAREDMEMORY_H diff --git a/libraries/syscore/include/syscalls.h b/libraries/syscore/include/syscalls.h index 30e4c5ce..de2ba03a 100644 --- a/libraries/syscore/include/syscalls.h +++ b/libraries/syscore/include/syscalls.h @@ -5,8 +5,8 @@ #ifndef SYSCORE_SYSCALLS_H #define SYSCORE_SYSCALLS_H -#include -#include +#include +#include namespace syscore{ diff --git a/libraries/syscore/src/filesystem/directory.cpp b/libraries/syscore/src/filesystem/directory.cpp index d0fa5887..903221c7 100644 --- a/libraries/syscore/src/filesystem/directory.cpp +++ b/libraries/syscore/src/filesystem/directory.cpp @@ -4,104 +4,103 @@ #include -namespace syscore{ - namespace filesystem{ - - - /** - * @brief Opens a directory from a path (must end in /) - * - * @param path The path to the directory - * @return The handle of the opened directory or 0 if it failed - */ - uint64_t open_directory(const char* path){ - return resource_open(ResourceType::FILESYSTEM, path, 0); - } - - /** - * @brief Rename the directory - * - * @param handle The directory to rename - * @param name What to rename the directory to - */ - void rename_directory(uint64_t handle, const char* name){ - resource_write(handle, name, strlen(name), (size_t)DirectoryFlags::WRITE_NAME); - } - - /** - * @brief Closes an open directory - * - * @param handle The directory open - */ - void close_directory(uint64_t handle){ - resource_close(handle, 0); - } - - /** - * @brief Gets the size required to hold the list of directory entries - * - * @param handle The directory to list - * @return The size of the total entries - */ - size_t directory_entries_size(uint64_t handle){ - return resource_read(handle, 0,0, (size_t)DirectoryFlags::READ_ENTRIES_SIZE); - } - - /** - * @brief Reads the contents of a directory (as a list of entry_information_t) - * - * @param handle The directory to read - * @param buffer Where to read the list - * @param size How big is the buffer - */ - void directory_entries(uint64_t handle, void* buffer, size_t size){ - - resource_read(handle, buffer, size,(size_t)DirectoryFlags::READ_ENTRIES); - } - - /** - * @brief Creates a new file in the directory - * - * @param handle The directory to create the file in - * @param name The name of the new file - */ - void new_file(uint64_t handle, const char* name){ - - resource_write(handle, name, strlen(name), (size_t)DirectoryFlags::WRITE_NEW_FILE); - } - - /** - * @brief Creates a new subdirectory in the directory - * - * @param handle The directory to create the subdirectory in - * @param name The name of the new directory - */ - void new_directory(uint64_t handle, const char* name){ - - resource_write(handle, name, strlen(name), (size_t)DirectoryFlags::WRITE_NEW_DIR); - } - - /** - * @brief Removes a file from the directory - * - * @param handle The directory to remove the file from - * @param name The name of the file to remove - */ - void remove_file(uint64_t handle, const char* name){ - - resource_write(handle, name, strlen(name), (size_t)DirectoryFlags::WRITE_REMOVE_FILE); - } - - /** - * @brief Removes a subdirectory from the directory - * - * @param handle The directory to remove the subdirectory from - * @param name The name of the subdirectory to remove - */ - void remove_directory(uint64_t handle, const char* name){ - - resource_write(handle, name, strlen(name), (size_t)DirectoryFlags::WRITE_REMOVE_DIR); - } +namespace syscore::filesystem { + + + /** + * @brief Opens a directory from a path (must end in /) + * + * @param path The path to the directory + * @return The handle of the opened directory or 0 if it failed + */ + uint64_t open_directory(const char* path) { + return resource_open(ResourceType::FILESYSTEM, path, 0); + } + + /** + * @brief Rename the directory + * + * @param handle The directory to rename + * @param name What to rename the directory to + */ + void rename_directory(uint64_t handle, const char* name) { + resource_write(handle, name, strlen(name), (size_t) DirectoryFlags::WRITE_NAME); + } + + /** + * @brief Closes an open directory + * + * @param handle The directory open + */ + void close_directory(uint64_t handle) { + resource_close(handle, 0); + } + + /** + * @brief Gets the size required to hold the list of directory entries + * + * @param handle The directory to list + * @return The size of the total entries + */ + size_t directory_entries_size(uint64_t handle) { + return resource_read(handle, nullptr, 0, (size_t) DirectoryFlags::READ_ENTRIES_SIZE); + } + + /** + * @brief Reads the contents of a directory (as a list of entry_information_t) + * + * @param handle The directory to read + * @param buffer Where to read the list + * @param size How big is the buffer + */ + void directory_entries(uint64_t handle, void* buffer, size_t size) { + + resource_read(handle, buffer, size, (size_t) DirectoryFlags::READ_ENTRIES); + } + + /** + * @brief Creates a new file in the directory + * + * @param handle The directory to create the file in + * @param name The name of the new file + */ + void new_file(uint64_t handle, const char* name) { + + resource_write(handle, name, strlen(name), (size_t) DirectoryFlags::WRITE_NEW_FILE); + } + + /** + * @brief Creates a new subdirectory in the directory + * + * @param handle The directory to create the subdirectory in + * @param name The name of the new directory + */ + void new_directory(uint64_t handle, const char* name) { + + resource_write(handle, name, strlen(name), (size_t) DirectoryFlags::WRITE_NEW_DIR); + } + + /** + * @brief Removes a file from the directory + * + * @param handle The directory to remove the file from + * @param name The name of the file to remove + */ + void remove_file(uint64_t handle, const char* name) { + + resource_write(handle, name, strlen(name), (size_t) DirectoryFlags::WRITE_REMOVE_FILE); + } + + /** + * @brief Removes a subdirectory from the directory + * + * @param handle The directory to remove the subdirectory from + * @param name The name of the subdirectory to remove + */ + void remove_directory(uint64_t handle, const char* name) { + + resource_write(handle, name, strlen(name), (size_t) DirectoryFlags::WRITE_REMOVE_DIR); } -} \ No newline at end of file + +} diff --git a/libraries/syscore/src/filesystem/file.cpp b/libraries/syscore/src/filesystem/file.cpp index 81f28191..834fa625 100644 --- a/libraries/syscore/src/filesystem/file.cpp +++ b/libraries/syscore/src/filesystem/file.cpp @@ -4,56 +4,55 @@ #include -namespace syscore { - namespace filesystem { - uint64_t open_file(const char* path){ - return resource_open(ResourceType::FILESYSTEM, path, 0); - } +namespace syscore::filesystem { - void close_file(uint64_t handle){ - resource_close(handle, 0); - } + uint64_t open_file(const char* path) { + return resource_open(ResourceType::FILESYSTEM, path, 0); + } - size_t file_size(uint64_t handle){ - return resource_read(handle, 0, 0, (size_t)FileFlags::READ_SIZE); - } + void close_file(uint64_t handle) { + resource_close(handle, 0); + } - size_t file_offset(uint64_t handle){ - return resource_read(handle, 0, 0, (size_t)FileFlags::READ_OFFSET); - } + size_t file_size(uint64_t handle) { + return resource_read(handle, nullptr, 0, (size_t) FileFlags::READ_SIZE); + } - size_t file_read(uint64_t handle, void* buffer, size_t size){ - return resource_read(handle, buffer, size, (size_t)FileFlags::DEFAULT); - } + size_t file_offset(uint64_t handle) { + return resource_read(handle, nullptr, 0, (size_t) FileFlags::READ_OFFSET); + } - size_t file_write(uint64_t handle, void* buffer, size_t size){ - return resource_write(handle, buffer, size, (size_t)FileFlags::DEFAULT); - } + size_t file_read(uint64_t handle, void* buffer, size_t size) { + return resource_read(handle, buffer, size, (size_t) FileFlags::DEFAULT); + } - void rename_file(uint64_t handle, const char* name){ + size_t file_write(uint64_t handle, void* buffer, size_t size) { + return resource_write(handle, buffer, size, (size_t) FileFlags::DEFAULT); + } - resource_write(handle, name, strlen(name), (size_t)FileFlags::WRITE_NAME); - } + void rename_file(uint64_t handle, const char* name) { - void seek_file(uint64_t handle, size_t position, SeekType seek_type){ + resource_write(handle, name, strlen(name), (size_t) FileFlags::WRITE_NAME); + } - switch (seek_type) { + void seek_file(uint64_t handle, size_t position, SeekType seek_type) { - case SeekType::SET: - resource_write(handle, 0, position, (size_t)FileFlags::WRITE_SEEK_SET); - break; + switch(seek_type) { - case SeekType::CURRENT: - resource_write(handle, 0, position, (size_t)FileFlags::WRITE_SEEK_CUR); - break; + case SeekType::SET: + resource_write(handle, nullptr, position, (size_t) FileFlags::WRITE_SEEK_SET); + break; - case SeekType::END: - resource_write(handle, 0, position, (size_t)FileFlags::WRITE_SEEK_END); - break; + case SeekType::CURRENT: + resource_write(handle, nullptr, position, (size_t) FileFlags::WRITE_SEEK_CUR); + break; - } - } + case SeekType::END: + resource_write(handle, nullptr, position, (size_t) FileFlags::WRITE_SEEK_END); + break; + } } -} \ No newline at end of file + +} diff --git a/libraries/syscore/src/ipc/messages.cpp b/libraries/syscore/src/ipc/messages.cpp index 6aa3f50a..b5730792 100644 --- a/libraries/syscore/src/ipc/messages.cpp +++ b/libraries/syscore/src/ipc/messages.cpp @@ -4,70 +4,69 @@ #include -namespace syscore{ - namespace ipc{ - /** - * @brief Create a new endpoint for sending and receiving messages - * - * @param name The name of the endpoint - * @return The handle of the new endpoint or 0 if it failed - */ - uint64_t create_endpoint(const char* name){ +namespace syscore::ipc { - // Create the resource - if(!resource_create(ResourceType::MESSAGE_ENDPOINT, name, 0)) - return 0; + /** + * @brief Create a new endpoint for sending and receiving messages + * + * @param name The name of the endpoint + * @return The handle of the new endpoint or 0 if it failed + */ + uint64_t create_endpoint(const char* name) { - return open_endpoint(name); - } + // Create the resource + if(!resource_create(ResourceType::MESSAGE_ENDPOINT, name, 0)) + return 0; - /** - * @brief Opens an endpoint under a specific name - * - * @param name The name of the endpoint to open - * @return The endpoint handle or 0 if it failed to open - */ - uint64_t open_endpoint(const char* name){ - return (uint64_t) resource_open(ResourceType::MESSAGE_ENDPOINT, name, 0); - } + return open_endpoint(name); + } - /** - * @brief Closes an endpoint - * - * @param endpoint The endpoint handle to close - */ - void close_endpoint(uint64_t endpoint){ + /** + * @brief Opens an endpoint under a specific name + * + * @param name The name of the endpoint to open + * @return The endpoint handle or 0 if it failed to open + */ + uint64_t open_endpoint(const char* name) { + return (uint64_t) resource_open(ResourceType::MESSAGE_ENDPOINT, name, 0); + } - if(endpoint) - resource_close(endpoint, 0); + /** + * @brief Closes an endpoint + * + * @param endpoint The endpoint handle to close + */ + void close_endpoint(uint64_t endpoint) { - } + if(endpoint) + resource_close(endpoint, 0); - /** - * @brief Queues a message on the endpoint (FIFO) - * - * @param endpoint The endpoint handle - * @param buffer The message - * @param size The size of the message - */ - void send_message(uint64_t endpoint, void* buffer, size_t size){ + } - if(endpoint) - resource_write(endpoint, buffer, size, 0); + /** + * @brief Queues a message on the endpoint (FIFO) + * + * @param endpoint The endpoint handle + * @param buffer The message + * @param size The size of the message + */ + void send_message(uint64_t endpoint, void* buffer, size_t size) { - } + if(endpoint) + resource_write(endpoint, buffer, size, 0); + + } - /** - * @brief Fetches the oldest message on the endpoint (FIFO) - * - * @param endpoint The endpoint handle - * @param buffer Where to read the message into - * @param size How much of the message to read - */ - void read_message(uint64_t endpoint, void* buffer, size_t size){ - if(endpoint) - resource_read(endpoint, buffer, size, 0); - } + /** + * @brief Fetches the oldest message on the endpoint (FIFO) + * + * @param endpoint The endpoint handle + * @param buffer Where to read the message into + * @param size How much of the message to read + */ + void read_message(uint64_t endpoint, void* buffer, size_t size) { + if(endpoint) + resource_read(endpoint, buffer, size, 0); } -} \ No newline at end of file +} diff --git a/libraries/syscore/src/ipc/sharedmemory.cpp b/libraries/syscore/src/ipc/sharedmemory.cpp index 530e3d5a..81c2c896 100644 --- a/libraries/syscore/src/ipc/sharedmemory.cpp +++ b/libraries/syscore/src/ipc/sharedmemory.cpp @@ -37,5 +37,5 @@ namespace syscore{ return (void*)address; } - }; + } } diff --git a/libraries/syscore/src/syscalls.cpp b/libraries/syscore/src/syscalls.cpp index 5731191a..21d17e76 100644 --- a/libraries/syscore/src/syscalls.cpp +++ b/libraries/syscore/src/syscalls.cpp @@ -122,7 +122,7 @@ namespace syscore{ } /** - * @brief Write a certain amount of bytes to a resource + * @brief write a certain amount of bytes to a resource * * @param handle The handle number of the resource * @param buffer The buffer to read from @@ -144,7 +144,7 @@ namespace syscore{ } /** - * @brief Read a certain amount of bytes from a resource + * @brief read a certain amount of bytes from a resource * * @param handle The handle number of the resource * @param buffer The buffer to read into diff --git a/programs/Example/src/main.cpp b/programs/Example/src/main.cpp index c092c23e..2b96fa59 100644 --- a/programs/Example/src/main.cpp +++ b/programs/Example/src/main.cpp @@ -1,8 +1,8 @@ // // Created by 98max on 21/03/2025. // -#include -#include +#include +#include #include #include diff --git a/programs/Example2/src/main.cpp b/programs/Example2/src/main.cpp index 519e4996..6769e9f2 100644 --- a/programs/Example2/src/main.cpp +++ b/programs/Example2/src/main.cpp @@ -1,8 +1,8 @@ // // Created by 98max on 21/03/2025. // -#include -#include +#include +#include #include #include #include diff --git a/toolchain/pre_process/symbols.sh b/toolchain/pre_process/symbols.sh index c8c79ceb..a6df8b3f 100755 --- a/toolchain/pre_process/symbols.sh +++ b/toolchain/pre_process/symbols.sh @@ -57,6 +57,7 @@ DATE_STR="$DATE_STR $(date +' %B %Y')" # Write the header cat > "$OUT" <<'EOF' + /** * @file symbols.h * @brief Defines kernel symbol resolution functions @@ -71,24 +72,22 @@ cat > "$OUT" <<'EOF' #include #include -namespace MaxOS{ - - namespace common{ - - /** - * @struct KernelSymbol - * @brief Holds the address and name of a kernel symbol - * - * @typedef kernel_sym_t - * @brief alias for KernelSymbol - */ - typedef struct KernelSymbol { - uintptr_t address; ///< The address of the symbol (loaded address) - const char* name; ///< The stripped name of the symbol (including namespaces) - } kernel_sym_t; - - /// Holds a list of address/name pairs for kernel symbols - const kernel_sym_t kernel_symbols[] = { +namespace MaxOS::common{ + + /** + * @struct KernelSymbol + * @brief Holds the address and name of a kernel symbol + * + * @typedef kernel_sym_t + * @brief alias for KernelSymbol + */ + typedef struct KernelSymbol { + uintptr_t address; ///< The address of the symbol (loaded address) + const char* name; ///< The stripped name of the symbol (including namespaces) + } kernel_sym_t; + + /// Holds a list of address/name pairs for kernel symbols + const kernel_sym_t kernel_symbols[] = { EOF if [ ! -s "$RAW" ]; then COUNT=0 @@ -137,15 +136,14 @@ fi # Write the footer cat >> "$OUT" < Date: Sat, 22 Nov 2025 18:04:11 +1300 Subject: [PATCH 07/12] Release / Debug Running --- .idea/inspectionProfiles/Project_Default.xml | 3 --- kernel/include/filesystem/partition/msdos.h | 2 +- kernel/src/drivers/ethernet/amd_am79c973.cpp | 2 ++ 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index bfb0810c..bf1cb1f3 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -23,10 +23,8 @@ - - - \ No newline at end of file diff --git a/kernel/include/filesystem/partition/msdos.h b/kernel/include/filesystem/partition/msdos.h index 751eb254..75202929 100644 --- a/kernel/include/filesystem/partition/msdos.h +++ b/kernel/include/filesystem/partition/msdos.h @@ -304,7 +304,7 @@ namespace MaxOS::filesystem::partition { */ typedef struct PACKED PartitionTableEntry { - uint8_t bootable; ///< Is this partition bootable? (0x80 = bootable, 0x00 = not bootable) + uint8_t bootable; ///< Is this partition bootable? (0x80 = bootable, 0x00 = not bootable) uint8_t start_head; ///< The starting head of the partition uint8_t start_sector : 6; ///< The first sector of the partition diff --git a/kernel/src/drivers/ethernet/amd_am79c973.cpp b/kernel/src/drivers/ethernet/amd_am79c973.cpp index 31e18f01..1dda17a8 100644 --- a/kernel/src/drivers/ethernet/amd_am79c973.cpp +++ b/kernel/src/drivers/ethernet/amd_am79c973.cpp @@ -126,6 +126,8 @@ AMD_AM79C973::~AMD_AM79C973() = default; */ void AMD_AM79C973::activate() { + return; + init_done = false; // Set initDone to false register_address_port.write(0); // Tell device to write to register 0 register_data_port.write(0x41); // Enable Interrupts and start the device From 1aca2c28b0c8c54e4e8f86ba1a0ece3bfcc18d80 Mon Sep 17 00:00:00 2001 From: Max Tyson <98maxt98@gmail.com> Date: Sun, 23 Nov 2025 16:15:32 +1300 Subject: [PATCH 08/12] Testing Framework --- kernel/CMakeLists.txt | 10 +- kernel/include/common/logger.h | 34 +++--- kernel/include/runtime/kasan.h | 38 ++++++ kernel/include/tests/common.h | 18 +++ kernel/include/tests/test.h | 128 ++++++++++++++++++++ kernel/src/common/logger.cpp | 15 +++ kernel/src/kernel.cpp | 4 +- kernel/src/runtime/kasan.cpp | 214 +++++++++++++++++++++++++++++++++ kernel/src/tests/common.cpp | 46 +++++++ kernel/src/tests/test.cpp | 132 ++++++++++++++++++++ 10 files changed, 621 insertions(+), 18 deletions(-) create mode 100644 kernel/include/runtime/kasan.h create mode 100644 kernel/include/tests/common.h create mode 100644 kernel/include/tests/test.h create mode 100644 kernel/src/runtime/kasan.cpp create mode 100644 kernel/src/tests/common.cpp create mode 100644 kernel/src/tests/test.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index fd284c2c..a4c4ea09 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -1,7 +1,10 @@ # Set the flags SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffreestanding -fno-exceptions -fno-rtti -fpermissive -nostdlib -mno-red-zone -mno-80387 -mno-mmx -mcmodel=kernel -fno-use-cxa-atexit -m64 -mno-sse -mno-sse2 -mno-sse3 -mno-sse4 -mno-avx -mno-avx2") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-pointer-arith -Wno-address-of-packed-member -Wno-trigraphs -Wno-unused-variable -Wno-unused-function -Wno-unused-result -Wno-unused-parameter") # Warnings -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fstack-protector-all -g") # Debug +IF(CMAKE_BUILD_TYPE STREQUAL "Debug") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fstack-protector-all -g") # Debug -fsanitize=kernel-address +ENDIF() + # Enable assembly SET(CMAKE_ASM_FLAGS "-f elf64") @@ -12,6 +15,11 @@ SET_SOURCE_FILES_PROPERTIES(${ASM_SRCS} PROPERTIES LANGUAGE ASM) # Find all the cpp and s files in the src directory (recursive) FILE(GLOB_RECURSE KERNEL_SRCS src/*.cpp src/*.s) +# Remove the tests if not in Debug mode +IF(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + LIST(FILTER KERNEL_SRCS EXCLUDE REGEX "src/tests/.*") +ENDIF() + # Update the version before building SET(VERSION_HEADER "${CMAKE_SOURCE_DIR}/kernel/include/common/version.h") SET(VERSION_HEADER_TMP "${CMAKE_SOURCE_DIR}/kernel/include/common/version.h.tmp") diff --git a/kernel/include/common/logger.h b/kernel/include/common/logger.h index 3e3cbae7..c5d2ead6 100644 --- a/kernel/include/common/logger.h +++ b/kernel/include/common/logger.h @@ -13,18 +13,19 @@ #include #include -namespace MaxOS{ +namespace MaxOS { -/** - * @enum LogLevel - * @brief Priority levels for logging messages. Different levels may be used to filter messages based on their importance depending on build type. - */ + /** + * @enum LogLevel + * @brief Priority levels for logging messages. Different levels may be used to filter messages based on their importance depending on build type. + */ enum class LogLevel { - WARNING, ERROR, + WARNING, HEADER, INFO, + TEST, DEBUG, }; @@ -36,10 +37,10 @@ namespace MaxOS{ constexpr LogLevel MAX_LOG_LEVEL = LogLevel::DEBUG; ///< The maximum log level for this build (messages above this level will not be logged) #endif -/** - * @class Logger - * @brief A class that handles logging messages to the console and files. - */ + /** + * @class Logger + * @brief A class that handles logging messages to the console and files. + */ class Logger : public MaxOS::common::OutputStream { private: @@ -72,16 +73,17 @@ namespace MaxOS{ static Logger* active_logger(); - static Logger &Out(); + static Logger& Out(); + static Logger ERROR(); + static Logger WARNING(); static Logger HEADER(); static Logger INFO(); + static Logger TEST(); static Logger DEBUG(); - static Logger WARNING(); - static Logger ERROR(); - using OutputStream::operator<<; - Logger &operator<<(LogLevel log_level); + using OutputStream::operator <<; + Logger& operator <<(LogLevel log_level); }; /** @@ -95,7 +97,7 @@ namespace MaxOS{ * * @see Logger::ASSERT */ - #define ASSERT(condition, format, ...) Logger::ASSERT(condition, format, ##__VA_ARGS__) +#define ASSERT(condition, format, ...) Logger::ASSERT(condition, format, ##__VA_ARGS__) } diff --git a/kernel/include/runtime/kasan.h b/kernel/include/runtime/kasan.h new file mode 100644 index 00000000..ab98ef3a --- /dev/null +++ b/kernel/include/runtime/kasan.h @@ -0,0 +1,38 @@ +/** + * @file kasan.h + * @brief Defines structures and a handler for Kernel Address Sanitizer (KASan) runtime errors + * + * @date 22nd November 2025 + * @author Max Tyson + */ + +#ifndef MAXOS_RUNTIME_UBSAN_H +#define MAXOS_RUNTIME_UBSAN_H + +#include +#include + +namespace MaxOS::runtime { + + /** + * @class UBSanHandler + * @brief Handles undefined behaviour sanitizer runtime errors + * + * @todo finish when cbf + */ + class KASanHandler { + + public: + KASanHandler(); + ~KASanHandler(); + + static void handle(bool write, uintptr_t address, size_t size, void* rip); + + static void initialize(); + static void poison_stack(uintptr_t address, size_t size); + static void unpoison_stack(uintptr_t address, size_t size); + }; +} + + +#endif // MAXOS_RUNTIME_UBSAN_H diff --git a/kernel/include/tests/common.h b/kernel/include/tests/common.h new file mode 100644 index 00000000..fdf6df75 --- /dev/null +++ b/kernel/include/tests/common.h @@ -0,0 +1,18 @@ +/** + * @file common.cpp + * @brief Defines the tests for all common components of MaxOS + * + * @date 23rd November 2025 + * @author Max Tyson +*/ + +#ifndef MAXOS_TESTS_COMMON_H +#define MAXOS_TESTS_COMMON_H + +#include + +namespace MaxOS::tests { + void register_tests_common(); +} + +#endif //MAXOS_TESTS_COMMON_H diff --git a/kernel/include/tests/test.h b/kernel/include/tests/test.h new file mode 100644 index 00000000..a749677b --- /dev/null +++ b/kernel/include/tests/test.h @@ -0,0 +1,128 @@ +/** + * @file test.h + * @brief Defines a basic test class for MaxOS + * + * @date 23rd November 2025 + * @author Max Tyson + */ + +#ifndef MAXOS_TESTS_TEST_H +#define MAXOS_TESTS_TEST_H + +#include +#include + + +#define PASS return TestStatus::TEST_PASS +#define FAIL return TestStatus::TEST_FAIL +#define SKIP return TestStatus::TEST_SKIP +#define MAXOS_CONDITIONAL_TEST(name, type) \ + auto test = new ConditionalTest(#name, type, []() + +namespace MaxOS::tests { + + /** + * @enum TestStatus + * @brief The possible outcomes of a test + */ + enum class TestStatus { + TEST_PASS, + TEST_FAIL, + TEST_SKIP + }; + + /** + * @enum TestType + * @brief The different types of tests + */ + enum class TestType { + COMMON, + DRIVER, + FILESYSTEM, + GUI, + HARDWARE_COMMUNICATION, + MEMORY, + NETWORK, + PROCESSES, + RUNTIME, + SYSTEM, + MAX_TEST_TYPES + }; + + /// String representations of the TestType enum + constexpr const char* TEST_TYPE_STRINGS[] = { + "COMMON", + "DRIVER", + "FILESYSTEM", + "GUI", + "HARDWARE_COMMUNICATION", + "MEMORY", + "NETWORK", + "PROCESSES", + "RUNTIME", + "SYSTEM", + "UNKNOWN" + }; + + /** + * @class Test + * @brief A basic test class + */ + class Test { + + private: + string m_name; + TestType m_type; + + public: + Test(const string& name, TestType type); + virtual ~Test(); + + TestStatus run(); + virtual TestStatus execute() = 0; + + const string& name() const; + TestType type() const; + + }; + + /** + * @class ConditionalTest + * @brief A test that only checks a condition to determine pass/fail + */ + class ConditionalTest : public Test { + private: + bool (*m_condition)(); + + public: + ConditionalTest(const string& name, TestType type, bool (*condition)()); + ~ConditionalTest() override; + + TestStatus execute() override; + }; + + constexpr bool QUITE_TESTING = false; ///< If true, suppresses test output + + /** + * @class TestRunner + * @brief A class to run all tests + */ + class TestRunner { + + private: + inline static common::Vector s_tests = common::Vector(); + + public: + + static void test_kernel(); + + static void run_all_tests(); + static void run_all_types(TestType type); + + static void add_all_tests(); + static void add_test(Test* test); + + }; +} + +#endif //MAXOS_TESTS_TEST_H diff --git a/kernel/src/common/logger.cpp b/kernel/src/common/logger.cpp index 8a6092a7..28e0dbc2 100644 --- a/kernel/src/common/logger.cpp +++ b/kernel/src/common/logger.cpp @@ -102,6 +102,10 @@ void Logger::set_log_level(LogLevel log_level) { *this << ANSI_COLOURS[ANSIColour::FG_Cyan] << "[ INFO ]" << ANSI_COLOURS[ANSIColour::FG_White] << " "; break; + case LogLevel::TEST: + *this << ANSI_COLOURS[ANSIColour::FG_Green] << "[ TEST ]" << ANSI_COLOURS[ANSIColour::FG_White] << " "; + break; + case LogLevel::DEBUG: *this << ANSI_COLOURS[ANSIColour::FG_Yellow] << "[ DEBUG ]" << ANSI_COLOURS[ANSIColour::Reset] << " "; break; @@ -170,6 +174,17 @@ Logger Logger::INFO() { return Out(); } +/** + * @brief Gets active logger set to test level + * + * @return The test logger + */ +Logger Logger::TEST() { + + s_active_logger->set_log_level(LogLevel::TEST); + return Out(); +} + /** * @brief Gets active logger set to DEBUG level * diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp index 52b2fc2b..6e1baf8a 100644 --- a/kernel/src/kernel.cpp +++ b/kernel/src/kernel.cpp @@ -22,6 +22,7 @@ #include #include #include +#include using namespace MaxOS; using namespace MaxOS::common; @@ -36,6 +37,7 @@ using namespace MaxOS::processes; using namespace MaxOS::system; using namespace MaxOS::memory; using namespace MaxOS::filesystem; +using namespace MaxOS::tests; extern "C" void call_constructors(); ///< Calls the C++ static constructors extern "C" uint8_t core_boot_info[]; ///< The boot info structure for the core being started @@ -112,6 +114,7 @@ extern "C" [[noreturn]] void kernel_main(unsigned long addr, unsigned long magic VFSResourceRegistry vfs_registry(&vfs); SyscallManager syscalls; console.finish(); + TestRunner::test_kernel(); GlobalScheduler::activate(); // Idle loop (read Idle.md) @@ -121,7 +124,6 @@ extern "C" [[noreturn]] void kernel_main(unsigned long addr, unsigned long magic } /** - * @todo Kernel configuration (debug/release) * @todo Test suite of common functions & other statics (paths) * @todo Thread storage (when clib) * @todo Once kernel done, turn into mono repo and seperate components diff --git a/kernel/src/runtime/kasan.cpp b/kernel/src/runtime/kasan.cpp new file mode 100644 index 00000000..02cb7af2 --- /dev/null +++ b/kernel/src/runtime/kasan.cpp @@ -0,0 +1,214 @@ +/** + * @file kasan.cpp + * @brief Implementation of the Kernel Address Sanitizer (KASan) handler + * + * @date 22nd November 2025 + * @author Max Tyson + */ + +#include +#include + +using namespace MaxOS; +using namespace MaxOS::runtime; + +KASanHandler::KASanHandler() = default; + +KASanHandler::~KASanHandler() = default; + +/** + * @brief Handles a KASan error by panicking and printing the details + * + * @param write Whether the access was a write (true) or read (false) + * @param address The address that was accessed + * @param size The size of the access in bytes + * @param rip The instruction pointer where the access occurred + */ +void KASanHandler::handle(bool write, uintptr_t address, size_t size, void* rip) { + ASSERT(false, "KASAN ERROR: %s of size %zu at address 0x%lx from RIP 0x%p", write ? "WRITE" : "READ", size, address, rip); +} + +/** + * @brief Triggered when a memory load access violation of 1 byte is detected + * + * @param address The address that was accessed + */ +extern "C" void __asan_load1_noabort(uintptr_t address) { + KASanHandler::handle(false, address, 1, __builtin_return_address(0)); +} + +/** + * @brief Triggered when a memory load access violation of 2 bytes is detected + * + * @param address The address that was accessed + */ +extern "C" void __asan_load2_noabort(uintptr_t address) { + KASanHandler::handle(false, address, 2, __builtin_return_address(0)); +} + +/** + * @brief Triggered when a memory load access violation of 4 bytes is detected + * + * @param address The address that was accessed + */ +extern "C" void __asan_load4_noabort(uintptr_t address) { + KASanHandler::handle(false, address, 4, __builtin_return_address(0)); +} + +/** + * @brief Triggered when a memory load access violation of 8 bytes is detected + * + * @param address The address that was accessed + */ +extern "C" void __asan_load8_noabort(uintptr_t address) { + KASanHandler::handle(false, address, 8, __builtin_return_address(0)); +} + +/** + * @brief Triggered when a memory load access violation of 16 bytes is detected + * + * @param address The address that was accessed + */ +extern "C" void __asan_load16_noabort(uintptr_t address) { + KASanHandler::handle(false, address, 16, __builtin_return_address(0)); +} + +/** + * @brief Triggered when a memory load access violation of arbitrary size is detected + * + * @param address The address that was accessed + * @param size The size of the access in bytes + */ +extern "C" void __asan_loadN_noabort(uintptr_t address, size_t size) { + KASanHandler::handle(false, address, size, __builtin_return_address(0)); +} + +/** + * @brief Triggered when a memory store access violation of 1 byte is detected + * + * @param address The address that was accessed + */ +extern "C" void __asan_store1_noabort(uintptr_t address) { + KASanHandler::handle(true, address, 1, __builtin_return_address(0)); +} + +/** + * @brief Triggered when a memory store access violation of 2 bytes is detected + * + * @param address The address that was accessed + */ +extern "C" void __asan_store2_noabort(uintptr_t address) { + KASanHandler::handle(true, address, 2, __builtin_return_address(0)); +} + +/** + * @brief Triggered when a memory store access violation of 4 bytes is detected + * + * @param address The address that was accessed + */ +extern "C" void __asan_store4_noabort(uintptr_t address) { + KASanHandler::handle(true, address, 4, __builtin_return_address(0)); +} + +/** + * @brief Triggered when a memory store access violation of 8 bytes is detected + * + * @param address The address that was accessed + */ +extern "C" void __asan_store8_noabort(uintptr_t address) { + KASanHandler::handle(true, address, 8, __builtin_return_address(0)); +} + +/** + * @brief Triggered when a memory store access violation of 16 bytes is detected + * + * @param address The address that was accessed + */ +extern "C" void __asan_store16_noabort(uintptr_t address) { + KASanHandler::handle(true, address, 16, __builtin_return_address(0)); +} + +/** + * @brief Triggered when a memory store access violation of arbitrary size is detected + * + * @param address The address that was accessed + * @param size The size of the access in bytes + */ +extern "C" void __asan_storeN_noabort(uintptr_t address, size_t size) { + KASanHandler::handle(false, address, size, __builtin_return_address(0)); +} + +/** + * @brief Triggered when a function that is expected to not return does return + */ +extern "C" void __asan_handle_no_return() { + ASSERT(false, "KASAN ERROR: Function marked 'noreturn' has returned"); +} + +/** + * @brief Poisons a region of stack memory allocated with alloca + * + * @param address The starting address of the allocated memory + * @param size The size of the allocated memory in bytes + */ +extern "C" void __asan_alloca_poison(uintptr_t address, size_t size) { + //TODO: Implement stack poisoning + ASSERT(false, "KASAN ERROR: Stack poisoning not implemented for address 0x%lx of size %zu", address, size); +} + +/** + * @brief Unpoisons a region of stack memory allocated with alloca + * + * @param address The starting address of the allocated memory + * @param size The size of the allocated memory in bytes + */ +extern "C" void __asan_alloca_unpoison(void* stack_top, void* stack_bottom) { + //TODO: Implement stack unpoisoning + ASSERT(false, "KASAN ERROR: Stack unpoisoning not implemented for range 0x%p - 0x%p", stack_bottom, stack_top); +} + +/** + * @brief Unpoisons a region of memory, marking it as accessible + * + * @param pointer The starting address of the memory + * @param size The size of the memory region in bytes + */ +extern "C" void __asan_set_shadow_00(void* pointer, size_t size) { + + // Clear the memory to mark it as unpoisoned + for(int i = 0; i < size; ++i) + ((int8_t*)pointer)[i] = 0; + +} + +/** + * @brief Poisons a region of memory, marking it as inaccessible + * + * @param pointer The starting address of the memory + * @param size The size of the memory region in bytes + */ +extern "C" void __asan_set_shadow_f8(void *pointer, size_t size){ + + // Fill the memory to mark it as poisoned + for(int i = 0; i < size; ++i) + ((int8_t*)pointer)[i] = 0xF8; + +} + +/** + * @brief Called before dynamic initialization of a module + * + * @param module_name The name of the module being initialized + */ +extern "C" void __asan_before_dynamic_init(const void *module_name) { + // Nothing to do +} + +/** + * @brief Called after dynamic initialization of a module + * + * @param module_name The name of the module that was initialized + */ + extern "C" void __asan_after_dynamic_init(const void *module_name) { + // Nothing to do + } \ No newline at end of file diff --git a/kernel/src/tests/common.cpp b/kernel/src/tests/common.cpp new file mode 100644 index 00000000..b52f0f21 --- /dev/null +++ b/kernel/src/tests/common.cpp @@ -0,0 +1,46 @@ +/** + * @file common.cpp + * @brief Implements the tests for all common components of MaxOS + * + * @date 23rd November 2025 + * @author Max Tyson +*/ + +#include + +using namespace::MaxOS; +using namespace::MaxOS::tests; + + +void register_buffer_tests(){ + +} + +void register_colour_tests(){ + +} + +void register_graphicsContext_tests(){ + +} + + + + +/** + * @brief Registers all common tests with the test runner + */ +void MaxOS::tests::register_tests_common() { + + // String Tests + + MAXOS_CONDITIONAL_TEST(StringConcatenation, TestType::COMMON) + { + string a = "Hello"; + a += " World"; + return a == "Hello World"; + }); + + + +} \ No newline at end of file diff --git a/kernel/src/tests/test.cpp b/kernel/src/tests/test.cpp new file mode 100644 index 00000000..43fa96f1 --- /dev/null +++ b/kernel/src/tests/test.cpp @@ -0,0 +1,132 @@ +/** + * @file test.cpp + * @brief Implements a basic test class for MaxOS + * + * @date 23rd November 2025 + * @author Max Tyson + */ + +#include +#include + +using namespace MaxOS; +using namespace MaxOS::tests; + +Test::Test(string const& name, TestType type) +: m_name(name), + m_type(type) +{ + TestRunner::add_test(this); +} + +/** + * @brief Runs the test and returns the result + * + * @return TestStatus The status of the test after running + */ +TestStatus Test::run() { + + // Run the test + auto result = execute(); + ASSERT(result != TestStatus::TEST_FAIL, "Test '%s' of type %s FAILED", m_name.c_str(), TEST_TYPE_STRINGS[(size_t)m_type]); + + // Print the outcome + if (!QUITE_TESTING) + Logger::TEST() << "Test '" << m_name << "' of type " << TEST_TYPE_STRINGS[(size_t)m_type] << " " << (result == TestStatus::TEST_PASS ? "PASSED" : "SKIPPED") << "\n"; + + return result; +} + +/** + * @brief Gets the name of the test + * + * @return The name of the test + */ +const string& Test::name() const { + return m_name; +} + +/** + * @brief Gets the type of the test + * + * @return The type of the test + */ +TestType Test::type() const { + return m_type; +} + +Test::~Test() = default; + + +ConditionalTest::ConditionalTest(string const& name, TestType type, bool (* condition)()) +: Test(name, type), + m_condition(condition) +{ +} + +/** + * @brief Executes the conditional test based on the provided condition function + * + * @return TestStatus The status of the test after execution + */ +TestStatus ConditionalTest::execute() { + + if (m_condition()) + return TestStatus::TEST_PASS; + else + return TestStatus::TEST_FAIL; + +} + + +ConditionalTest::~ConditionalTest() = default; + +/** + * @brief Runs all registered tests + */ +void TestRunner::run_all_tests() { + Logger::TEST() << "Running all tests... (" << (int )s_tests.size() << " tests found)\n"; + for (auto& test : s_tests) + test->run(); +} + +/** + * @brief Runs all tests of a specific type + * + * @param type The type of tests to run + */ +void TestRunner::run_all_types(TestType type) { + for (auto& test : s_tests) + if (test->type() == type) + test->run(); +} + +/** + * @brief Adds a test to the test runner + * + * @param test The test to add + */ +void TestRunner::add_test(Test* test) { + s_tests.push_back(test); +} + +/** + * @brief Adds all predefined tests to the test runner + */ +void TestRunner::add_all_tests() { + register_tests_common(); +} + +/** + * @brief Setups the TestRunner and runs all kernel tests + */ +void TestRunner::test_kernel() { + + // Add all tests + s_tests = common::Vector(); + add_all_tests(); + + // Run all system tests + run_all_tests(); + +} From ee0050e719f5e9c4d99e92057ea485f96d0e09e4 Mon Sep 17 00:00:00 2001 From: Max Tyson <98maxt98@gmail.com> Date: Mon, 24 Nov 2025 15:31:36 +1300 Subject: [PATCH 09/12] Common Tests --- kernel/include/common/macros.h | 2 + kernel/include/tests/test.h | 29 +- kernel/src/common/buffer.cpp | 9 +- kernel/src/kernel.cpp | 1 - kernel/src/tests/common.cpp | 888 ++++++++++++++++++++++++++++++++- kernel/src/tests/test.cpp | 27 +- 6 files changed, 922 insertions(+), 34 deletions(-) diff --git a/kernel/include/common/macros.h b/kernel/include/common/macros.h index d3827907..c7bcedb3 100644 --- a/kernel/include/common/macros.h +++ b/kernel/include/common/macros.h @@ -23,6 +23,8 @@ namespace MaxOS{ #define PAGE_ALIGNED __attribute__((aligned(4096))) #endif + #define CONCATENATE(a, b) CONCATENATE_IMPL(a, b) + #define CONCATENATE_IMPL(a, b) a##b } diff --git a/kernel/include/tests/test.h b/kernel/include/tests/test.h index a749677b..ac4c328a 100644 --- a/kernel/include/tests/test.h +++ b/kernel/include/tests/test.h @@ -11,13 +11,10 @@ #include #include +#include - -#define PASS return TestStatus::TEST_PASS -#define FAIL return TestStatus::TEST_FAIL -#define SKIP return TestStatus::TEST_SKIP #define MAXOS_CONDITIONAL_TEST(name, type) \ - auto test = new ConditionalTest(#name, type, []() + auto CONCATENATE(test_, __COUNTER__) = new ConditionalTest(#name, type, []() namespace MaxOS::tests { @@ -26,9 +23,9 @@ namespace MaxOS::tests { * @brief The possible outcomes of a test */ enum class TestStatus { - TEST_PASS, - TEST_FAIL, - TEST_SKIP + PASS, + FAIL, + SKIP }; /** @@ -83,9 +80,19 @@ namespace MaxOS::tests { const string& name() const; TestType type() const; - }; + template bool compare(T1 const& actual, T2 const& expected) { + + // Direct comparison + if (actual == expected) + return true; + + // Report what failed + Logger::WARNING() << "Test failed comparison: expected [" << expected << "], got [" << actual << "]\n"; + return false; + } + /** * @class ConditionalTest * @brief A test that only checks a condition to determine pass/fail @@ -101,11 +108,11 @@ namespace MaxOS::tests { TestStatus execute() override; }; - constexpr bool QUITE_TESTING = false; ///< If true, suppresses test output - /** * @class TestRunner * @brief A class to run all tests + * + * @todo Revisit when cbf */ class TestRunner { diff --git a/kernel/src/common/buffer.cpp b/kernel/src/common/buffer.cpp index 6c309bc5..3324d0d1 100644 --- a/kernel/src/common/buffer.cpp +++ b/kernel/src/common/buffer.cpp @@ -78,10 +78,13 @@ void Buffer::clear() { void Buffer::full(uint8_t byte, size_t offset, size_t amount) { // Prevent writing past the buffer bounds - if (amount == 0) amount = m_capacity - m_offset - offset; - ASSERT(m_offset + offset + amount <= capacity(), "Buffer overflow"); + size_t start = m_offset + offset; + ASSERT(start <= m_capacity, "Offset past buffer end"); - memset(m_bytes + m_offset + offset, byte, amount); + if (amount == 0) amount = m_capacity - start; + ASSERT(start + amount <= m_capacity, "Buffer overflow"); + + memset(m_bytes + start, byte, amount); } diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp index 6e1baf8a..b297c869 100644 --- a/kernel/src/kernel.cpp +++ b/kernel/src/kernel.cpp @@ -114,7 +114,6 @@ extern "C" [[noreturn]] void kernel_main(unsigned long addr, unsigned long magic VFSResourceRegistry vfs_registry(&vfs); SyscallManager syscalls; console.finish(); - TestRunner::test_kernel(); GlobalScheduler::activate(); // Idle loop (read Idle.md) diff --git a/kernel/src/tests/common.cpp b/kernel/src/tests/common.cpp index b52f0f21..81c04acb 100644 --- a/kernel/src/tests/common.cpp +++ b/kernel/src/tests/common.cpp @@ -7,40 +7,900 @@ */ #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -using namespace::MaxOS; -using namespace::MaxOS::tests; +using namespace ::MaxOS; +using namespace ::MaxOS::tests; +using namespace ::MaxOS::common; +/** + * @brief Registers all buffer tests + */ +void register_buffer_tests() { -void register_buffer_tests(){ + MAXOS_CONDITIONAL_TEST(Buffer_Construct_Size, TestType::COMMON) + { + Buffer buf(10); + return compare(buf.capacity(), 10); + }); -} + MAXOS_CONDITIONAL_TEST(Buffer_Construct_FromSource, TestType::COMMON) + { + // Create from existing data + uint8_t data[5] = { 1, 2, 3, 4, 5 }; + Buffer buf(data, 5); -void register_colour_tests(){ + // Make sure data matches + for(size_t i = 0; i < 5; i++) + if(!compare(buf.read(0), data[i])) + return false; -} + return true; + }); + + MAXOS_CONDITIONAL_TEST(Buffer_Clear, TestType::COMMON) + { + // Create buffer and fill with non-zero data + Buffer buf(5); + buf.full(0xFF); + + // Ensure buffer is cleared to zeroes + buf.clear(); + for(size_t i = 0; i < buf.capacity(); i++) + if(!compare(buf.read(0), 0x00)) + return false; + + return true; + }); + + MAXOS_CONDITIONAL_TEST(Buffer_Full, TestType::COMMON) + { + // Create buffer and fill with specific byte + Buffer buf(5); + buf.full(0xAA); + + // Ensure buffer is filled with the correct byte + for(size_t i = 0; i < buf.capacity(); i++) + if(!compare(buf.read(0), 0xAA)) + return false; + + return true; + }); + + MAXOS_CONDITIONAL_TEST(Buffer_WriteRead_Offset, TestType::COMMON) + { + // Setup buffer with byes at specific offsets + Buffer buf(3); + buf.write(0x12); + buf.write(1, 0x34); + + // Read back bytes and verify + if(!compare(buf.read(0), 0x12)) return false; + if(!compare(buf.read(1), 0x34)) return false; + return true; + }); + + MAXOS_CONDITIONAL_TEST(Buffer_Resize, TestType::COMMON) + { + Buffer buf(5); + buf.resize(10); + return compare(buf.capacity(), 10); + }); + + MAXOS_CONDITIONAL_TEST(Buffer_CopyFromBuffer, TestType::COMMON) + { + // Create source and destination buffers with known data + Buffer src(5); + Buffer dst(5); + src.full(0x55); + + // Ensure data is copied correctly + dst.copy_from(&src); + for(size_t i = 0; i < dst.capacity(); i++) + if(!compare(dst.read(0), 0x55)) + return false; + + return true; + }); + + MAXOS_CONDITIONAL_TEST(Buffer_CopyToBuffer, TestType::COMMON) + { + // Create source and destination buffers with known data + Buffer src(5); + Buffer dst(5); + src.full(0x77); + + // Ensure data is copied correctly + src.copy_to(&dst); + for(size_t i = 0; i < dst.capacity(); i++) + if(!compare(dst.read(0), 0x77)) + return false; + + return true; + }); + + MAXOS_CONDITIONAL_TEST(Buffer_CopyFromRawPointer, TestType::COMMON) + { + // Create raw data and copy into buffer + uint8_t data[3] = { 0x01, 0x02, 0x03 }; + Buffer buf(3); + buf.copy_from(data, 3); + + // Ensure data is copied correctly + return compare(buf.read(0), 0x01) + && compare(buf.read(1), 0x02) + && compare(buf.read(2), 0x03); + }); + + MAXOS_CONDITIONAL_TEST(Buffer_CopyToRawPointer, TestType::COMMON) + { + // Create buffer with known data + Buffer buf(3); + buf.full(0x99); + + // Copy data to raw pointer + uint8_t out[3] = { 0 }; + buf.copy_to(out, 3); + + return compare(out[0], 0x99) + && compare(out[1], 0x99) + && compare(out[2], 0x99); + }); + + MAXOS_CONDITIONAL_TEST(Buffer_Offset_Update, TestType::COMMON) + { + // Create a buffer and fill with data that will move the offset + Buffer buf(3, true); + buf.write(0x10); + buf.write(0x20); + + // Overwrite first byte and check offset moved correctly + buf.set_offset(0); + buf.write(0x30); + return compare(buf.read(0), 0x30) + && compare(buf.read(1), 0x20) + && compare(buf.read(2), 0x00); + }); + + MAXOS_CONDITIONAL_TEST(Buffer_Offset_Disabled, TestType::COMMON) + { + // Create a buffer and fill with data that will move the offset + Buffer buf(3, false); + buf.write(0x11); + buf.write(0x22); + + // Overwrite first byte and check offset did not move + buf.set_offset(0); + buf.write(0x33); + return compare(buf.read(0), 0x33) + && compare(buf.read(1), 0x22) + && compare(buf.read(2), 0x00); + }); + + MAXOS_CONDITIONAL_TEST(Buffer_CopyPartial_FromBuffer, TestType::COMMON) + { + // Setup source and destination buffers + Buffer src(5); + Buffer dst(5); + src.full(0x55); + + // Verify that only part of the buffer is copied + dst.copy_from(&src, 3); + return dst.read(0) == 0x55 && dst.read(1) == 0x55 && dst.read(2) == 0x55 && dst.read(3) == 0x00; + }); + + MAXOS_CONDITIONAL_TEST(Buffer_CopyPartial_ToBuffer, TestType::COMMON) + { + // Setup source and destination buffers + Buffer src(5); + Buffer dst(5); + src.full(0x66); + + // Verify that only part of the buffer is copied + src.copy_to(&dst, 3); + return compare(dst.read(0), 0x66) + && compare(dst.read(1), 0x66) + && compare(dst.read(2), 0x66) + && compare(dst.read(3), 0x00); + }); -void register_graphicsContext_tests(){ + MAXOS_CONDITIONAL_TEST(Buffer_Full_Partial, TestType::COMMON) + { + Buffer buf(5); + buf.full(0x99, 1, 3); + return compare(buf.read(0), 0x00) + && compare(buf.read(1), 0x99) + && compare(buf.read(2), 0x99) + && compare(buf.read(3), 0x99) + && compare(buf.read(4), 0x00); + }); + // TODO: Test bounds checking (some sorta exception handling) } +/** + * @brief Registers all colour tests + */ +void register_colour_tests() { + + MAXOS_CONDITIONAL_TEST(Colour_DefaultConstructor, TestType::COMMON) + { + Colour c; + return compare(c.red, 0) + && compare(c.green, 0) + && compare(c.blue, 0) + && compare(c.alpha, 0); + }); + + MAXOS_CONDITIONAL_TEST(Colour_RGBConstructor, TestType::COMMON) + { + Colour c(10, 20, 30); + return compare(c.red, 10) + && compare(c.green, 20) + && compare(c.blue, 30) + && compare(c.alpha, 0); + }); + + MAXOS_CONDITIONAL_TEST(Colour_RGBAConstructor, TestType::COMMON) + { + Colour c(10, 20, 30, 40); + return compare(c.red, 10) + && compare(c.green, 20) + && compare(c.blue, 30) + && compare(c.alpha, 40); + }); + + MAXOS_CONDITIONAL_TEST(Colour_ConsoleColourConstructor_Red, TestType::COMMON) + { + Colour c(ConsoleColour::Red); + return compare(c.red, 255) + && compare(c.green, 0) + && compare(c.blue, 0); + }); + MAXOS_CONDITIONAL_TEST(Colour_HexStringConstructor_Magenta, TestType::COMMON) + { + Colour c("FF00FF"); + return compare(c.red, 255) + && compare(c.green, 0) + && compare(c.blue, 255); + }); + MAXOS_CONDITIONAL_TEST(Colour_ANSIStringConstructor_FGGreen, TestType::COMMON) + { + Colour c("\033[0;32m"); + return compare(c.red, 0) + && compare(c.green, 255) + && compare(c.blue, 0); + }); + + MAXOS_CONDITIONAL_TEST(Colour_ToConsoleColour_Red, TestType::COMMON) + { + Colour c(255, 0, 0); + return c.to_console_colour() == ConsoleColour::Red; + }); + + MAXOS_CONDITIONAL_TEST(Colour_ConsoleColourRoundTrip_Blue, TestType::COMMON) + { + Colour c(ConsoleColour::Blue); + return c.to_console_colour() == ConsoleColour::Blue; + }); + + MAXOS_CONDITIONAL_TEST(Colour_AlphaPreservation, TestType::COMMON) + { + Colour c(10, 20, 30, 128); + return compare(c.alpha, 128); + }); + +} /** - * @brief Registers all common tests with the test runner + * @brief Registers all map tests */ -void MaxOS::tests::register_tests_common() { +void register_map_tests() { + + MAXOS_CONDITIONAL_TEST(Map_EmptyOnConstruct, TestType::COMMON) + { + Map m; + return compare(m.empty(), true); + }); + + MAXOS_CONDITIONAL_TEST(Map_PushBack_SizeAndFind, TestType::COMMON) + { + // Create map and add an element + Map m; + m.push_back(1, 100); + + // Verify size is correct + if(!compare(m.size(), 1)) + return false; + + // Verify element can be found + auto it = m.find(1); + return it != m.end() && compare(it->first, 1) && compare(it->second, 100); + }); + + MAXOS_CONDITIONAL_TEST(Map_PushBack_PopBack, TestType::COMMON) + { + // Create map and add elements + Map m; + m.push_back(1, 10); + m.push_back(2, 20); + + // Verify size + if(!compare(m.size(), 2)) + return false; + + // Confirm last element is correct + Pair last = m.pop_back(); + if(!compare(last.first, 2)) return false; + if(!compare(last.second, 20)) return false; + + // Verify size after pop + return compare(m.size(), 1); + }); + + MAXOS_CONDITIONAL_TEST(Map_PushFront_PopFront, TestType::COMMON) + { + // Create map and add elements + Map m; + m.push_back(2, 20); + m.push_front(1, 10); + + // Verify size + if(!compare(m.size(), 2)) + return false; + + // Confirm first element is correct + Pair first = m.pop_front(); + if(!compare(first.first, 1)) return false; + if(!compare(first.second, 10)) return false; + + // Verify size after pop + return compare(m.size(), 1); + }); + + MAXOS_CONDITIONAL_TEST(Map_Insert_AddAndUpdate, TestType::COMMON) + { + // Create map and add an element + Map m; + m.insert(1, 100); + + // Verify size after insert + if(!compare(m.size(), 1)) + return false; + + // Update the existing element and verify size remains the same + m.insert(1, 200); + if(!compare(m.size(), 1)) return false; + + // Verify the value was updated + auto it = m.find(1); + if(it == m.end()) return false; + return compare(it->second, 200); + }); + + MAXOS_CONDITIONAL_TEST(Map_Erase_ByKey, TestType::COMMON) + { + // Create map and add elements + Map m; + m.push_back(1, 10); + m.push_back(2, 20); + + // Verify size before erase + if(!compare(m.size(), 2)) return false; + + // Erase one element and verify size and contents + m.erase(1); + if(!compare(m.size(), 1)) return false; + return (m.find(1) == m.end()) && (m.find(2) != m.end()); + }); + + MAXOS_CONDITIONAL_TEST(Map_Erase_ByIterator, TestType::COMMON) + { + // Create map and add elements + Map m; + m.push_back(1, 11); + m.push_back(2, 22); + + // Verify size before erase + if(!compare(m.size(), 2)) return false; + + // Erase one element + auto it = m.find(1); + if(it == m.end()) return false; + m.erase(it); + + // Verify size and contents after erase + if(!compare(m.size(), 1)) return false; + return (m.find(1) == m.end()) && (m.find(2) != m.end()); + }); + + MAXOS_CONDITIONAL_TEST(Map_Clear_Empties, TestType::COMMON) + { + // Create map and add elements + Map m; + m.push_back(1, 1); + m.push_back(2, 2); + + // Clear the map and verify it's empty + m.clear(); + return compare(m.empty(), true) && compare(m.size(), 0); + }); + + MAXOS_CONDITIONAL_TEST(Map_ReserveAndIncreaseSize, TestType::COMMON) + { + // Create map and reserve space + Map m; + m.reserve(16); + + // Verify size is still zero + if(!compare(m.size(), 0)) return false; + + // Increase size and verify still zero //TODO: also verify capacity increased? + m.increase_size(); + return compare(m.size(), 0); + }); +} + +void register_rectangle_tests() { + + MAXOS_CONDITIONAL_TEST(Rectangle_DefaultConstructor, TestType::COMMON) + { + Rectangle r; + + if(!compare(r.left, 0)) return false; + if(!compare(r.top, 0)) return false; + if(!compare(r.width, 0)) return false; + if(!compare(r.height, 0)) return false; + return true; + }); + + MAXOS_CONDITIONAL_TEST(Rectangle_Construct_PositiveValues, TestType::COMMON) + { + Rectangle r(1, 2, 3, 4); + + if(!compare(r.left, 1)) return false; + if(!compare(r.top, 2)) return false; + if(!compare(r.width, 3)) return false; + if(!compare(r.height, 4)) return false; + return true; + }); + + MAXOS_CONDITIONAL_TEST(Rectangle_Construct_NegativeSize_Normalises, TestType::COMMON) + { + Rectangle r(-2, -3, -4, -5); + + if(!compare(r.left, -6)) return false; + if(!compare(r.top, -8)) return false; + if(!compare(r.width, 4)) return false; + if(!compare(r.height, 5)) return false; + return true; + }); + + + MAXOS_CONDITIONAL_TEST(Rectangle_Intersects_Overlaps, TestType::COMMON) + { + Rectangle a(0, 0, 10, 10); + Rectangle b(5, 5, 2, 2); + + return compare(a.intersects(b), true); + }); + + MAXOS_CONDITIONAL_TEST(Rectangle_Intersects_EdgeTouch_NoIntersect, TestType::COMMON) + { + Rectangle a(0, 0, 10, 10); + Rectangle b(10, 10, 5, 5); + Rectangle c(11, 0, 2, 2); + + if(!compare(a.intersects(b), false)) return false; + if(!compare(a.intersects(c), false)) return false; + return true; + }); + + MAXOS_CONDITIONAL_TEST(Rectangle_Intersection_CorrectValues, TestType::COMMON) + { + Rectangle a(0, 0, 10, 10); + Rectangle b(5, 5, 10, 10); + Rectangle inter = a.intersection(b); + + if(!compare(inter.left, 5)) return false; + if(!compare(inter.top, 5)) return false; + if(!compare(inter.width, 5)) return false; + if(!compare(inter.height, 5)) return false; + return true; + }); + + MAXOS_CONDITIONAL_TEST(Rectangle_Contains_Rectangle_Inside, TestType::COMMON) + { + Rectangle outer(0, 0, 10, 10); + Rectangle inner(2, 2, 3, 3); + + return compare(outer.contains(inner), true); + }); + + MAXOS_CONDITIONAL_TEST(Rectangle_Contains_Rectangle_EdgeTouch_False, TestType::COMMON) + { + Rectangle a(0, 0, 4, 4); + Rectangle b(4, 1, 2, 2); + Rectangle c(-1, -1, 1, 1); + + if(!compare(a.contains(b), false)) return false; + if(!compare(a.contains(c), false)) return false; + return true; + }); + + MAXOS_CONDITIONAL_TEST(Rectangle_Contains_Point, TestType::COMMON) + { + Rectangle r(1, 1, 4, 4); + + if(!compare(r.contains(1, 1), true)) return false; + if(!compare(r.contains(4, 1), false)) return false; + if(!compare(r.contains(3, 3), true)) return false; + if(!compare(r.contains(0, 0), false)) return false; + return true; + }); + + MAXOS_CONDITIONAL_TEST(Rectangle_Subtract_NoIntersection_ReturnsOriginal, TestType::COMMON) + { + Rectangle a(0, 0, 4, 4); + Rectangle b(5, 5, 2, 2); + + auto res = a.subtract(b); + const Rectangle& r = res[0]; + + if(!compare((int)res.size(), 1)) return false; + if(!compare(r.left, a.left)) return false; + if(!compare(r.top, a.top)) return false; + if(!compare(r.width, a.width)) return false; + if(!compare(r.height, a.height)) return false; + return true; + }); + + MAXOS_CONDITIONAL_TEST(Rectangle_Subtract_FullyCovered_EmptyResult, TestType::COMMON) + { + Rectangle a(0, 0, 4, 4); + Rectangle b(0, 0, 4, 4); + + auto res = a.subtract(b); + return compare((int)res.size(), 0); + }); + +} + +void register_string_tests() { + + + MAXOS_CONDITIONAL_TEST(String_DefaultConstructor, TestType::COMMON) + { + String s; + return compare(s.length(), (size_t)0); + }); + + MAXOS_CONDITIONAL_TEST(String_CharConstructor, TestType::COMMON) + { + String s('A'); + return compare(s.length(), (size_t)1) && compare(s[0], 'A'); + }); + + MAXOS_CONDITIONAL_TEST(String_CStringConstructor, TestType::COMMON) + { + String s("Hello"); + return compare(s.length(), (size_t)5) && compare(s, String("Hello")); + }); + + MAXOS_CONDITIONAL_TEST(String_CopyConstructor_Assignment, TestType::COMMON) + { + String a("CopyMe"); + String b(a); + String c; + c = a; + return compare(b, a) && compare(c, a); + }); + + MAXOS_CONDITIONAL_TEST(String_Concat_Plus_PlusEquals, TestType::COMMON) + { + String a("Hello"); + String b("World"); + + String combined = a + String(" ") + b; + a += String(" "); + a += b; + + return compare(combined, String("Hello World")) && compare(a, combined); + }); + + MAXOS_CONDITIONAL_TEST(String_Substring_StartsWith, TestType::COMMON) + { + String s("This is a test"); + String sub = s.substring(5, 2); + + return compare(sub, String("is")) && compare(s.starts_with(String("This")), true); + }); + + MAXOS_CONDITIONAL_TEST(String_Split_Simple, TestType::COMMON) + { + String s("one,two,three"); + auto parts = s.split(String(",")); + + if(!compare((size_t)parts.size(), (size_t)3)) return false; + if(!compare(parts[0], String("one"))) return false; + if(!compare(parts[1], String("two"))) return false; + return compare(parts[2], String("three")); + }); + + MAXOS_CONDITIONAL_TEST(String_Strip_Center, TestType::COMMON) + { + String s(" padded "); + String stripped = s.strip(' '); + String centered = String("hi").center(6, '.'); + + if(!compare(stripped, String(" padded"))) return false; + return compare(centered, String("..hi..")); + }); + + MAXOS_CONDITIONAL_TEST(String_Formatted_Integer_Hex_String, TestType::COMMON) + { + String f = String::formatted("num:%d hex:%x str:%s", 42, (uint64_t)0x2A, (char*)"ok"); + + return compare(f, String("num:42 hex:2A str:ok")); + }); + + MAXOS_CONDITIONAL_TEST(String_Length_AnsiHandling, TestType::COMMON) + { + String s = String("\033[0;31m") + String("X") + String("\033[0m") + String("Y"); + + + if(!compare(s.length(true), (size_t)8)) return false; + return compare(s.length(false), (size_t)2); + }); - // String Tests + MAXOS_CONDITIONAL_TEST(String_OperatorMultiply, TestType::COMMON) + { + String s("ab"); + String r = s * 3; + + return compare(r, String("ababab")) && compare(r.length(), (size_t)6); + }); + + MAXOS_CONDITIONAL_TEST(String_Comparisons_LexValue, TestType::COMMON) + { + String a("aaa"); + String b("bbb"); - MAXOS_CONDITIONAL_TEST(StringConcatenation, TestType::COMMON) + if(!compare(a < b, true)) return false; + if(!compare(b > a, true)) return false; + if(!compare(a <= a, true)) return false; + return compare(b >= a, true); + }); + + MAXOS_CONDITIONAL_TEST(String_StringBuilder_Append, TestType::COMMON) { - string a = "Hello"; - a += " World"; - return a == "Hello World"; + StringBuilder sb; + sb << "val:" << 123 << (uint64_t)0x10 << true; + String out = sb.out; + + if(!compare(out.starts_with(String("val:")), true)) return false; + if(!compare(out.length() > (size_t)5, true)) return false; + return true; }); +} + +void register_time_tests() { + MAXOS_CONDITIONAL_TEST(Time_IsLeapYear_True, TestType::COMMON) + { + Time t { 2020, 2, 1, 0, 0, 0 }; + return compare(t.is_leap_year(), true); + }); + + MAXOS_CONDITIONAL_TEST(Time_IsLeapYear_False, TestType::COMMON) + { + Time t { 2019, 3, 1, 0, 0, 0 }; + return compare(t.is_leap_year(), false); + }); + + MAXOS_CONDITIONAL_TEST(Time_Epoch_1970_01_01, TestType::COMMON) + { + Time t { 1970, 1, 1, 0, 0, 0 }; + return compare(time_to_epoch(t), (uint64_t)0ULL); + }); + + MAXOS_CONDITIONAL_TEST(Time_Epoch_1970_01_02, TestType::COMMON) + { + Time t { 1970, 1, 2, 0, 0, 0 }; + return compare(time_to_epoch(t), (uint64_t)86400ULL); + }); + + MAXOS_CONDITIONAL_TEST(Time_Epoch_1971_01_01, TestType::COMMON) + { + Time t { 1971, 1, 1, 0, 0, 0 }; + return compare(time_to_epoch(t), (uint64_t)31536000ULL); + }); + + MAXOS_CONDITIONAL_TEST(Time_Epoch_1972_03_01_LeapYear, TestType::COMMON) + { + Time t { 1972, 3, 1, 0, 0, 0 }; + return compare(time_to_epoch(t), (uint64_t)68256000ULL); + }); + + MAXOS_CONDITIONAL_TEST(Time_MonthsArray_Bounds, TestType::COMMON) + { + return compare(string(Months[0]), string("January")) && compare(string(Months[11]), string("December")); + }); + +} + +void register_vector_tests() { + + MAXOS_CONDITIONAL_TEST(Vector_Default_Construct_Empty, TestType::COMMON) + { + Vector v; + return compare((int)v.size(), 0) && compare(v.empty(), true); + }); + + + MAXOS_CONDITIONAL_TEST(Vector_Construct_Size_Fill, TestType::COMMON) + { + Vector v(4, 7); + return compare((size_t)v.size(), 4) + && compare(v[0], 7) + && compare(v[1], 7) + && compare(v[2], 7) + && compare(v[3], 7); + }); + + MAXOS_CONDITIONAL_TEST(Vector_PushBack_PopBack, TestType::COMMON) + { + Vector v; + v.push_back(1); + v.push_back(2); + v.push_back(3); + + if(!compare((size_t)v.size(), 3)) return false; + + int popped = v.pop_back(); + if(!compare(popped, 3)) return false; + return compare((size_t)v.size(), 2); + }); + + MAXOS_CONDITIONAL_TEST(Vector_PushFront_PopFront, TestType::COMMON) + { + Vector v; + v.push_back(2); + v.push_back(3); + v.push_front(1); + + if(!compare((size_t)v.size(), 3)) return false; + if(!compare(v[0], 1)) return false; + + int front = v.pop_front(); + if(!compare(front, 1)) return false; + return compare((size_t)v.size(), 2); + }); + + MAXOS_CONDITIONAL_TEST(Vector_Reserve_IncreaseSize_Preserves, TestType::COMMON) + { + Vector v; + v.push_back(9); + v.push_back(8); + v.reserve(16); + + if(!compare((size_t)v.size(), 2)) return false; + if(!compare(v[0], 9)) return false; + if(!compare(v[1], 8)) return false; + + v.increase_size(); + return compare(v[0], 9); + }); + + MAXOS_CONDITIONAL_TEST(Vector_CopyConstructor_Independent, TestType::COMMON) + { + Vector original; + original.push_back(4); + original.push_back(5); + Vector copy = original; + + original.pop_back(); + if(!compare((size_t)original.size(), 1)) return false; + return compare((size_t)copy.size(), 2) + && compare(copy[1], 5); + }); + + + MAXOS_CONDITIONAL_TEST(Vector_MoveConstructor_Transfers, TestType::COMMON) + { + Vector src; + src.push_back(10); + src.push_back(11); + Vector moved = static_cast&&>(src); + + if(!compare((size_t)moved.size(), 2)) return false; + return compare((size_t)src.size(), 0); + }); + + MAXOS_CONDITIONAL_TEST(Vector_Assignment_Copy_And_Move, TestType::COMMON) + { + Vector a; + a.push_back(1); + a.push_back(2); + + Vector b; + b = a; + if(!compare((size_t)b.size(), 2)) return false; + if(!compare(b[1], 2)) return false; + + Vector c; + c = static_cast&&>(b); // move assign + if(!compare((size_t)c.size(), 2)) return false; + return compare((size_t)b.size(), 0); + }); + + MAXOS_CONDITIONAL_TEST(Vector_Erase_ByValue_RemovesAll, TestType::COMMON) + { + Vector v; + v.push_back(3); + v.push_back(4); + v.push_back(3); + v.push_back(5); + v.erase(3); + + if(!compare((size_t)v.size(), 2)) return false; + return compare(v[0], 4) + && compare(v[1], 5); + }); + + MAXOS_CONDITIONAL_TEST(Vector_Erase_ByIterator_RemovesSingle, TestType::COMMON) + { + Vector v; + v.push_back(7); + v.push_back(8); + v.push_back(9); + auto it = v.begin() + 1; + v.erase(it); + + if(!compare((size_t)v.size(), 2)) return false; + return compare(v[0], 7) + && compare(v[1], 9); + }); + + MAXOS_CONDITIONAL_TEST(Vector_Find_Present_And_Absent, TestType::COMMON) + { + Vector v; + v.push_back(21); + v.push_back(22); + v.push_back(23); + + bool found22 = (v.find(22) != v.end()); + bool found99 = (v.find(99) != v.end()); + + if(!compare(found22, true)) return false; + return compare(found99, false); + }); +} + + +/** + * @brief Registers all common tests with the test runner + */ +void MaxOS::tests::register_tests_common() { + register_buffer_tests(); + register_colour_tests(); + register_map_tests(); + register_rectangle_tests(); + register_string_tests(); + register_time_tests(); + register_vector_tests(); } \ No newline at end of file diff --git a/kernel/src/tests/test.cpp b/kernel/src/tests/test.cpp index 43fa96f1..61dacaa3 100644 --- a/kernel/src/tests/test.cpp +++ b/kernel/src/tests/test.cpp @@ -28,11 +28,28 @@ TestStatus Test::run() { // Run the test auto result = execute(); - ASSERT(result != TestStatus::TEST_FAIL, "Test '%s' of type %s FAILED", m_name.c_str(), TEST_TYPE_STRINGS[(size_t)m_type]); + StringBuilder msg; + + // Build the message + msg << "Test "; + switch(result) { + case TestStatus::PASS: + msg << "PASSED"; + break; + case TestStatus::SKIP: + msg << "SKIPPED"; + break; + case TestStatus::FAIL: + msg << "FAILED"; + break; + } + msg << " - " << m_name << "\n"; // Print the outcome - if (!QUITE_TESTING) - Logger::TEST() << "Test '" << m_name << "' of type " << TEST_TYPE_STRINGS[(size_t)m_type] << " " << (result == TestStatus::TEST_PASS ? "PASSED" : "SKIPPED") << "\n"; + if (result == TestStatus::FAIL) + Logger::ERROR() << msg.out; + else + Logger::TEST() << msg.out; return result; } @@ -72,9 +89,9 @@ ConditionalTest::ConditionalTest(string const& name, TestType type, bool (* cond TestStatus ConditionalTest::execute() { if (m_condition()) - return TestStatus::TEST_PASS; + return TestStatus::PASS; else - return TestStatus::TEST_FAIL; + return TestStatus::FAIL; } From 5ff5a0c41da9f6e28f897b3664663e50e41b8a04 Mon Sep 17 00:00:00 2001 From: Max Tyson <98maxt98@gmail.com> Date: Mon, 24 Nov 2025 15:45:29 +1300 Subject: [PATCH 10/12] Doxy Can Gen --- kernel/include/common/string.h | 1 - kernel/include/runtime/kasan.h | 4 ++-- kernel/include/tests/test.h | 16 +++++++++++++++ kernel/src/gui/widget.cpp | 22 ++++++++++---------- kernel/src/gui/widgets/inputbox.cpp | 8 +++++--- kernel/src/kernel.cpp | 3 +-- kernel/src/net/ipv4.cpp | 8 ++++---- kernel/src/runtime/kasan.cpp | 31 +++++++++++++++++++++++++++-- kernel/src/tests/common.cpp | 12 +++++++++++ kernel/src/tests/test.cpp | 14 ++++++++++++- 10 files changed, 93 insertions(+), 26 deletions(-) diff --git a/kernel/include/common/string.h b/kernel/include/common/string.h index fdb788ea..df9a778c 100644 --- a/kernel/include/common/string.h +++ b/kernel/include/common/string.h @@ -112,7 +112,6 @@ namespace MaxOS { int strlen(const char* str); char* itoa(int base, int64_t number); char* htoa(uint64_t number); -char* ftoa(float number); // Compare functions bool strcmp(char const* str1, char const* str2); diff --git a/kernel/include/runtime/kasan.h b/kernel/include/runtime/kasan.h index ab98ef3a..2aa618f6 100644 --- a/kernel/include/runtime/kasan.h +++ b/kernel/include/runtime/kasan.h @@ -15,8 +15,8 @@ namespace MaxOS::runtime { /** - * @class UBSanHandler - * @brief Handles undefined behaviour sanitizer runtime errors + * @class KASanHandler + * @brief Handles kernel address sanitizer runtime errors * * @todo finish when cbf */ diff --git a/kernel/include/tests/test.h b/kernel/include/tests/test.h index ac4c328a..32807649 100644 --- a/kernel/include/tests/test.h +++ b/kernel/include/tests/test.h @@ -13,6 +13,7 @@ #include #include +/// Simplified macro to define a conditional test #define MAXOS_CONDITIONAL_TEST(name, type) \ auto CONCATENATE(test_, __COUNTER__) = new ConditionalTest(#name, type, []() @@ -76,12 +77,27 @@ namespace MaxOS::tests { virtual ~Test(); TestStatus run(); + + /** + * @brief Executes the test and returns the status of the test + * + * @return The result of the test execution + */ virtual TestStatus execute() = 0; const string& name() const; TestType type() const; }; + /** + * @brief Compares two values and logs a warning if they are not equal + * + * @tparam T1 The type of the actual value + * @tparam T2 The type of the expected value + * @param actual The actual value + * @param expected The expected value + * @return True if the values are equal, false otherwise + */ template bool compare(T1 const& actual, T2 const& expected) { // Direct comparison diff --git a/kernel/src/gui/widget.cpp b/kernel/src/gui/widget.cpp index d921160e..9210a2e3 100644 --- a/kernel/src/gui/widget.cpp +++ b/kernel/src/gui/widget.cpp @@ -249,32 +249,32 @@ void Widget::bring_to_front(Widget* widget) { /** * @brief Handles the event when the mouse is moved on to the widget * - * @param toX The x coordinate of the mouse - * @param toY The y coordinate of the mouse + * @param to_x The x coordinate of the mouse + * @param to_y The y coordinate of the mouse */ -void Widget::on_mouse_enter_widget(uint32_t, uint32_t) { +void Widget::on_mouse_enter_widget(uint32_t to_x, uint32_t to_y) { } /** * @brief Handles the event when the mouse is moved out of the widget * - * @param fromX The x coordinate of the mouse - * @param fromY The y coordinate of the mouse + * @param from_x The x coordinate of the mouse + * @param from_y The y coordinate of the mouse */ -void Widget::on_mouse_leave_widget(uint32_t, uint32_t) { +void Widget::on_mouse_leave_widget(uint32_t from_x, uint32_t from_y) { } /** * @brief Handles the event when the mouse is moved over the widget * - * @param fromX The x original coordinate of the mouse - * @param fromY The y original coordinate of the mouse - * @param toX The x new coordinate of the mouse - * @param toY The y new coordinate of the mouse + * @param from_x The x original coordinate of the mouse + * @param from_y The y original coordinate of the mouse + * @param to_x The x new coordinate of the mouse + * @param to_y The y new coordinate of the mouse */ -void Widget::on_mouse_move_widget(uint32_t, uint32_t, uint32_t, uint32_t) { +void Widget::on_mouse_move_widget(uint32_t from_x, uint32_t from_y, uint32_t to_x, uint32_t to_y) { } diff --git a/kernel/src/gui/widgets/inputbox.cpp b/kernel/src/gui/widgets/inputbox.cpp index 81f43441..672e8f46 100644 --- a/kernel/src/gui/widgets/inputbox.cpp +++ b/kernel/src/gui/widgets/inputbox.cpp @@ -38,6 +38,8 @@ Event* InputBoxEventHandler::on_event(Event* eve /** * @brief Event triggered when the text in the input box is changed + * + * @param text The new text in the input box */ void InputBoxEventHandler::on_input_box_text_changed(const string& text) { @@ -97,12 +99,12 @@ void InputBox::draw(GraphicsContext* gc, Rectangle& area) { Widget::draw(gc, area); // Get the absolute m_position of the input box - Coordinates inputBoxCoordinates = absolute_coordinates(Coordinates(0, 0)); + Coordinates input_box_coordinates = absolute_coordinates(Coordinates(0, 0)); Rectangle input_box_position = position(); // Get the x and y m_position of the input box - int32_t x = inputBoxCoordinates.first; - int32_t y = inputBoxCoordinates.second; + int32_t x = input_box_coordinates.first; + int32_t y = input_box_coordinates.second; // Draw the background for the input box gc->fill_rectangle(x + area.left, y + area.top, x + area.left + area.width, diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp index b297c869..15fd8bfb 100644 --- a/kernel/src/kernel.cpp +++ b/kernel/src/kernel.cpp @@ -123,7 +123,6 @@ extern "C" [[noreturn]] void kernel_main(unsigned long addr, unsigned long magic } /** - * @todo Test suite of common functions & other statics (paths) * @todo Thread storage (when clib) - * @todo Once kernel done, turn into mono repo and seperate components + * @todo Once kernel done, turn into mono repo and separate components */ \ No newline at end of file diff --git a/kernel/src/net/ipv4.cpp b/kernel/src/net/ipv4.cpp index 7e0e0ee4..a8e4054b 100644 --- a/kernel/src/net/ipv4.cpp +++ b/kernel/src/net/ipv4.cpp @@ -41,10 +41,10 @@ MediaAccessControlAddress IPV4AddressResolver::resolve(InternetProtocolAddress a /** * @brief Stores an IP address to MAC address mapping. (Default, does nothing, override for use) * - * @param internetProtocolAddress The IP address. - * @param mediaAccessControlAddress The MAC address. + * @param internet_protocol_address The IP address. + * @param media_access_control_address The MAC address. */ -void IPV4AddressResolver::store(InternetProtocolAddress, drivers::ethernet::MediaAccessControlAddress) { +void IPV4AddressResolver::store(InternetProtocolAddress internet_protocol_address, MediaAccessControlAddress media_access_control_address) { } @@ -271,7 +271,7 @@ uint16_t InternetProtocolHandler::checksum(const uint16_t* data, uint32_t length /** * @brief Registers an IP address resolver. * - * @param resolver The resolver to register. + * @param ipv4_resolver The resolver to register. */ void InternetProtocolHandler::register_ipv_4_address_resolver(IPV4AddressResolver* ipv4_resolver) { diff --git a/kernel/src/runtime/kasan.cpp b/kernel/src/runtime/kasan.cpp index 02cb7af2..4e91bfb1 100644 --- a/kernel/src/runtime/kasan.cpp +++ b/kernel/src/runtime/kasan.cpp @@ -28,6 +28,33 @@ void KASanHandler::handle(bool write, uintptr_t address, size_t size, void* rip) ASSERT(false, "KASAN ERROR: %s of size %zu at address 0x%lx from RIP 0x%p", write ? "WRITE" : "READ", size, address, rip); } +/** + * @brief Initializes the KASan handler by setting up the shadow memory + */ +void KASanHandler::initialize() { + +} + +/** + * @brief Marks a region of stack memory as poisoned (inaccessible) + * + * @param address The starting address of the region + * @param size The size of the region in bytes + */ +void KASanHandler::poison_stack(uintptr_t address, size_t size) { + +} + +/** + * @brief Marks a region of stack memory as unpoisoned (accessible) + * + * @param address The starting address of the region + * @param size The size of the region in bytes + */ +void KASanHandler::unpoison_stack(uintptr_t address, size_t size) { + +} + /** * @brief Triggered when a memory load access violation of 1 byte is detected * @@ -159,8 +186,8 @@ extern "C" void __asan_alloca_poison(uintptr_t address, size_t size) { /** * @brief Unpoisons a region of stack memory allocated with alloca * - * @param address The starting address of the allocated memory - * @param size The size of the allocated memory in bytes + * @param stack_top The top address of the allocated memory + * @param stack_bottom The bottom address of the allocated memory */ extern "C" void __asan_alloca_unpoison(void* stack_top, void* stack_bottom) { //TODO: Implement stack unpoisoning diff --git a/kernel/src/tests/common.cpp b/kernel/src/tests/common.cpp index 81c04acb..04b1d20d 100644 --- a/kernel/src/tests/common.cpp +++ b/kernel/src/tests/common.cpp @@ -453,6 +453,9 @@ void register_map_tests() { }); } +/** + * @brief Registers all rectangle tests + */ void register_rectangle_tests() { MAXOS_CONDITIONAL_TEST(Rectangle_DefaultConstructor, TestType::COMMON) @@ -578,6 +581,9 @@ void register_rectangle_tests() { } +/** + * @brief Registers all string tests + */ void register_string_tests() { @@ -697,6 +703,9 @@ void register_string_tests() { } +/** + * @brief Registers all time tests + */ void register_time_tests() { @@ -743,6 +752,9 @@ void register_time_tests() { } +/** + * @brief Registers all vector tests + */ void register_vector_tests() { MAXOS_CONDITIONAL_TEST(Vector_Default_Construct_Empty, TestType::COMMON) diff --git a/kernel/src/tests/test.cpp b/kernel/src/tests/test.cpp index 61dacaa3..02a659c1 100644 --- a/kernel/src/tests/test.cpp +++ b/kernel/src/tests/test.cpp @@ -12,6 +12,12 @@ using namespace MaxOS; using namespace MaxOS::tests; +/** + * @brief Constructs a Test with a name and type, and registers it with the TestRunner + * + * @param name The name of the test + * @param type The type of the test + */ Test::Test(string const& name, TestType type) : m_name(name), m_type(type) @@ -74,7 +80,13 @@ TestType Test::type() const { Test::~Test() = default; - +/** + * @brief Constructs a ConditionalTest with a name, type, and condition function + * + * @param name The name of the test + * @param type The type of the test + * @param condition The condition function to evaluate + */ ConditionalTest::ConditionalTest(string const& name, TestType type, bool (* condition)()) : Test(name, type), m_condition(condition) From f9fd24023ad1a0c635d1057acab1f08be3ac8a74 Mon Sep 17 00:00:00 2001 From: Max Tyson <98maxt98@gmail.com> Date: Mon, 24 Nov 2025 16:11:30 +1300 Subject: [PATCH 11/12] Fix Workflow --- .github/workflows/max-os.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/max-os.yml b/.github/workflows/max-os.yml index 5a3e02d4..56c29dad 100644 --- a/.github/workflows/max-os.yml +++ b/.github/workflows/max-os.yml @@ -67,6 +67,9 @@ jobs: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 + - name: Install epstopdf + run: sudo apt-get update && sudo apt-get install -y texlive-font-utils + - name: Generate Docs run: | cd toolchain From 1a4add87ad50874c049ca4f363fdea17062ff311 Mon Sep 17 00:00:00 2001 From: Max Tyson <98maxt98@gmail.com> Date: Mon, 24 Nov 2025 16:13:41 +1300 Subject: [PATCH 12/12] Fix Workflow - Caches --- .github/workflows/max-os.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/max-os.yml b/.github/workflows/max-os.yml index 56c29dad..f920a899 100644 --- a/.github/workflows/max-os.yml +++ b/.github/workflows/max-os.yml @@ -44,6 +44,7 @@ jobs: run: | cd toolchain/pre_process ./version.sh --force + ./symbols.sh pre ../../kernel/include/common/symbols.h cd ../../ mkdir -p cmake-release cd cmake-release