Skip to content

Use internal libefivar for FreeBSD #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,12 @@ elseif(WIN32)
message("Use Windows API for EFI operations")
# TODO: Add include and lib from Windows API
else()
message("Use my libefivar for EFI operations")
endif()

if(PATCH_FREEBSD_EFIVAR)
# Patch efivar 0.15 build for FreeBSD
# TODO(Inoki): check 0.15 build for FreeBSD
add_definitions(-DEFIVAR_FREEBSD_PATCH)
target_link_libraries(QEFI PRIVATE geom)
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
# Link with FreeBSD system-level libefivar and geom
# see source code of usr.sbin/efibootmgr/Makefile and usr.sbin/efivar/Makefile
target_link_libraries(QEFI PUBLIC efivar geom)
endif()
message("Use qefivar implementations for EFI operations")
endif()

install(
Expand Down
163 changes: 142 additions & 21 deletions qefi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -677,17 +677,10 @@ void qefi_set_variable(QUuid uuid, QString name, QByteArray value)
}

#else
/* Implementation based on libefivar */
extern "C" {
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>

}
/* Implementation based on libefivar */
#define EFI_VARIABLE_NON_VOLATILE ((uint64_t)0x0000000000000001)
#define EFI_VARIABLE_BOOTSERVICE_ACCESS ((uint64_t)0x0000000000000002)
#define EFI_VARIABLE_RUNTIME_ACCESS ((uint64_t)0x0000000000000004)
Expand All @@ -696,13 +689,123 @@ extern "C" {
#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS ((uint64_t)0x0000000000000020)
#define EFI_VARIABLE_APPEND_WRITE ((uint64_t)0x0000000000000040)
#define EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS ((uint64_t)0x0000000000000080)
}

#include <QByteArray>
#include <QFile>
#include <QFileInfo>

/* Get rid of efivar */
#if defined(Q_OS_FREEBSD)

extern "C" {
// Use FreeBSD system-level libefivar
#include <efivar.h>
}
#include <iostream>

int qefivar_variables_supported(void)
{
return efi_variables_supported();
}

static int qefivar_get_variable_size(const QUuid &uuid, const QString &name, size_t *size)
{
int return_code;

std::string std_name = name.toStdString();
const char *c_name = std_name.c_str();
std::string std_uuid = uuid.toString(QUuid::WithoutBraces).toStdString();
const char *c_uuid = std_uuid.c_str();

efi_guid_t guid;
return_code = efi_str_to_guid(c_uuid, &guid);
if (return_code < 0)
{
return return_code;
}
return_code = efi_get_variable_size(guid, c_name, size);

return 0;
}

static int qefivar_get_variable(QUuid &uuid, QString &name, uint8_t **data, size_t *size, uint32_t *attributes)
{
int return_code;

std::string std_name = name.toStdString();
const char *c_name = std_name.c_str();
std::string std_uuid = uuid.toString(QUuid::WithoutBraces).toStdString();
const char *c_uuid = std_uuid.c_str();

efi_guid_t guid;
return_code = efi_str_to_guid(c_uuid, &guid);
if (return_code < 0)
{
return return_code;
}

return_code = efi_get_variable_size(guid, c_name, size);
if (*size == 0 || return_code < 0)
{
return return_code;
}

uint8_t *temp_data;
return_code = efi_get_variable(guid, c_name, &temp_data, size, attributes);
if (*size == 0 || return_code < 0)
{
return return_code;
}
// Allocate to have the same behaviour with Linux efivar
*data = (uint8_t *)malloc(*size);
std::memcpy(*data, temp_data, *size);

if (return_code < 0)
{
return return_code;
}
return 0;
}

static int qefivar_set_variable(const QUuid &uuid, const QString &name, uint8_t *data,
size_t data_size, uint32_t attributes, mode_t mode)
{
int return_code;

std::string std_name = name.toStdString();
const char *c_name = std_name.c_str();
std::string std_uuid = uuid.toString(QUuid::WithoutBraces).toStdString();
const char *c_uuid = std_uuid.c_str();

efi_guid_t guid;
return_code = efi_str_to_guid(c_uuid, &guid);
if (return_code < 0)
{
return return_code;
}

// Arg "mode" is not supported here
return_code = efi_set_variable(guid, c_name, data, data_size, attributes);

if (return_code < 0)
{
return return_code;
}

return 0;
}

#else
extern "C" {
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
}

static QString const default_efivarfs_path = QStringLiteral("/sys/firmware/efi/efivars/");
static QString efivarfs_path;

Expand All @@ -727,7 +830,7 @@ static QString get_efivarfs_path(void)
return efivarfs_path;
}

int efi_variables_supported(void)
int qefivar_variables_supported(void)
{
QFileInfo fileInfo(get_efivarfs_path());
if (!fileInfo.exists() || !fileInfo.isDir())
Expand Down Expand Up @@ -758,6 +861,11 @@ static int qefivar_efivarfs_get_variable_size(const QUuid &guid, const QString &
return ret;
}

static int inline qefivar_get_variable_size(const QUuid &guid, const QString &name, size_t *size)
{
return qefivar_efivarfs_get_variable_size(guid, name, size);
}

static int qefivar_efivarfs_get_variable(QUuid &guid, QString &name, uint8_t **data, size_t *size, uint32_t *attributes)
{
int ret = -1;
Expand Down Expand Up @@ -799,8 +907,13 @@ static int qefivar_efivarfs_get_variable(QUuid &guid, QString &name, uint8_t **d
return ret;
}

static int inline qefivar_get_variable(QUuid &guid, QString &name, uint8_t **data, size_t *size, uint32_t *attributes)
{
return qefivar_efivarfs_get_variable(guid, name, data, size, attributes);
}

static int
qefi_efivarfs_del_variable(const QUuid &guid, const QString &name)
qefivar_efivarfs_del_variable(const QUuid &guid, const QString &name)
{
const QString &rawPath = make_efivarfs_path(guid, name);
const char *path = rawPath.toLocal8Bit().constData();
Expand All @@ -814,7 +927,7 @@ qefi_efivarfs_del_variable(const QUuid &guid, const QString &name)
}

static int
qefi_efivarfs_set_variable(const QUuid &guid, const QString &name, const uint8_t *data,
qefivar_efivarfs_set_variable(const QUuid &guid, const QString &name, uint8_t *data,
size_t data_size, uint32_t attributes, mode_t mode)
{
QByteArray buf((qsizetype)(sizeof (attributes) + data_size), (char)0);
Expand All @@ -841,7 +954,7 @@ qefi_efivarfs_set_variable(const QUuid &guid, const QString &name, const uint8_t
const char *path = rawPath.toLocal8Bit().constData();

if (!access(path, F_OK) && !(attributes & EFI_VARIABLE_APPEND_WRITE)) {
rc = qefi_efivarfs_del_variable(guid, name);
rc = qefivar_efivarfs_del_variable(guid, name);
if (rc < 0)
goto err;
}
Expand All @@ -867,11 +980,19 @@ qefi_efivarfs_set_variable(const QUuid &guid, const QString &name, const uint8_t
errno = errno_value;
return ret;
}

static inline int
qefivar_set_variable(const QUuid &guid, const QString &name, uint8_t *data,
size_t data_size, uint32_t attributes, mode_t mode)
{
return qefivar_efivarfs_set_variable(guid, name, data, data_size, attributes, mode);
}
#endif
/* End: Get rid of efivar */

bool qefi_is_available()
{
return efi_variables_supported();
return qefivar_variables_supported();
}

bool qefi_has_privilege()
Expand All @@ -884,15 +1005,15 @@ quint16 qefi_get_variable_uint16(QUuid uuid, QString name)
{
int return_code;
size_t var_size;
return_code = qefivar_efivarfs_get_variable_size(uuid, name, &var_size);
return_code = qefivar_get_variable_size(uuid, name, &var_size);
if (var_size == 0 || return_code != 0)
{
return 0;
}

uint8_t *data;
uint32_t attributes;
return_code = qefivar_efivarfs_get_variable(uuid, name, &data, &var_size, &attributes);
return_code = qefivar_get_variable(uuid, name, &data, &var_size, &attributes);

quint16 value;
if (return_code != 0)
Expand All @@ -914,15 +1035,15 @@ QByteArray qefi_get_variable(QUuid uuid, QString name)
int return_code;

size_t var_size;
return_code = qefivar_efivarfs_get_variable_size(uuid, name, &var_size);
return_code = qefivar_get_variable_size(uuid, name, &var_size);
if (var_size == 0 || return_code != 0)
{
return QByteArray();
}

uint8_t *data;
uint32_t attributes;
return_code = qefivar_efivarfs_get_variable(uuid, name, &data, &var_size, &attributes);
return_code = qefivar_get_variable(uuid, name, &data, &var_size, &attributes);

QByteArray value;
if (return_code != 0)
Expand Down Expand Up @@ -951,7 +1072,7 @@ void qefi_set_variable_uint16(QUuid uuid, QString name, quint16 value)

uint8_t buffer[2];
*((uint16_t *)buffer) = qToLittleEndian<quint16>(value);
return_code = qefi_efivarfs_set_variable(uuid, name, buffer, 2,
return_code = qefivar_set_variable(uuid, name, buffer, 2,
default_write_attribute,
0644);

Expand All @@ -962,7 +1083,7 @@ void qefi_set_variable(QUuid uuid, QString name, QByteArray value)
{
int return_code;

return_code = qefi_efivarfs_set_variable(uuid, name, (uint8_t *)value.data(), value.size(),
return_code = qefivar_set_variable(uuid, name, (uint8_t *)value.data(), value.size(),
default_write_attribute,
0644);

Expand Down
Loading