Skip to content

Commit

Permalink
openmv: Finished alif bootloader recovery code.
Browse files Browse the repository at this point in the history
  • Loading branch information
kwagyeman committed Nov 20, 2024
1 parent ec69240 commit 2fb7f9f
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 51 deletions.
2 changes: 0 additions & 2 deletions src/plugins/openmv/bootloaders/openmvpluginalifbootloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,6 @@ void OpenMVPlugin::openmvAlifBootloader(const QString &forceFirmwarePath,
if((m_autoUpdate.isEmpty()) && (!m_autoErase)) QMessageBox::information(Core::ICore::dialogParent(),
Tr::tr("Connect"),
Tr::tr("Firmware update complete!\n\n") +
Tr::tr("If you are forcing SBL mode, disconnect your OpenMV Cam from your computer and reset the SBL switch. "
"Then reconnect your OpenMV Cam to your computer.\n\n") +
Tr::tr("Click the Ok button after your OpenMV Cam has enumerated and finished running its built-in self test (blue led blinking - this takes a while).") +
Tr::tr("\n\nIf you overwrote main.py on your OpenMV Cam and did not erase the disk then your OpenMV Cam will just run that main.py."
"\n\nIn this case click OK when you see your OpenMV Cam's internal flash drive mount (a window may or may not pop open)."));
Expand Down
184 changes: 135 additions & 49 deletions src/plugins/openmv/tools/alif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,24 +284,22 @@ bool alifDownloadFirmware(const QString &port, const QString &originalFirmwareFo
QMutexLocker locker(&alif_tools_working);

QFile file(Core::ICore::userResourcePath(QStringLiteral("alif/version.json")).toString());

int current_version_major = 0;
int current_version_minor = 0;
int current_version_patch = 0;

if (file.open(QFile::ReadOnly))
{
QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
file.close();

current_version_major = doc.object().value(QStringLiteral("version_major")).toInt();
current_version_minor = doc.object().value(QStringLiteral("version_minor")).toInt();
current_version_patch = doc.object().value(QStringLiteral("version_patch")).toInt();

file.close();
}

QJsonObject dfuBootloaderProgramCommand = obj.value(QStringLiteral("dfuBootloaderProgramCommand")).toObject();
int sesVersionMajor = 0;
int sesVersionMinor = 0;
int sesVersionPatch = 0;

bool result = true;
Utils::Process process;
Expand All @@ -316,22 +314,40 @@ bool alifDownloadFirmware(const QString &port, const QString &originalFirmwareFo
QString *stdOutBufferPtr = &stdOutBuffer;
bool stdOutFirstTime = true;
bool *stdOutFirstTimePtr = &stdOutFirstTime;

int sesVersionMajor = 0;
int sesVersionMinor = 0;
int sesVersionPatch = 0;
int *sesVersionMajorPtr = &sesVersionMajor;
int *sesVersionMinorPtr = &sesVersionMinor;
int *sesVersionPatchPtr = &sesVersionPatch;

bool enterHardMaintenanceMode = false;
bool exitHardMaintenanceMode = false;
bool hardMaintenanceRequired = false;
bool *enterHardMaintenanceModePtr = &enterHardMaintenanceMode;
bool *exitHardMaintenanceModePtr = &exitHardMaintenanceMode;
QMessageBox *userButtonMessageBox = new QMessageBox(QMessageBox::Information, Tr::tr("Alif Tools"),Tr::tr("Press the user button on the board."), QMessageBox::NoButton, dialog,
bool *hardMaintenanceRequiredPtr = &hardMaintenanceRequired;

bool startGetBootInfo = false;
bool stopGetBootInfo = false;
bool appLoaded = false;
bool *startGetBootInfoPtr = &startGetBootInfo;
bool *stopGetBootInfoPtr = &stopGetBootInfo;
bool *appLoadedPtr = &appLoaded;

QMessageBox *userButtonMessageBox = new QMessageBox(QMessageBox::Information, Tr::tr("Alif Tools"),
Tr::tr("Please turn on the hard maintenance mode switch, it not enabled, and then press the user button on your OpenMV Cam."),
QMessageBox::NoButton, dialog,
Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint |
(Utils::HostOsInfo::isMacHost() ? Qt::WindowType(0) : Qt::WindowCloseButtonHint));

QObject::connect(&process, &Utils::Process::textOnStandardOutput, dialog,
[processPtr, dialog, stdOutBufferPtr, stdOutFirstTimePtr,
sesVersionMajorPtr, sesVersionMinorPtr, sesVersionPatchPtr,
enterHardMaintenanceModePtr, exitHardMaintenanceModePtr, userButtonMessageBox] (const QString &text) {
enterHardMaintenanceModePtr, exitHardMaintenanceModePtr, hardMaintenanceRequiredPtr,
startGetBootInfoPtr, stopGetBootInfoPtr, appLoadedPtr,
userButtonMessageBox] (const QString &text) {
stdOutBufferPtr->append(text);
QStringList list = stdOutBufferPtr->split(QRegularExpression(QStringLiteral("[\r\n]")), Qt::KeepEmptyParts);

Expand Down Expand Up @@ -431,14 +447,44 @@ bool alifDownloadFirmware(const QString &port, const QString &originalFirmwareFo
userButtonMessageBox->show();
*enterHardMaintenanceModePtr = false;
*exitHardMaintenanceModePtr = true;
*hardMaintenanceRequiredPtr = true;
}

if (*stopGetBootInfoPtr && out.contains(QStringLiteral("HP_BOOT")))
{
*appLoadedPtr = true;
}

if (*stopGetBootInfoPtr && out.contains(QStringLiteral("2 - Device Information")))
{
processPtr->write(QStringLiteral("\n"));
}

if (*startGetBootInfoPtr && out.contains(QStringLiteral("2 - Device Information")))
{
processPtr->write(QStringLiteral("2\n"));
}

if (*stopGetBootInfoPtr && out.contains(QStringLiteral("1 - Get TOC info")))
{
processPtr->write(QStringLiteral("\n"));
}

if (*startGetBootInfoPtr && out.contains(QStringLiteral("1 - Get TOC info")))
{
processPtr->write(QStringLiteral("1\n"));
*startGetBootInfoPtr = false;
*stopGetBootInfoPtr = true;
}

if (out.startsWith("\e"))
{
continue;
}

// More terminal cleanup.
out.remove(QStringLiteral("\e[?25l"));
out.remove(QRegularExpression(QStringLiteral("\e\\[94m.*$")));

dialog->appendPlainText(out);
}
Expand Down Expand Up @@ -612,62 +658,102 @@ bool alifDownloadFirmware(const QString &port, const QString &originalFirmwareFo
{
QApplication::processEvents();
}
}
else if(process.result() == Utils::ProcessResult::TerminatedAbnormally)
{
result = false;
goto cleanup;
}
}

// Erase Mram
{
QStringList args = QStringList() << QStringLiteral("-e") << QStringLiteral("APP");
if (!hardMaintenanceRequired) // Check if an app is loaded.
{
startGetBootInfo = true;

QString command = QString(QStringLiteral("%1 %2")).arg(appWriteMramBinary.toString()).arg(args.join(QLatin1Char(' ')));
dialog->appendColoredText(command);
QStringList args = QStringList();

std::chrono::seconds timeout(300); // 5 minutes...
process.setTextChannelMode(Utils::Channel::Output, Utils::TextChannelMode::MultiLine);
process.setTextChannelMode(Utils::Channel::Error, Utils::TextChannelMode::MultiLine);
process.setProcessMode(Utils::ProcessMode::Writer);
process.setWorkingDirectory(appWriteMramBinary.parentDir());
process.setCommand(Utils::CommandLine(appWriteMramBinary, args));
process.runBlocking(timeout, Utils::EventLoopMode::On, QEventLoop::AllEvents);
QString command = QString(QStringLiteral("%1 %2")).arg(maintenanceBinary.toString()).arg(args.join(QLatin1Char(' ')));
dialog->appendColoredText(command);

if((process.result() != Utils::ProcessResult::FinishedWithSuccess) && (process.result() != Utils::ProcessResult::TerminatedAbnormally))
{
QMessageBox box(QMessageBox::Critical, Tr::tr("Alif Tools"), Tr::tr("Timeout Error!"), QMessageBox::Ok, Core::ICore::dialogParent(),
Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint |
(Utils::HostOsInfo::isMacHost() ? Qt::WindowType(0) : Qt::WindowCloseButtonHint));
box.setDetailedText(command + QStringLiteral("\n\n") + process.stdOut() + QStringLiteral("\n") + process.stdErr());
box.setDefaultButton(QMessageBox::Ok);
box.setEscapeButton(QMessageBox::Cancel);
box.exec();
std::chrono::seconds timeout(300); // 5 minutes...
process.setTextChannelMode(Utils::Channel::Output, Utils::TextChannelMode::MultiLine);
process.setTextChannelMode(Utils::Channel::Error, Utils::TextChannelMode::MultiLine);
process.setProcessMode(Utils::ProcessMode::Writer);
process.setWorkingDirectory(maintenanceBinary.parentDir());
process.setCommand(Utils::CommandLine(maintenanceBinary, args));
process.runBlocking(timeout, Utils::EventLoopMode::On, QEventLoop::AllEvents);

result = false;
goto cleanup;
}
else if(process.result() == Utils::ProcessResult::TerminatedAbnormally)
{
result = false;
goto cleanup;
}
}
userButtonMessageBox->hide();

if (QMessageBox::information(Core::ICore::dialogParent(),
Tr::tr("Alif Tools"),
Tr::tr("Please turn off the hard maintenance mode switch, if enabled, and press Ok."),
QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok)
!= QMessageBox::Ok)
{
result = false;
goto cleanup;
}
if((process.result() != Utils::ProcessResult::FinishedWithSuccess) && (process.result() != Utils::ProcessResult::TerminatedAbnormally))
{
QMessageBox box(QMessageBox::Critical, Tr::tr("Alif Tools"), Tr::tr("Timeout Error!"), QMessageBox::Ok, Core::ICore::dialogParent(),
Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint |
(Utils::HostOsInfo::isMacHost() ? Qt::WindowType(0) : Qt::WindowCloseButtonHint));
box.setDetailedText(command + QStringLiteral("\n\n") + process.stdOut() + QStringLiteral("\n") + process.stdErr());
box.setDefaultButton(QMessageBox::Ok);
box.setEscapeButton(QMessageBox::Cancel);
box.exec();

result = false;
goto cleanup;
}
else if(process.result() == Utils::ProcessResult::TerminatedAbnormally)
{
result = false;
goto cleanup;
}
}

if (appLoaded || hardMaintenanceRequired) // Erase Mram
{
QStringList args = QStringList() << QStringLiteral("-e") << QStringLiteral("APP");

QString command = QString(QStringLiteral("%1 %2")).arg(appWriteMramBinary.toString()).arg(args.join(QLatin1Char(' ')));
dialog->appendColoredText(command);

std::chrono::seconds timeout(300); // 5 minutes...
process.setTextChannelMode(Utils::Channel::Output, Utils::TextChannelMode::MultiLine);
process.setTextChannelMode(Utils::Channel::Error, Utils::TextChannelMode::MultiLine);
process.setProcessMode(Utils::ProcessMode::Writer);
process.setWorkingDirectory(appWriteMramBinary.parentDir());
process.setCommand(Utils::CommandLine(appWriteMramBinary, args));
process.runBlocking(timeout, Utils::EventLoopMode::On, QEventLoop::AllEvents);

if((process.result() != Utils::ProcessResult::FinishedWithSuccess) && (process.result() != Utils::ProcessResult::TerminatedAbnormally))
{
QMessageBox box(QMessageBox::Critical, Tr::tr("Alif Tools"), Tr::tr("Timeout Error!"), QMessageBox::Ok, Core::ICore::dialogParent(),
Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint |
(Utils::HostOsInfo::isMacHost() ? Qt::WindowType(0) : Qt::WindowCloseButtonHint));
box.setDetailedText(command + QStringLiteral("\n\n") + process.stdOut() + QStringLiteral("\n") + process.stdErr());
box.setDefaultButton(QMessageBox::Ok);
box.setEscapeButton(QMessageBox::Cancel);
box.exec();

result = false;
goto cleanup;
}
else if(process.result() == Utils::ProcessResult::TerminatedAbnormally)
{
result = false;
goto cleanup;
}

if (QMessageBox::information(Core::ICore::dialogParent(),
Tr::tr("Alif Tools"),
Tr::tr("Please disconnect your OpenMV Cam from your computer, turn off the hard maintenance mode switch, if enabled, reconnect your OpenMV Cam to your computer, and then press Ok."),
QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok)
!= QMessageBox::Ok)
{
result = false;
goto cleanup;
}
}

if((current_version_major < sesVersionMajor)
|| ((current_version_major == sesVersionMajor) && (current_version_minor < sesVersionMinor))
|| ((current_version_major == sesVersionMajor) && (current_version_minor == sesVersionMinor) && (current_version_patch < sesVersionPatch)))
if(hardMaintenanceRequired
|| (sesVersionMajor < current_version_major)
|| ((sesVersionMajor == current_version_major) && (sesVersionMinor < current_version_minor))
|| ((sesVersionMajor == current_version_major) && (sesVersionMinor == current_version_minor) && (sesVersionPatch < current_version_patch)))
{
// Update System Package
{
Expand Down

0 comments on commit 2fb7f9f

Please sign in to comment.