From 9db2524e5a36fc2059db73380982fc2806c484c8 Mon Sep 17 00:00:00 2001 From: Nanosonde <2073569+nanosonde@users.noreply.github.com> Date: Mon, 6 Jul 2020 14:53:30 +0200 Subject: [PATCH] Refactor master reset --- examples/knx-linux/main.cpp | 9 ------- src/knx/bau27B0.cpp | 8 ++++++ src/knx/bau27B0.h | 1 + src/knx/bau57B0.cpp | 8 ++++++ src/knx/bau57B0.h | 3 ++- src/knx/bau_systemB.cpp | 39 +++++++++++++++++++-------- src/knx/bau_systemB.h | 4 ++- src/knx/interface_object.cpp | 6 +++++ src/knx/interface_object.h | 5 ++++ src/knx/security_interface_object.cpp | 2 +- src/knx/security_interface_object.h | 2 +- src/knx_facade.h | 5 ---- 12 files changed, 63 insertions(+), 29 deletions(-) diff --git a/examples/knx-linux/main.cpp b/examples/knx-linux/main.cpp index 2b96854..f835e0e 100644 --- a/examples/knx-linux/main.cpp +++ b/examples/knx-linux/main.cpp @@ -121,15 +121,6 @@ int main(int argc, char **argv) { printf("main() start.\n"); - if (argc > 1) - { - EraseCode eraseCode = (EraseCode) atoi(argv[2]); - - print("Performing factory reset with erase code: "); - println(eraseCode, HEX); - knx.masterReset(eraseCode, 0); - } - uint8_t serialNumber[] = { 0x00, 0xFA, 0x01, 0x02, 0x03, 0x04}; uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; diff --git a/src/knx/bau27B0.cpp b/src/knx/bau27B0.cpp index 2e4c2b4..0ef567a 100644 --- a/src/knx/bau27B0.cpp +++ b/src/knx/bau27B0.cpp @@ -120,6 +120,14 @@ InterfaceObject* Bau27B0::getInterfaceObject(ObjectType objectType, uint8_t obje } } +void Bau27B0::doMasterReset(EraseCode eraseCode, uint8_t channel) +{ + // Common SystemB objects + BauSystemB::doMasterReset(eraseCode, channel); + + _rfMediumObj.masterReset(eraseCode, channel); +} + DataLinkLayer& Bau27B0::dataLinkLayer() { return _dlLayer; diff --git a/src/knx/bau27B0.h b/src/knx/bau27B0.h index af08284..63f2844 100644 --- a/src/knx/bau27B0.h +++ b/src/knx/bau27B0.h @@ -20,6 +20,7 @@ class Bau27B0 : public BauSystemB InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance); DataLinkLayer& dataLinkLayer(); + virtual void doMasterReset(EraseCode eraseCode, uint8_t channel) override; private: RfDataLinkLayer _dlLayer; RfMediumObject _rfMediumObj; diff --git a/src/knx/bau57B0.cpp b/src/knx/bau57B0.cpp index 7d2c007..eee3cc2 100644 --- a/src/knx/bau57B0.cpp +++ b/src/knx/bau57B0.cpp @@ -116,6 +116,14 @@ InterfaceObject* Bau57B0::getInterfaceObject(ObjectType objectType, uint8_t obje } } +void Bau57B0::doMasterReset(EraseCode eraseCode, uint8_t channel) +{ + // Common SystemB objects + BauSystemB::doMasterReset(eraseCode, channel); + + _ipParameters.masterReset(eraseCode, channel); +} + DataLinkLayer& Bau57B0::dataLinkLayer() { return _dlLayer; diff --git a/src/knx/bau57B0.h b/src/knx/bau57B0.h index df0dc4b..85c5ca0 100644 --- a/src/knx/bau57B0.h +++ b/src/knx/bau57B0.h @@ -17,6 +17,7 @@ class Bau57B0 : public BauSystemB InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance); DataLinkLayer& dataLinkLayer(); + virtual void doMasterReset(EraseCode eraseCode, uint8_t channel) override; private: IpParameterObject _ipParameters; IpDataLinkLayer _dlLayer; @@ -25,4 +26,4 @@ class Bau57B0 : public BauSystemB CemiServerObject _cemiServerObject; #endif }; -#endif \ No newline at end of file +#endif diff --git a/src/knx/bau_systemB.cpp b/src/knx/bau_systemB.cpp index 686e682..8d20f59 100644 --- a/src/knx/bau_systemB.cpp +++ b/src/knx/bau_systemB.cpp @@ -169,7 +169,7 @@ bool BauSystemB::configured() return _configured; } -uint8_t BauSystemB::masterReset(EraseCode eraseCode, uint8_t channel) +uint8_t BauSystemB::checkmasterResetValidity(EraseCode eraseCode, uint8_t channel) { static constexpr uint8_t successCode = 0x00; // Where does this come from? It is the code for "success". static constexpr uint8_t invalidEraseCode = 0x02; // Where does this come from? It is the error code for "unspported erase code". @@ -206,18 +206,15 @@ uint8_t BauSystemB::masterReset(EraseCode eraseCode, uint8_t channel) return successCode; } case EraseCode::FactoryReset: + { + // TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER) + println("Factory reset requested. type: with IA"); + return successCode; + } case EraseCode::FactoryResetWithoutIA: { // TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER) - print("Factory reset requested. type: "); - println(eraseCode == EraseCode::FactoryReset ? "FactoryReset with IA" : "FactoryReset without IA"); -#ifdef USE_DATASECURE - // If erase code is FactoryReset or FactoryResetWithoutIA, set FDSK as toolkey again - // and disable security mode. - // FIXME: the A_RestartResponse PDU has still to be sent with the current toolkey. - // Idea: use local confirmation of sent A_RestartResponse PDU to trigger writing the FDSK afterwards - _secIfObj.masterReset(eraseCode); -#endif + println("Factory reset requested. type: without IA"); return successCode; } default: @@ -267,6 +264,21 @@ void BauSystemB::memoryExtReadIndication(Priority priority, HopCountType hopType _appLayer.memoryExtReadResponse(AckRequested, priority, hopType, asap, secCtrl, ReturnCodes::Success, number, memoryAddress, _memory.toAbsolute(memoryAddress)); } +void BauSystemB::doMasterReset(EraseCode eraseCode, uint8_t channel) +{ + _addrTable.masterReset(eraseCode, channel); + _assocTable.masterReset(eraseCode, channel); + _groupObjTable.masterReset(eraseCode, channel); + _appProgram.masterReset(eraseCode, channel); +#ifdef USE_DATASECURE + // If erase code is FactoryReset or FactoryResetWithoutIA, set FDSK as toolkey again + // and disable security mode. + // FIXME: the A_RestartResponse PDU has still to be sent with the current toolkey. + // Idea: use local confirmation of sent A_RestartResponse PDU to trigger writing the FDSK afterwards + _secIfObj.masterReset(eraseCode, channel); +#endif +} + void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, RestartType restartType, EraseCode eraseCode, uint8_t channel) { if (restartType == RestartType::BasicRestart) @@ -275,12 +287,17 @@ void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopTyp } else if (restartType == RestartType::MasterReset) { - uint8_t errorCode = masterReset(eraseCode, channel); + uint8_t errorCode = checkmasterResetValidity(eraseCode, channel); + // We send the restart response now before actually applying the reset values + // Processing time is kRestartProcessTime (example 3 seconds) that we require for the applying the master reset with restart _appLayer.restartResponse(AckRequested, priority, hopType, secCtrl, errorCode, (errorCode == 0) ? kRestartProcessTime : 0); + doMasterReset(eraseCode, channel); } else { // Cannot happen as restartType is just one bit + println("Unhandled restart type."); + _platform.fatalError(); } // Flush the EEPROM before resetting diff --git a/src/knx/bau_systemB.h b/src/knx/bau_systemB.h index 2a7e059..b485942 100644 --- a/src/knx/bau_systemB.h +++ b/src/knx/bau_systemB.h @@ -32,7 +32,7 @@ class BauSystemB : protected BusAccessUnit void writeMemory(); void addSaveRestore(SaveRestore* obj); bool restartRequest(uint16_t asap, const SecurityControl secCtrl); - uint8_t masterReset(EraseCode eraseCode, uint8_t channel); + uint8_t checkmasterResetValidity(EraseCode eraseCode, uint8_t channel); void propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t& numberOfElements, uint16_t startIndex, @@ -100,6 +100,8 @@ class BauSystemB : protected BusAccessUnit void updateGroupObject(GroupObject& go, uint8_t* data, uint8_t length); void nextRestartState(); + virtual void doMasterReset(EraseCode eraseCode, uint8_t channel); + enum RestartState { Idle, diff --git a/src/knx/interface_object.cpp b/src/knx/interface_object.cpp index 6b6aa32..0789992 100644 --- a/src/knx/interface_object.cpp +++ b/src/knx/interface_object.cpp @@ -54,6 +54,12 @@ void InterfaceObject::readPropertyDescription(uint8_t& propertyId, uint8_t& prop } } +void InterfaceObject::masterReset(EraseCode eraseCode, uint8_t channel) +{ + // every interface object shall implement this + // However, for the time being we provide an empty default implementation +} + void InterfaceObject::readProperty(PropertyID id, uint16_t start, uint8_t& count, uint8_t* data) { Property* prop = property(id); diff --git a/src/knx/interface_object.h b/src/knx/interface_object.h index 375d14d..b287735 100644 --- a/src/knx/interface_object.h +++ b/src/knx/interface_object.h @@ -3,6 +3,7 @@ #include #include "property.h" #include "save_restore.h" +#include "knx_types.h" /** Enum for the type of an interface object. See Section 2.2 of knx:3/7/3 */ enum ObjectType @@ -149,6 +150,10 @@ class InterfaceObject : public SaveRestore */ void readPropertyDescription(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access); + // every interface object shall implement this + // However, for the time being we provide an empty default implementation + virtual void masterReset(EraseCode eraseCode, uint8_t channel); + /** * Gets property with PropertyID id if it exists and nullptr otherwise. */ diff --git a/src/knx/security_interface_object.cpp b/src/knx/security_interface_object.cpp index b3f85ce..cf8bbf8 100644 --- a/src/knx/security_interface_object.cpp +++ b/src/knx/security_interface_object.cpp @@ -331,7 +331,7 @@ void SecurityInterfaceObject::errorCode(ErrorCode errorCode) prop->write(data); } -void SecurityInterfaceObject::masterReset(EraseCode eraseCode) +void SecurityInterfaceObject::masterReset(EraseCode eraseCode, uint8_t channel) { // TODO handle different erase codes println("Factory reset of security interface object requested."); diff --git a/src/knx/security_interface_object.h b/src/knx/security_interface_object.h index 5cf9cd7..754f2ea 100644 --- a/src/knx/security_interface_object.h +++ b/src/knx/security_interface_object.h @@ -15,7 +15,7 @@ public: void secureApplicationLayer(SecureApplicationLayer& secAppLayer); - void masterReset(EraseCode eraseCode); + virtual void masterReset(EraseCode eraseCode, uint8_t channel) override; bool isSecurityModeEnabled(); diff --git a/src/knx_facade.h b/src/knx_facade.h index 2d64640..923195f 100644 --- a/src/knx_facade.h +++ b/src/knx_facade.h @@ -93,11 +93,6 @@ template class KnxFacade : private SaveRestore return _bau.configured(); } - void masterReset(EraseCode erasecode, uint8_t channel) - { - _bau.masterReset(erasecode, channel); - } - /** * returns HIGH if led is active on HIGH, LOW otherwise */