mirror of
https://github.com/SerenityOS/serenity
synced 2026-05-13 10:27:05 +02:00
EFIPrekernel: Add basic skeleton
This commit is contained in:
committed by
Tim Schumacher
parent
9e306b858a
commit
faeb9ff521
@@ -908,7 +908,9 @@ endif()
|
||||
serenity_install_headers(Kernel)
|
||||
serenity_install_sources(Kernel)
|
||||
|
||||
# Only x86 needs a Prekernel
|
||||
# Only x86 uses the Multiboot Prekernel
|
||||
if ("${SERENITY_ARCH}" STREQUAL "x86_64")
|
||||
add_subdirectory(Prekernel)
|
||||
endif()
|
||||
|
||||
add_subdirectory(EFIPrekernel)
|
||||
|
||||
69
Kernel/EFIPrekernel/CMakeLists.txt
Normal file
69
Kernel/EFIPrekernel/CMakeLists.txt
Normal file
@@ -0,0 +1,69 @@
|
||||
set(PREKERNEL_KERNEL_IMAGE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../Kernel_shared_object)
|
||||
configure_file(KernelImage.S.in KernelImage.S @ONLY)
|
||||
|
||||
set(SOURCES
|
||||
init.cpp
|
||||
|
||||
DebugOutput.cpp
|
||||
Panic.cpp
|
||||
Runtime.cpp
|
||||
kmalloc.cpp
|
||||
|
||||
KernelImage.S
|
||||
|
||||
../Firmware/EFI/EFI.cpp
|
||||
../Library/MiniStdLib.cpp
|
||||
../Prekernel/UBSanitizer.cpp
|
||||
|
||||
../../AK/Format.cpp
|
||||
../../AK/StringBuilder.cpp
|
||||
../../AK/StringUtils.cpp
|
||||
../../AK/StringView.cpp
|
||||
)
|
||||
|
||||
set_source_files_properties(KernelImage.S PROPERTIES OBJECT_DEPENDS ${PREKERNEL_KERNEL_IMAGE_PATH})
|
||||
|
||||
add_compile_definitions(PREKERNEL)
|
||||
|
||||
add_executable(EFIPrekernel ${SOURCES})
|
||||
|
||||
add_dependencies(EFIPrekernel Kernel)
|
||||
add_dependencies(EFIPrekernel install_libc_headers)
|
||||
|
||||
target_compile_options(EFIPrekernel PRIVATE -fno-threadsafe-statics)
|
||||
target_link_options(EFIPrekernel PRIVATE LINKER:-T ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld LINKER:--no-dynamic-linker -nostdlib)
|
||||
set_target_properties(EFIPrekernel PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
target_link_libraries(EFIPrekernel PRIVATE gcc)
|
||||
|
||||
# Prevent naively implemented string functions (like strlen) from being "optimized" into a call to themselves.
|
||||
set_source_files_properties(../Library/MiniStdLib.cpp
|
||||
PROPERTIES COMPILE_FLAGS "-fno-tree-loop-distribution -fno-tree-loop-distribute-patterns")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang$")
|
||||
target_link_libraries(EFIPrekernel PRIVATE clang_rt.builtins)
|
||||
endif()
|
||||
|
||||
# The PrekernelPEImageGenerator doesn't support RELR relocations.
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang$")
|
||||
target_link_options(EFIPrekernel PRIVATE LINKER:-z,nopack-relative-relocs LINKER:--pack-dyn-relocs=none)
|
||||
elseif("${SERENITY_ARCH}" STREQUAL "x86_64")
|
||||
target_link_options(EFIPrekernel PRIVATE LINKER:-z,nopack-relative-relocs)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Kernel.efi
|
||||
COMMAND $<TARGET_FILE:Lagom::PrekernelPEImageGenerator> ${CMAKE_CURRENT_BINARY_DIR}/EFIPrekernel ${CMAKE_CURRENT_BINARY_DIR}/Kernel.efi
|
||||
VERBATIM
|
||||
DEPENDS EFIPrekernel Lagom::PrekernelPEImageGenerator
|
||||
)
|
||||
|
||||
add_custom_target(generate_kernel_efi_image ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Kernel.efi)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Kernel.efi DESTINATION boot)
|
||||
|
||||
# Remove options which the Prekernel environment doesn't support.
|
||||
get_target_property(EFI_PREKERNEL_COMPILE_OPTIONS EFIPrekernel COMPILE_OPTIONS)
|
||||
list(REMOVE_ITEM EFI_PREKERNEL_COMPILE_OPTIONS "-fsanitize-coverage=trace-pc")
|
||||
list(REMOVE_ITEM EFI_PREKERNEL_COMPILE_OPTIONS "-fsanitize=kernel-address")
|
||||
set_target_properties(EFIPrekernel PROPERTIES COMPILE_OPTIONS "${EFI_PREKERNEL_COMPILE_OPTIONS}")
|
||||
18
Kernel/EFIPrekernel/Error.h
Normal file
18
Kernel/EFIPrekernel/Error.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Sönke Holz <sholz8530@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Error.h>
|
||||
|
||||
#include <Kernel/Firmware/EFI/EFI.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
template<typename T>
|
||||
using EFIErrorOr = ErrorOr<T, EFI::Status>;
|
||||
|
||||
}
|
||||
11
Kernel/EFIPrekernel/KernelImage.S.in
Normal file
11
Kernel/EFIPrekernel/KernelImage.S.in
Normal file
@@ -0,0 +1,11 @@
|
||||
// The kernel image has to be in a writable section, so we can apply relocations while EFI boot services are still available
|
||||
// (we are not allowed to change page tables until we call ExitBootServices()).
|
||||
.section .data
|
||||
|
||||
.global start_of_kernel_image
|
||||
.global end_of_kernel_image
|
||||
|
||||
.p2align 12
|
||||
start_of_kernel_image:
|
||||
.incbin "@PREKERNEL_KERNEL_IMAGE_PATH@"
|
||||
end_of_kernel_image:
|
||||
22
Kernel/EFIPrekernel/Panic.cpp
Normal file
22
Kernel/EFIPrekernel/Panic.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Sönke Holz <sholz8530@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Format.h>
|
||||
|
||||
#include <Kernel/EFIPrekernel/DebugOutput.h>
|
||||
#include <Kernel/EFIPrekernel/Panic.h>
|
||||
#include <Kernel/EFIPrekernel/Runtime.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
[[noreturn]] void __panic(char const* file, unsigned int line, char const* function)
|
||||
{
|
||||
dbgln("at {}:{} in {}", file, line, function);
|
||||
|
||||
halt();
|
||||
}
|
||||
|
||||
}
|
||||
24
Kernel/EFIPrekernel/Panic.h
Normal file
24
Kernel/EFIPrekernel/Panic.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Sönke Holz <sholz8530@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Format.h>
|
||||
|
||||
#include <Kernel/EFIPrekernel/DebugOutput.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
[[noreturn]] void __panic(char const* file, unsigned int line, char const* function);
|
||||
|
||||
#define PANIC(...) \
|
||||
do { \
|
||||
::Kernel::ucs2_dbgln(u"PREKERNEL PANIC! :^("); \
|
||||
dbgln(__VA_ARGS__); \
|
||||
::Kernel::__panic(__FILE__, __LINE__, __PRETTY_FUNCTION__); \
|
||||
} while (0)
|
||||
|
||||
}
|
||||
28
Kernel/EFIPrekernel/Runtime.cpp
Normal file
28
Kernel/EFIPrekernel/Runtime.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Sönke Holz <sholz8530@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Platform.h>
|
||||
|
||||
#include <Kernel/EFIPrekernel/Runtime.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
[[noreturn]] void halt()
|
||||
{
|
||||
for (;;) {
|
||||
#if ARCH(AARCH64)
|
||||
asm volatile("msr daifset, #2; wfi");
|
||||
#elif ARCH(RISCV64)
|
||||
asm volatile("csrw sie, zero; wfi");
|
||||
#elif ARCH(X86_64)
|
||||
asm volatile("cli; hlt");
|
||||
#else
|
||||
# error Unknown architecture
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
13
Kernel/EFIPrekernel/Runtime.h
Normal file
13
Kernel/EFIPrekernel/Runtime.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Sönke Holz <sholz8530@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
[[noreturn]] void halt();
|
||||
|
||||
}
|
||||
31
Kernel/EFIPrekernel/VirtualMemoryLayout.h
Normal file
31
Kernel/EFIPrekernel/VirtualMemoryLayout.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Sönke Holz <sholz8530@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Types.h>
|
||||
|
||||
#include <Kernel/Sections.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
// Kernel virtual memory layout:
|
||||
// Kernel stack | BootInfo | Quickmap page table | EFI memory map | Kernel
|
||||
// ^ KERNEL_MAPPING_BASE
|
||||
// NOTE: If the memory map overflows into the kernel memory range, we catch that in the map_pages function (a page is not allowed to be remapped)
|
||||
|
||||
static constexpr size_t KERNEL_STACK_SIZE = 64 * KiB;
|
||||
static_assert(KERNEL_STACK_SIZE % PAGE_SIZE == 0);
|
||||
|
||||
static constexpr FlatPtr KERNEL_STACK_VADDR = KERNEL_MAPPING_BASE;
|
||||
static constexpr FlatPtr BOOT_INFO_VADDR = KERNEL_MAPPING_BASE + KERNEL_STACK_SIZE;
|
||||
|
||||
static constexpr FlatPtr QUICKMAP_PAGE_TABLE_VADDR = round_up_to_power_of_two(BOOT_INFO_VADDR + sizeof(BootInfo), PAGE_SIZE);
|
||||
|
||||
// This assumes PAGE_SIZE == PAGE_TABLE_SIZE
|
||||
static constexpr FlatPtr EFI_MEMORY_MAP_VADDR = QUICKMAP_PAGE_TABLE_VADDR + PAGE_SIZE;
|
||||
|
||||
}
|
||||
62
Kernel/EFIPrekernel/init.cpp
Normal file
62
Kernel/EFIPrekernel/init.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Sönke Holz <sholz8530@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Firmware/EFI/EFI.h>
|
||||
#include <Kernel/Firmware/EFI/SystemTable.h>
|
||||
|
||||
#include <Kernel/EFIPrekernel/DebugOutput.h>
|
||||
#include <Kernel/EFIPrekernel/Panic.h>
|
||||
#include <Kernel/EFIPrekernel/Runtime.h>
|
||||
|
||||
// FIXME: Initialize the __stack_chk_guard with a random value via the EFI_RNG_PROTOCOL or other arch-specific methods.
|
||||
uintptr_t __stack_chk_guard __attribute__((used));
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
extern "C" [[noreturn]] void __stack_chk_fail();
|
||||
extern "C" [[noreturn]] void __stack_chk_fail()
|
||||
{
|
||||
PANIC("Stack protector failure, stack smashing detected!");
|
||||
}
|
||||
|
||||
EFI::Handle g_efi_image_handle = 0;
|
||||
EFI::SystemTable* g_efi_system_table = nullptr;
|
||||
|
||||
static_assert(EFI::EFI_PAGE_SIZE == PAGE_SIZE, "The EFIPrekernel assumes that EFI_PAGE_SIZE == PAGE_SIZE");
|
||||
|
||||
extern "C" EFIAPI EFI::Status init(EFI::Handle image_handle, EFI::SystemTable* system_table);
|
||||
extern "C" EFIAPI EFI::Status init(EFI::Handle image_handle, EFI::SystemTable* system_table)
|
||||
{
|
||||
// We use some EFI 1.10 functions from the System Table, so reject older versions.
|
||||
static constexpr u32 efi_version_1_10 = (1 << 16) | 10;
|
||||
if (system_table->hdr.signature != EFI::SystemTable::signature || system_table->hdr.revision < efi_version_1_10)
|
||||
return EFI::Status::Unsupported;
|
||||
|
||||
g_efi_image_handle = image_handle;
|
||||
g_efi_system_table = system_table;
|
||||
|
||||
system_table->con_out->set_attribute(system_table->con_out,
|
||||
EFI::TextAttribute {
|
||||
.foreground_color = EFI::TextAttribute::ForegroundColor::White,
|
||||
.background_color = EFI::TextAttribute::BackgroundColor::Black,
|
||||
});
|
||||
|
||||
// Clear the screen. This also removes the manufacturer logo, if present.
|
||||
system_table->con_out->clear_screen(system_table->con_out);
|
||||
|
||||
ucs2_dbgln(u"SerenityOS EFI Prekernel");
|
||||
|
||||
TODO();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __assertion_failed(char const* msg, char const* file, unsigned int line, char const* func)
|
||||
{
|
||||
dbgln("ASSERTION FAILED: {}", msg);
|
||||
dbgln("{}:{} in {}", file, line, func);
|
||||
Kernel::halt();
|
||||
}
|
||||
Reference in New Issue
Block a user