From 90533a5880b5cc7e0be2e68b38a8701a2bc2a6db Mon Sep 17 00:00:00 2001 From: Kirill Zhumarin Date: Wed, 28 Aug 2024 09:28:21 +0000 Subject: [PATCH] new methods --- package-lock.json | 19 ++++++++++++++ package.json | 1 + src/index.js | 1 + src/xbi.js | 21 +++++++++++----- src/xfs.js | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 src/xfs.js diff --git a/package-lock.json b/package-lock.json index 49ee8d0..de55998 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "debug": "^4.3.4", + "iconv-lite": "^0.6.3", "sprintf-js": "^1.1.3" } }, @@ -29,11 +30,29 @@ } } }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", diff --git a/package.json b/package.json index 446e4b8..323c5a0 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "description": "Tools for Siemens Mobile firmware files.", "dependencies": { "debug": "^4.3.4", + "iconv-lite": "^0.6.3", "sprintf-js": "^1.1.3" }, "repository": { diff --git a/src/index.js b/src/index.js index fb849fd..9c12b61 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,4 @@ export * from './exe.js'; export * from './xbi.js'; export * from './swupik.js'; +export * from './xfs.js'; diff --git a/src/xbi.js b/src/xbi.js index 65039c3..5c69699 100644 --- a/src/xbi.js +++ b/src/xbi.js @@ -30,7 +30,7 @@ const XBI_FILEDS = { 0x23: ['flashSize', 'uint32be'], 0x28: ['model', 'str'], 0x29: ['vendor', 'str'], - 0x2A: ['baseline0', 'str'], + 0x2A: ['baseline', 'str'], 0x30: ['eraseRegions[]', 'region'], 0x37: ['swCode', 'swCode'], 0x34: ['projectType', 'uint8'], @@ -44,9 +44,9 @@ const XBI_FILEDS = { 0x56: ['hashAreaSize', 'uint16le'], 0x60: ['t9', 'uint8'], - 0x61: ['baseline1', 'str'], - 0x62: ['baseline2', 'str'], - 0x63: ['baseline3', 'str'], + 0x61: ['databaseName', 'str'], + 0x62: ['baselineVersion', 'str'], + 0x63: ['baselineRelease', 'str'], 0x64: ['mobileName', 'str2'], 0x70: ['dll', 'str2'], @@ -157,8 +157,17 @@ export function parseXbi(buffer) { return info; } -export function convertXbiToFlash(buffer) { - let xbi = parseXbi(buffer); +export function getXbiExtension(xbi) { + if (xbi.updateType == 'ExtendedNewSplit') { + return 'xfs'; + } else if (xbiInfo.databaseName == 'klf_bootcore') { + return 'xbb'; + } + return xbi.compressionType == 0 ? 'xbi' : 'xbz'; +} + +export function convertXbiToFlash(buffer, xbi = null) { + xbi = xbi || parseXbi(buffer); let flash = Buffer.alloc(xbi.flashSize); flash.fill(0xFF, 0); diff --git a/src/xfs.js b/src/xfs.js new file mode 100644 index 0000000..9ba5e67 --- /dev/null +++ b/src/xfs.js @@ -0,0 +1,64 @@ +import iconv from 'iconv-lite'; + +export function getVersionFromFFS(buffer) { + return _getVersionFromFFS_SG(buffer) || _getVersionFromFFS_NSG(buffer); +} + +function _getVersionFromFFS_NSG(buffer) { + let fileNamePtr = iconv.encode("info.txt", "utf16-be"); + let lastIndex = 0; + while (true) { + let index = buffer.indexOf(fileNamePtr, lastIndex); + if (index < 0) + break; + + index += fileNamePtr.length; + + let possibleString = buffer.subarray(index, index + 256).filter((byte) => byte != 0xFF).toString(); + let matches = possibleString.match(/([\w\d]+_\d+_[\w\d-]+_\d+_\d+)\n/i); + + if (matches && matches[1]) + return matches[1]; + + lastIndex = index + 1; + } + + return null; +} + +function _getVersionFromFFS_SG(buffer) { + let patterns = [ + iconv.encode("ccq_vinfo.txt", "utf16-be"), + Buffer.concat([ Buffer.from("ccq_vinfo.txt", "utf-8"), Buffer.from([0]) ]) + ]; + + for (let fileNamePtr of patterns) { + let lastIndex = 0; + while (true) { + let index = buffer.indexOf(fileNamePtr, lastIndex); + if (index < 0) + break; + + index += fileNamePtr.length; + + let chars = []; + while (index < buffer.length && buffer[index] != 0x0A) { + if (buffer[index] > 0x7F || buffer[index] < 0x20) { + if (buffer[index] != 0x0A) + chars = []; + break; + } + chars.push(buffer[index]); + index++; + } + + let possibleString = Buffer.from(chars).toString(); + if (possibleString.match(/^[\w\d]+_\d+_[\w\d-]+_\d+_\d+$/i)) + return possibleString; + + lastIndex = index + 1; + } + } + + return null; +}