diff --git a/serial.txt b/serial.txt new file mode 100644 index 0000000..deea15e --- /dev/null +++ b/serial.txt @@ -0,0 +1,156 @@ +[=3h[=3h[=3hBdsDxe: loading Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Master,0x0) +BdsDxe: starting Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Master,0x0) + + +This is BadAppleOS and everything is fine! + +Key event: scancode=S(0x1B), down=true, repeat=false +Key event: scancode=E(0x24), down=true, repeat=false +Key event: scancode=D(0x23), down=true, repeat=false +Key event: scancode=D(0x23), down=false, repeat=false +Key event: scancode=S(0x1B), down=false, repeat=false +Key event: scancode=E(0x24), down=false, repeat=false +Key event: scancode=F(0x2B), down=true, repeat=false +Key event: scancode=O(0x44), down=true, repeat=false +Key event: scancode=I(0x43), down=true, repeat=false +Key event: scancode=O(0x44), down=false, repeat=false +Key event: scancode=I(0x43), down=false, repeat=false +Key event: scancode=N(0x31), down=true, repeat=false +Key event: scancode=F(0x2B), down=false, repeat=false +Key event: scancode=E(0x24), down=true, repeat=false +Key event: scancode=W(0x1D), down=true, repeat=false +Key event: scancode=N(0x31), down=false, repeat=false +Key event: scancode=W(0x1D), down=false, repeat=false +Key event: scancode=O(0x44), down=true, repeat=false +Key event: scancode=E(0x24), down=false, repeat=false +Key event: scancode=J(0x3B), down=true, repeat=false +Key event: scancode=F(0x2B), down=true, repeat=false +Key event: scancode=J(0x3B), down=false, repeat=false +Key event: scancode=O(0x44), down=false, repeat=false +Key event: scancode=N(0x31), down=true, repeat=false +Key event: scancode=F(0x2B), down=false, repeat=false +Key event: scancode=E(0x24), down=true, repeat=false +Key event: scancode=W(0x1D), down=true, repeat=false +Key event: scancode=R(0x2D), down=true, repeat=false +Key event: scancode=N(0x31), down=false, repeat=false +Key event: scancode=W(0x1D), down=false, repeat=false +Key event: scancode=O(0x44), down=true, repeat=false +Key event: scancode=I(0x43), down=true, repeat=false +Key event: scancode=J(0x3B), down=true, repeat=false +Key event: scancode=L(0x4B), down=true, repeat=false +Key event: scancode=K(0x42), down=true, repeat=false +Key event: scancode=R(0x2D), down=false, repeat=false +Key event: scancode=P(0x4D), down=true, repeat=false +Key event: scancode=E(0x24), down=false, repeat=false +Key event: scancode=K(0x42), down=false, repeat=false +Key event: scancode=I(0x43), down=false, repeat=false +Key event: scancode=L(0x4B), down=false, repeat=false +Key event: scancode=O(0x44), down=false, repeat=false +Key event: scancode=J(0x3B), down=false, repeat=false +Key event: scancode=G(0x34), down=true, repeat=false +Key event: scancode=P(0x4D), down=false, repeat=false +Key event: scancode=N(0x31), down=true, repeat=false +Key event: scancode=E(0x24), down=true, repeat=false +Key event: scancode=G(0x34), down=false, repeat=false +Key event: scancode=R(0x2D), down=true, repeat=false +Key event: scancode=T(0x2C), down=true, repeat=false +Key event: scancode=N(0x31), down=false, repeat=false +Key event: scancode=J(0x3B), down=true, repeat=false +Key event: scancode=O(0x44), down=true, repeat=false +Key event: scancode=T(0x2C), down=false, repeat=false +Key event: scancode=P(0x4D), down=true, repeat=false +Key event: scancode=J(0x3B), down=false, repeat=false +Key event: scancode=O(0x44), down=false, repeat=false +Key event: scancode=R(0x2D), down=false, repeat=false +Key event: scancode=P(0x4D), down=false, repeat=false +Key event: scancode=G(0x34), down=true, repeat=false +Key event: scancode=E(0x24), down=false, repeat=false +Key event: scancode=N(0x31), down=true, repeat=false +Key event: scancode=N(0x31), down=false, repeat=false +Key event: scancode=G(0x34), down=false, repeat=false +Key event: scancode=R(0x2D), down=true, repeat=false +Key event: scancode=I(0x43), down=true, repeat=false +Key event: scancode=O(0x44), down=true, repeat=false +Key event: scancode=E(0x24), down=true, repeat=false +Key event: scancode=J(0x3B), down=true, repeat=false +Key event: scancode=O(0x44), down=false, repeat=false +Key event: scancode=J(0x3B), down=false, repeat=false +Key event: scancode=I(0x43), down=false, repeat=false +Key event: scancode=E(0x24), down=false, repeat=false +Key event: scancode=R(0x2D), down=false, repeat=false +Key event: scancode=N(0x31), down=true, repeat=false +Key event: scancode=G(0x34), down=true, repeat=false +Key event: scancode=N(0x31), down=false, repeat=false +Key event: scancode=I(0x43), down=true, repeat=false +Key event: scancode=J(0x3B), down=true, repeat=false +Key event: scancode=O(0x44), down=true, repeat=false +Key event: scancode=G(0x34), down=false, repeat=false +Key event: scancode=E(0x24), down=true, repeat=false +Key event: scancode=O(0x44), down=false, repeat=false +Key event: scancode=R(0x2D), down=true, repeat=false +Key event: scancode=I(0x43), down=false, repeat=false +Key event: scancode=J(0x3B), down=false, repeat=false +Key event: scancode=N(0x31), down=true, repeat=false +Key event: scancode=R(0x2D), down=false, repeat=false +Key event: scancode=E(0x24), down=false, repeat=false +Key event: scancode=G(0x34), down=true, repeat=false +Key event: scancode=N(0x31), down=false, repeat=false +Key event: scancode=J(0x3B), down=true, repeat=false +Key event: scancode=O(0x44), down=true, repeat=false +Key event: scancode=I(0x43), down=true, repeat=false +Key event: scancode=U(0x3C), down=true, repeat=false +Key event: scancode=U(0x3C), down=false, repeat=false +Key event: scancode=I(0x43), down=false, repeat=false +Key event: scancode=O(0x44), down=false, repeat=false +Key event: scancode=G(0x34), down=false, repeat=false +Key event: scancode=R(0x2D), down=true, repeat=false +Key event: scancode=J(0x3B), down=false, repeat=false +Key event: scancode=E(0x24), down=true, repeat=false +Key event: scancode=N(0x31), down=true, repeat=false +Key event: scancode=E(0x24), down=false, repeat=false +Key event: scancode=R(0x2D), down=false, repeat=false +Key event: scancode=N(0x31), down=false, repeat=false +Key event: scancode=G(0x34), down=true, repeat=false +Key event: scancode=I(0x43), down=true, repeat=false +Key event: scancode=J(0x3B), down=true, repeat=false +Key event: scancode=K(0x42), down=true, repeat=false +Key event: scancode=K(0x42), down=false, repeat=false +Key event: scancode=J(0x3B), down=false, repeat=false +Key event: scancode=I(0x43), down=false, repeat=false +Key event: scancode=E(0x24), down=true, repeat=false +Key event: scancode=N(0x31), down=true, repeat=false +Key event: scancode=G(0x34), down=false, repeat=false +Key event: scancode=T(0x2C), down=true, repeat=false +Key event: scancode=T(0x2C), down=false, repeat=false +Key event: scancode=E(0x24), down=false, repeat=false +Key event: scancode=N(0x31), down=false, repeat=false +Key event: scancode=G(0x34), down=true, repeat=false +Key event: scancode=K(0x42), down=true, repeat=false +Key event: scancode=J(0x3B), down=true, repeat=false +Key event: scancode=J(0x3B), down=false, repeat=false +Key event: scancode=K(0x42), down=false, repeat=false +Key event: scancode=N(0x31), down=true, repeat=false +Key event: scancode=E(0x24), down=true, repeat=false +Key event: scancode=G(0x34), down=false, repeat=false +Key event: scancode=R(0x2D), down=true, repeat=false +Key event: scancode=K(0x42), down=true, repeat=false +Key event: scancode=N(0x31), down=false, repeat=false +Key event: scancode=J(0x3B), down=true, repeat=false +Key event: scancode=E(0x24), down=false, repeat=false +Key event: scancode=R(0x2D), down=false, repeat=false +Key event: scancode=G(0x34), down=true, repeat=false +Key event: scancode=J(0x3B), down=false, repeat=false +Key event: scancode=N(0x31), down=true, repeat=false +Key event: scancode=K(0x42), down=false, repeat=false +Key event: scancode=E(0x24), down=true, repeat=false +Key event: scancode=G(0x34), down=false, repeat=false +Key event: scancode=R(0x2D), down=true, repeat=false +Key event: scancode=K(0x42), down=true, repeat=false +Key event: scancode=J(0x3B), down=true, repeat=false +Key event: scancode=N(0x31), down=false, repeat=false +Key event: scancode=R(0x2D), down=false, repeat=false +Key event: scancode=E(0x24), down=false, repeat=false +Key event: scancode=G(0x34), down=true, repeat=false +Key event: scancode=N(0x31), down=true, repeat=false +Key event: scancode=K(0x42), down=false, repeat=false +Key event: scancode=J(0x3B), down=false, repeat=false \ No newline at end of file diff --git a/targets/_any/include/os/tools/printf_helper.hpp b/targets/_any/include/os/tools/printf_helper.hpp new file mode 100644 index 0000000..b262cf4 --- /dev/null +++ b/targets/_any/include/os/tools/printf_helper.hpp @@ -0,0 +1,227 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_OS_TOOLS_PRINTF_HELPER_HPP_INCLUDED) +#define BAD_APPLE_OS_OS_TOOLS_PRINTF_HELPER_HPP_INCLUDED + +#include +#include +#include +#include +#include + +#if !defined(BAOS_IPRINTF_FUNC_ATTRIBUTE) +#define BAOS_IPRINTF_FUNC_ATTRIBUTE +#endif + +namespace baos +{ +template +class PrintFHelper +{ +private: + TPrinter mPrinter; +public: + BAOS_IPRINTF_FUNC_ATTRIBUTE + explicit PrintFHelper(TPrinter printer = {}) noexcept : mPrinter(std::move(printer)) {} + + BAOS_IPRINTF_FUNC_ATTRIBUTE + int printInt(long value) + { + if (value == 0) + { + mPrinter.putchar('0'); + return 1; + } + if (value < 0) + { + mPrinter.putchar('-'); + return printInt(-value) + 1; + } + + char digits[19]; // 9223372036854775807 has 10 digits + char* pos = &digits[0]; + + while (value > 0) + { + *pos = static_cast('0' + (value % 10)); + value /= 10; + ++pos; + } + for (char* chr = pos - 1; chr >= digits; --chr) + { + mPrinter.putchar(*chr); + } + return pos - digits; + } + + BAOS_IPRINTF_FUNC_ATTRIBUTE + int printUInt(uint64_t value) + { + if (value == 0) + { + mPrinter.putchar('0'); + return 1; + } + + char digits[20]; // 18,446,744,073,709,551,615 has 20 digits + char* pos = &digits[0]; + + while (value > 0) + { + *pos = static_cast('0' + (value % 10)); + value /= 10; + ++pos; + } + for (char* chr = pos - 1; chr >= digits; --chr) + { + mPrinter.putchar(*chr); + } + return pos - digits; + } + + BAOS_IPRINTF_FUNC_ATTRIBUTE + int printHexInt(uint64_t value) + { + if (value == 0) + { + mPrinter.putchar('0'); + return 1; + } + + char digits[16]; // FFFFFFFFFFFFFFFF has 16 digits + char* pos = &digits[0]; + + while (value > 0) + { + const uint64_t digit = (value % 16); + if (digit < 10) + { + *pos = static_cast('0' + digit); + } + else + { + *pos = static_cast('A' + digit - 10); + } + value /= 16; + ++pos; + } + for (char* chr = pos - 1; chr >= digits; --chr) + { + mPrinter.putchar(*chr); + } + return pos - digits; + } + + BAOS_IPRINTF_FUNC_ATTRIBUTE + int printPointer(void* ptr) + { + return printHexInt(reinterpret_cast(ptr)); + } + + BAOS_IPRINTF_FUNC_ATTRIBUTE + int printString(const char* str) + { + int len = 0; + while (*str) + { + mPrinter.putchar(*str); + ++str; + ++len; + } + return static_cast(len); + } + + BAOS_IPRINTF_FUNC_ATTRIBUTE + int printByteSize(size_t bytes) + { + const char* suffixes[] = { + "B", "KiB", "MiB", "GiB", "TiB" + }; + int suffixIdx = 0; + for (; suffixIdx < sizeof(suffixes) / sizeof(suffixes[0]); ++suffixIdx) + { + if (bytes < 1024) { + break; + } + bytes /= 1024; + } + return printUInt(bytes) + printString(suffixes[suffixIdx]); + } + + BAOS_IPRINTF_FUNC_ATTRIBUTE + int vprintf(const char* format, va_list vlist) noexcept + { + int result = 0; + const char* pos = format; + while (*pos != '\0') + { + if (*pos == '%') + { + ++pos; + switch (*pos) + { + case '%': + mPrinter.putchar('%'); + ++result; + break; + case '\0': + // TODO: invalid format string, do something + assert(!"Invalid format string, ends with %."); + return -1; + case 'b': + result += printByteSize(va_arg(vlist, size_t)); + break; + case 'c': + { + const char chr = static_cast(va_arg(vlist, int)); + mPrinter.putchar(chr); + ++result; + break; + } + case 's': + result += printString(va_arg(vlist, const char*)); + break; + case 'd': + result += printInt(va_arg(vlist, int)); + break; + case 'p': + result += printPointer(va_arg(vlist, void*)); + break; + case 'X': + result += printHexInt(va_arg(vlist, unsigned)); + break; + case 'l': + ++pos; + switch (*pos) + { + case '\0': + assert(!"Invalid format string, ends with %l."); + return -1; + case 'd': + result += printInt(va_arg(vlist, long)); + break; + case 'X': + result += printHexInt(va_arg(vlist, unsigned long)); + break; + default: + return -1; + } + break; + default: + assert(!"Invalid format string, unknown format identifier."); + return -1; + } + } else + { + mPrinter.putchar(*pos); + } + ++pos; + } + ++result; + return result; + } +}; +} + +#endif // !defined(BAD_APPLE_OS_OS_TOOLS_PRINTF_HELPER_HPP_INCLUDED) diff --git a/targets/_any/include/stdio.h b/targets/_any/include/stdio.h index fe7564b..e9c0749 100644 --- a/targets/_any/include/stdio.h +++ b/targets/_any/include/stdio.h @@ -5,6 +5,7 @@ #define BAD_APPLE_OS_STDIO_H_INCLUDED #include +#include #include "./detail/common.h" BA_EXTERN_C_BEGIN @@ -13,6 +14,8 @@ int putchar(int chr) BA_CXX_NOEXCEPT; int puts(const char* str) BA_CXX_NOEXCEPT; int printf(const char* format, ...) BA_CXX_NOEXCEPT __attribute__((format(printf, 1, 2))); int vprintf(const char* format, va_list vlist) BA_CXX_NOEXCEPT; +int snprintf(char* buffer, size_t bufferSize, const char* format, ...) BA_CXX_NOEXCEPT __attribute__((format(printf, 3, 4))); +int vsnprintf(char* buffer, size_t bufferSize, const char* format, va_list vlist) BA_CXX_NOEXCEPT; BA_EXTERN_C_END diff --git a/targets/_any/src/cstdlib/stdio.cpp b/targets/_any/src/cstdlib/stdio.cpp index 109d101..360dd2b 100644 --- a/targets/_any/src/cstdlib/stdio.cpp +++ b/targets/_any/src/cstdlib/stdio.cpp @@ -1,135 +1,43 @@ #include +#include #include #include +#include #include #include "os/serial.hpp" #include "os/tty.hpp" +#include "os/tools/printf_helper.hpp" + +namespace +{ +struct RegularPrinter +{ + void putchar(int chr) noexcept // NOLINT + { + ::putchar(chr); + } +}; + +struct BufferPrinter +{ + char* pos = nullptr; + char* end = nullptr; + + void putchar(int chr) noexcept // NOLINT + { + if (pos != end) + { + *pos = static_cast(chr); + ++pos; + } + } +}; +} extern "C" { -namespace -{ - -int printInt(long value) -{ - if (value == 0) - { - putchar('0'); - return 1; - } - if (value < 0) - { - putchar('-'); - return printInt(-value) + 1; - } - - char digits[19]; // 9223372036854775807 has 10 digits - char* pos = &digits[0]; - - while (value > 0) - { - *pos = static_cast('0' + (value % 10)); - value /= 10; - ++pos; - } - for (char* chr = pos - 1; chr >= digits; --chr) - { - putchar(*chr); - } - return pos - digits; -} - -int printUInt(uint64_t value) -{ - if (value == 0) - { - putchar('0'); - return 1; - } - - char digits[20]; // 18,446,744,073,709,551,615 has 20 digits - char* pos = &digits[0]; - - while (value > 0) - { - *pos = static_cast('0' + (value % 10)); - value /= 10; - ++pos; - } - for (char* chr = pos - 1; chr >= digits; --chr) - { - putchar(*chr); - } - return pos - digits; -} - -int printHexInt(uint64_t value) -{ - if (value == 0) - { - putchar('0'); - return 1; - } - - char digits[16]; // FFFFFFFFFFFFFFFF has 16 digits - char* pos = &digits[0]; - - while (value > 0) - { - const uint64_t digit = (value % 16); - if (digit < 10) - { - *pos = static_cast('0' + digit); - } - else - { - *pos = static_cast('A' + digit - 10); - } - value /= 16; - ++pos; - } - for (char* chr = pos - 1; chr >= digits; --chr) - { - putchar(*chr); - } - return pos - digits; -} - -int printPointer(void* ptr) -{ - return printHexInt(reinterpret_cast(ptr)); -} - -int printString(const char* str) -{ - const size_t len = std::strlen(str); - - for (size_t idx = 0; idx < len; ++idx) - { - putchar(str[idx]); - } - return static_cast(len); -} - -int printByteSize(size_t bytes) -{ - const char* suffixes[] = { - "B", "KiB", "MiB", "GiB", "TiB" - }; - int suffixIdx = 0; - for (; suffixIdx < sizeof(suffixes) / sizeof(suffixes[0]); ++suffixIdx) - { - if (bytes < 1024) { - break; - } - bytes /= 1024; - } - return printUInt(bytes) + printString(suffixes[suffixIdx]); -} -} - int putchar(int chr) noexcept { tty::putChar(static_cast(chr)); @@ -167,74 +75,30 @@ int printf(const char* format, ...) noexcept int vprintf(const char* format, va_list vlist) BA_CXX_NOEXCEPT { - int result = 0; - const char* pos = format; - while (*pos != '\0') - { - if (*pos == '%') - { - ++pos; - switch (*pos) - { - case '%': - putchar('%'); - ++result; - break; - case '\0': - // TODO: invalid format string, do something - assert(!"Invalid format string, ends with %."); - return -1; - case 'b': - result += printByteSize(va_arg(vlist, size_t)); - break; - case 'c': - { - const char chr = static_cast(va_arg(vlist, int)); - putchar(chr); - ++result; - break; - } - case 's': - result += printString(va_arg(vlist, const char*)); - break; - case 'd': - result += printInt(va_arg(vlist, int)); - break; - case 'p': - result += printPointer(va_arg(vlist, void*)); - break; - case 'X': - result += printHexInt(va_arg(vlist, unsigned)); - break; - case 'l': - ++pos; - switch (*pos) - { - case '\0': - assert(!"Invalid format string, ends with %l."); - return -1; - case 'd': - result += printInt(va_arg(vlist, long)); - break; - case 'X': - result += printHexInt(va_arg(vlist, unsigned long)); - break; - default: - return -1; - } - break; - default: - assert(!"Invalid format string, unknown format identifier."); - return -1; - } - } else - { - putchar(*pos); - } - ++pos; - } - ++result; + return baos::PrintFHelper().vprintf(format, vlist); +} + +int snprintf(char* buffer, size_t bufferSize, const char* format, ...) noexcept +{ + va_list parameters; + va_start(parameters, format); + const int result = vsnprintf(buffer, bufferSize, format, parameters); + va_end(parameters); return result; } + +int vsnprintf(char* buffer, size_t bufferSize, const char* format, va_list vlist) noexcept +{ + BufferPrinter printer{ + .pos = buffer, + .end = bufferSize > 0 ? buffer + bufferSize - 1 : buffer + }; + const int length = baos::PrintFHelper(printer).vprintf(format, vlist); + if (bufferSize > 0) + { + buffer[std::min(static_cast(bufferSize - 1), length)] = '\0'; + } + return length; +} } // extern "C" diff --git a/targets/_any/src/os/interrupt.cpp b/targets/_any/src/os/interrupt.cpp index 1c7c6a2..ebc8dad 100644 --- a/targets/_any/src/os/interrupt.cpp +++ b/targets/_any/src/os/interrupt.cpp @@ -1,17 +1,49 @@ +#define BAOS_IPRINTF_FUNC_ATTRIBUTE __attribute__((no_caller_saved_registers)) +#include "os/tools/printf_helper.hpp" + #include "os/interrupt.hpp" + +#include #include "os/serial.hpp" -#include "os/tty.hpp" namespace baos { +namespace +{ +struct InterruptPrinter +{ + __attribute__((no_caller_saved_registers)) + void putchar(char chr) noexcept // NOLINT + { + if (chr == '\n') { + writePortByte(PORT_COM1, '\r'); + } + writePortByte(PORT_COM1, static_cast(chr)); + } +}; + +__attribute__((no_caller_saved_registers, format(printf, 1, 2))) +void iprintf(const char* format, ...) noexcept +{ + std::va_list parameters; + va_start(parameters, format); + PrintFHelper().vprintf(format, parameters); + va_end(parameters); +} +} + extern "C" [[noreturn]] void __halt(); __attribute__((no_caller_saved_registers)) void handleException(const char* name, InterruptFrame* interruptFrame) noexcept { - tty::write(name); - serialWriteString(PORT_COM1, name); + iprintf("Exception occurred: %s\n", name); + iprintf("IP: 0x%lX\n", interruptFrame->ip); + iprintf("CS: 0x%lX\n", interruptFrame->cs); + iprintf("FLAGS: 0x%lX\n", interruptFrame->flags); + iprintf("SP: 0x%lX\n", interruptFrame->sp); + iprintf("SS: 0x%lX\n", interruptFrame->ss); __halt(); } diff --git a/targets/x86_64/src/kernel/startup.cpp b/targets/x86_64/src/kernel/startup.cpp index dc57f6a..4219e56 100644 --- a/targets/x86_64/src/kernel/startup.cpp +++ b/targets/x86_64/src/kernel/startup.cpp @@ -240,6 +240,10 @@ void kernel_main() event.down ? "true" : "false", event.repeat ? "true" : "false" ); + if (event.down && event.scancode == ps2::Scancode::ESCAPE) + { + int x = 1 / 0; + } } main();