Skip to content

Commit

Permalink
Merge pull request #23 from Inokinoki/get-rid-of-efivar
Browse files Browse the repository at this point in the history
Use internal libefivar for FreeBSD
  • Loading branch information
Inokinoki authored Nov 15, 2024
2 parents ac006ff + a88c20c commit e2d94f5
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 29 deletions.
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

0 comments on commit e2d94f5

Please sign in to comment.