mirror of
https://github.com/SerenityOS/serenity.git
synced 2026-11-08 02:08:33 -10:00
78 lines
2.8 KiB
C++
78 lines
2.8 KiB
C++
/*
|
|
* Copyright (c) 2025, Sönke Holz <[email protected]>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/ByteBuffer.h>
|
|
#include <Kernel/EFIPrekernel/Filesystem.h>
|
|
#include <Kernel/EFIPrekernel/Globals.h>
|
|
|
|
namespace Kernel {
|
|
|
|
EFIErrorOr<EFI::FileProtocol*> open_root_directory(EFI::LoadedImageProtocol* loaded_image_protocol)
|
|
{
|
|
// EFI_LOADED_IMAGE_PROTOCOL.DeviceHandle is the device handle where we were loaded from.
|
|
auto simple_file_system_protocol_guid = EFI::SimpleFileSystemProtocol::guid;
|
|
EFI::SimpleFileSystemProtocol* root_fs;
|
|
if (auto status = g_efi_system_table->boot_services->handle_protocol(loaded_image_protocol->device_handle, &simple_file_system_protocol_guid, reinterpret_cast<void**>(&root_fs)); status != EFI::Status::Success)
|
|
return status;
|
|
|
|
EFI::FileProtocol* root_dir;
|
|
if (auto status = root_fs->open_volume(root_fs, &root_dir); status != EFI::Status::Success)
|
|
return status;
|
|
|
|
return root_dir;
|
|
}
|
|
|
|
EFIErrorOr<EFI::FileProtocol*> open_file(EFI::FileProtocol* base_directory, char16_t const* path, EFI::FileOpenMode open_mode, EFI::FileAttribute attributes)
|
|
{
|
|
EFI::FileProtocol* file = nullptr;
|
|
if (auto status = base_directory->open(base_directory, &file, const_cast<char16_t*>(path), open_mode, attributes); status != EFI::Status::Success)
|
|
return status;
|
|
|
|
return file;
|
|
}
|
|
|
|
EFIErrorOr<void> close_file(EFI::FileProtocol* file)
|
|
{
|
|
if (auto status = file->close(file); status != EFI::Status::Success)
|
|
return status;
|
|
return {};
|
|
}
|
|
|
|
EFIErrorOr<ByteBuffer> read_entire_file(EFI::FileProtocol* file)
|
|
{
|
|
auto file_info_guid = EFI::FileInfo::guid;
|
|
|
|
// The file size can be retrieved via EFI_FILE_PROTOCOL.GetInfo().
|
|
// To get the EFI_FILE_INFO, we first need to determine the size of it and then allocate a buffer of that size.
|
|
FlatPtr file_info_size = 0;
|
|
if (auto status = file->get_info(file, &file_info_guid, &file_info_size, nullptr); status != EFI::Status::BufferTooSmall)
|
|
return status;
|
|
|
|
ByteBuffer file_info_buffer;
|
|
if (file_info_buffer.try_resize(file_info_size).is_error())
|
|
return EFI::Status::OutOfResources;
|
|
|
|
// Get the EFI_FILE_INFO for this file.
|
|
if (auto status = file->get_info(file, &file_info_guid, &file_info_size, file_info_buffer.data()); status != EFI::Status::Success)
|
|
return status;
|
|
|
|
auto const* file_info = reinterpret_cast<EFI::FileInfo const*>(file_info_buffer.data());
|
|
|
|
ByteBuffer file_data;
|
|
if (file_data.try_resize(file_info->file_size).is_error())
|
|
return EFI::Status::OutOfResources;
|
|
|
|
// Read the entire file.
|
|
FlatPtr file_size = file_info->file_size;
|
|
if (auto status = file->read(file, &file_size, file_data.data()); status != EFI::Status::Success)
|
|
return status;
|
|
|
|
VERIFY(file_size == file_info->file_size);
|
|
return file_data;
|
|
}
|
|
|
|
}
|