diff --git a/src/lib/flash-helper.js b/src/lib/flash-helper.js index f5e70e9e3..42b3adc1f 100644 --- a/src/lib/flash-helper.js +++ b/src/lib/flash-helper.js @@ -16,6 +16,11 @@ const ensureError = utilities.ensureError; // Flashing an NCP firmware can take a few minutes const FLASH_TIMEOUT = 4 * 60000; +// Minimum version of Device OS that supports protected modules +const PROTECTED_MINIMUM_VERSION = '6.0.0'; +const PROTECTED_MINIMUM_SYSTEM_VERSION = 6000; +const PROTECTED_MINIMUM_BOOTLOADER_VERSION = 3000; + async function flashFiles({ device, flashSteps, resetAfterFlash = true, ui, verbose=true }) { let progress = null; progress = verbose ? _createFlashProgress({ flashSteps, ui, verbose }) : null; @@ -358,8 +363,32 @@ function validateDFUSupport({ device, ui }) { } } -function validateModulesForProtection({ modules, device }) { +async function validateModulesForProtection({ modules, device }) { + try { + const s = await device.getProtectionState(); + + if (!s.protected && !s.overridden) { + // Device is not protected -> Don't enforce Device OS version + return; + } + } catch (error) { + // Device does not support device protection -> Don't enforce Device OS version + if (error.message === 'Not supported') { + return; + } + throw error; + } + + for (const module of modules) { + const oldSystem = module.moduleFunction === ModuleInfo.FunctionType.SYSTEM_PART && + module.moduleVersion < PROTECTED_MINIMUM_SYSTEM_VERSION; + const oldBootloader = module.moduleFunction === ModuleInfo.FunctionType.BOOTLOADER && + module.moduleIndex === 0 && module.moduleVersion < PROTECTED_MINIMUM_BOOTLOADER_VERSION; + if (oldSystem || oldBootloader) { + throw new Error(`Cannot downgrade Device OS below version ${PROTECTED_MINIMUM_VERSION} on a Protected Device`); + } + } } module.exports = { diff --git a/src/lib/flash-helper.test.js b/src/lib/flash-helper.test.js index 87c5625ac..d8145301d 100644 --- a/src/lib/flash-helper.test.js +++ b/src/lib/flash-helper.test.js @@ -689,29 +689,29 @@ describe('flash-helper', () => { beforeEach(() => { device = { - getProtectedState: sinon.stub(), + getProtectionState: sinon.stub(), }; }); describe('device is not protected', () => { beforeEach(() => { - device.getProtectedState.returns({ protected: false, overriden: false }); + device.getProtectionState.returns({ protected: false, overridden: false }); }); - it('does does not reject old modules', () => { + it('does does not reject old modules', async () => { let error; try { - validateModulesForProtection({ device, modules: modulesOldBootloader }); + await validateModulesForProtection({ device, modules: modulesOldBootloader }); } catch (_error) { error = _error; } expect(error).to.be.undefined; }); - it('does does not reject new modules', () => { + it('does does not reject new modules', async () => { let error; try { - validateModulesForProtection({ device, modules: modulesNew }); + await validateModulesForProtection({ device, modules: modulesNew }); } catch (_error) { error = _error; } @@ -719,35 +719,35 @@ describe('flash-helper', () => { }); }); - describe('device is protected', () => { + describe('device is protected', () => { beforeEach(() => { - device.getProtectedState.returns({ protected: true, overriden: false }); + device.getProtectionState.returns({ protected: true, overridden: false }); }); - it('throws an exception if the bootloader is too old', () => { + it('throws an exception if the bootloader is too old', async () => { let error; try { - validateModulesForProtection({ device, modules: modulesOldBootloader }); + await validateModulesForProtection({ device, modules: modulesOldBootloader }); } catch (_error) { error = _error; } expect(error).to.have.property('message').that.eql('Cannot downgrade Device OS below version 6.0.0 on a Protected Device'); }); - it('throws an exception if the system part is too old', () => { + it('throws an exception if the system part is too old', async () => { let error; try { - validateModulesForProtection({ device, modules: modulesOldSystem }); + await validateModulesForProtection({ device, modules: modulesOldSystem }); } catch (_error) { error = _error; } expect(error).to.have.property('message').that.eql('Cannot downgrade Device OS below version 6.0.0 on a Protected Device'); }); - it('does does not reject new modules', () => { + it('does does not reject new modules', async () => { let error; try { - validateModulesForProtection({ device, modules: modulesNew }); + await validateModulesForProtection({ device, modules: modulesNew }); } catch (_error) { error = _error; } @@ -757,23 +757,23 @@ describe('flash-helper', () => { describe('device does not support protection', () => { beforeEach(() => { - device.getProtectedState.throws(new Error('Not supported')); + device.getProtectionState.throws(new Error('Not supported')); }); - it('does does not reject old modules', () => { + it('does does not reject old modules', async () => { let error; try { - validateModulesForProtection({ device, modules: modulesOldBootloader }); + await validateModulesForProtection({ device, modules: modulesOldBootloader }); } catch (_error) { error = _error; } expect(error).to.be.undefined; }); - it('does does not reject new modules', () => { + it('does does not reject new modules', async () => { let error; try { - validateModulesForProtection({ device, modules: modulesNew }); + await validateModulesForProtection({ device, modules: modulesNew }); } catch (_error) { error = _error; }