diff --git a/Kernel/Prekernel/Arch/aarch64/BootPPMParser.cpp b/Kernel/Prekernel/Arch/aarch64/BootPPMParser.cpp new file mode 100644 index 0000000000..6061e1c427 --- /dev/null +++ b/Kernel/Prekernel/Arch/aarch64/BootPPMParser.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2021, Marcin Undak + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "BootPPMParser.h" + +namespace Prekernel { + +BootPPMParser::BootPPMParser(u8 const* buffer, u32 buffer_size) +{ + m_cursor = reinterpret_cast(buffer); + m_buffer_end = m_cursor + buffer_size; +} + +bool BootPPMParser::parse() +{ + if (!check_position()) { + return false; + } + if (!parse_magic()) { + return false; + } + if (!parse_new_line()) { + return false; + } + if (!parse_comment()) { + return false; + } + if (!parse_integer(image.width)) { + return false; + } + if (!parse_integer(image.height)) { + return false; + } + u32 max_color_value; + if (!parse_integer(max_color_value) || max_color_value != 255) { + return false; + } + + image.pixel_data = reinterpret_cast(m_cursor); + + return true; +} + +bool BootPPMParser::check_position() const +{ + if (m_cursor >= m_buffer_end) { + return false; + } + return true; +} + +bool BootPPMParser::parse_magic() +{ + if (m_cursor[0] != 'P' || m_cursor[1] != '6') { + return false; + } + m_cursor += 2; + + return check_position(); +} + +bool BootPPMParser::parse_new_line() +{ + if (*m_cursor != '\n') { + return false; + } + ++m_cursor; + + return check_position(); +} + +bool BootPPMParser::parse_comment() +{ + if (*m_cursor == '#') { + // Skip to the next new line character + while (check_position() && *m_cursor != '\n') { + ++m_cursor; + } + ++m_cursor; + } + + return check_position(); +} + +bool BootPPMParser::parse_integer(u32& value) +{ + auto begin = m_cursor; + while (check_position() && *m_cursor != ' ' && *m_cursor != '\n') { + ++m_cursor; + } + auto end = m_cursor; + ++m_cursor; + + if (!check_position()) { + return false; + } + + value = 0; + u32 multiplier = 1; + while (--end >= begin) { + value += multiplier * (*end - '0'); + multiplier *= 10; + } + + return true; +} + +} diff --git a/Kernel/Prekernel/Arch/aarch64/BootPPMParser.h b/Kernel/Prekernel/Arch/aarch64/BootPPMParser.h new file mode 100644 index 0000000000..a311a50a7a --- /dev/null +++ b/Kernel/Prekernel/Arch/aarch64/BootPPMParser.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021, Marcin Undak + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Prekernel { + +// Quick parser for .ppm image format (raw PortablePixMap) +// This is much simpler version than userland implementation in PPMLoader.cpp +class BootPPMParser { +public: + struct { + u32 width = 0; + u32 height = 0; + u8 const* pixel_data = nullptr; + } image; + + BootPPMParser(u8 const* buffer, u32 buffer_size); + + bool parse(); + +private: + char const* m_cursor; + char const* m_buffer_end; + + bool check_position() const; + bool parse_magic(); + bool parse_new_line(); + bool parse_comment(); + bool parse_integer(u32& value); +}; + +} diff --git a/Kernel/Prekernel/CMakeLists.txt b/Kernel/Prekernel/CMakeLists.txt index bdedd59c9a..9fde4dcb59 100644 --- a/Kernel/Prekernel/CMakeLists.txt +++ b/Kernel/Prekernel/CMakeLists.txt @@ -6,6 +6,7 @@ if ("${SERENITY_ARCH}" STREQUAL "aarch64") set(SOURCES ${SOURCES} Arch/aarch64/Aarch64_asm_utils.S + Arch/aarch64/BootPPMParser.cpp Arch/aarch64/GPIO.cpp Arch/aarch64/Framebuffer.cpp Arch/aarch64/Mailbox.cpp