diff --git a/include/bootentryform.h b/include/bootentryform.h index e747a3bc..88c4bd29 100644 --- a/include/bootentryform.h +++ b/include/bootentryform.h @@ -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); diff --git a/include/efibootdata.h b/include/efibootdata.h index 796cb23e..3f94d52d 100644 --- a/include/efibootdata.h +++ b/include/efibootdata.h @@ -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}; @@ -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); @@ -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); diff --git a/include/efibooteditor.h b/include/efibooteditor.h index 1ef842b4..398b3f14 100644 --- a/include/efibooteditor.h +++ b/include/efibooteditor.h @@ -74,6 +74,8 @@ public slots: void setOsIndication(bool checked); + void updateBootOptionSupport(uint32_t flags); + void undoViewChanged(const QModelIndex &index); signals: diff --git a/include/efivar-lite/efivar.h b/include/efivar-lite/efivar.h index 1a356fd2..950c93fa 100644 --- a/include/efivar-lite/efivar.h +++ b/include/efivar-lite/efivar.h @@ -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; diff --git a/src/bootentryform.cpp b/src/bootentryform.cpp index 877b939a..ad14f021 100644 --- a/src/bootentryform.cpp +++ b/src/bootentryform.cpp @@ -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; diff --git a/src/efibootdata.cpp b/src/efibootdata.cpp index 1e88f69d..61860c02 100644 --- a/src/efibootdata.cpp +++ b/src/efibootdata.cpp @@ -56,6 +56,7 @@ void EFIBootData::clear() setSetupMode(false); setAuditMode(false); setDeployedMode(false); + setBootOptionSupport(0); setOsIndicationsSupported(0); setOsIndications(0); setAppleBootArgs(""); @@ -159,6 +160,12 @@ void EFIBootData::reload() save_error, true); + process_entry( + "BootOptionSupport", EFIBoot::get_variable, [&](const uint32_t &value, const auto &) + { setBootOptionSupport(value); }, + save_error, + true); + process_entry( "OsIndicationsSupported", EFIBoot::get_variable, [&](const uint64_t &value, const auto &) { setOsIndicationsSupported(value); }, @@ -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((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) @@ -661,7 +687,7 @@ void EFIBootData::dump(const QString &file_name) output[prefix] = entries; } - for(const auto &key: std::vector{"Timeout", "BootCurrent", "BootNext", "SecureBoot", "VendorKeys", "SetupMode", "AuditMode", "DeployedMode", "OsIndicationsSupported", "OsIndications"}) + for(const auto &key: std::vector{"Timeout", "BootCurrent", "BootNext", "SecureBoot", "VendorKeys", "SetupMode", "AuditMode", "DeployedMode", "BootOptionSupport", "OsIndicationsSupported", "OsIndications"}) process_entry(output, key, _T(""), true); // Apple @@ -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) @@ -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(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) @@ -1137,6 +1211,11 @@ void EFIBootData::importRawEFIData(const QJsonObject &input) { setDeployedMode(value); }, "", true); + process_entry( + input, "BootOptionSupport", EFIBoot::deserialize, [&](const uint32_t &value, const auto &) + { setBootOptionSupport(value); }, + "", true); + process_entry( input, "OsIndicationsSupported", EFIBoot::deserialize, [&](const uint64_t &value, const auto &) { setOsIndicationsSupported(value); }, diff --git a/src/efibooteditor.cpp b/src/efibooteditor.cpp index 4d73e846..ea70a495 100644 --- a/src/efibooteditor.cpp +++ b/src/efibooteditor.cpp @@ -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); @@ -92,6 +93,8 @@ EFIBootEditor::EFIBootEditor(QWidget *parent) ui->entries->setCurrentIndex(0); ui->settings->setCurrentIndex(0); + + updateBootOptionSupport(0); } EFIBootEditor::~EFIBootEditor() @@ -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();