After exiting UEFI, the bootloader had no way of displaying status to the user. Now it will display a series of small boxes as a progress bar along the bottom of the screen if a framebuffer exists. Errors or warnings during a step will cause that step's box to turn red or orange, and display bars above it to signal the error code. This caused the simplification of the error handling system (which was mostly just calling status_line::fail) and added different types of status objects.
115 lines
2.4 KiB
C++
115 lines
2.4 KiB
C++
#include <uefi/types.h>
|
|
#include <uefi/protos/file.h>
|
|
#include <uefi/protos/file_info.h>
|
|
#include <uefi/protos/loaded_image.h>
|
|
#include <uefi/protos/simple_file_system.h>
|
|
|
|
#include "fs.h"
|
|
#include "console.h"
|
|
#include "error.h"
|
|
#include "memory.h"
|
|
#include "status.h"
|
|
|
|
namespace boot {
|
|
namespace fs {
|
|
|
|
file::file(uefi::protos::file *f, uefi::boot_services *bs) :
|
|
m_file(f),
|
|
m_bs(bs)
|
|
{
|
|
}
|
|
|
|
file::file(file &o) :
|
|
m_file(o.m_file),
|
|
m_bs(o.m_bs)
|
|
{
|
|
o.m_file = nullptr;
|
|
}
|
|
|
|
file::file(file &&o) :
|
|
m_file(o.m_file),
|
|
m_bs(o.m_bs)
|
|
{
|
|
o.m_file = nullptr;
|
|
}
|
|
|
|
file::~file()
|
|
{
|
|
if (m_file)
|
|
m_file->close();
|
|
}
|
|
|
|
file
|
|
file::open(const wchar_t *path)
|
|
{
|
|
uefi::protos::file *fh = nullptr;
|
|
|
|
try_or_raise(
|
|
m_file->open(&fh, path, uefi::file_mode::read, uefi::file_attr::none),
|
|
L"Could not open relative path to file");
|
|
|
|
return file(fh, m_bs);
|
|
}
|
|
|
|
buffer
|
|
file::load(uefi::memory_type mem_type)
|
|
{
|
|
uint8_t info_buf[sizeof(uefi::protos::file_info) + 100];
|
|
size_t size = sizeof(info_buf);
|
|
uefi::guid info_guid = uefi::protos::file_info::guid;
|
|
|
|
try_or_raise(
|
|
m_file->get_info(&info_guid, &size, &info_buf),
|
|
L"Could not get file info");
|
|
|
|
uefi::protos::file_info *info =
|
|
reinterpret_cast<uefi::protos::file_info*>(&info_buf);
|
|
|
|
size_t pages = memory::bytes_to_pages(info->file_size);
|
|
void *data = nullptr;
|
|
try_or_raise(
|
|
m_bs->allocate_pages(
|
|
uefi::allocate_type::any_pages,
|
|
mem_type, pages, &data),
|
|
L"Could not allocate pages to load file");
|
|
|
|
size = info->file_size;
|
|
try_or_raise(
|
|
m_file->read(&size, data),
|
|
L"Could not read from file");
|
|
|
|
return { .data = data, .size = size };
|
|
}
|
|
|
|
file
|
|
get_boot_volume(uefi::handle image, uefi::boot_services *bs)
|
|
{
|
|
status_line status(L"Looking up boot volume");
|
|
|
|
const uefi::guid le_guid = uefi::protos::loaded_image::guid;
|
|
uefi::protos::loaded_image *loaded_image = nullptr;
|
|
|
|
try_or_raise(
|
|
bs->handle_protocol(image, &le_guid,
|
|
reinterpret_cast<void**>(&loaded_image)),
|
|
L"Could not find currently running UEFI loaded image");
|
|
|
|
const uefi::guid sfs_guid = uefi::protos::simple_file_system::guid;
|
|
uefi::protos::simple_file_system *fs;
|
|
try_or_raise(
|
|
bs->handle_protocol(loaded_image->device_handle, &sfs_guid,
|
|
reinterpret_cast<void**>(&fs)),
|
|
L"Could not find filesystem protocol for boot volume");
|
|
|
|
uefi::protos::file *f;
|
|
try_or_raise(
|
|
fs->open_volume(&f),
|
|
L"Could not open the boot volume");
|
|
|
|
return file(f, bs);
|
|
}
|
|
|
|
} // namespace fs
|
|
} // namespace boot
|
|
|