binary-version-reader
Advanced tools
Comparing version
@@ -791,2 +791,206 @@ const { Flags: ModuleFlags, MODULE_PREFIX_SIZE, MIN_MODULE_SUFFIX_SIZE, MAX_MODULE_SUFFIX_SIZE, ModuleInfoExtension, ModuleFunction } = require('./ModuleInfo.js'); | ||
/** | ||
* Remove extensions of a particular type. | ||
* | ||
* @param {Buffer} module Module to update | ||
* @param {Array} exts List of extensions to add | ||
* @param {Boolean} replaceWithSameType Append extensions as-is or replace existing extensions of the same type | ||
* @returns {Promise<Buffer>} | ||
*/ | ||
async function removeModuleExtensions({ module, exts = [] } = {}) { | ||
if (exts.length === 0) { | ||
throw new RangeError('Empty extension list'); | ||
} | ||
const parser = new HalModuleParser(); | ||
const { prefixInfo: prefix } = await parser.parsePrefix({ fileBuffer: module }); | ||
const { suffixInfo: suffix } = await parser.parseSuffix({ fileBuffer: module }); | ||
prefix.moduleStartAddy = sanitizeAddress(prefix.moduleStartAddy); | ||
prefix.moduleEndAddy = sanitizeAddress(prefix.moduleEndAddy); | ||
const flags = prefix.moduleFlags; | ||
if (flags & ModuleFlags.COMPRESSED) { | ||
throw new RangeError(`Can't add extensions to a compressed module`); | ||
} | ||
if (flags & ModuleFlags.COMBINED) { | ||
throw new RangeError(`Can\'t add extensions to a combined module`); | ||
} | ||
const suffixSize = suffix.suffixSize; | ||
if (suffixSize < MIN_MODULE_SUFFIX_SIZE || suffixSize > MAX_MODULE_SUFFIX_SIZE) { | ||
throw new RangeError('Invalid suffix size'); | ||
} | ||
let dataSize = prefix.moduleEndAddy - prefix.moduleStartAddy + 4 /* CRC-32 */; | ||
const prefixOffs = prefix.prefixOffset || 0; | ||
if (module.length < prefixOffs + MODULE_PREFIX_SIZE + suffixSize + 4 || module.length !== dataSize) { | ||
throw new RangeError('Invalid size of the module data'); | ||
} | ||
const moduleInfo = firmwareModuleInfoForPlatformAndFunction(prefix.platformID, prefix.moduleFunction, prefix.moduleIndex); | ||
let extensionsInPrefix = false; | ||
if ((prefix.moduleFlags & ModuleInfo.Flags.PREFIX_EXTENSIONS) || (moduleInfo && moduleInfo.growsLeft)) { | ||
extensionsInPrefix = true; | ||
} | ||
let extensions = []; | ||
if (extensionsInPrefix) { | ||
extensions = prefix.extensions; | ||
} else { | ||
extensions = suffix.extensions; | ||
} | ||
if (!extensions) { | ||
extensions = []; | ||
} | ||
extensions = extensions.filter((val) => { | ||
for (let ext of exts) { | ||
if (val.type === ext) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
}); | ||
let buffer = null; | ||
if (extensionsInPrefix) {; | ||
prefix.extensions = extensions; | ||
} else { | ||
suffix.extensions = extensions; | ||
} | ||
// Always add END extension: it is mandatory to be present in module prefix extensions | ||
// and due to the fact that product data for some of the platforms may not use an extension and just be | ||
// raw data, to indicate end we will also use END extension here. | ||
if (extensions.length > 0 && extensions[extensions.length - 1].type !== ModuleInfo.ModuleInfoExtension.END && | ||
extensions[extensions.length - 1].type !== ModuleInfo.ModuleInfoExtension.PRODUCT_DATA) { | ||
extensions.push({ | ||
type: ModuleInfo.ModuleInfoExtension.END | ||
}); | ||
} | ||
if (extensionsInPrefix && extensions.length > 0) { | ||
if (prefixOffs > 0) { | ||
throw new RangeError('Extensions in prefix are not supported for modules with non-zero prefix offset'); | ||
} | ||
prefix.moduleFlags |= ModuleInfo.Flags.PREFIX_EXTENSIONS; | ||
prefix.extensions = extensions; | ||
const originalPrefixSize = prefix.prefixSize; | ||
delete extensions[extensions.length - 1].data; | ||
delete extensions[extensions.length - 1].length; | ||
prefix.prefixSize = calculateModulePrefixSize(prefix); | ||
let newSize = module.length + (prefix.prefixSize - originalPrefixSize); | ||
let newStartAddr = prefix.moduleEndAddy - (newSize - 4); | ||
let alignment = 0; | ||
if (newStartAddr % DEFAULT_START_ALIGNMENT !== 0) { | ||
alignment = (newStartAddr % DEFAULT_START_ALIGNMENT); | ||
newSize += alignment; | ||
} | ||
extensions[extensions.length - 1].padding = alignment; | ||
prefix.prefixSize += alignment; | ||
console.log(prefix); | ||
buffer = Buffer.alloc(newSize); | ||
module.copy(buffer, prefix.prefixSize, originalPrefixSize /* source offset */); | ||
prefix.moduleStartAddy = prefix.moduleEndAddy - (buffer.length - 4); | ||
if (suffix.extensions) { | ||
for (let ext of suffix.extensions) { | ||
if (ext.type === ModuleInfo.ModuleInfoExtension.DYNAMIC_LOCATION) { | ||
// This has to be updated for certain platforms if start address is moved | ||
delete ext.data; | ||
ext.moduleStartAddress = prefix.moduleStartAddy; | ||
} | ||
} | ||
} | ||
} else if (extensions.length > 0) { | ||
// In suffix | ||
suffix.extensions = extensions; | ||
const originalSuffixSize = suffix.suffixSize; | ||
suffix.suffixSize = calculateModuleSuffixSize(suffix); | ||
buffer = Buffer.alloc(module.length + (suffix.suffixSize - originalSuffixSize)); | ||
module.copy(buffer, 0, 0, module.length - originalSuffixSize - 4 /* CRC-32 */); | ||
prefix.moduleEndAddy = prefix.moduleStartAddy + buffer.length - 4; | ||
} | ||
if (moduleInfo && moduleInfo.maxSize) { | ||
if (buffer.length > moduleInfo.maxSize) { | ||
throw new PlatformLimitError({}, 'Resulting module exceeds platform size limits'); | ||
} | ||
} | ||
updateModulePrefix(buffer, prefix); | ||
updateModuleSuffix(buffer, suffix); | ||
updateModuleSha256(buffer); | ||
updateModuleCrc32(buffer); | ||
return buffer; | ||
} | ||
/** | ||
* list extensions of a particular type. | ||
* | ||
* @param {Buffer} module Module to update | ||
* @param {Array} exts List of extensions to add | ||
* @returns {Promise<[]>} | ||
*/ | ||
async function listModuleExtensions({ module, exts = [] } = {}) { | ||
if (exts.length === 0) { | ||
throw new RangeError('Empty extension list'); | ||
} | ||
const parser = new HalModuleParser(); | ||
const { prefixInfo: prefix } = await parser.parsePrefix({ fileBuffer: module }); | ||
const { suffixInfo: suffix } = await parser.parseSuffix({ fileBuffer: module }); | ||
prefix.moduleStartAddy = sanitizeAddress(prefix.moduleStartAddy); | ||
prefix.moduleEndAddy = sanitizeAddress(prefix.moduleEndAddy); | ||
const flags = prefix.moduleFlags; | ||
if (flags & ModuleFlags.COMPRESSED) { | ||
throw new RangeError(`Can't add extensions to a compressed module`); | ||
} | ||
if (flags & ModuleFlags.COMBINED) { | ||
throw new RangeError(`Can\'t add extensions to a combined module`); | ||
} | ||
const suffixSize = suffix.suffixSize; | ||
if (suffixSize < MIN_MODULE_SUFFIX_SIZE || suffixSize > MAX_MODULE_SUFFIX_SIZE) { | ||
throw new RangeError('Invalid suffix size'); | ||
} | ||
let dataSize = prefix.moduleEndAddy - prefix.moduleStartAddy + 4 /* CRC-32 */; | ||
const prefixOffs = prefix.prefixOffset || 0; | ||
if (module.length < prefixOffs + MODULE_PREFIX_SIZE + suffixSize + 4 || module.length !== dataSize) { | ||
throw new RangeError('Invalid size of the module data'); | ||
} | ||
const moduleInfo = firmwareModuleInfoForPlatformAndFunction(prefix.platformID, prefix.moduleFunction, prefix.moduleIndex); | ||
let extensionsInPrefix = false; | ||
if ((prefix.moduleFlags & ModuleInfo.Flags.PREFIX_EXTENSIONS) || (moduleInfo && moduleInfo.growsLeft)) { | ||
extensionsInPrefix = true; | ||
} | ||
let extensions = []; | ||
if (extensionsInPrefix) { | ||
extensions = prefix.extensions; | ||
} else { | ||
extensions = suffix.extensions; | ||
} | ||
if (!extensions) { | ||
extensions = []; | ||
} | ||
extensions = extensions.filter((val) => { | ||
for (let ext of exts) { | ||
if (val.type === ext) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
}); | ||
return extensions; | ||
} | ||
/** | ||
* Update module info to include a set of asset dependencies | ||
@@ -1452,3 +1656,5 @@ * | ||
createProtectedModule, | ||
addModuleExtensions | ||
addModuleExtensions, | ||
removeModuleExtensions, | ||
listModuleExtensions | ||
}; |
{ | ||
"name": "binary-version-reader", | ||
"version": "2.4.0", | ||
"version": "2.5.0", | ||
"main": "main.js", | ||
@@ -18,6 +18,6 @@ "license": "Apache-2.0", | ||
"peerDependencies": { | ||
"@particle/device-constants": "^3.2.0" | ||
"@particle/device-constants": "^3.5.0" | ||
}, | ||
"devDependencies": { | ||
"@particle/device-constants": "^3.2.0", | ||
"@particle/device-constants": "^3.5.0", | ||
"buffer-offset": "^0.1.2", | ||
@@ -24,0 +24,0 @@ "chai": "^4.0.0", |
1675285
0.42%6132
3.02%