diff --git a/qefidpeditorview.cpp b/qefidpeditorview.cpp index bb97d70..98fe90a 100644 --- a/qefidpeditorview.cpp +++ b/qefidpeditorview.cpp @@ -1,6 +1,7 @@ #include "qefidpeditorview.h" #include "helpers.h" +#include QEFIDPEditorView::QEFIDPEditorView(QEFIDevicePath *dp, QWidget *parent) : QWidget(parent) @@ -69,6 +70,178 @@ QEFIDPEditorView::~QEFIDPEditorView() } } +#include + +QVariant retrieveDPEditComponent(enum QEFIDPEditType type, QWidget *widget) { + QVariant v; + switch (type) + { + case QEFIDPEditType::EditType_Text: + case QEFIDPEditType::EditType_Path: + { + QLineEdit *edit = dynamic_cast(widget); + if (edit != nullptr) { + v = QVariant(edit->text()); + } + } + break; + case QEFIDPEditType::EditType_HexData: + { + QLineEdit *edit = dynamic_cast(widget); + if (edit != nullptr) { + v = QVariant(QByteArray::fromHex(edit->text().toLatin1())); + } + } + break; + case QEFIDPEditType::EditType_UUID: + { + QLineEdit *edit = dynamic_cast(widget); + if (edit != nullptr) { + v = QVariant(QUuid(edit->text())); + } + } + break; + case QEFIDPEditType::EditType_Number: + case QEFIDPEditType::EditType_HexNumber: + { + QSpinBox *edit = dynamic_cast(widget); + if (edit != nullptr) { + v = QVariant(edit->value()); + } + } + break; + case QEFIDPEditType::EditType_Enum: + { + QComboBox *edit = dynamic_cast(widget); + if (edit != nullptr) { + v = edit->currentData(); + } + } + break; + default: + { + QLineEdit *edit = dynamic_cast(widget); + if (edit != nullptr) { + v = QVariant(edit->text()); + } + } + break; + } + qDebug() << v; + + return v; +} + +QEFIDevicePath *QEFIDPEditorView::getDevicePath() +{ + // Instantiate the device path + int type = (m_dpTypeSelector != nullptr ? + m_dpTypeSelector->itemData(m_dpTypeSelected).toInt() : 0); + int subtype = (m_dpTypeSelector != nullptr ? + m_dpSubtypeSelector->itemData(m_dpSubtypeSelected).toInt() : 0); + QEFIDevicePath *dp = nullptr; + switch (type) + { + case QEFIDevicePathType::DP_Hardware: + break; + case QEFIDevicePathType::DP_ACPI: + break; + case QEFIDevicePathType::DP_Message: + break; + case QEFIDevicePathType::DP_Media: + switch (subtype) + { + case QEFIDevicePathMediaSubType::MEDIA_HD: + { + quint32 partitionNumber; + quint64 start; + quint64 size; + quint8 signature[16]; + quint8 format; + quint8 signatureType; + QString filepath; + for (int i = 0; i < m_currentWidgets.size(); i++) { + qDebug() << m_currentWidgets[i].first; + // TODO: Int range + if (m_currentWidgets[i].first == QStringLiteral("Partition Num")) { + QVariant data = retrieveDPEditComponent( + QEFIDPEditType::EditType_Number, m_currentWidgets[i].second); + if (data.isNull()) return dp; + partitionNumber = data.toInt(); + } else if (m_currentWidgets[i].first == QStringLiteral("Start")) { + QVariant data = retrieveDPEditComponent( + QEFIDPEditType::EditType_Number, m_currentWidgets[i].second); + if (data.isNull()) return dp; + start = data.toInt(); + } else if (m_currentWidgets[i].first == QStringLiteral("Size")) { + QVariant data = retrieveDPEditComponent( + QEFIDPEditType::EditType_Number, m_currentWidgets[i].second); + if (data.isNull()) return dp; + size = data.toInt(); + } else if (m_currentWidgets[i].first == QStringLiteral("Format")) { + QVariant data = retrieveDPEditComponent( + QEFIDPEditType::EditType_Enum, m_currentWidgets[i].second); + if (data.isNull()) return dp; + format = data.toInt(); + } else if (m_currentWidgets[i].first == QStringLiteral("Signature Type")) { + QVariant data = retrieveDPEditComponent( + QEFIDPEditType::EditType_Enum, m_currentWidgets[i].second); + if (data.isNull()) return dp; + signatureType = data.toInt(); + } else if (m_currentWidgets[i].first == QStringLiteral("Signature")) { + QVariant data = retrieveDPEditComponent( + QEFIDPEditType::EditType_HexData, m_currentWidgets[i].second); + if (data.isNull() || data.type() != QVariant::Type::ByteArray) return dp; + QByteArray sig = data.toByteArray(); + for (int i = 0; i < 16 && i < sig.size(); i++) { + signature[i] = sig[i]; + } + } + } + dp = new QEFIDevicePathMediaHD(partitionNumber, start, size, + signature, format, signatureType); + } + break; + case QEFIDevicePathMediaSubType::MEDIA_CDROM: + break; + case QEFIDevicePathMediaSubType::MEDIA_Vendor: + break; + case QEFIDevicePathMediaSubType::MEDIA_File: + { + QString filepath; + for (int i = 0; i < m_currentWidgets.size(); i++) { + if (m_currentWidgets[i].first == QStringLiteral("File")) { + QVariant data = retrieveDPEditComponent( + QEFIDPEditType::EditType_Path, m_currentWidgets[i].second); + if (data.isNull() || data.type() != QVariant::Type::String) return dp; + filepath = data.toString(); + } + } + dp = new QEFIDevicePathMediaFile(filepath); + } + break; + case QEFIDevicePathMediaSubType::MEDIA_Protocol: + break; + case QEFIDevicePathMediaSubType::MEDIA_FirmwareFile: + break; + case QEFIDevicePathMediaSubType::MEDIA_FirmwareVolume: + break; + case QEFIDevicePathMediaSubType::MEDIA_RelativeOffset: + break; + case QEFIDevicePathMediaSubType::MEDIA_RamDisk: + break; + default: + break; + } + break; + case QEFIDevicePathType::DP_BIOSBoot: + break; + default: + break; + } + return dp; +} + void QEFIDPEditorView::dpTypeComboBoxCurrentIndexChanged(int index) { if (m_dpSubtypeSelector != nullptr && m_dpTypeSelected != index) { diff --git a/qefidpeditorview.h b/qefidpeditorview.h index 28fa125..cafb230 100644 --- a/qefidpeditorview.h +++ b/qefidpeditorview.h @@ -33,6 +33,8 @@ class QEFIDPEditorView: public QWidget QWidget *parent = nullptr); ~QEFIDPEditorView(); + QEFIDevicePath *getDevicePath(); // Ownership is yours + public slots: void dpTypeComboBoxCurrentIndexChanged(int index); void dpSubtypeComboBoxCurrentIndexChanged(int index); diff --git a/qefientryview.cpp b/qefientryview.cpp index e039d56..a93c534 100644 --- a/qefientryview.cpp +++ b/qefientryview.cpp @@ -494,6 +494,7 @@ public slots: // Init the class from the view if (m_view != nullptr) { m_bootID = m_view->getBootEntryID(); + // FIXME: This method cannot be called the second time m_loadOptionData = m_view->generateLoadOption(); qDebug() << "Will add Boot Entry " << m_bootID << m_loadOptionData; } diff --git a/qefiloadoptioneditorview.cpp b/qefiloadoptioneditorview.cpp index d1d1d17..efe6bee 100644 --- a/qefiloadoptioneditorview.cpp +++ b/qefiloadoptioneditorview.cpp @@ -3,11 +3,17 @@ #include #include +#include + +#include "helpers.h" class EditorDialog : public QDialog { QEFIDPEditorView *m_view; QBoxLayout *m_topLevelLayout; + QDialogButtonBox *m_buttonBox; + + QEFIDevicePath * m_currentDP; public: EditorDialog(QWidget *parent = nullptr) : QDialog(parent) @@ -16,12 +22,41 @@ class EditorDialog : public QDialog setWindowTitle(QStringLiteral("Add Device Path")); m_topLevelLayout = new QBoxLayout(QBoxLayout::Down, this); m_topLevelLayout->addWidget(m_view); + + m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | + QDialogButtonBox::Cancel); + m_topLevelLayout->addWidget(m_buttonBox); + + connect(m_buttonBox, &QDialogButtonBox::accepted, this, &EditorDialog::onAccept); + connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); } ~EditorDialog() { if (m_topLevelLayout) m_topLevelLayout->deleteLater(); if (m_view) m_view->deleteLater(); + if (m_buttonBox) m_buttonBox->deleteLater(); + } + + QEFIDevicePath *takeCurrentDP() + { + QEFIDevicePath *dp = m_currentDP; m_currentDP = nullptr; return dp; + } + +public slots: + void onAccept() { + // Init the class from the view + if (m_view != nullptr) { + QEFIDevicePath *dp = m_view->getDevicePath(); + if (dp == nullptr) { + reject(); + return; + } + m_currentDP = dp; + accept(); + return; + } + reject(); } }; @@ -49,6 +84,10 @@ QEFILoadOptionEditorView::QEFILoadOptionEditorView(QEFILoadOption *option, QWidg m_topLevelLayout->addRow(QStringLiteral(""), button); connect(button, &QPushButton::clicked, this, &QEFILoadOptionEditorView::createDPClicked); + QPushButton *clearButton = new QPushButton(QStringLiteral("Clear Device Path"), this); + m_topLevelLayout->addRow(QStringLiteral(""), clearButton); + connect(clearButton, &QPushButton::clicked, + this, &QEFILoadOptionEditorView::clearDPClicked); setLayout(m_topLevelLayout); } @@ -60,6 +99,12 @@ QEFILoadOptionEditorView::~QEFILoadOptionEditorView() m_topLevelLayout = nullptr; } if (m_idSpinBox != nullptr) m_idSpinBox->deleteLater(); + + // Clear and delete + for (int i = 0; i < m_dps.size(); i++) { + delete m_dps[i]; + } + m_dps.clear(); } void QEFILoadOptionEditorView::createDPClicked(bool checked) @@ -67,7 +112,17 @@ void QEFILoadOptionEditorView::createDPClicked(bool checked) Q_UNUSED(checked); EditorDialog dialog(this); if (dialog.exec() == QDialog::Rejected) return; - // TODO: Get Device Path and add it + // Get Device Path and add it + QEFIDevicePath *dp = dialog.takeCurrentDP(); + if (dp != nullptr) { + m_dps << dp; + if (m_topLevelLayout->rowCount() > DP_BEGIN_INDEX) { + m_topLevelLayout->insertRow(DP_BEGIN_INDEX + m_dps.size() - 1, + QString::asprintf("Device Path:"), new QLabel( + convert_device_path_type_to_name(dp->type()) + " " + + convert_device_path_subtype_to_name(dp->type(), dp->subType()))); + } + } } QByteArray QEFILoadOptionEditorView::generateLoadOption() @@ -84,7 +139,11 @@ QByteArray QEFILoadOptionEditorView::generateLoadOption() // Check format if (optionalData.size() * 2 != m_optionalDataTextEdit->text().length()) return data; newLoadOption.setOptionalData(optionalData); - // TODO: Format DPs + // Format DPs and clear it + for (int i = 0; i < m_dps.size(); i++) { + newLoadOption.addDevicePath(m_dps[i]); + } + m_dps.clear(); return newLoadOption.format(); } @@ -94,3 +153,12 @@ quint16 QEFILoadOptionEditorView::getBootEntryID() if (m_idSpinBox == nullptr) return 0; return (quint16)(m_idSpinBox->value() & 0xFFFF); } + +void QEFILoadOptionEditorView::clearDPClicked(bool checked) +{ + Q_UNUSED(checked); + for (int i = 0; i < m_dps.size(); i++) { + delete m_dps[i]; + } + m_dps.clear(); +} diff --git a/qefiloadoptioneditorview.h b/qefiloadoptioneditorview.h index 08d898f..2fb3e96 100644 --- a/qefiloadoptioneditorview.h +++ b/qefiloadoptioneditorview.h @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include @@ -21,6 +23,7 @@ class QEFILoadOptionEditorView: public QWidget QLineEdit *m_nameTextEdit; QLineEdit *m_optionalDataTextEdit; + QList m_dps; public: QEFILoadOptionEditorView(QEFILoadOption *option = nullptr, QWidget *parent = nullptr); @@ -31,6 +34,7 @@ class QEFILoadOptionEditorView: public QWidget public slots: void createDPClicked(bool checked); + void clearDPClicked(bool checked); }; #endif // QEFILOADOPTIONEDITORVIEW_H \ No newline at end of file