@onekeyfe/hd-core 1.2.0-alpha.157 → 1.2.0-alpha.159

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.
@@ -32,12 +32,13 @@ import {
32
32
  } from '../protocols/protocol-v2';
33
33
  import { requestProtocolV2DeviceInfo } from '../protocols/protocol-v2/features';
34
34
  import {
35
+ PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH,
35
36
  PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH,
36
37
  PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_SIZE,
38
+ type ProtocolV2ResourcePackageHeader,
37
39
  isProtocolV2ResourceArchiveEntryName,
38
40
  parseProtocolV2ResourcePackage,
39
41
  parseProtocolV2ResourcePackageHeader,
40
- type ProtocolV2ResourcePackageHeader,
41
42
  } from '../protocols/protocol-v2/resources';
42
43
  import {
43
44
  getProtocolV2UnknownErrorText,
@@ -48,20 +49,12 @@ import {
48
49
  readFirmwareByteSourceFully,
49
50
  writeFirmwareByteSource,
50
51
  } from './firmware/FirmwareArtifactSource';
51
- import {
52
- registerFirmwareUpdateHostBinding,
53
- resolveFirmwareUpdateHostBinding,
54
- unregisterFirmwareUpdateHostBinding,
55
- } from './firmware/FirmwareHostBinding';
52
+ import { resolveFirmwareUpdateHostBinding } from './firmware/FirmwareHostBinding';
56
53
  import {
57
54
  assertFirmwareUpdatePreparedPlanBinding,
58
55
  assertFirmwareUpdatePreparedPlanDeviceIdentity,
59
- prepareFirmwareUpdatePlan,
60
56
  validateFirmwareUpdatePreparedPlan,
61
57
  } from './firmware/FirmwareUpdatePreparedPlan';
62
- import { prepareFirmwareUpdateV4MemoryHost } from './firmware/FirmwareMemoryHost';
63
- import { buildProtocolV2LocalFirmwareUpdatePlan } from './firmware/FirmwareUpdatePlan';
64
-
65
58
  import type {
66
59
  FirmwareArtifactReference,
67
60
  FirmwareUpdateV4Params,
@@ -78,11 +71,6 @@ import type {
78
71
  KnownDevice,
79
72
  } from '../types';
80
73
  import type { FirmwareByteSource } from './firmware/FirmwareArtifactSource';
81
- import type {
82
- FirmwareMemoryArtifact,
83
- FirmwareMemoryArtifactEntry,
84
- FirmwareUpdateV4MemoryHost,
85
- } from './firmware/FirmwareMemoryHost';
86
74
 
87
75
  const Log = getLogger(LoggerNames.Method);
88
76
 
@@ -231,7 +219,6 @@ type ProtocolV2ResourceBundleSource = {
231
219
 
232
220
  type ProtocolV2LocalResourceArchive = {
233
221
  binary: ArrayBuffer;
234
- materializedEntries: FirmwareMemoryArtifactEntry[];
235
222
  resources: Array<{
236
223
  entryName: string;
237
224
  binary: ArrayBuffer;
@@ -302,13 +289,9 @@ const PROTOCOL_V2_FIRMWARE_STAGING_PATHS = new Set(
302
289
  )
303
290
  );
304
291
 
305
- const isProtocolV2BootResourcePackagePath = (devicePath: string) => {
306
- if (typeof devicePath !== 'string') return false;
307
- const normalized = devicePath.toLowerCase();
308
- return (
309
- normalized.startsWith('vol0:/loaders/bootloader/') && normalized.endsWith('.okpkg.staging')
310
- );
311
- };
292
+ const isProtocolV2BootResourcePackagePath = (devicePath: string) =>
293
+ typeof devicePath === 'string' &&
294
+ devicePath.toLowerCase() === PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH;
312
295
 
313
296
  const PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID = new Map<
314
297
  number,
@@ -797,15 +780,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
797
780
  this.params.resourceArchiveBinary &&
798
781
  this.params.targetsToUpdate?.includes('resource')
799
782
  ) {
800
- const localMemoryHost = await this.prepareProtocolV2LocalMemoryHost({
801
- features: deviceFeatures,
802
- firmwareType,
803
- });
804
- try {
805
- return await this.runProtocolV2PreparedArtifacts(deviceFeatures, firmwareType);
806
- } finally {
807
- localMemoryHost.release();
808
- }
783
+ return this.runProtocolV2DirectArtifacts({});
809
784
  }
810
785
 
811
786
  const hasPreparedComponentArtifacts = Object.values(this.params.componentArtifacts ?? {}).some(
@@ -818,12 +793,12 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
818
793
  let fwBinaryMap: ProtocolV2TargetBinary[] = [];
819
794
  let bootloaderBinary: ArrayBuffer | null = null;
820
795
  let installItems: ProtocolV2InstallItem[] | undefined;
821
- let resourceMemoryHost: FirmwareUpdateV4MemoryHost | undefined;
796
+ let explicitInstallItems: ProtocolV2InstallItem[] | undefined;
822
797
  try {
823
798
  this.postTipMessage(FirmwareUpdateTipMessage.StartDownloadFirmware);
824
799
  fwBinaryMap = this.collectExplicitTargetBinaries();
825
800
  bootloaderBinary = this.prepareBootloaderBinary();
826
- const explicitInstallItems = this.buildProtocolV2InstallItems({
801
+ explicitInstallItems = this.buildProtocolV2InstallItems({
827
802
  bootloaderBinary,
828
803
  fwBinaryMap,
829
804
  });
@@ -879,15 +854,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
879
854
  deviceFeatures,
880
855
  firmwareType
881
856
  );
882
- resourceMemoryHost = await this.prepareProtocolV2LocalMemoryHost({
883
- features: deviceFeatures,
884
- firmwareType,
885
- availableInstallItems: installItems ?? explicitInstallItems,
886
- });
887
857
  }
888
858
  this.postTipMessage(FirmwareUpdateTipMessage.FinishDownloadFirmware);
889
859
  } catch (err) {
890
- resourceMemoryHost?.release();
891
860
  if (
892
861
  typeof err === 'object' &&
893
862
  err !== null &&
@@ -902,12 +871,11 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
902
871
  throw normalizeFirmwarePreparationError(err);
903
872
  }
904
873
 
905
- if (resourceMemoryHost) {
906
- try {
907
- return await this.runProtocolV2PreparedArtifacts(deviceFeatures, firmwareType, false);
908
- } finally {
909
- resourceMemoryHost.release();
910
- }
874
+ if (wantsResources && this.params.resourceArchiveBinary) {
875
+ return this.runProtocolV2DirectArtifacts({
876
+ availableInstallItems: installItems ?? explicitInstallItems,
877
+ announceDownload: false,
878
+ });
911
879
  }
912
880
 
913
881
  if (!bootloaderBinary && fwBinaryMap.length === 0 && !installItems?.length) {
@@ -1060,133 +1028,69 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
1060
1028
  return installSources;
1061
1029
  }
1062
1030
 
1063
- private async prepareProtocolV2LocalMemoryHost({
1064
- features,
1065
- firmwareType,
1066
- availableInstallItems = this.buildProtocolV2InstallItems({
1067
- bootloaderBinary: this.prepareBootloaderBinary(),
1068
- fwBinaryMap: this.collectExplicitTargetBinaries(),
1069
- }),
1031
+ private async runProtocolV2DirectArtifacts({
1032
+ availableInstallItems,
1033
+ announceDownload = true,
1070
1034
  }: {
1071
- features: Features;
1072
- firmwareType: EFirmwareType;
1073
1035
  availableInstallItems?: ProtocolV2InstallItem[];
1074
- }): Promise<FirmwareUpdateV4MemoryHost> {
1075
- const requestedComponentTargets = new Set(
1076
- (this.params.targetsToUpdate ?? []).filter(
1077
- (target): target is Exclude<FirmwareUpdateV4Target, 'resource' | 'boot_resources'> =>
1078
- target !== 'resource' && target !== 'boot_resources'
1079
- )
1080
- );
1081
- const localComponentTargets = new Set(
1082
- availableInstallItems.flatMap(item => {
1083
- const target = PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(item.targetId);
1084
- return target ? [target] : [];
1085
- })
1086
- );
1087
- const missingTarget = Array.from(requestedComponentTargets).find(
1088
- target => !localComponentTargets.has(target)
1089
- );
1090
- if (missingTarget) {
1091
- throw ERRORS.TypedError(
1092
- HardwareErrorCode.RuntimeError,
1093
- `Protocol V2 local update has no binary for requested target ${missingTarget}`,
1094
- {
1095
- firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
1096
- artifactName: missingTarget,
1097
- }
1036
+ announceDownload?: boolean;
1037
+ }) {
1038
+ try {
1039
+ if (announceDownload) {
1040
+ this.postTipMessage(FirmwareUpdateTipMessage.StartDownloadFirmware);
1041
+ }
1042
+ const installItems = this.filterProtocolV2LocalInstallItems(
1043
+ availableInstallItems ??
1044
+ this.buildProtocolV2InstallItems({
1045
+ bootloaderBinary: this.prepareBootloaderBinary(),
1046
+ fwBinaryMap: this.collectExplicitTargetBinaries(),
1047
+ })
1098
1048
  );
1099
- }
1100
- const installItems = this.filterProtocolV2LocalInstallItems(availableInstallItems);
1101
-
1102
- const planArtifacts: Parameters<typeof buildProtocolV2LocalFirmwareUpdatePlan>[0]['artifacts'] =
1103
- [];
1104
- const memoryArtifacts: FirmwareMemoryArtifact[] = [];
1105
- for (const item of installItems) {
1106
- const target = PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(item.targetId);
1107
- if (!target || item.binary.byteLength <= 0) {
1049
+ const installSources = await Promise.all(
1050
+ installItems.map(async item => ({
1051
+ fileName: item.fileName,
1052
+ source: await this.openProtocolV2MemorySource(item.binary),
1053
+ targetId: item.targetId,
1054
+ kind: item.kind,
1055
+ }))
1056
+ );
1057
+ const resourceSources = this.params.resourceArchiveBinary
1058
+ ? await this.createProtocolV2ResourceSourcesFromArchive(this.params.resourceArchiveBinary)
1059
+ : [];
1060
+ if (installSources.length === 0 && resourceSources.length === 0) {
1108
1061
  throw ERRORS.TypedError(
1109
- HardwareErrorCode.RuntimeError,
1110
- `Protocol V2 local firmware artifact is invalid: ${item.fileName}`,
1111
- { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' }
1062
+ HardwareErrorCode.FirmwareUpdateDownloadFailed,
1063
+ 'No firmware to update'
1112
1064
  );
1113
1065
  }
1114
- const artifactId = `component:${target}`;
1115
- planArtifacts.push({
1116
- artifactId,
1117
- target,
1118
- container: 'raw',
1119
- logicalName: item.fileName,
1120
- expectedSize: item.binary.byteLength,
1121
- expectedSha256: bytesToHex(sha256(new Uint8Array(item.binary))),
1122
- ...(this.params.expectedTargetVersions?.[target]
1123
- ? { targetVersion: this.params.expectedTargetVersions[target] }
1124
- : {}),
1066
+ if (announceDownload) {
1067
+ this.postTipMessage(FirmwareUpdateTipMessage.FinishDownloadFirmware);
1068
+ }
1069
+ return await this.executeProtocolV2SourceUpdate({
1070
+ installSources,
1071
+ resourceSources,
1125
1072
  });
1126
- memoryArtifacts.push({ artifactId, binary: item.binary });
1073
+ } finally {
1074
+ await this.closeProtocolV2PreparedSources();
1127
1075
  }
1076
+ }
1128
1077
 
1129
- const resourceArchive = await this.prepareProtocolV2LocalResourceArchive(
1130
- this.params.resourceArchiveBinary as ArrayBuffer
1131
- );
1132
- const resourceArtifactId = 'resource:archive';
1133
- planArtifacts.push({
1134
- artifactId: resourceArtifactId,
1135
- target: 'resource',
1136
- container: 'zip',
1137
- logicalName: 'protocol-v2-local-resource-archive',
1138
- expectedSize: resourceArchive.binary.byteLength,
1139
- expectedSha256: bytesToHex(sha256(new Uint8Array(resourceArchive.binary))),
1140
- });
1141
- memoryArtifacts.push({
1142
- artifactId: resourceArtifactId,
1143
- binary: resourceArchive.binary,
1144
- materializedEntries: resourceArchive.materializedEntries,
1145
- });
1146
-
1147
- const plan = buildProtocolV2LocalFirmwareUpdatePlan({
1148
- features,
1149
- firmwareType,
1150
- platform: this.params.platform,
1151
- artifacts: planArtifacts,
1152
- });
1153
- let memoryHost: FirmwareUpdateV4MemoryHost | undefined;
1154
- try {
1155
- memoryHost = prepareFirmwareUpdateV4MemoryHost({
1156
- sdk: {
1157
- prepareFirmwareUpdatePlan,
1158
- registerFirmwareUpdateHostBinding,
1159
- unregisterFirmwareUpdateHostBinding,
1160
- },
1161
- plan,
1162
- artifacts: memoryArtifacts,
1163
- });
1164
- const preparedPlan = validateFirmwareUpdatePreparedPlan(memoryHost.preparedPlan);
1165
- assertFirmwareUpdatePreparedPlanBinding({
1166
- preparedPlan,
1167
- executor: 'v4',
1168
- platform: this.params.platform,
1169
- scopeTargets: [],
1170
- bindings: [],
1171
- });
1172
- assertFirmwareUpdatePreparedPlanDeviceIdentity({
1173
- preparedPlan,
1174
- deviceIdentity: this.protocolV2ExpectedSerialNumber,
1175
- deviceModel: this.getProtocolV2PreparedPlanDeviceModel(features),
1078
+ private async createProtocolV2ResourceSourcesFromArchive(
1079
+ binary: ArrayBuffer
1080
+ ): Promise<ProtocolV2ResourceBundleSource[]> {
1081
+ const archive = await this.prepareProtocolV2LocalResourceArchive(binary);
1082
+ const sources: ProtocolV2ResourceBundleSource[] = [];
1083
+ for (const resource of archive.resources) {
1084
+ sources.push({
1085
+ name: resource.entryName.split('/').pop() ?? resource.entryName,
1086
+ source: await this.openProtocolV2MemorySource(resource.binary),
1087
+ devicePath: resource.header.devicePath,
1088
+ version: resource.header.version,
1089
+ payloadHash: resource.header.payloadHash,
1090
+ headerHash: resource.header.headerHash,
1176
1091
  });
1177
- const hostBinding = resolveFirmwareUpdateHostBinding(
1178
- memoryHost.hostBindingGeneration,
1179
- preparedPlan.preparedPlanDigest
1180
- );
1181
- this.params.preparedPlan = preparedPlan;
1182
- this.params.targetsToUpdate = [...preparedPlan.targetsToUpdate] as FirmwareUpdateV4Target[];
1183
- this.params.artifactReader = hostBinding.artifactReader;
1184
- this.params.componentArtifacts = undefined;
1185
- return memoryHost;
1186
- } catch (error) {
1187
- memoryHost?.release();
1188
- throw error;
1189
1092
  }
1093
+ return sources;
1190
1094
  }
1191
1095
 
1192
1096
  private async prepareProtocolV2LocalResourceArchive(
@@ -1225,7 +1129,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
1225
1129
  }
1226
1130
 
1227
1131
  let totalSize = 0;
1228
- const materializedEntries: FirmwareMemoryArtifactEntry[] = [];
1229
1132
  const resources: ProtocolV2LocalResourceArchive['resources'] = [];
1230
1133
  const devicePaths = new Set<string>();
1231
1134
  for (const entry of resourceEntries) {
@@ -1269,10 +1172,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
1269
1172
  );
1270
1173
  }
1271
1174
  devicePaths.add(canonicalDevicePath);
1272
- materializedEntries.push({ entryName: entry.name, binary: fileBinary });
1273
1175
  resources.push({ entryName: entry.name, binary: fileBinary, header });
1274
1176
  }
1275
- return { binary, materializedEntries, resources };
1177
+ return { binary, resources };
1276
1178
  }
1277
1179
 
1278
1180
  private async prepareProtocolV2ResourceSources(): Promise<ProtocolV2ResourceBundleSource[]> {
@@ -1339,20 +1241,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
1339
1241
 
1340
1242
  // The verified ZIP bytes are authoritative. Non-okpkg entries are release
1341
1243
  // metadata only; each RESOURCE package carries its own device path.
1342
- const verifiedArchive = await this.prepareProtocolV2LocalResourceArchive(archiveBinary);
1343
- const sources: ProtocolV2ResourceBundleSource[] = [];
1344
- for (const resource of verifiedArchive.resources) {
1345
- const source = await this.openProtocolV2MemorySource(resource.binary);
1346
- sources.push({
1347
- name: resource.entryName.split('/').pop() ?? resource.entryName,
1348
- source,
1349
- devicePath: resource.header.devicePath,
1350
- version: resource.header.version,
1351
- payloadHash: resource.header.payloadHash,
1352
- headerHash: resource.header.headerHash,
1353
- });
1354
- }
1355
- return sources;
1244
+ return this.createProtocolV2ResourceSourcesFromArchive(archiveBinary);
1356
1245
  }
1357
1246
 
1358
1247
  private async runProtocolV2PreparedArtifacts(
@@ -1836,6 +1725,12 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
1836
1725
  return `vol0:/${path}`;
1837
1726
  }
1838
1727
 
1728
+ private getProtocolV2ResourceComparePath(devicePath: string) {
1729
+ return isProtocolV2BootResourcePackagePath(devicePath)
1730
+ ? PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH
1731
+ : devicePath;
1732
+ }
1733
+
1839
1734
  private async readProtocolV2DeviceFileHeader(path: string, expectedSize?: number) {
1840
1735
  const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
1841
1736
  const filePath = this.getProtocolV2ResourceFilePath(path);
@@ -1898,7 +1793,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
1898
1793
 
1899
1794
  try {
1900
1795
  const header = await this.readProtocolV2DeviceFileHeader(
1901
- bundle.devicePath,
1796
+ this.getProtocolV2ResourceComparePath(bundle.devicePath),
1902
1797
  bundle.source.size
1903
1798
  );
1904
1799
  if (!header) return false;
@@ -2157,11 +2052,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2157
2052
  let totalSize = installSources.reduce((total, item) => total + item.source.size, 0);
2158
2053
  const resourcesToSync: ProtocolV2ResourceBundleSource[] = [];
2159
2054
  for (const resource of resourceSources) {
2160
- // Early boot promotes this mounted package's staging file. Always replace any
2161
- // stale staging bytes with the artifact approved by the current PreparedPlan,
2162
- // even when the mounted final file itself is already current.
2163
- const requiresFreshStaging = isProtocolV2BootResourcePackagePath(resource.devicePath);
2164
- if (!requiresFreshStaging && (await this.isProtocolV2ResourceBundleUpToDate(resource))) {
2055
+ if (await this.isProtocolV2ResourceBundleUpToDate(resource)) {
2165
2056
  Log.log(`[FirmwareUpdateV4] skip RESC bundle ${resource.name}; already up to date`);
2166
2057
  } else {
2167
2058
  resourcesToSync.push(resource);
@@ -654,47 +654,6 @@ const finalizeFirmwareUpdatePlan = ({
654
654
  });
655
655
  };
656
656
 
657
- export type ProtocolV2LocalFirmwareUpdatePlanArtifact = {
658
- artifactId: string;
659
- target: Exclude<FirmwareUpdateV4Target, 'boot_resources'>;
660
- container: 'raw' | 'zip';
661
- logicalName: string;
662
- expectedSize: number;
663
- expectedSha256: string;
664
- targetVersion?: string;
665
- };
666
-
667
- export const buildProtocolV2LocalFirmwareUpdatePlan = ({
668
- features,
669
- firmwareType,
670
- platform,
671
- artifacts,
672
- }: {
673
- features: Features;
674
- firmwareType: EFirmwareType;
675
- platform: FirmwareUpdatePlatform;
676
- artifacts: ProtocolV2LocalFirmwareUpdatePlanArtifact[];
677
- }): FirmwareUpdatePlan => {
678
- if (artifacts.length === 0) {
679
- return planError('Protocol V2 local firmware plan has no artifacts');
680
- }
681
- const plan = finalizeFirmwareUpdatePlan({
682
- features,
683
- firmwareType,
684
- platform,
685
- artifacts: artifacts.map(artifact => ({
686
- ...artifact,
687
- role: artifact.target === 'resource' ? 'resourceBundle' : 'component',
688
- url: `https://local-firmware.invalid/${encodeURIComponent(artifact.artifactId)}`,
689
- })),
690
- targetsToUpdate: artifacts.map(artifact => artifact.target),
691
- });
692
- if (plan.executor !== 'v4') {
693
- return planError('Protocol V2 local firmware plan requires executor v4');
694
- }
695
- return plan;
696
- };
697
-
698
657
  export const buildProtocolV2FirmwareUpdatePlan = ({
699
658
  features,
700
659
  firmwareType,
@@ -73,6 +73,8 @@ export const getFirmwareUpdateResourceName = (value: unknown): string => {
73
73
 
74
74
  const getPreparedEntryIdentity = (entryName: unknown): string => {
75
75
  getFirmwareUpdateResourceName(entryName);
76
+ // Protocol V2 resource ZIPs can ship the same basename from different
77
+ // directories, such as rom/params.okpkg and bootloader/params.okpkg.
76
78
  return (entryName as string).toLowerCase();
77
79
  };
78
80
 
@@ -69,7 +69,9 @@ export default class TransportManager {
69
69
  } else if (env === 'desktop-web-ble') {
70
70
  await this.transport.init(WebBleLogger, DevicePool.emitter);
71
71
  } else if (env === 'webusb' || env === 'desktop-webusb') {
72
- await this.transport.init(WebUsbLogger);
72
+ // The emitter is what turns a navigator.usb 'disconnect' into a
73
+ // DEVICE.DISCONNECT; without it WebUSB never reports device removal.
74
+ await this.transport.init(WebUsbLogger, DevicePool.emitter);
73
75
  } else {
74
76
  await this.transport.init(HttpLogger);
75
77
  }
package/src/index.ts CHANGED
@@ -21,12 +21,6 @@ export { executeCallback, cleanupCallback };
21
21
  export { preloadSessionCache } from './device/Device';
22
22
  export { projectFeatures as projectDeviceStateFeatures } from './device/DeviceStateProjector';
23
23
  export { getMethodSupportedProtocols } from './api/utils';
24
- export { prepareFirmwareUpdateV4MemoryHost } from './api/firmware/FirmwareMemoryHost';
25
- export type {
26
- FirmwareMemoryArtifact,
27
- FirmwareMemoryArtifactEntry,
28
- FirmwareUpdateV4MemoryHost,
29
- } from './api/firmware/FirmwareMemoryHost';
30
24
  export {
31
25
  getFirmwareUpdateHostBindingGeneration,
32
26
  registerFirmwareUpdateHostBinding,
@@ -158,7 +158,7 @@ export interface FirmwareUpdateV4Params {
158
158
  se02Binary?: ArrayBuffer;
159
159
  se03Binary?: ArrayBuffer;
160
160
  se04Binary?: ArrayBuffer;
161
- /** Complete Protocol V2 resource ZIP for local development; Core converts it to a local PreparedPlan. */
161
+ /** Complete Protocol V2 resource ZIP. Core parses RESC packages and writes only changed files. */
162
162
  resourceArchiveBinary?: ArrayBuffer;
163
163
  forcedUpdateRes?: boolean;
164
164
  artifactReader?: FirmwareArtifactReader;
@@ -31,7 +31,9 @@ export const getDeviceTypeByBleName = (name?: string): IDeviceType => {
31
31
  if (/^Touch/i.test(name)) return EDeviceType.Touch;
32
32
 
33
33
  const compactName = name.replace(/[\s-]/g, '');
34
- if (/\bPro\s*2\b/i.test(name) || /^Pro2/i.test(name) || /^(?:OneKey)?Pro2/i.test(compactName)) {
34
+ // Require a 4-hex Pro2 suffix in the compact form. A bare `^Pro2` prefix
35
+ // would also match OneKey Pro names such as "Pro 22D8" / "Pro 2D8F".
36
+ if (/\bPro\s*2\b/i.test(name) || /^(?:OneKey)?Pro2[a-f0-9]{4}$/i.test(compactName)) {
35
37
  return EDeviceType.Pro2;
36
38
  }
37
39
  if (/\bNeo\b/i.test(name) || /^Neo/i.test(name) || /^(?:OneKey)?Neo/i.test(compactName)) {
@@ -1,126 +0,0 @@
1
- import { prepareFirmwareUpdateV4MemoryHost } from '../src/api/firmware/FirmwareMemoryHost';
2
-
3
- import type { CoreApi } from '../src/types/api';
4
- import type { FirmwareUpdatePlan } from '../src/types/api/firmwareUpdatePlan';
5
-
6
- describe('prepareFirmwareUpdateV4MemoryHost', () => {
7
- test('registers artifact-backed component and resource readers', async () => {
8
- const componentBinary = new Uint8Array([1, 2, 3, 4]).buffer;
9
- const archiveBinary = new Uint8Array([5, 6]).buffer;
10
- const manifestBinary = new TextEncoder().encode('{"schema":1}').buffer;
11
- let artifactReader: Parameters<
12
- CoreApi['registerFirmwareUpdateHostBinding']
13
- >[0]['artifactReader'];
14
- const unregisterFirmwareUpdateHostBinding = jest.fn();
15
- const sdk = {
16
- prepareFirmwareUpdatePlan: jest.fn(({ plan, artifacts }) => ({
17
- schemaVersion: 2,
18
- preparedPlanDigest: 'b'.repeat(64),
19
- planDigest: plan.planDigest,
20
- networkPolicy: 'forbid',
21
- executor: plan.executor,
22
- deviceIdentity: plan.deviceIdentity,
23
- deviceModel: plan.deviceModel,
24
- firmwareType: plan.firmwareType,
25
- platform: plan.platform,
26
- leaseRef: 'test-lease',
27
- targetsToUpdate: plan.targetsToUpdate,
28
- artifacts: plan.artifacts.map(planArtifact => {
29
- const input = artifacts.find(item => item.artifactId === planArtifact.artifactId);
30
- return {
31
- ...planArtifact,
32
- artifact: input?.artifact,
33
- materializedEntries: input?.materializedEntries,
34
- };
35
- }),
36
- })),
37
- registerFirmwareUpdateHostBinding: jest.fn(binding => {
38
- artifactReader = binding.artifactReader;
39
- return 7;
40
- }),
41
- unregisterFirmwareUpdateHostBinding,
42
- } as unknown as Pick<
43
- CoreApi,
44
- | 'prepareFirmwareUpdatePlan'
45
- | 'registerFirmwareUpdateHostBinding'
46
- | 'unregisterFirmwareUpdateHostBinding'
47
- >;
48
- const plan = {
49
- schemaVersion: 2,
50
- planDigest: 'a'.repeat(64),
51
- executor: 'v4',
52
- deviceIdentity: 'device-id',
53
- deviceModel: 'pro2',
54
- firmwareType: 0,
55
- platform: 'web',
56
- targetsToUpdate: ['boot', 'resource'],
57
- artifacts: [
58
- {
59
- artifactId: 'component:boot',
60
- role: 'component',
61
- target: 'boot',
62
- url: 'https://example.com/boot.okpkg',
63
- container: 'raw',
64
- },
65
- {
66
- artifactId: 'resource:archive',
67
- role: 'resourceBundle',
68
- target: 'resource',
69
- url: 'https://example.com/resource.zip',
70
- container: 'zip',
71
- logicalName: 'resource-archive',
72
- },
73
- ],
74
- } as FirmwareUpdatePlan;
75
-
76
- const host = prepareFirmwareUpdateV4MemoryHost({
77
- sdk,
78
- plan,
79
- artifacts: [
80
- { artifactId: 'component:boot', binary: componentBinary },
81
- {
82
- artifactId: 'resource:archive',
83
- binary: archiveBinary,
84
- materializedEntries: [{ entryName: 'manifest.json', binary: manifestBinary }],
85
- },
86
- ],
87
- });
88
-
89
- expect(host.hostBindingGeneration).toBe(7);
90
- expect(sdk.registerFirmwareUpdateHostBinding).toHaveBeenCalledWith(
91
- expect.objectContaining({ preparedPlanDigest: host.preparedPlan.preparedPlanDigest })
92
- );
93
- const componentArtifact = host.preparedPlan.artifacts.find(
94
- artifact => artifact.target === 'boot'
95
- )?.artifact;
96
- const resourceEntryArtifact = host.preparedPlan.artifacts.find(
97
- artifact => artifact.target === 'resource'
98
- )?.materializedEntries?.[0]?.artifact;
99
- expect(componentArtifact?.size).toBe(componentBinary.byteLength);
100
- expect(resourceEntryArtifact?.size).toBe(manifestBinary.byteLength);
101
- if (!artifactReader || !componentArtifact || !resourceEntryArtifact) {
102
- throw new Error('Firmware memory host test setup is incomplete');
103
- }
104
- new Uint8Array(componentBinary).fill(9);
105
- const opened = await artifactReader.open({
106
- artifactRef: componentArtifact.artifactRef,
107
- });
108
- const chunk = await artifactReader.read({
109
- readerId: opened.readerId,
110
- offset: 1,
111
- length: 2,
112
- });
113
- expect(Array.from(new Uint8Array(chunk.data))).toEqual([2, 3]);
114
- await artifactReader.close({ readerId: opened.readerId });
115
-
116
- // Materialized ZIP entries are receipts only. Execution opens the approved
117
- // archive and re-derives these bytes, so the memory host must not retain a
118
- // second readable copy of every expanded resource file.
119
- expect(() => artifactReader.open({ artifactRef: resourceEntryArtifact.artifactRef })).toThrow(
120
- 'Firmware memory artifact is unavailable'
121
- );
122
-
123
- host.release();
124
- expect(unregisterFirmwareUpdateHostBinding).toHaveBeenCalledWith(7);
125
- });
126
- });
@@ -1,22 +0,0 @@
1
- import type { CoreApi } from '../../types/api';
2
- import type { FirmwareUpdatePlan } from '../../types/api/firmwareUpdatePlan';
3
- export type FirmwareMemoryArtifactEntry = {
4
- entryName: string;
5
- binary: ArrayBuffer;
6
- };
7
- export type FirmwareMemoryArtifact = {
8
- artifactId: string;
9
- binary: ArrayBuffer;
10
- materializedEntries?: FirmwareMemoryArtifactEntry[];
11
- };
12
- export type FirmwareUpdateV4MemoryHost = {
13
- preparedPlan: ReturnType<CoreApi['prepareFirmwareUpdatePlan']>;
14
- hostBindingGeneration: number;
15
- release: () => void;
16
- };
17
- export declare function prepareFirmwareUpdateV4MemoryHost({ sdk, plan, artifacts, }: {
18
- sdk: Pick<CoreApi, 'prepareFirmwareUpdatePlan' | 'registerFirmwareUpdateHostBinding' | 'unregisterFirmwareUpdateHostBinding'>;
19
- plan: FirmwareUpdatePlan;
20
- artifacts: FirmwareMemoryArtifact[];
21
- }): FirmwareUpdateV4MemoryHost;
22
- //# sourceMappingURL=FirmwareMemoryHost.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"FirmwareMemoryHost.d.ts","sourceRoot":"","sources":["../../../src/api/firmware/FirmwareMemoryHost.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAK/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAE7E,MAAM,MAAM,2BAA2B,GAAG;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,mBAAmB,CAAC,EAAE,2BAA2B,EAAE,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,YAAY,EAAE,UAAU,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC,CAAC;IAC/D,qBAAqB,EAAE,MAAM,CAAC;IAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAaF,wBAAgB,iCAAiC,CAAC,EAChD,GAAG,EACH,IAAI,EACJ,SAAS,GACV,EAAE;IACD,GAAG,EAAE,IAAI,CACP,OAAO,EACL,2BAA2B,GAC3B,mCAAmC,GACnC,qCAAqC,CACxC,CAAC;IACF,IAAI,EAAE,kBAAkB,CAAC;IACzB,SAAS,EAAE,sBAAsB,EAAE,CAAC;CACrC,GAAG,0BAA0B,CA0F7B"}