Skip to content

Commit

Permalink
Support reading boot manager capabilities (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
Neverous authored Jul 22, 2023
1 parent 1aba8b9 commit a3131cc
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/bootentryform.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class BootEntryForm: public QWidget
~BootEntryForm() override;

void setReadOnly(bool readonly);
void showCategory(bool visible);

void setBootEntryListModel(BootEntryListModel &model);
void setItem(const QModelIndex &index, const BootEntry *item);
Expand Down
3 changes: 3 additions & 0 deletions include/efibootdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class EFIBootData: public QObject
bool setup_mode{false};
bool audit_mode{false};
bool deployed_mode{false};
uint32_t boot_option_support{0};

uint64_t supported_indications{0};
uint64_t indications{0};
Expand Down Expand Up @@ -67,6 +68,7 @@ public slots:
void setupModeChanged(bool enabled);
void auditModeChanged(bool enabled);
void deployedModeChanged(bool enabled);
void bootOptionSupportChanged(uint32_t flags);
void appleBootArgsChanged(const QString &text);
void osIndicationsSupportedChanged(uint64_t value);
void osIndicationsChanged(const uint64_t &value);
Expand All @@ -77,6 +79,7 @@ public slots:
void setSetupMode(bool enabled);
void setAuditMode(bool enabled);
void setDeployedMode(bool enabled);
void setBootOptionSupport(uint32_t flags);
void setOsIndicationsSupported(uint64_t value);
void importJSONEFIData(const QJsonObject &input);
void importRawEFIData(const QJsonObject &input);
Expand Down
2 changes: 2 additions & 0 deletions include/efibooteditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ public slots:

void setOsIndication(bool checked);

void updateBootOptionSupport(uint32_t flags);

void undoViewChanged(const QModelIndex &index);

signals:
Expand Down
5 changes: 5 additions & 0 deletions include/efivar-lite/efivar.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ static const uint64_t EFI_OS_INDICATIONS_START_OS_RECOVERY = 0x0000000000000020;
static const uint64_t EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY = 0x0000000000000040;
static const uint64_t EFI_OS_INDICATIONS_JSON_CONFIG_DATA_REFRESH = 0x0000000000000080;

static const uint32_t EFI_BOOT_OPTION_SUPPORT_KEY = 0x00000001;
static const uint32_t EFI_BOOT_OPTION_SUPPORT_APP = 0x00000002;
static const uint32_t EFI_BOOT_OPTION_SUPPORT_SYSPREP = 0x00000010;
static const uint32_t EFI_BOOT_OPTION_SUPPORT_COUNT = 0x00000300;

extern const efi_guid_t efi_guid_global;
extern const efi_guid_t efi_guid_apple;

Expand Down
6 changes: 6 additions & 0 deletions src/bootentryform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ void BootEntryForm::setReadOnly(bool readonly)
ui->error_text->setDisabled(readonly);
}

void BootEntryForm::showCategory(bool visible)
{
ui->category_label->setVisible(visible);
ui->category_combo->setVisible(visible);
}

void BootEntryForm::setBootEntryListModel(BootEntryListModel &model)
{
entries_list_model = &model;
Expand Down
81 changes: 80 additions & 1 deletion src/efibootdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ void EFIBootData::clear()
setSetupMode(false);
setAuditMode(false);
setDeployedMode(false);
setBootOptionSupport(0);
setOsIndicationsSupported(0);
setOsIndications(0);
setAppleBootArgs("");
Expand Down Expand Up @@ -159,6 +160,12 @@ void EFIBootData::reload()
save_error,
true);

process_entry(
"BootOptionSupport", EFIBoot::get_variable<uint32_t>, [&](const uint32_t &value, const auto &)
{ setBootOptionSupport(value); },
save_error,
true);

process_entry(
"OsIndicationsSupported", EFIBoot::get_variable<uint64_t>, [&](const uint64_t &value, const auto &)
{ setOsIndicationsSupported(value); },
Expand Down Expand Up @@ -517,6 +524,25 @@ void EFIBootData::export_(const QString &file_name)
output["AuditMode"] = audit_mode != 0;
output["DeployedMode"] = deployed_mode != 0;

if(boot_option_support)
{
QJsonObject obj;
QJsonArray caps;

if(boot_option_support & EFIBoot::EFI_BOOT_OPTION_SUPPORT_KEY)
caps.push_back("KEY");

if(boot_option_support & EFIBoot::EFI_BOOT_OPTION_SUPPORT_APP)
caps.push_back("APP");

if(boot_option_support & EFIBoot::EFI_BOOT_OPTION_SUPPORT_SYSPREP)
caps.push_back("SYSPREP");

obj["capabilities"] = caps;
obj["key_count"] = static_cast<int>((boot_option_support & EFIBoot::EFI_BOOT_OPTION_SUPPORT_COUNT) >> 8);
output["BootOptionSupport"] = obj;
}

{
QJsonArray arr;
if(supported_indications & EFIBoot::EFI_OS_INDICATIONS_BOOT_TO_FW_UI)
Expand Down Expand Up @@ -661,7 +687,7 @@ void EFIBootData::dump(const QString &file_name)
output[prefix] = entries;
}

for(const auto &key: std::vector<const char *>{"Timeout", "BootCurrent", "BootNext", "SecureBoot", "VendorKeys", "SetupMode", "AuditMode", "DeployedMode", "OsIndicationsSupported", "OsIndications"})
for(const auto &key: std::vector<const char *>{"Timeout", "BootCurrent", "BootNext", "SecureBoot", "VendorKeys", "SetupMode", "AuditMode", "DeployedMode", "BootOptionSupport", "OsIndicationsSupported", "OsIndications"})
process_entry(output, key, _T(""), true);

// Apple
Expand Down Expand Up @@ -784,6 +810,15 @@ void EFIBootData::setDeployedMode(bool enabled)
emit deployedModeChanged(deployed_mode);
}

void EFIBootData::setBootOptionSupport(uint32_t flags)
{
if(boot_option_support == flags)
return;

boot_option_support = flags;
emit bootOptionSupportChanged(boot_option_support);
}

void EFIBootData::setOsIndicationsSupported(uint64_t value)
{
if(supported_indications == value)
Expand Down Expand Up @@ -864,6 +899,45 @@ void EFIBootData::importJSONEFIData(const QJsonObject &input)
{ setDeployedMode(value.toBool()); },
"", true);

process_entry(
input, "BootOptionSupport", &QJsonValue::isObject, tr("object"), [&](const QJsonValue &value)
{
uint32_t val = 0;
const auto obj = value.toObject();
if(obj["capabilities"].isArray())
{
const auto caps = obj["capabilities"].toArray();
int i = -1;
for(const auto cap: caps)
{
++i;
const auto qname = QString("BootOptionSupport/capabilities[%1]").arg(i);
if(!cap.isString())
{
errors.push_back(tr("%1: %2 expected").arg(qname, tr("string")));
continue;
}

if(cap == "KEY")
val |= EFIBoot::EFI_BOOT_OPTION_SUPPORT_KEY;
else if(cap == "APP")
val |= EFIBoot::EFI_BOOT_OPTION_SUPPORT_APP;
else if(cap == "SYSPREP")
val |= EFIBoot::EFI_BOOT_OPTION_SUPPORT_SYSPREP;
else
{
errors.push_back(tr("%1: unknown boot manager capability").arg(qname));
continue;
}
}
}

if(obj["key_count"].isDouble())
val |= (static_cast<uint32_t>(obj["key_count"].toInt()) << 8) & EFIBoot::EFI_BOOT_OPTION_SUPPORT_COUNT;

setBootOptionSupport(val); },
"", true);

process_entry(
input, "OsIndicationsSupported", &QJsonValue::isArray, tr("array"),
[&](const QJsonValue &value)
Expand Down Expand Up @@ -1137,6 +1211,11 @@ void EFIBootData::importRawEFIData(const QJsonObject &input)
{ setDeployedMode(value); },
"", true);

process_entry(
input, "BootOptionSupport", EFIBoot::deserialize<uint32_t>, [&](const uint32_t &value, const auto &)
{ setBootOptionSupport(value); },
"", true);

process_entry(
input, "OsIndicationsSupported", EFIBoot::deserialize<uint64_t>, [&](const uint64_t &value, const auto &)
{ setOsIndicationsSupported(value); },
Expand Down
10 changes: 10 additions & 0 deletions src/efibooteditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ EFIBootEditor::EFIBootEditor(QWidget *parent)
QObject::connect(&data, &EFIBootData::setupModeChanged, ui->setup_mode, &QRadioButton::setChecked);
QObject::connect(&data, &EFIBootData::auditModeChanged, ui->audit_mode, &QRadioButton::setChecked);
QObject::connect(&data, &EFIBootData::deployedModeChanged, ui->deployed_mode, &QRadioButton::setChecked);
QObject::connect(&data, &EFIBootData::bootOptionSupportChanged, this, &EFIBootEditor::updateBootOptionSupport);

QObject::connect(&data, &EFIBootData::appleBootArgsChanged, ui->boot_args_text, &QLineEdit::setText);
QObject::connect(ui->boot_args_text, &QLineEdit::textEdited, &data, &EFIBootData::setAppleBootArgs);
Expand Down Expand Up @@ -92,6 +93,8 @@ EFIBootEditor::EFIBootEditor(QWidget *parent)

ui->entries->setCurrentIndex(0);
ui->settings->setCurrentIndex(0);

updateBootOptionSupport(0);
}

EFIBootEditor::~EFIBootEditor()
Expand Down Expand Up @@ -284,6 +287,13 @@ void EFIBootEditor::setOsIndication(bool)
emit osIndicationsChanged(getOsIndications());
}

void EFIBootEditor::updateBootOptionSupport(uint32_t flags)
{
// TODO: (flags & EFIBoot::EFI_BOOT_OPTION_SUPPORT_KEY)
ui->entry_form->showCategory(flags & EFIBoot::EFI_BOOT_OPTION_SUPPORT_APP);
ui->entries->setTabVisible(ui->entries->indexOf(ui->sysprep_tab), flags & EFIBoot::EFI_BOOT_OPTION_SUPPORT_SYSPREP);
}

void EFIBootEditor::undoViewChanged(const QModelIndex &)
{
refreshBootEntryEditor();
Expand Down

0 comments on commit a3131cc

Please sign in to comment.