-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/sc 123873/check hash #693
Changes from 5 commits
58265e3
85e6c95
752eb20
04d2c14
1f23d9c
9d32f23
4606e41
cfb6edd
d42e020
698d47d
6e3fcfd
cdcf8c9
bb4d225
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,8 +41,9 @@ class BinaryCommand { | |
async inspectBinary(file) { | ||
await this._checkFile(file); | ||
const extractedFiles = await this._extractFiles(file); | ||
const parsedBinaryInfo = await this._parseApplicationBinary(extractedFiles.application); | ||
await this._verifyBundle(parsedBinaryInfo, extractedFiles.assets); | ||
const parsedAppInfo = await this._parseApplicationBinary(extractedFiles.application); | ||
const assets = extractedFiles.assets; | ||
await this._verifyBundle(parsedAppInfo, assets); | ||
} | ||
|
||
async _checkFile(file) { | ||
|
@@ -85,21 +86,23 @@ class BinaryCommand { | |
return fileInfo; | ||
} | ||
|
||
async _verifyBundle(binaryFileInfo, assets) { | ||
if (binaryFileInfo.assets && assets.length){ | ||
async _verifyBundle(appInfo, assets) { | ||
const appAssets = appInfo.assets; | ||
if (appAssets && assets.length > 0) { | ||
console.log('It depends on assets:'); | ||
for (const assetInfo of binaryFileInfo.assets) { | ||
const asset = assets.find((asset) => asset.name === assetInfo.name); | ||
for (const appAsset of appAssets) { | ||
const asset = assets.find((bundleAsset) => bundleAsset.name === appAsset.name); | ||
if (asset) { | ||
const valid = isAssetValid(asset.data, assetInfo); | ||
const valid = isAssetValid(asset.data, appAsset); | ||
// isAssetValid(); | ||
|
||
if (valid) { | ||
console.log(' ' + chalk.bold(assetInfo.name) + ' (hash ' + assetInfo.hash + ')'); | ||
console.log(' ' + chalk.bold(appAsset.name) + ' (hash ' + appAsset.hash + ')'); | ||
} else { | ||
console.log(chalk.red(' ' + assetInfo.name + ' failed' + ' (hash should be ' + assetInfo.hash + ')')); | ||
console.log(chalk.red(' ' + appAsset.name + ' failed' + ' (hash should be ' + appAsset.hash + ')')); | ||
} | ||
} else { | ||
console.log(chalk.red(' ' + assetInfo.name + ' failed' + ' (hash should be ' + assetInfo.hash + ' but is not in the bundle)')); | ||
console.log(chalk.red(' ' + appAsset.name + ' failed' + ' (hash should be ' + appAsset.hash + ' but is not in the bundle)')); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No functional change here. Felt like the readability of this code could be improved. |
||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
const fs = require('fs-extra'); | ||
const os = require('os'); | ||
const ParticleApi = require('./api'); | ||
const { ModuleInfo } = require('binary-version-reader'); | ||
const { ModuleInfo, unwrapAssetModule } = require('binary-version-reader'); | ||
const { errors: { usageError } } = require('../app/command-processor'); | ||
const usbUtils = require('./usb-util'); | ||
const CLICommandBase = require('./base'); | ||
|
@@ -16,6 +16,7 @@ const { knownAppNames, knownAppsForPlatform } = require('../lib/known-apps'); | |
const { sourcePatterns, binaryPatterns, binaryExtensions } = require('../lib/file-types'); | ||
const deviceOsUtils = require('../lib/device-os-version-util'); | ||
const semver = require('semver'); | ||
const crypto = require('crypto'); | ||
const { | ||
createFlashSteps, | ||
filterModulesToFlash, | ||
|
@@ -125,40 +126,82 @@ module.exports = class FlashCommand extends CLICommandBase { | |
const { api, auth } = this._particleApi(); | ||
const device = await usbUtils.getOneUsbDevice({ idOrName: deviceIdOrName, api, auth, ui: this.ui }); | ||
|
||
const platformName = platformForId(device.platformId).name; | ||
const platformId = device.platformId; | ||
const platformName = platformForId(platformId).name; | ||
const currentDeviceOsVersion = device.firmwareVersion; | ||
|
||
this.ui.write(`Flashing ${platformName} ${deviceIdOrName || device.id}`); | ||
|
||
validateDFUSupport({ device, ui: this.ui }); | ||
|
||
let { skipDeviceOSFlash, files: filesToFlash } = await this._prepareFilesToFlash({ | ||
knownApp, | ||
parsedFiles, | ||
platformId: device.platformId, | ||
platformId, | ||
platformName, | ||
target | ||
}); | ||
|
||
filesToFlash = await this._processBundle({ filesToFlash }); | ||
|
||
const fileModules = await parseModulesToFlash({ files: filesToFlash }); | ||
await this._validateModulesForPlatform({ modules: fileModules, platformId: device.platformId, platformName }); | ||
|
||
const eligibleModules = await this._filterAssetsOnDevice(device, fileModules); | ||
|
||
await this._validateModulesForPlatform({ modules: eligibleModules, platformId, platformName }); | ||
|
||
const deviceOsBinaries = await this._getDeviceOsBinaries({ | ||
currentDeviceOsVersion: device.firmwareVersion, | ||
currentDeviceOsVersion, | ||
skipDeviceOSFlash, | ||
target, | ||
modules: fileModules, | ||
platformId: device.platformId, | ||
modules: eligibleModules, | ||
platformId, | ||
applicationOnly | ||
}); | ||
const deviceOsModules = await parseModulesToFlash({ files: deviceOsBinaries }); | ||
let modulesToFlash = [...fileModules, ...deviceOsModules]; | ||
modulesToFlash = filterModulesToFlash({ modules: modulesToFlash, platformId: device.platformId }); | ||
let modulesToFlash = [...eligibleModules, ...deviceOsModules]; | ||
modulesToFlash = filterModulesToFlash({ modules: modulesToFlash, platformId }); | ||
|
||
const flashSteps = await createFlashSteps({ | ||
modules: modulesToFlash, | ||
isInDfuMode: device.isInDfuMode, | ||
platformId | ||
}); | ||
|
||
const flashSteps = await createFlashSteps({ modules: modulesToFlash, isInDfuMode: device.isInDfuMode , platformId: device.platformId }); | ||
await flashFiles({ device, flashSteps, ui: this.ui }); | ||
} | ||
|
||
async _filterAssetsOnDevice(device, modules) { | ||
if (device.isInDfuMode) { | ||
device = await usbUtils.reopenInNormalMode(device, { reset: true }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use a different approach because this makes flashing less reliable. If the application firmware is crashing and someone manually puts the device in DFU mode to reflash it and the CLI reopens it in normal mode, the device will crash before it can get the asset info. This will also call I think we could create the flash steps as if we're flashing all the assets, but in |
||
} | ||
const { available } = await device.getAssetInfo(); | ||
|
||
const filteredModules = await Promise.all( | ||
modules.map(async (module) => { | ||
if (module.prefixInfo.moduleFunction !== ModuleInfo.FunctionType.ASSET) { | ||
return module; // Keep non-asset modules | ||
} | ||
|
||
const hashAssetToBeFlashed = await this._get256Hash(module); | ||
if (available.some((asset) => { | ||
return hashAssetToBeFlashed === asset.hash; | ||
})) { | ||
this.ui.write(`Skipping asset ${path.basename(module.filename)} because it is already on the device`); | ||
return null; | ||
} | ||
return module; | ||
}) | ||
); | ||
return filteredModules.filter(Boolean); // Remove null values | ||
} | ||
|
||
async _get256Hash(module) { | ||
if (module && module.fileBuffer) { | ||
const assetModule = await unwrapAssetModule(module.fileBuffer); | ||
return crypto.createHash('sha256').update(assetModule).digest('hex'); | ||
} | ||
} | ||
|
||
async _analyzeFiles(files) { | ||
const apps = knownAppNames(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reminder to remove commented out code