@onekeyfe/hd-core 1.2.0-alpha.145 → 1.2.0-alpha.147

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -466,13 +466,10 @@ const getDeviceTypeByBleName = (name) => {
466
466
  return hdShared.EDeviceType.Touch;
467
467
  if (/^Touch/i.test(name))
468
468
  return hdShared.EDeviceType.Touch;
469
- const compactName = name.replace(/[\s-]/g, '');
470
- if (/\bPro\s*2\b/i.test(name) || /^Pro2/i.test(name) || /^(?:OneKey)?Pro2/i.test(compactName)) {
469
+ if (/\bPro\s*2\b/i.test(name) || /^Pro2/i.test(name))
471
470
  return hdShared.EDeviceType.Pro2;
472
- }
473
- if (/\bNeo\b/i.test(name) || /^Neo/i.test(name) || /^(?:OneKey)?Neo/i.test(compactName)) {
471
+ if (/\bNeo\b/i.test(name) || /^Neo/i.test(name))
474
472
  return hdShared.EDeviceType.Neo;
475
- }
476
473
  if (/\bPro\b/i.test(name) || /^Pro/i.test(name))
477
474
  return hdShared.EDeviceType.Pro;
478
475
  return hdShared.EDeviceType.Unknown;
@@ -40678,16 +40675,18 @@ const findLatestRelease = (releases) => {
40678
40675
  return leastRelease;
40679
40676
  };
40680
40677
 
40681
- const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH = 'vol0:/loaders/bootloader/boot_resource.okpkg';
40682
- const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH = `${PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH}.staging`;
40683
- const PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_SIZE = 0x5f90;
40684
- const PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_VERSION = 1;
40685
- const PROTOCOL_V2_RESOURCE_PACKAGE_FLEXIBLE_OFFSET = 0x6c;
40686
- const PROTOCOL_V2_RESOURCE_PACKAGE_FLEXIBLE_SIZE = 64;
40687
- const PROTOCOL_V2_RESOURCE_PACKAGE_PAYLOAD_HASH_OFFSET = 0x200;
40688
- const PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_HASH_OFFSET = 0x240;
40689
- const PROTOCOL_V2_RESOURCE_PACKAGE_HASH_SIZE = 64;
40690
- const PROTOCOL_V2_RESOURCE_PACKAGE_TYPE = 'RESC';
40678
+ const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH$1 = 'vol0:/loaders/bootloader/boot_resource.okpkg';
40679
+ const SHA256_HEX_LENGTH = 64;
40680
+ function normalizeHex$1(value, expectedLength, field) {
40681
+ if (typeof value !== 'string') {
40682
+ throw new Error(`Invalid Pro2 resource ${field}: expected a hexadecimal string`);
40683
+ }
40684
+ const normalized = value.replace(/^0x/i, '').toLowerCase();
40685
+ if (normalized.length !== expectedLength || !/^[0-9a-f]+$/.test(normalized)) {
40686
+ throw new Error(`Invalid Pro2 resource ${field}: expected ${expectedLength} hexadecimal characters`);
40687
+ }
40688
+ return normalized;
40689
+ }
40691
40690
  function parseProtocolV2Resources(value) {
40692
40691
  if (value === undefined)
40693
40692
  return undefined;
@@ -40716,75 +40715,86 @@ function parseProtocolV2Resources(value) {
40716
40715
  },
40717
40716
  };
40718
40717
  }
40719
- const PROTOCOL_V2_RESOURCE_DEVICE_ROOTS = ['vol0:/bundles/', 'vol0:/loaders/rom/'];
40720
- function isAllowedResourceDevicePath(path) {
40721
- if (path.includes('\\') ||
40718
+ const PROTOCOL_V2_RESOURCE_MANIFEST_DEVICE_ROOTS = [
40719
+ 'vol0:/bundles/',
40720
+ 'vol0:/loaders/rom/',
40721
+ ];
40722
+ function isAllowedManifestDevicePath(path) {
40723
+ if (!path.endsWith('.okpkg') ||
40724
+ path.includes('\\') ||
40722
40725
  path.includes('//') ||
40723
- [...path].some(char => {
40724
- const code = char.charCodeAt(0);
40725
- return code <= 0x1f || code === 0x7f;
40726
- }) ||
40727
40726
  path.split('/').some(part => part === '.' || part === '..')) {
40728
40727
  return false;
40729
40728
  }
40730
- if (path === PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH) {
40729
+ if (path === PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH$1) {
40731
40730
  return true;
40732
40731
  }
40733
- return (path.endsWith('.okpkg') && PROTOCOL_V2_RESOURCE_DEVICE_ROOTS.some(root => path.startsWith(root)));
40732
+ return PROTOCOL_V2_RESOURCE_MANIFEST_DEVICE_ROOTS.some(root => path.startsWith(root));
40734
40733
  }
40735
- function readAscii(bytes, offset, length) {
40736
- return Array.from(bytes.slice(offset, offset + length))
40737
- .map(byte => String.fromCharCode(byte))
40738
- .join('');
40734
+ function assertManifestString(value, field) {
40735
+ if (typeof value !== 'string' || value.length === 0) {
40736
+ throw new Error(`Invalid Pro2 resource manifest ${field}`);
40737
+ }
40738
+ return value;
40739
40739
  }
40740
- function readResourceDevicePath(bytes) {
40741
- const metadata = bytes.slice(PROTOCOL_V2_RESOURCE_PACKAGE_FLEXIBLE_OFFSET, PROTOCOL_V2_RESOURCE_PACKAGE_FLEXIBLE_OFFSET + PROTOCOL_V2_RESOURCE_PACKAGE_FLEXIBLE_SIZE);
40742
- const terminator = metadata.indexOf(0);
40743
- const pathBytes = terminator === -1 ? metadata : metadata.slice(0, terminator);
40744
- const padding = terminator === -1 ? new Uint8Array(0) : metadata.slice(terminator);
40745
- if (pathBytes.byteLength === 0 ||
40746
- Array.from(pathBytes).some(byte => byte < 0x20 || byte > 0x7e) ||
40747
- Array.from(padding).some(byte => byte !== 0)) {
40748
- throw new Error('Invalid Pro2 RESOURCE package device path metadata');
40749
- }
40750
- const path = readAscii(pathBytes, 0, pathBytes.byteLength);
40751
- if (!isAllowedResourceDevicePath(path)) {
40752
- throw new Error(`Invalid Pro2 RESOURCE package device path: ${path}`);
40740
+ function assertManifestRelativePath(value, field) {
40741
+ const path = assertManifestString(value, field);
40742
+ if (path.startsWith('/') ||
40743
+ path.includes('\\') ||
40744
+ path.includes(':') ||
40745
+ path.split('/').some(part => !part || part === '.' || part === '..')) {
40746
+ throw new Error(`Invalid Pro2 resource manifest ${field}`);
40753
40747
  }
40754
40748
  return path;
40755
40749
  }
40756
- function parseProtocolV2ResourcePackageHeader(bytes, packageSize) {
40757
- if (bytes.byteLength < PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_SIZE) {
40758
- throw new Error('Pro2 RESOURCE package is shorter than its header');
40750
+ function parseProtocolV2ResourceManifestFile(value, index) {
40751
+ var _a;
40752
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
40753
+ throw new Error(`Invalid Pro2 resource manifest files[${index}]`);
40754
+ }
40755
+ const file = value;
40756
+ const archivePath = assertManifestRelativePath(file.archive_path, `files[${index}].archive_path`);
40757
+ const originalName = file.original_name === undefined
40758
+ ? (_a = archivePath.split('/').pop()) !== null && _a !== void 0 ? _a : archivePath
40759
+ : assertManifestRelativePath(file.original_name, `files[${index}].original_name`);
40760
+ if (originalName.includes('/')) {
40761
+ throw new Error(`Invalid Pro2 resource manifest files[${index}].original_name`);
40762
+ }
40763
+ const devicePath = assertManifestString(file.device_path, `files[${index}].device_path`);
40764
+ if (!isAllowedManifestDevicePath(devicePath)) {
40765
+ throw new Error(`Invalid Pro2 resource manifest files[${index}].device_path`);
40766
+ }
40767
+ if (!Number.isSafeInteger(file.size) || Number(file.size) <= 0) {
40768
+ throw new Error(`Invalid Pro2 resource manifest files[${index}].size`);
40769
+ }
40770
+ const digest = normalizeHex$1(file.sha256, SHA256_HEX_LENGTH, `files[${index}].sha256`);
40771
+ if (!archivePath.endsWith('.okpkg') || !originalName.endsWith('.okpkg')) {
40772
+ throw new Error(`Invalid Pro2 resource manifest files[${index}] package extension`);
40773
+ }
40774
+ return Object.assign(Object.assign(Object.assign({ archive_path: archivePath, original_name: originalName, device_path: devicePath, size: Number(file.size), sha256: digest }, (file.signed === undefined ? {} : { signed: file.signed })), (file.sig_algo === undefined ? {} : { sig_algo: file.sig_algo })), (file.payload_version === undefined ? {} : { payload_version: file.payload_version }));
40775
+ }
40776
+ function parseProtocolV2ResourceManifest(value) {
40777
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
40778
+ throw new Error('Invalid Pro2 resource manifest');
40759
40779
  }
40760
- const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
40761
- const headerVersion = view.getUint32(0x04, true);
40762
- const headerLength = view.getUint32(0x0c, true);
40763
- const payloadLength = view.getUint32(0x14, true);
40764
- if (readAscii(bytes, 0, 4) !== 'OKPP' ||
40765
- readAscii(bytes, 0x08, 4) !== PROTOCOL_V2_RESOURCE_PACKAGE_TYPE ||
40766
- headerVersion !== PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_VERSION ||
40767
- headerLength !== PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_SIZE ||
40768
- payloadLength <= 0 ||
40769
- headerLength + payloadLength !== packageSize) {
40770
- throw new Error('Invalid Pro2 RESOURCE package header');
40780
+ const manifest = value;
40781
+ if (!Array.isArray(manifest.files)) {
40782
+ throw new Error('Invalid Pro2 resource manifest files');
40783
+ }
40784
+ const files = manifest.files.map(parseProtocolV2ResourceManifestFile);
40785
+ const devicePaths = new Set(files.map(file => file.device_path));
40786
+ const archivePaths = new Set(files.map(file => file.archive_path));
40787
+ if (files.length === 0 ||
40788
+ devicePaths.size !== files.length ||
40789
+ archivePaths.size !== files.length) {
40790
+ throw new Error('Invalid Pro2 resource manifest file set');
40771
40791
  }
40772
- const packedVersion = view.getUint32(0x10, true);
40773
40792
  return {
40774
- version: [
40775
- Math.floor(packedVersion / 0x10000) % 0x100,
40776
- Math.floor(packedVersion / 0x100) % 0x100,
40777
- packedVersion % 0x100,
40778
- ],
40779
- payloadLength,
40780
- devicePath: readResourceDevicePath(bytes),
40781
- payloadHash: utils.bytesToHex(bytes.slice(PROTOCOL_V2_RESOURCE_PACKAGE_PAYLOAD_HASH_OFFSET, PROTOCOL_V2_RESOURCE_PACKAGE_PAYLOAD_HASH_OFFSET + PROTOCOL_V2_RESOURCE_PACKAGE_HASH_SIZE)),
40782
- headerHash: utils.bytesToHex(bytes.slice(PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_HASH_OFFSET, PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_HASH_OFFSET + PROTOCOL_V2_RESOURCE_PACKAGE_HASH_SIZE)),
40793
+ files,
40783
40794
  };
40784
40795
  }
40785
- function parseProtocolV2ResourcePackage(binary) {
40786
- const bytes = binary instanceof Uint8Array ? binary : new Uint8Array(binary);
40787
- return parseProtocolV2ResourcePackageHeader(bytes, bytes.byteLength);
40796
+ function selectProtocolV2ResourceManifestFiles({ manifest, targetsToUpdate, }) {
40797
+ return targetsToUpdate.includes('resource') ? [...manifest.files] : [];
40788
40798
  }
40789
40799
 
40790
40800
  var _a$1;
@@ -51761,8 +51771,17 @@ const PROTOCOL_V2_TRANSFER_PROGRESS_HEARTBEAT_MS = 1000;
51761
51771
  const PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE = 'FirmwareInstallStatusConflict';
51762
51772
  const PROTOCOL_V2_INSTALL_FAILED_CODE = 'FirmwareInstallFailed';
51763
51773
  const PROTOCOL_V2_INSTALL_TIMEOUT_CODE = 'FirmwareInstallTimeout';
51774
+ const PROTOCOL_V2_OKPP_HEADER_SIZE = 0x52a0;
51775
+ const PROTOCOL_V2_OKPP_PAYLOAD_HASH_OFFSET = 0x200;
51776
+ const PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET = 0x240;
51777
+ const PROTOCOL_V2_OKPP_HASH_SIZE = 64;
51778
+ const PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES = 1024 * 1024;
51764
51779
  const PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT = 512;
51765
51780
  const PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES = 256 * 1024 * 1024;
51781
+ const getProtocolV2LocalResourceArchivePath = (entryName) => {
51782
+ const match = entryName.match(/(?:^|\/)((?:bundles\/|loaders\/(?:bootloader|rom)\/).+\.okpkg)$/iu);
51783
+ return match === null || match === void 0 ? void 0 : match[1];
51784
+ };
51766
51785
  const PROTOCOL_V2_NEO_UNSUPPORTED_TARGETS = new Set(['se03', 'se04']);
51767
51786
  const getProtocolV2ZipEntrySizes = (entry) => {
51768
51787
  var _a;
@@ -51856,8 +51875,14 @@ const PROTOCOL_V2_REMOTE_COMPONENT_TARGETS = {
51856
51875
  },
51857
51876
  };
51858
51877
  const PROTOCOL_V2_FIRMWARE_STAGING_PATHS = new Set(Object.values(PROTOCOL_V2_REMOTE_COMPONENT_TARGETS).map(target => `${PROTOCOL_V2_FIRMWARE_STAGING_VOLUME}${target.fileName}`));
51878
+ const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH = 'vol0:/loaders/bootloader/boot_resource.okpkg';
51879
+ const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH = `${PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH}.staging`;
51859
51880
  const isProtocolV2BootResourcePackagePath = (devicePath) => typeof devicePath === 'string' &&
51860
- devicePath.toLowerCase() === PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH;
51881
+ devicePath.replace(/^vol0:(?!\/)/i, 'vol0:/').toLowerCase() ===
51882
+ PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH;
51883
+ const resolveProtocolV2ResourceWritePath = (devicePath) => isProtocolV2BootResourcePackagePath(devicePath)
51884
+ ? PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH
51885
+ : devicePath;
51861
51886
  const PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID = new Map([
51862
51887
  [ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_BOOTLOADER, 'boot'],
51863
51888
  [ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P1, 'app_v1'],
@@ -51983,6 +52008,30 @@ const toProtocolV2FiniteNumber = (value) => {
51983
52008
  }
51984
52009
  return undefined;
51985
52010
  };
52011
+ const readProtocolV2Ascii = (bytes, offset, length) => Array.from(bytes.slice(offset, offset + length))
52012
+ .map(byte => String.fromCharCode(byte))
52013
+ .join('');
52014
+ const parseProtocolV2OkppHeader = (bytes) => {
52015
+ if (bytes.byteLength < PROTOCOL_V2_OKPP_HEADER_SIZE)
52016
+ return null;
52017
+ if (readProtocolV2Ascii(bytes, 0, 4) !== 'OKPP')
52018
+ return null;
52019
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
52020
+ const headerLen = view.getUint32(0x0c, true);
52021
+ if (headerLen !== PROTOCOL_V2_OKPP_HEADER_SIZE)
52022
+ return null;
52023
+ const packedVersion = view.getUint32(0x10, true);
52024
+ return {
52025
+ type: readProtocolV2Ascii(bytes, 0x08, 4),
52026
+ version: [
52027
+ Math.floor(packedVersion / 0x10000) % 0x100,
52028
+ Math.floor(packedVersion / 0x100) % 0x100,
52029
+ packedVersion % 0x100,
52030
+ ],
52031
+ payloadHash: bytesToHex(bytes.slice(PROTOCOL_V2_OKPP_PAYLOAD_HASH_OFFSET, PROTOCOL_V2_OKPP_PAYLOAD_HASH_OFFSET + PROTOCOL_V2_OKPP_HASH_SIZE)),
52032
+ headerHash: bytesToHex(bytes.slice(PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET, PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET + PROTOCOL_V2_OKPP_HASH_SIZE)),
52033
+ };
52034
+ };
51986
52035
  const isProtocolV2FirmwareFingerprintValid = (binary, fingerprint) => {
51987
52036
  const expectedFingerprint = normalizeProtocolV2Hex(fingerprint);
51988
52037
  if (!expectedFingerprint)
@@ -52490,6 +52539,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52490
52539
  });
52491
52540
  }
52492
52541
  prepareProtocolV2LocalResourceArchive(binary) {
52542
+ var _a;
52493
52543
  return __awaiter(this, void 0, void 0, function* () {
52494
52544
  if (binary.byteLength <= 0 || binary.byteLength > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
52495
52545
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP archive size is invalid', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
@@ -52498,47 +52548,91 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52498
52548
  try {
52499
52549
  zip = yield JSZip__default["default"].loadAsync(binary);
52500
52550
  }
52501
- catch (_a) {
52551
+ catch (_b) {
52502
52552
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 resource ZIP cannot be parsed', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52503
52553
  }
52504
52554
  const zipEntries = Object.values(zip.files);
52505
- const resourceEntries = zipEntries.filter(entry => !entry.dir && entry.name.toLowerCase().endsWith('.okpkg'));
52506
- if (resourceEntries.length === 0 ||
52507
- resourceEntries.length > PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT) {
52508
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 resource ZIP has no valid resource package set', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52509
- }
52510
- let totalSize = 0;
52511
- const materializedEntries = [];
52512
- const resources = [];
52513
- const devicePaths = new Set();
52514
- for (const entry of resourceEntries) {
52515
- const { compressedSize, uncompressedSize } = getProtocolV2ZipEntrySizes(entry);
52516
- totalSize += uncompressedSize;
52517
- if (compressedSize > binary.byteLength ||
52518
- uncompressedSize > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES ||
52519
- totalSize > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
52520
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 resource package size is invalid: ${entry.name}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52555
+ if (zipEntries.some(entry => entry.unsafeOriginalName && entry.unsafeOriginalName !== entry.name)) {
52556
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP contains an unsafe entry path', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52557
+ }
52558
+ const entries = zipEntries.filter(entry => !entry.dir);
52559
+ if (entries.length === 0) {
52560
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP entry set is invalid', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52561
+ }
52562
+ const manifestEntry = entries.find(entry => entry.name.split('/').pop() === 'manifest.json');
52563
+ let manifestBinary;
52564
+ let manifestDirectory = '';
52565
+ let selectedFiles;
52566
+ if (manifestEntry) {
52567
+ if (getProtocolV2ZipEntrySizes(manifestEntry).uncompressedSize >
52568
+ PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES) {
52569
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource manifest size is invalid', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52521
52570
  }
52522
- const fileBinary = yield entry.async('arraybuffer');
52523
- if (fileBinary.byteLength !== uncompressedSize) {
52524
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 resource package is incomplete: ${entry.name}`, { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52571
+ manifestBinary = yield manifestEntry.async('arraybuffer');
52572
+ if (manifestBinary.byteLength <= 0 ||
52573
+ manifestBinary.byteLength > PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES) {
52574
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource manifest size is invalid', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52525
52575
  }
52526
- let header;
52576
+ let manifestValue;
52527
52577
  try {
52528
- header = parseProtocolV2ResourcePackage(fileBinary);
52578
+ manifestValue = JSON.parse(new TextDecoder().decode(manifestBinary));
52529
52579
  }
52530
52580
  catch (error) {
52531
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 resource package is invalid: ${entry.name}: ${String(error)}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52581
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource manifest is invalid: ${String(error)}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52582
+ }
52583
+ selectedFiles = selectProtocolV2ResourceManifestFiles({
52584
+ manifest: parseProtocolV2ResourceManifest(manifestValue),
52585
+ targetsToUpdate: (_a = this.params.targetsToUpdate) !== null && _a !== void 0 ? _a : [],
52586
+ });
52587
+ manifestDirectory = manifestEntry.name.slice(0, -'manifest.json'.length);
52588
+ }
52589
+ else {
52590
+ selectedFiles = entries.flatMap(entry => {
52591
+ var _a;
52592
+ const archivePath = getProtocolV2LocalResourceArchivePath(entry.name);
52593
+ if (!archivePath)
52594
+ return [];
52595
+ return [
52596
+ {
52597
+ archive_path: archivePath,
52598
+ original_name: (_a = archivePath.split('/').pop()) !== null && _a !== void 0 ? _a : archivePath,
52599
+ device_path: `vol0:/${archivePath}`,
52600
+ size: getProtocolV2ZipEntrySizes(entry).uncompressedSize,
52601
+ sha256: '',
52602
+ },
52603
+ ];
52604
+ });
52605
+ }
52606
+ if (selectedFiles.length === 0 || selectedFiles.length > PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT) {
52607
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP has no resource packages', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52608
+ }
52609
+ let totalSize = 0;
52610
+ const materializedEntries = [];
52611
+ const normalizedFiles = [];
52612
+ for (const file of selectedFiles) {
52613
+ const entry = manifestEntry
52614
+ ? zip.file(`${manifestDirectory}${file.archive_path}`)
52615
+ : entries.find(candidate => getProtocolV2LocalResourceArchivePath(candidate.name) === file.archive_path);
52616
+ if (!entry) {
52617
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource ZIP is missing ${file.archive_path}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52618
+ }
52619
+ const { uncompressedSize } = getProtocolV2ZipEntrySizes(entry);
52620
+ totalSize += uncompressedSize;
52621
+ if (uncompressedSize !== file.size || totalSize > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
52622
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource file declared size is invalid: ${file.archive_path}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52532
52623
  }
52533
- const canonicalDevicePath = header.devicePath.toLowerCase();
52534
- if (devicePaths.has(canonicalDevicePath)) {
52535
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 resource ZIP contains duplicate device path: ${header.devicePath}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52624
+ const fileBinary = yield entry.async('arraybuffer');
52625
+ const digest = bytesToHex(sha256.sha256(new Uint8Array(fileBinary)));
52626
+ if (fileBinary.byteLength !== file.size ||
52627
+ (file.sha256 && digest !== file.sha256.toLowerCase())) {
52628
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource file does not match manifest: ${file.archive_path}`, { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52536
52629
  }
52537
- devicePaths.add(canonicalDevicePath);
52538
- materializedEntries.push({ entryName: entry.name, binary: fileBinary });
52539
- resources.push({ entryName: entry.name, binary: fileBinary, header });
52630
+ normalizedFiles.push(Object.assign(Object.assign({}, file), { sha256: digest }));
52631
+ materializedEntries.push({ entryName: file.archive_path, binary: fileBinary });
52540
52632
  }
52541
- return { binary, materializedEntries, resources };
52633
+ manifestBinary !== null && manifestBinary !== void 0 ? manifestBinary : (manifestBinary = new TextEncoder().encode(JSON.stringify({ files: normalizedFiles })).buffer);
52634
+ materializedEntries.unshift({ entryName: 'manifest.json', binary: manifestBinary });
52635
+ return { binary, materializedEntries };
52542
52636
  });
52543
52637
  }
52544
52638
  prepareProtocolV2ResourceSources() {
@@ -52584,17 +52678,48 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52584
52678
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive does not match its approved receipt', { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52585
52679
  }
52586
52680
  const verifiedArchive = yield this.prepareProtocolV2LocalResourceArchive(archiveBinary);
52681
+ const verifiedEntriesByName = new Map(verifiedArchive.materializedEntries.map(entry => [entry.entryName, entry.binary]));
52682
+ const manifestBinary = verifiedEntriesByName.get('manifest.json');
52683
+ if (!manifestBinary) {
52684
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive has no valid manifest.json', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52685
+ }
52686
+ let manifestValue;
52687
+ try {
52688
+ manifestValue = JSON.parse(new TextDecoder().decode(manifestBinary));
52689
+ }
52690
+ catch (error) {
52691
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 prepared resource manifest is invalid: ${String(error)}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52692
+ }
52693
+ const manifest = parseProtocolV2ResourceManifest(manifestValue);
52694
+ const selectedFiles = selectProtocolV2ResourceManifestFiles({
52695
+ manifest,
52696
+ targetsToUpdate: (_c = this.params.targetsToUpdate) !== null && _c !== void 0 ? _c : [],
52697
+ });
52698
+ if (selectedFiles.length > PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT) {
52699
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive contains too many files', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52700
+ }
52701
+ let totalSize = 0;
52587
52702
  const sources = [];
52588
- for (const resource of verifiedArchive.resources) {
52589
- const source = yield this.openProtocolV2MemorySource(resource.binary);
52590
- sources.push({
52591
- name: (_c = resource.entryName.split('/').pop()) !== null && _c !== void 0 ? _c : resource.entryName,
52592
- source,
52593
- devicePath: resource.header.devicePath,
52594
- version: resource.header.version,
52595
- payloadHash: resource.header.payloadHash,
52596
- headerHash: resource.header.headerHash,
52597
- });
52703
+ for (const [index, file] of selectedFiles.entries()) {
52704
+ const binary = verifiedEntriesByName.get(file.archive_path);
52705
+ if (!binary || binary.byteLength !== file.size) {
52706
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 prepared resource file does not match manifest: ${file.archive_path}`, { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52707
+ }
52708
+ totalSize += binary.byteLength;
52709
+ if (totalSize > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
52710
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive exceeds the total size limit', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52711
+ }
52712
+ const source = yield this.openProtocolV2MemorySource(binary);
52713
+ const header = source.size >= PROTOCOL_V2_OKPP_HEADER_SIZE
52714
+ ? parseProtocolV2OkppHeader(new Uint8Array(yield source.readAt(0, PROTOCOL_V2_OKPP_HEADER_SIZE)))
52715
+ : null;
52716
+ sources.push(Object.assign({ name: file.original_name || `resource-${index}`, source, devicePath: file.device_path }, (header
52717
+ ? {
52718
+ version: header.version,
52719
+ payloadHash: header.payloadHash,
52720
+ headerHash: header.headerHash,
52721
+ }
52722
+ : {})));
52598
52723
  }
52599
52724
  return sources;
52600
52725
  });
@@ -52976,15 +53101,15 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52976
53101
  if (!((_b = pathInfoRes.message) === null || _b === void 0 ? void 0 : _b.exist) ||
52977
53102
  ((_c = pathInfoRes.message) === null || _c === void 0 ? void 0 : _c.directory) ||
52978
53103
  fileSize === undefined ||
52979
- fileSize < PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_SIZE ||
53104
+ fileSize < PROTOCOL_V2_OKPP_HEADER_SIZE ||
52980
53105
  (expectedSize !== undefined && fileSize !== expectedSize)) {
52981
53106
  return null;
52982
53107
  }
52983
53108
  const chunkSize = this.getProtocolV2FirmwareChunkSize('read');
52984
53109
  const chunks = [];
52985
53110
  let offset = 0;
52986
- while (offset < PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_SIZE) {
52987
- const readLen = Math.min(chunkSize, PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_SIZE - offset);
53111
+ while (offset < PROTOCOL_V2_OKPP_HEADER_SIZE) {
53112
+ const readLen = Math.min(chunkSize, PROTOCOL_V2_OKPP_HEADER_SIZE - offset);
52988
53113
  const res = yield typedCall('FilesystemFileRead', 'FilesystemFile', {
52989
53114
  file: {
52990
53115
  path: filePath,
@@ -53006,12 +53131,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53006
53131
  headerBytes.set(chunk, cursor);
53007
53132
  cursor += chunk.byteLength;
53008
53133
  });
53009
- try {
53010
- return parseProtocolV2ResourcePackageHeader(headerBytes, fileSize);
53011
- }
53012
- catch (_e) {
53013
- return null;
53014
- }
53134
+ return parseProtocolV2OkppHeader(headerBytes);
53015
53135
  });
53016
53136
  }
53017
53137
  isProtocolV2ResourceBundleUpToDate(bundle) {
@@ -53237,7 +53357,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53237
53357
  this.protocolV2LastTransferProgressAt = 0;
53238
53358
  let processedSize = 0;
53239
53359
  for (const resource of resourcesToSync) {
53240
- const writePath = resource.devicePath;
53360
+ const writePath = resolveProtocolV2ResourceWritePath(resource.devicePath);
53241
53361
  processedSize = yield this.protocolV2SourceUpdateProcess({
53242
53362
  source: resource.source,
53243
53363
  filePath: writePath,
@@ -53888,7 +54008,7 @@ class PromptWebDeviceAccess extends BaseMethod {
53888
54008
  }
53889
54009
  if (isWebUsbEnv) {
53890
54010
  const usbDevice = device;
53891
- const path = hdShared.resolveOneKeyUsbDevicePath(usbDevice);
54011
+ const path = usbDevice.serialNumber;
53892
54012
  if (!path) {
53893
54013
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WebDevicePromptAccessError);
53894
54014
  }
@@ -54326,8 +54446,7 @@ class DeviceUploadWallpaper extends BaseMethod {
54326
54446
  });
54327
54447
  this.path = `${WALLPAPER_DIRECTORY}/${normalizeFileName(fileName, this.encoded.data)}`;
54328
54448
  this.params = { jpegBase64, fileName, chunkSize };
54329
- this.unlockPolicy = 'unlock-before-run';
54330
- this.protocolV2PreUnlockPinType = hdTransport.DeviceSessionPinType.Any;
54449
+ this.unlockPolicy = 'none';
54331
54450
  this.skipForceUpdateCheck = true;
54332
54451
  this.useDevicePassphraseState = false;
54333
54452
  }
@@ -54483,8 +54602,7 @@ class DeviceUploadNft extends BaseMethod {
54483
54602
  paceMs,
54484
54603
  timeoutMs,
54485
54604
  };
54486
- this.unlockPolicy = 'unlock-before-run';
54487
- this.protocolV2PreUnlockPinType = hdTransport.DeviceSessionPinType.Any;
54605
+ this.unlockPolicy = 'none';
54488
54606
  this.skipForceUpdateCheck = true;
54489
54607
  this.useDevicePassphraseState = false;
54490
54608
  }
@@ -65164,6 +65282,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
65164
65282
  if ((_g = method.payload) === null || _g === void 0 ? void 0 : _g.onlyConnectBleDevice) {
65165
65283
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
65166
65284
  Log.debug('Call API - only connect ble device: ', device === null || device === void 0 ? void 0 : device.mainId);
65285
+ requestQueue.releaseTask(method.responseID);
65167
65286
  return createResponseMessage(method.responseID, true, null);
65168
65287
  }
65169
65288
  Log.debug('Call API - setDevice: ', device.mainId);
@@ -65513,10 +65632,8 @@ function canSkipInitialize(method, device) {
65513
65632
  return true;
65514
65633
  }
65515
65634
  function isRetryableBleProtocolV2ProbeError(method, error) {
65516
- const typedError = error;
65517
- const message = typeof (typedError === null || typedError === void 0 ? void 0 : typedError.message) === 'string' ? typedError.message : String(error !== null && error !== void 0 ? error : '');
65635
+ const message = error instanceof Error ? error.message : String(error !== null && error !== void 0 ? error : '');
65518
65636
  return (method.payload.connectProtocol === 'V2' &&
65519
- (typedError === null || typedError === void 0 ? void 0 : typedError.errorCode) === hdShared.HardwareErrorCode.RuntimeError &&
65520
65637
  message.includes('Device protocol mismatch') &&
65521
65638
  message.includes('expected V2') &&
65522
65639
  message.includes('did not respond to expected protocol'));
@@ -65528,7 +65645,31 @@ function isMissingDetectedProtocolV2Error(method, error) {
65528
65645
  typeof typedError.message === 'string' &&
65529
65646
  typedError.message.includes('Device protocol has not been detected'));
65530
65647
  }
65531
- function connectDeviceForBle(method, device, retryCount = 0) {
65648
+ const BLE_ACQUIRE_DEADLINE_MS = 60 * 1000;
65649
+ function raceBleAcquire(acquirePromise, abortSignal) {
65650
+ return new Promise((resolve, reject) => {
65651
+ let settled = false;
65652
+ const settle = (fn) => {
65653
+ if (settled)
65654
+ return;
65655
+ settled = true;
65656
+ clearTimeout(deadline);
65657
+ abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.removeEventListener('abort', onAbort);
65658
+ fn();
65659
+ };
65660
+ const onAbort = () => settle(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled)));
65661
+ const deadline = setTimeout(() => settle(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, `BLE acquire exceeded ${BLE_ACQUIRE_DEADLINE_MS}ms deadline`))), BLE_ACQUIRE_DEADLINE_MS);
65662
+ acquirePromise.then(value => settle(() => resolve(value)), error => settle(() => reject(error)));
65663
+ if (abortSignal) {
65664
+ if (abortSignal.aborted) {
65665
+ onAbort();
65666
+ return;
65667
+ }
65668
+ abortSignal.addEventListener('abort', onAbort);
65669
+ }
65670
+ });
65671
+ }
65672
+ function connectDeviceForBle(method, device, abortSignal, retryCount = 0) {
65532
65673
  var _a;
65533
65674
  return __awaiter(this, void 0, void 0, function* () {
65534
65675
  try {
@@ -65540,9 +65681,31 @@ function connectDeviceForBle(method, device, retryCount = 0) {
65540
65681
  !device.commands ||
65541
65682
  device.commands.disposed;
65542
65683
  if (shouldAcquire) {
65543
- yield device.acquire(method.payload.connectProtocol, {
65544
- forceProtocolDetection: method.payload.forceProtocolDetection,
65545
- });
65684
+ const useAcquireGuards = DataManager.getSettings('env') === 'desktop-web-ble';
65685
+ if (useAcquireGuards && (abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted)) {
65686
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
65687
+ }
65688
+ if (!useAcquireGuards) {
65689
+ yield device.acquire(method.payload.connectProtocol, {
65690
+ forceProtocolDetection: method.payload.forceProtocolDetection,
65691
+ });
65692
+ }
65693
+ else {
65694
+ try {
65695
+ yield raceBleAcquire(device.acquire(method.payload.connectProtocol, {
65696
+ forceProtocolDetection: method.payload.forceProtocolDetection,
65697
+ }), abortSignal);
65698
+ }
65699
+ catch (err) {
65700
+ if (err.errorCode === hdShared.HardwareErrorCode.BleTimeoutError &&
65701
+ device.mainId &&
65702
+ device.deviceConnector) {
65703
+ yield device.deviceConnector.disconnect(device.mainId).catch(() => undefined);
65704
+ device.markTransportDisconnected();
65705
+ }
65706
+ throw err;
65707
+ }
65708
+ }
65546
65709
  }
65547
65710
  if ((_a = method.payload) === null || _a === void 0 ? void 0 : _a.onlyConnectBleDevice) {
65548
65711
  if (shouldAcquire) {
@@ -65577,7 +65740,7 @@ function connectDeviceForBle(method, device, retryCount = 0) {
65577
65740
  const nextRetry = retryCount + 1;
65578
65741
  Log.debug(`Bluetooth connection will retry, retry count: ${nextRetry}`);
65579
65742
  yield wait(3000);
65580
- yield connectDeviceForBle(method, device, nextRetry);
65743
+ yield connectDeviceForBle(method, device, abortSignal, nextRetry);
65581
65744
  }
65582
65745
  else {
65583
65746
  throw err;
@@ -65659,7 +65822,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
65659
65822
  if (abort()) {
65660
65823
  return;
65661
65824
  }
65662
- yield connectDeviceForBle(method, device);
65825
+ yield connectDeviceForBle(method, device, abortSignal);
65663
65826
  }
65664
65827
  resolve(device);
65665
65828
  return;
@@ -66255,12 +66418,14 @@ exports.normalizeSafetyCheckLevel = normalizeSafetyCheckLevel;
66255
66418
  exports.normalizeVersionArray = normalizeVersionArray;
66256
66419
  exports.parseConnectSettings = parseConnectSettings;
66257
66420
  exports.parseMessage = parseMessage;
66421
+ exports.parseProtocolV2ResourceManifest = parseProtocolV2ResourceManifest;
66258
66422
  exports.patchFeatures = patchFeatures;
66259
66423
  exports.preloadSessionCache = preloadSessionCache;
66260
66424
  exports.prepareFirmwareUpdateV4MemoryHost = prepareFirmwareUpdateV4MemoryHost;
66261
66425
  exports.projectDeviceStateFeatures = projectFeatures;
66262
66426
  exports.registerFirmwareUpdateHostBinding = registerFirmwareUpdateHostBinding;
66263
66427
  exports.safeThrowError = safeThrowError;
66428
+ exports.selectProtocolV2ResourceManifestFiles = selectProtocolV2ResourceManifestFiles;
66264
66429
  exports.setLoggerPostMessage = setLoggerPostMessage;
66265
66430
  exports.supportInputPinOnSoftware = supportInputPinOnSoftware;
66266
66431
  exports.switchTransport = switchTransport;