mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-02 22:24:26 +00:00
Prekernel: Add support for assertion printing
This is done by using a FixedStringBuffer as the foundation to perform string formatting, which ensures that we avoid memory allocations in the prekernel stage.
This commit is contained in:
parent
00c9a57345
commit
f6e01aae9a
|
@ -12,7 +12,7 @@
|
|||
#include <AK/TypedTransfer.h>
|
||||
#include <AK/Userspace.h>
|
||||
|
||||
#ifdef KERNEL
|
||||
#if defined(KERNEL) && !defined(PREKERNEL)
|
||||
# include <Kernel/Arch/SafeMem.h>
|
||||
# include <Kernel/Arch/SmapDisabler.h>
|
||||
# include <Kernel/Memory/MemorySections.h>
|
||||
|
@ -64,7 +64,7 @@ public:
|
|||
m_storage[index] = '\0';
|
||||
}
|
||||
|
||||
#ifdef KERNEL
|
||||
#if defined(KERNEL) && !defined(PREKERNEL)
|
||||
ErrorOr<void> copy_characters_from_user(Userspace<char const*> user_str, size_t user_str_size)
|
||||
{
|
||||
if (user_str_size > Size)
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
# include <serenity.h>
|
||||
#endif
|
||||
|
||||
#ifdef KERNEL
|
||||
#if defined(PREKERNEL)
|
||||
#elif defined(KERNEL)
|
||||
# include <Kernel/Tasks/Process.h>
|
||||
# include <Kernel/Tasks/Thread.h>
|
||||
# include <Kernel/Time/TimeManagement.h>
|
||||
|
@ -1152,7 +1153,9 @@ void vdbg(StringView fmtstr, TypeErasedFormatParams& params, bool newline)
|
|||
StringBuilder builder;
|
||||
|
||||
if (is_rich_debug_enabled) {
|
||||
#ifdef KERNEL
|
||||
#if defined(PREKERNEL)
|
||||
;
|
||||
#elif defined(KERNEL)
|
||||
if (Kernel::Processor::is_initialized() && TimeManagement::is_initialized()) {
|
||||
auto time = TimeManagement::the().monotonic_time(TimePrecision::Coarse);
|
||||
if (Kernel::Thread::current()) {
|
||||
|
@ -1195,7 +1198,7 @@ void vdbg(StringView fmtstr, TypeErasedFormatParams& params, bool newline)
|
|||
auto const string = builder.string_view();
|
||||
|
||||
#ifdef AK_OS_SERENITY
|
||||
# ifdef KERNEL
|
||||
# if defined(KERNEL) && !defined(PREKERNEL)
|
||||
if (!Kernel::Processor::is_initialized()) {
|
||||
kernelearlyputstr(string.characters_without_null_termination(), string.length());
|
||||
return;
|
||||
|
@ -1205,7 +1208,7 @@ void vdbg(StringView fmtstr, TypeErasedFormatParams& params, bool newline)
|
|||
dbgputstr(string.characters_without_null_termination(), string.length());
|
||||
}
|
||||
|
||||
#ifdef KERNEL
|
||||
#if defined(KERNEL) && !defined(PREKERNEL)
|
||||
void vdmesgln(StringView fmtstr, TypeErasedFormatParams& params)
|
||||
{
|
||||
StringBuilder builder;
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
#include <AK/StringView.h>
|
||||
#include <AK/Vector.h>
|
||||
|
||||
#ifdef KERNEL
|
||||
#if defined(PREKERNEL)
|
||||
# include <Kernel/Library/MiniStdLib.h>
|
||||
#elif defined(KERNEL)
|
||||
# include <Kernel/Library/StdLib.h>
|
||||
#else
|
||||
# include <AK/ByteString.h>
|
||||
|
|
|
@ -5,10 +5,13 @@
|
|||
*/
|
||||
|
||||
#include <Kernel/Arch/DebugOutput.h>
|
||||
#include <Kernel/Arch/Processor.h>
|
||||
#include <Kernel/Arch/x86_64/BochsDebugOutput.h>
|
||||
#include <Kernel/Arch/x86_64/IO.h>
|
||||
|
||||
#if !defined(PREKERNEL)
|
||||
# include <Kernel/Arch/Processor.h>
|
||||
#endif
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
static constexpr u16 serial_com1_io_port = 0x3F8;
|
||||
|
@ -35,8 +38,13 @@ void debug_output(char ch)
|
|||
serial_ready = true;
|
||||
}
|
||||
|
||||
while ((IO::in8(serial_com1_io_port + 5) & 0x20) == 0)
|
||||
while ((IO::in8(serial_com1_io_port + 5) & 0x20) == 0) {
|
||||
#if !defined(PREKERNEL)
|
||||
Processor::wait_check();
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ch == '\n' && !was_cr)
|
||||
IO::out8(serial_com1_io_port, '\r');
|
||||
|
|
14
Kernel/Prekernel/Assertions.cpp
Normal file
14
Kernel/Prekernel/Assertions.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Prekernel/DebugOutput.h>
|
||||
|
||||
void __assertion_failed(char const* msg, char const* file, unsigned line, char const* func)
|
||||
{
|
||||
write_debug_output("ASSERTION FAILED: {}\n", msg);
|
||||
write_debug_output("{}:{} in {}\n", file, line, func);
|
||||
halt();
|
||||
}
|
|
@ -1,14 +1,26 @@
|
|||
set(SOURCES
|
||||
../../AK/StringBuilder.cpp
|
||||
../../AK/StringUtils.cpp
|
||||
../../AK/StringView.cpp
|
||||
../../AK/Format.cpp
|
||||
UBSanitizer.cpp
|
||||
../Library/MiniStdLib.cpp
|
||||
Assertions.cpp
|
||||
boot.S
|
||||
multiboot.S
|
||||
init.cpp
|
||||
DebugOutput.cpp
|
||||
kmalloc.cpp
|
||||
Runtime.cpp
|
||||
../../Userland/Libraries/LibELF/Relocation.cpp
|
||||
)
|
||||
|
||||
if ("${SERENITY_ARCH}" STREQUAL "x86_64")
|
||||
set(SOURCES
|
||||
${SOURCES}
|
||||
../Arch/x86_64/DebugOutput.cpp)
|
||||
endif()
|
||||
|
||||
if ("${SERENITY_ARCH}" STREQUAL "x86_64")
|
||||
set(PREKERNEL_TARGET kernel_x86-64)
|
||||
elseif("${SERENITY_ARCH}" STREQUAL "aarch64")
|
||||
|
@ -23,6 +35,8 @@ set_property(TARGET KernelObject PROPERTY
|
|||
IMPORTED_OBJECTS ${CMAKE_CURRENT_BINARY_DIR}/../Kernel.o
|
||||
)
|
||||
|
||||
add_compile_definitions(PREKERNEL)
|
||||
|
||||
add_executable(${PREKERNEL_TARGET} ${SOURCES} $<TARGET_OBJECTS:KernelObject>)
|
||||
add_dependencies(${PREKERNEL_TARGET} Kernel)
|
||||
add_dependencies(${PREKERNEL_TARGET} install_libc_headers)
|
||||
|
|
32
Kernel/Prekernel/DebugOutput.cpp
Normal file
32
Kernel/Prekernel/DebugOutput.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Platform.h>
|
||||
#include <AK/kstdio.h>
|
||||
#include <Kernel/Arch/DebugOutput.h>
|
||||
#include <Kernel/Prekernel/DebugOutput.h>
|
||||
#if ARCH(X86_64)
|
||||
# include <Kernel/Arch/x86_64/BochsDebugOutput.h>
|
||||
#endif
|
||||
|
||||
void debug_write_string(StringView str)
|
||||
{
|
||||
if (str.is_null())
|
||||
return;
|
||||
for (u8 ch : str.bytes()) {
|
||||
Kernel::debug_output(ch);
|
||||
#if ARCH(X86_64)
|
||||
Kernel::bochs_debug_output(ch);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void dbgputstr(char const* characters, size_t length)
|
||||
{
|
||||
if (!characters)
|
||||
return;
|
||||
debug_write_string(StringView { characters, length });
|
||||
}
|
30
Kernel/Prekernel/DebugOutput.h
Normal file
30
Kernel/Prekernel/DebugOutput.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/CheckedFormatString.h>
|
||||
#include <AK/FixedStringBuffer.h>
|
||||
#include <AK/Format.h>
|
||||
#include <AK/kmalloc.h>
|
||||
#include <Kernel/Prekernel/Runtime.h>
|
||||
|
||||
void debug_write_string(StringView str);
|
||||
|
||||
template<typename... Parameters>
|
||||
void write_debug_output(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
|
||||
{
|
||||
AK::VariadicFormatParams<AK::AllowDebugOnlyFormatters::No, Parameters...> variadic_format_parameters { parameters... };
|
||||
auto message_buffer_or_error = FixedStringBuffer<128>::vformatted(fmtstr.view(), variadic_format_parameters);
|
||||
if (message_buffer_or_error.is_error()) {
|
||||
debug_write_string("PANIC: Failed to write message buffer:\n"sv);
|
||||
debug_write_string(fmtstr.view());
|
||||
halt();
|
||||
}
|
||||
|
||||
auto message_buffer = message_buffer_or_error.release_value();
|
||||
debug_write_string(message_buffer.representable_view());
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org>
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
* Copyright (c) 2021-2024, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -10,6 +10,7 @@
|
|||
#include <Kernel/Boot/Multiboot.h>
|
||||
#include <Kernel/Memory/PhysicalAddress.h>
|
||||
#include <Kernel/Memory/VirtualAddress.h>
|
||||
#include <Kernel/Prekernel/DebugOutput.h>
|
||||
#include <Kernel/Prekernel/Prekernel.h>
|
||||
#include <Kernel/Prekernel/Runtime.h>
|
||||
#include <LibELF/ELFABI.h>
|
||||
|
@ -54,11 +55,6 @@ void __stack_chk_fail()
|
|||
halt();
|
||||
}
|
||||
|
||||
void __assertion_failed(char const*, char const*, unsigned int, char const*)
|
||||
{
|
||||
halt();
|
||||
}
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
// boot.S expects these functions to exactly have the following signatures.
|
||||
|
@ -96,8 +92,7 @@ extern "C" [[noreturn]] void init()
|
|||
// We only consider the first specified multiboot module, and ignore
|
||||
// the rest of the modules.
|
||||
multiboot_module_entry_t* initrd_module = (multiboot_module_entry_t*)(FlatPtr)multiboot_info_ptr->mods_addr;
|
||||
if (initrd_module->start > initrd_module->end)
|
||||
halt();
|
||||
VERIFY(initrd_module->start < initrd_module->end);
|
||||
|
||||
initrd_module_start = initrd_module->start;
|
||||
initrd_module_end = initrd_module->end;
|
||||
|
@ -107,8 +102,7 @@ extern "C" [[noreturn]] void init()
|
|||
// copy the ELF header and program headers because we might end up overwriting them
|
||||
Elf_Ehdr kernel_elf_header = *(Elf_Ehdr*)kernel_image;
|
||||
Elf_Phdr kernel_program_headers[16];
|
||||
if (kernel_elf_header.e_phnum > array_size(kernel_program_headers))
|
||||
halt();
|
||||
VERIFY(kernel_elf_header.e_phnum < array_size(kernel_program_headers));
|
||||
__builtin_memcpy(kernel_program_headers, kernel_image + kernel_elf_header.e_phoff, sizeof(Elf_Phdr) * kernel_elf_header.e_phnum);
|
||||
|
||||
FlatPtr kernel_physical_base = (FlatPtr)0x200000;
|
||||
|
@ -136,10 +130,8 @@ extern "C" [[noreturn]] void init()
|
|||
continue;
|
||||
auto start = kernel_load_base + kernel_program_header.p_vaddr;
|
||||
auto end = start + kernel_program_header.p_memsz;
|
||||
if (start < (FlatPtr)end_of_prekernel_image)
|
||||
halt();
|
||||
if (kernel_physical_base + kernel_program_header.p_paddr < (FlatPtr)end_of_prekernel_image)
|
||||
halt();
|
||||
VERIFY(start > (FlatPtr)end_of_prekernel_image);
|
||||
VERIFY(kernel_physical_base + kernel_program_header.p_paddr > (FlatPtr)end_of_prekernel_image);
|
||||
if (end > kernel_load_end)
|
||||
kernel_load_end = end;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue