Index: sources/update/IEnterBootLoader.h =================================================================== diff -u --- sources/update/IEnterBootLoader.h (revision 0) +++ sources/update/IEnterBootLoader.h (revision 7cf31f6cfef97bb564a103c263821a3b722c8a2b) @@ -0,0 +1,43 @@ +/*! + * + * Copyright (c) 2023 Diality Inc. - All Rights Reserved. + * + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file IEnterBootloader.h + * \author (last) Phil Braica + * \date (last) 23-Jan-2023 + * \author (original) Phil Braica + * \date (original) 23-Jan-2023 + * + */ + +#ifndef I_ENTER_BOOT_LOADER_H_ +#define I_ENTER_BOOT_LOADER_H_ + +namespace SwUpdate { + +/*! + * \brief The interface class that allows the update to call the app to enter bootloader. + * + * See sendEnterBootloader. + */ +class IEnterBootLoader { +public: + /*! + * \brief Tell app layer to send it's app msg to enter bootloader. + * + * Bootloader will timeout after 5s or so if it hasn't seen a "start" + * command. This allows the App layer to evolve it's messages independently + * from the update software which can be basically static. + * + * \param asHd True=do the HD, False=do the DG. + */ + virtual void sendEnterBootloader(bool asHd) = 0; +}; + +} // namespace SwUpdate + +#endif // I_ENTER_BOOT_LOADER_H_ Index: sources/update/MsgLink.h =================================================================== diff -u -r110fa8df5fc77830fa05d04af55b349dd8f9c6d9 -r7cf31f6cfef97bb564a103c263821a3b722c8a2b --- sources/update/MsgLink.h (.../MsgLink.h) (revision 110fa8df5fc77830fa05d04af55b349dd8f9c6d9) +++ sources/update/MsgLink.h (.../MsgLink.h) (revision 7cf31f6cfef97bb564a103c263821a3b722c8a2b) @@ -131,7 +131,7 @@ _expecting = false; _ew.fireEvent(); } - + /*! * \brief Send a message, wait as needed for retry/response. * Index: sources/update/Package.cpp =================================================================== diff -u -rd49c2482be5cf36868b964681d0e93fb3abe5b7b -r7cf31f6cfef97bb564a103c263821a3b722c8a2b --- sources/update/Package.cpp (.../Package.cpp) (revision d49c2482be5cf36868b964681d0e93fb3abe5b7b) +++ sources/update/Package.cpp (.../Package.cpp) (revision 7cf31f6cfef97bb564a103c263821a3b722c8a2b) @@ -15,17 +15,20 @@ #include "Package.h" #include "Obfuscate.h" -#include #include "IDataProvider.h" +#include "IEnterBootLoader.h" #include "UiSwUpdate.h" #include "UiProtocol.h" -#include -#include -#include +#include #include #include +#include +// For Debug: +// #include +// #include + /*! * Must be greater than a signature, and big enough to be good for streaming. * @@ -60,7 +63,8 @@ _info(""), _startXml(0), _startData(0), - _pFileUpdating(nullptr) { + _pFileUpdating(nullptr), + _pIEnterBL(nullptr) { ; // NOP. } @@ -200,7 +204,7 @@ for (std::size_t ii = 0; ii < _streams.size(); ii++) { sv.push_back(&_streams[ii]); } - return SwUpdate::UiSwUpdate::instance().start(sv); + return SwUpdate::UiSwUpdate::instance().start(sv, _pIEnterBL); } /*! @@ -261,7 +265,7 @@ sv.push_back(&_streams[ii]); } - return SwUpdate::UiSwUpdate::instance().start(sv); + return SwUpdate::UiSwUpdate::instance().start(sv, _pIEnterBL); } /*! @@ -840,29 +844,26 @@ { if (std::find(_avoid.begin(), _avoid.end(), fileNamePath) == _avoid.end()) { _avoid.push_back(fileNamePath); - qDebug() << "Not added " << QString::fromStdString(fileNamePath) << "\n"; + // qDebug() << "Not added " << QString::fromStdString(fileNamePath) << "\n"; } } } else { - // Keep seeing errno = 0x18 = 24 which is EMFILE = ran out of file handles for the app. - // Which indicates an fclose didn't happen, which makes no sense. - int err = errno; - qDebug() << "Not opened " << QString::fromStdString(fileNamePath) << " errno = " << err << "\n"; + // int err = errno; + // qDebug() << "Not opened " << QString::fromStdString(fileNamePath) << " errno = " << err << "\n"; } } catch (...) { - qDebug() << "Throw 1\n"; + // qDebug() << "Throw 1\n"; ; // Allow the user to keep iterating across the rest of this directory. } // Close it. if (fp != NULL) { int fclose_rv = fclose(fp); if (fclose_rv != 0) { - int err = errno; - - qDebug() << "Not closed " << QString::fromStdString(fileNamePath) << " errno = " << err << " fcloserv = " << fclose_rv << "\n"; + // int err = errno; + // qDebug() << "Not closed " << QString::fromStdString(fileNamePath) << " errno = " << err << " fcloserv = " << fclose_rv << "\n"; } } } Index: sources/update/Package.h =================================================================== diff -u -r61c46e9379ca82d826fbe7fae018b8362a107d9d -r7cf31f6cfef97bb564a103c263821a3b722c8a2b --- sources/update/Package.h (.../Package.h) (revision 61c46e9379ca82d826fbe7fae018b8362a107d9d) +++ sources/update/Package.h (.../Package.h) (revision 7cf31f6cfef97bb564a103c263821a3b722c8a2b) @@ -19,6 +19,7 @@ #include "UpdateProtocol.h" #include "UiUpdateStatus.h" #include "IDataProvider.h" +#include "IEnterBootLoader.h" #include #include @@ -29,6 +30,7 @@ #include "PackageItem.h" #include "SignRsa.h" + /*! * \brief Utility container for UI */ @@ -251,6 +253,16 @@ // Reboot to run the firmware (both HD and DG) apps if they are valid. void rebootFW(); + + /*! + * \brief Tell this class which interface to use if any to enter bootloader. + * + * \param pIEnterBootLoader Pointer to interface class. + */ + void setEnterBootloader(SwUpdate::IEnterBootLoader *pIEnterBootLoader) { + _pIEnterBL = pIEnterBootLoader; + } + protected: bool parseInternal(FILE *fp); @@ -284,6 +296,7 @@ std::size_t _startData; ///< Where data starts in the file. FILE * _pFileUpdating; ///< File being updated. + SwUpdate::IEnterBootLoader* _pIEnterBL; ///< Command interface for app to enter bootloader. std::vector _streams; ///< Target streams. std::vector _packages; ///< Packages. std::vector _avoid; ///< Avoid these. Index: sources/update/UiProtocol.cpp =================================================================== diff -u -r110fa8df5fc77830fa05d04af55b349dd8f9c6d9 -r7cf31f6cfef97bb564a103c263821a3b722c8a2b --- sources/update/UiProtocol.cpp (.../UiProtocol.cpp) (revision 110fa8df5fc77830fa05d04af55b349dd8f9c6d9) +++ sources/update/UiProtocol.cpp (.../UiProtocol.cpp) (revision 7cf31f6cfef97bb564a103c263821a3b722c8a2b) @@ -15,10 +15,10 @@ */ #include "UiProtocol.h" -#include "UiSwUpdate.h" #include "IDataProvider.h" - +#include "IEnterBootLoader.h" #include "Logger.h" +#include "UiSwUpdate.h" #include #include @@ -62,8 +62,9 @@ _retries(0), _lastRx{(uint8)0}, _link(KBPS_WIRE), - _pThread(nullptr), - _completedOk(false) + _pThread(nullptr), + _completedOk(false), + _pEnterBL(nullptr) { ; // NOP. } @@ -253,7 +254,13 @@ // Reset the transfered counter. _transfered = 0; _link.resetRetries(); - + + // If enterbootloader exists, use it. + if (_pEnterBL != nullptr) { + _pEnterBL->sendEnterBootloader( + (_target == HD) || (_target == HDFPGA)); + } + // Send start. _state = UpdateState::Starting; bool ok = _sendCommand(SwUpdateCmdEnum::Start); Index: sources/update/UiProtocol.h =================================================================== diff -u -r61c46e9379ca82d826fbe7fae018b8362a107d9d -r7cf31f6cfef97bb564a103c263821a3b722c8a2b --- sources/update/UiProtocol.h (.../UiProtocol.h) (revision 61c46e9379ca82d826fbe7fae018b8362a107d9d) +++ sources/update/UiProtocol.h (.../UiProtocol.h) (revision 7cf31f6cfef97bb564a103c263821a3b722c8a2b) @@ -13,25 +13,25 @@ * \date (original) 23-Jan-2023 * */ + #ifndef UI_PROTOCOL_H_ #define UI_PROTOCOL_H_ +#include "IDataProvider.h" +#include "IEnterBootLoader.h" #include "HalStdTypes.h" #include "MsgLink.h" #include "UpdateProtocol.h" #include "UiUpdateStatus.h" -#include "IDataProvider.h" + #include #include #include #include namespace SwUpdate { -/** Forward declare. */ -class IDataProvider; - /*! * This class uses a thread plus a waitable condition variable * to impliment a linear procedure to update one firmware @@ -114,14 +114,15 @@ * \brief Start updating. * * \param pProvider Data provider. - * \param pNext Next if the updates occur in a chain. + * \param pEnterBoot The enter bootloader object or nullpointer. * * \return True on started ok. */ - void setProvider(IDataProvider* pProvider) { + void setProvider(IDataProvider* pProvider, SwUpdate::IEnterBootLoader *pEnterBoot) { std::lock_guard lockApi(_apiMutex); _pProvider = pProvider; _maxTransfer = pProvider->totalSize; + _pEnterBL = pEnterBoot; } static uint8 getNextMsgSlotId(); @@ -227,6 +228,7 @@ ::std::thread* _pThread; ///< Thread. ::std::mutex _apiMutex; ///< Mutex API. bool _completedOk; ///< Completed ok, false is either not started or in progress. + IEnterBootLoader * _pEnterBL; ///< Enter bootloader class. }; /*! Index: sources/update/UiSwUpdate.cpp =================================================================== diff -u -r20b370a54d2737831b307a0de82aec9e06e2b772 -r7cf31f6cfef97bb564a103c263821a3b722c8a2b --- sources/update/UiSwUpdate.cpp (.../UiSwUpdate.cpp) (revision 20b370a54d2737831b307a0de82aec9e06e2b772) +++ sources/update/UiSwUpdate.cpp (.../UiSwUpdate.cpp) (revision 7cf31f6cfef97bb564a103c263821a3b722c8a2b) @@ -16,6 +16,8 @@ #include "UiSwUpdate.h" #include "IDataProvider.h" +#include "IEnterBootLoader.h" + #include namespace SwUpdate { @@ -67,12 +69,13 @@ /*! * \brief Start updating. * - * \param dataProviders + * \param dataProviders Vector of Data providers. + * \param pEnterBL Class to call if need to enter bootloader. * * \return True on successfully started. */ bool UiSwUpdate::start( - std::vector & dataProviders) { + std::vector & dataProviders, SwUpdate::IEnterBootLoader * pEnterBL) { // Lock. std::lock_guard lock(_mutexApi); @@ -104,7 +107,7 @@ // Set the provider. UiProtocol* pTarget = _all[target]; aboutToStart[target] = pTarget; - _all[target]->setProvider(pDp); + _all[target]->setProvider(pDp, pEnterBL); // Ensure all non-file actions happen after the tasks. priorTargets.push_back(pTarget); Index: sources/update/UiSwUpdate.h =================================================================== diff -u -r20b370a54d2737831b307a0de82aec9e06e2b772 -r7cf31f6cfef97bb564a103c263821a3b722c8a2b --- sources/update/UiSwUpdate.h (.../UiSwUpdate.h) (revision 20b370a54d2737831b307a0de82aec9e06e2b772) +++ sources/update/UiSwUpdate.h (.../UiSwUpdate.h) (revision 7cf31f6cfef97bb564a103c263821a3b722c8a2b) @@ -17,6 +17,7 @@ #ifndef UI_SW_UPDATE_H_ #define UI_SW_UPDATE_H_ + #include "HalStdTypes.h" #include "MsgLink.h" #include "UpdateProtocol.h" @@ -26,10 +27,12 @@ #include #include + namespace SwUpdate { /** Forward declare. */ class IDataProvider; +class IEnterBootLoader; /*! * This class uses a thread plus a waitable condition variable @@ -52,15 +55,10 @@ */ static UiSwUpdate & instance(); - /*! - * \brief Start updating. - * - * \param dataProviders - * - * \return True on successfully started. - */ + // Start updating. bool start( - std::vector& dataProviders); + std::vector& dataProviders, + SwUpdate::IEnterBootLoader* pEnterBL); /*! * \brief Is it completed? Index: sources/update/UpdateProtocol.h =================================================================== diff -u -r93add8761e6a95bb575418ca3ad32818cb7a1b59 -r7cf31f6cfef97bb564a103c263821a3b722c8a2b --- sources/update/UpdateProtocol.h (.../UpdateProtocol.h) (revision 93add8761e6a95bb575418ca3ad32818cb7a1b59) +++ sources/update/UpdateProtocol.h (.../UpdateProtocol.h) (revision 7cf31f6cfef97bb564a103c263821a3b722c8a2b) @@ -109,13 +109,13 @@ so that the FW will dump it's indexes and be ready for new data. */ typedef enum SwUpdateCmdEnum { - Start = 0, - Abort, - RunApp, - Verify, - Version, - Verified, - Resync + Start = 0, ///< Start the update process. + Abort, ///< Abort the update process. + RunApp, ///< Ask FW to run it's app if it's valid/exists. + Verify, ///< Ask for the verify token. + Version, ///< Ask for the verified token. + Verified, ///< Tell FW that UI things the app is valid, FW might agree. + Resync ///< Data transfer resync. } SwUpdateCmdEnum; /*! Index: sources/update/VSwUpdate.cpp =================================================================== diff -u -r61c46e9379ca82d826fbe7fae018b8362a107d9d -r7cf31f6cfef97bb564a103c263821a3b722c8a2b --- sources/update/VSwUpdate.cpp (.../VSwUpdate.cpp) (revision 61c46e9379ca82d826fbe7fae018b8362a107d9d) +++ sources/update/VSwUpdate.cpp (.../VSwUpdate.cpp) (revision 7cf31f6cfef97bb564a103c263821a3b722c8a2b) @@ -103,6 +103,12 @@ this , &VSWUpdate::onSettingsDone); connect(&_ApplicationController, &ApplicationController::didPOSTDone, this , &VSWUpdate::onPostDone); + + // Tell the package code this class will send the enter bootloader command, + // if not set, this is skipped. + _package.setEnterBootloader(this); + + // Must be > 1 Hz. _timer.start(500); } @@ -247,20 +253,32 @@ return QVariant(); } + /*! + * \brief IEnterBootLoader interface. + * + * \param asHd If true HD processor if false DG processor. + */ +void VSWUpdate::sendEnterBootloader(bool asHd) { + sendAppCommand(MSG_ID_ENTER_BOOTLOADER_NOW, asHd); +} + +/*! * \brief The start/stop button was clicked. */ void VSWUpdate::startStopBtnClicked() { // Either we are updating or not. if (_updating) { + // Abort. _CanInterface.setSWUpdateMode(false); _package.abort(); set_progress("Aborted."); startStopUpdate("Aborted update", false); _ApplicationController.enableKeepAlive(true); } else { + // Start. int row_index = (int)_selected; if (row_index >= 0) { std::vector update; @@ -284,8 +302,6 @@ // // If these did fail which is extremely unlikely it feels to the user like they didn't quite // press the start button. - sendAppCommand(MSG_ID_ENTER_BOOTLOADER_NOW); - sendAppCommand(MSG_ID_ENTER_BOOTLOADER_NOW); ok = _package.start_hasKey(package_location, update); if (ok) @@ -419,9 +435,11 @@ * 0x8091 Set boot bit to stay in bootloader after reboot (MSG_ID_HD_SET_ENTER_BOOTLOADER) * * \param cmd 16 bit command. + * \param asHd As the HD (true) or else the DG (false) */ -void VSWUpdate::sendAppCommand(uint16 cmd) { +void VSWUpdate::sendAppCommand(uint16 cmd, bool asHd) { + // Do twice. for (std::size_t ii = 0; ii < 2; ii++) { QByteArray msg; msg.append(ePayload_Sync); // 0xA5 @@ -448,7 +466,7 @@ // Send it. // eChlid_UI_HD = 0x100, ///< UI => HD [Out] // eChlid_UI_DG = 0x110, ///< UI => DG [Out] - _CanInterface.sendSWUpdateMsg(ii == 0 ? eChlid_UI_HD : eChlid_UI_DG, (uint8_t *)msg.data(), 8); + _CanInterface.sendSWUpdateMsg(asHd ? eChlid_UI_HD : eChlid_UI_DG, (uint8_t *)msg.data(), 8); // Sleep long enough to ensure FW acted on it. // Index: sources/update/VSwUpdate.h =================================================================== diff -u -rf0118ee7e526bb64e9f78059f030929792a5a98a -r7cf31f6cfef97bb564a103c263821a3b722c8a2b --- sources/update/VSwUpdate.h (.../VSwUpdate.h) (revision f0118ee7e526bb64e9f78059f030929792a5a98a) +++ sources/update/VSwUpdate.h (.../VSwUpdate.h) (revision 7cf31f6cfef97bb564a103c263821a3b722c8a2b) @@ -17,20 +17,24 @@ #ifndef V_SW_UPDATE_H_ #define V_SW_UPDATE_H_ -#include +#include "IEnterBootLoader.h" +#include "Package.h" + #include + +#include #include #include #include #include #include #include -#include "Package.h" + /*! * \brief The view model for software update. */ -class VSWUpdate : public QAbstractTableModel +class VSWUpdate : public QAbstractTableModel, SwUpdate::IEnterBootLoader { Q_OBJECT Q_ENUMS(Roles) @@ -203,6 +207,9 @@ } } + // IEnterBootLoader interface. + void sendEnterBootloader(bool asHd); + signals: /*! Signal that data changed. */ @@ -252,7 +259,7 @@ protected: // Write an app styled can msg to control both FW nodes. - void sendAppCommand(uint16 cmd); + void sendAppCommand(uint16 cmd, bool asHd); // Log a message. void writeLog(const QString& msg, bool isDebug); @@ -302,6 +309,7 @@ bool _postWasOk; ///< Post was ok flag. bool _settingsOk; ///< Version and settings are ok. bool _wasTrialBoot; ///< This was a trial boot or normal. + std::chrono::time_point _lastPing; ///< Last ping time. }; #endif // V_SW_UPDATE_H_