From 8d62e719396d3a4999941f01dba905e07748235c Mon Sep 17 00:00:00 2001 From: keeramis Date: Fri, 6 Dec 2024 14:38:32 -0800 Subject: [PATCH] Command to flash Tachyon --- assets/qdl/qdl | Bin 0 -> 80968 bytes src/cli/flash.js | 11 +++++- src/cmd/flash.js | 94 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 103 insertions(+), 2 deletions(-) create mode 100755 assets/qdl/qdl diff --git a/assets/qdl/qdl b/assets/qdl/qdl new file mode 100755 index 0000000000000000000000000000000000000000..40124fe8f088af838d2c79b255acca1e3da265fd GIT binary patch literal 80968 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 av{4~u#6<3F&w|*JaY2*Q>5K;ZM*jyPuwtqJ literal 0 HcmV?d00001 diff --git a/src/cli/flash.js b/src/cli/flash.js index 2a1871b4d..b44c3aeb8 100644 --- a/src/cli/flash.js +++ b/src/cli/flash.js @@ -37,6 +37,14 @@ module.exports = ({ commandProcessor, root }) => { }, 'port': { describe: 'Use this serial port instead of auto-detecting. Useful if there are more than 1 connected device. Only available for serial' + }, + 'tachyon' : { + boolean: true, + description: 'Flash Tachyon' + }, + 'verbose' : { + boolean: false, + description: 'Enable logging' } }, handler: (args) => { @@ -54,7 +62,8 @@ module.exports = ({ commandProcessor, root }) => { '$0 $command --local application.bin': 'Flash the pre-compiled binary to the device connected over USB', '$0 $command --local application.zip': 'Flash the pre-compiled binary and assets from the bundle to the device connected over USB', '$0 $command --local tinker': 'Flash the default Tinker app to the device connected over USB', - '$0 $command --usb firmware.bin': 'Flash the binary over USB' + '$0 $command --usb firmware.bin': 'Flash the binary over USB', + '$0 $command --tachyon /path/to/unpackaged-tool-and-files': 'Flash Tachyon from the files in the specified directory. Use --verbose to see the progress', }, epilogue: unindent(` When passing the --local flag, Device OS will be updated if the version on the device is outdated. diff --git a/src/cmd/flash.js b/src/cmd/flash.js index f50fa505c..5a65cde36 100644 --- a/src/cmd/flash.js +++ b/src/cmd/flash.js @@ -14,6 +14,7 @@ const temp = require('temp').track(); const { knownAppNames, knownAppsForPlatform } = require('../lib/known-apps'); const { sourcePatterns, binaryPatterns, binaryExtensions } = require('../lib/file-types'); const deviceOsUtils = require('../lib/device-os-version-util'); +const os = require('os'); const semver = require('semver'); const { createFlashSteps, @@ -25,6 +26,7 @@ const { } = require('../lib/flash-helper'); const createApiCache = require('../lib/api-cache'); const { validateDFUSupport } = require('./device-util'); +const execa = require('execa'); module.exports = class FlashCommand extends CLICommandBase { constructor(...args) { @@ -39,9 +41,11 @@ module.exports = class FlashCommand extends CLICommandBase { target, port, yes, + verbose, + tachyon, 'application-only': applicationOnly }) { - if (!device && !binary && !local) { + if (!tachyon && !device && !binary && !local) { // if no device nor files are passed, show help throw usageError('You must specify a device or a file'); } @@ -55,11 +59,99 @@ module.exports = class FlashCommand extends CLICommandBase { } else if (local) { let allFiles = binary ? [binary, ...files] : files; await this.flashLocal({ files: allFiles, applicationOnly, target }); + } else if (tachyon) { + await this.flashTachyon({ verbose, binary }); } else { await this.flashCloud({ device, files, target }); } } + async flashTachyon({ verbose, binary }) { + this.ui.write(`Ensure only one device is connected to a computer${os.EOL}`); + + let unpackToolFolder = ''; + const stats = await fs.stat(binary); + if (stats.isDirectory()) { + unpackToolFolder = binary; + } + await fs.ensureDir(unpackToolFolder); + + const files = await fs.readdir(unpackToolFolder); + + const elfFiles = files.filter(f => f.startsWith('prog') && f.endsWith('.elf')); + const rawProgramFiles = files.filter(f => f.startsWith('rawprogram') && f.endsWith('.xml')); + const patchFiles = files.filter(f => f.startsWith('patch') && f.endsWith('.xml')); + + if (!elfFiles.length || !rawProgramFiles.length || !patchFiles.length) { + throw new Error('The directory should contain at least one .elf file, one rawprogram file and one patch file'); + } + + rawProgramFiles.sort((a, b) => { + const aNum = parseInt(a.match(/(\d+).xml/)[1]); + const bNum = parseInt(b.match(/(\d+).xml/)[1]); + return aNum - bNum; + }); + + patchFiles.sort((a, b) => { + const aNum = parseInt(a.match(/(\d+).xml/)[1]); + const bNum = parseInt(b.match(/(\d+).xml/)[1]); + return aNum - bNum; + }); + + if (rawProgramFiles.length !== patchFiles.length) { + throw new Error('The number of rawprogram files should match the number of patch files'); + } + + let filesToProgram = []; + // interleave the rawprogram files and patch files + for (let i = 0; i < rawProgramFiles.length; i++) { + filesToProgram.push(rawProgramFiles[i]); + filesToProgram.push(patchFiles[i]); + } + + filesToProgram.unshift(elfFiles[0]); + + this.ui.write(`Found the following files in the directory:${os.EOL}`); + this.ui.write('Loader file:'); + this.ui.write(` - ${elfFiles[0]}${os.EOL}`); + + this.ui.write('Program files:'); + for (const file of rawProgramFiles) { + this.ui.write(` - ${file}`); + } + this.ui.write(os.EOL); + + this.ui.write('Patch files:'); + for (const file of patchFiles) { + this.ui.write(` - ${file}`); + } + this.ui.write(os.EOL); + + const qdl = path.join(__dirname, '../../assets/qdl/qdl'); + await fs.ensureFile(qdl); + + this.ui.write(`Command: ${qdl} --storage ufs ${filesToProgram.join(' ')}${os.EOL}`); + this.ui.write(`Starting download. The download may take several minutes${os.EOL}`); + + try { + const res = await execa(qdl, ['--storage', 'ufs', ...filesToProgram], { + cwd: unpackToolFolder, + stdio: verbose ? 'inherit' : 'pipe' + }); + // put the output in a log file if not verbose + if (!verbose) { + const outputLog = path.join(process.cwd(), `qdl-${Date.now()}.log`); + await fs.writeFile(outputLog, res.stdout); + this.ui.write(`Download complete. Output log available at ${outputLog}${os.EOL}`); + } else { + this.ui.write(`Download complete${os.EOL}`); + } + } catch (err) { + throw new Error(`Download failed. Try powering up your board in EDL mode and try again.${os.EOL}Error: ${err.message}${os.EOL}`); + } + // TODO: Handle errors + } + async flashOverUsb({ binary, factory }) { if (utilities.getFilenameExt(binary) === '.zip') { throw new Error("Use 'particle flash --local' to flash a zipped bundle.");