@onekeyfe/hd-core 1.2.0-alpha.95 → 1.2.0-alpha.97

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.
Files changed (89) hide show
  1. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +84 -404
  2. package/__tests__/firmware-update/device-update-bootloader.test.ts +2 -6
  3. package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -9
  4. package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +112 -0
  5. package/__tests__/firmware-update/firmware-update-plan.test.ts +70 -131
  6. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +1 -53
  7. package/__tests__/protocol-v2-resources.test.ts +232 -148
  8. package/__tests__/protocol-v2.test.ts +517 -1106
  9. package/dist/api/CheckAllFirmwareRelease.d.ts +3 -2
  10. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  11. package/dist/api/CheckBLEFirmwareRelease.d.ts +2 -3
  12. package/dist/api/CheckBLEFirmwareRelease.d.ts.map +1 -1
  13. package/dist/api/CheckBootloaderRelease.d.ts +1 -2
  14. package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
  15. package/dist/api/CheckFirmwareRelease.d.ts +2 -3
  16. package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
  17. package/dist/api/FirmwareUpdateV2.d.ts +0 -1
  18. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  19. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  20. package/dist/api/FirmwareUpdateV4.d.ts +8 -6
  21. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  22. package/dist/api/UploadPortfolio.d.ts.map +1 -1
  23. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  24. package/dist/api/firmware/FirmwareHostBinding.d.ts +1 -1
  25. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -1
  26. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  27. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +1 -48
  28. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
  29. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -1
  30. package/dist/api/firmware/getBinary.d.ts +1 -0
  31. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  32. package/dist/data-manager/DataManager.d.ts +3 -4
  33. package/dist/data-manager/DataManager.d.ts.map +1 -1
  34. package/dist/index.d.ts +111 -103
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +849 -1301
  37. package/dist/protocols/protocol-v2/resources.d.ts +28 -10
  38. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
  39. package/dist/types/api/checkAllFirmwareRelease.d.ts +8 -20
  40. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  41. package/dist/types/api/checkBLEFirmwareRelease.d.ts +13 -2
  42. package/dist/types/api/checkBLEFirmwareRelease.d.ts.map +1 -1
  43. package/dist/types/api/checkBootloaderRelease.d.ts +6 -2
  44. package/dist/types/api/checkBootloaderRelease.d.ts.map +1 -1
  45. package/dist/types/api/checkFirmwareRelease.d.ts +13 -2
  46. package/dist/types/api/checkFirmwareRelease.d.ts.map +1 -1
  47. package/dist/types/api/checkFirmwareTypeAvailable.d.ts +2 -2
  48. package/dist/types/api/checkFirmwareTypeAvailable.d.ts.map +1 -1
  49. package/dist/types/api/export.d.ts +1 -1
  50. package/dist/types/api/export.d.ts.map +1 -1
  51. package/dist/types/api/firmwareUpdate.d.ts +11 -3
  52. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  53. package/dist/types/settings.d.ts +36 -35
  54. package/dist/types/settings.d.ts.map +1 -1
  55. package/package.json +4 -4
  56. package/src/api/CheckAllFirmwareRelease.ts +80 -108
  57. package/src/api/CheckBLEFirmwareRelease.ts +5 -37
  58. package/src/api/CheckBootloaderRelease.ts +3 -35
  59. package/src/api/CheckFirmwareRelease.ts +7 -35
  60. package/src/api/FirmwareUpdateV2.ts +3 -15
  61. package/src/api/FirmwareUpdateV3.ts +6 -13
  62. package/src/api/FirmwareUpdateV4.ts +407 -824
  63. package/src/api/UploadPortfolio.ts +0 -18
  64. package/src/api/device/DeviceUpdateBootloader.ts +5 -26
  65. package/src/api/firmware/FirmwareHostBinding.ts +3 -16
  66. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +2 -0
  67. package/src/api/firmware/FirmwareUpdatePlan.ts +88 -226
  68. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +3 -10
  69. package/src/data-manager/DataManager.ts +19 -35
  70. package/src/index.ts +0 -10
  71. package/src/protocols/protocol-v2/resources.ts +341 -157
  72. package/src/types/api/checkAllFirmwareRelease.ts +12 -27
  73. package/src/types/api/checkBLEFirmwareRelease.ts +13 -4
  74. package/src/types/api/checkBootloaderRelease.ts +6 -2
  75. package/src/types/api/checkFirmwareRelease.ts +13 -2
  76. package/src/types/api/checkFirmwareTypeAvailable.ts +2 -2
  77. package/src/types/api/export.ts +1 -6
  78. package/src/types/api/firmwareUpdate.ts +16 -10
  79. package/src/types/settings.ts +61 -35
  80. package/src/utils/deviceFeaturesUtils.ts +2 -2
  81. package/__tests__/check-firmware-release-protocol-v2.test.ts +0 -199
  82. package/__tests__/firmware-memory-host.test.ts +0 -112
  83. package/__tests__/firmware-update/firmware-prepared-host-digest.test.ts +0 -448
  84. package/dist/api/firmware/FirmwareMemoryHost.d.ts +0 -22
  85. package/dist/api/firmware/FirmwareMemoryHost.d.ts.map +0 -1
  86. package/dist/api/firmware/protocolV2Release.d.ts +0 -33
  87. package/dist/api/firmware/protocolV2Release.d.ts.map +0 -1
  88. package/src/api/firmware/FirmwareMemoryHost.ts +0 -142
  89. package/src/api/firmware/protocolV2Release.ts +0 -168
package/dist/index.js CHANGED
@@ -522,10 +522,6 @@ const PROTOCOL_V2_TARGETS = {
522
522
  SE03: 'se03',
523
523
  SE04: 'se04',
524
524
  };
525
- const PROTOCOL_V2_FIRMWARE_UPDATE_TARGETS = new Set([
526
- ...Object.values(PROTOCOL_V2_TARGETS),
527
- 'resource',
528
- ]);
529
525
  const asRecord = (value) => value && typeof value === 'object' && !Array.isArray(value)
530
526
  ? value
531
527
  : undefined;
@@ -613,18 +609,6 @@ const validateFirmwareUpdatePlanForceTargets = (value) => {
613
609
  }
614
610
  return [...value];
615
611
  };
616
- const validateProtocolV2FirmwareUpdateTargets = (value) => {
617
- if (value === undefined) {
618
- return [];
619
- }
620
- if (!Array.isArray(value) ||
621
- value.length > PROTOCOL_V2_FIRMWARE_UPDATE_TARGETS.size ||
622
- value.some(target => !PROTOCOL_V2_FIRMWARE_UPDATE_TARGETS.has(target)) ||
623
- new Set(value).size !== value.length) {
624
- return planError('Protocol V2 firmware update targets are invalid');
625
- }
626
- return [...value];
627
- };
628
612
  const assertExactKeys = (value, required, optional = []) => {
629
613
  const allowed = new Set([...required, ...optional]);
630
614
  if (required.some(key => !Object.prototype.hasOwnProperty.call(value, key)) ||
@@ -754,7 +738,7 @@ const assertFirmwareUpdatePlan = (value) => {
754
738
  plan.targetsToUpdate.some(target => legacyOnlyTargets.has(target))) ||
755
739
  (plan.artifacts.length > 0 &&
756
740
  (plan.platform === 'native' || plan.platform === 'desktop') &&
757
- plan.executor === 'v3' &&
741
+ plan.executor !== 'v2' &&
758
742
  plan.deviceIdentity === 'unavailable')) {
759
743
  return planError('Firmware update plan executor contract is invalid');
760
744
  }
@@ -789,7 +773,7 @@ const selectResourceUrl = ({ release, features, platform, }) => {
789
773
  };
790
774
  const getExecutor = (features) => {
791
775
  const deviceType = getDeviceType(features);
792
- if (deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo) {
776
+ if (deviceType === hdShared.EDeviceType.Pro2) {
793
777
  return 'v4';
794
778
  }
795
779
  if (deviceType === hdShared.EDeviceType.Pro &&
@@ -798,7 +782,7 @@ const getExecutor = (features) => {
798
782
  }
799
783
  return 'v2';
800
784
  };
801
- const buildProtocolV2Artifacts = (release, { includeComponents = true, componentTargets: selectedComponentTargets, } = {}) => {
785
+ const buildProtocolV2Artifacts = (release, { includeComponents = true, includeResources = true, } = {}) => {
802
786
  var _a;
803
787
  const components = asRecord(release.components);
804
788
  if (includeComponents && !components) {
@@ -810,42 +794,49 @@ const buildProtocolV2Artifacts = (release, { includeComponents = true, component
810
794
  const componentKeys = includeComponents && components
811
795
  ? [...installOrder, ...Object.keys(components).filter(key => !installOrder.includes(key))]
812
796
  : [];
813
- const selectedComponentKeys = selectedComponentTargets
814
- ? componentKeys.filter(key => {
815
- var _a;
816
- const component = asRecord(components === null || components === void 0 ? void 0 : components[key]);
817
- const targetName = (_a = asString(component === null || component === void 0 ? void 0 : component.target)) === null || _a === void 0 ? void 0 : _a.toUpperCase();
818
- const target = targetName ? PROTOCOL_V2_TARGETS[targetName] : undefined;
819
- return !!target && selectedComponentTargets.has(target);
820
- })
821
- : componentKeys;
822
797
  const artifacts = [];
823
798
  const targets = [];
824
- const componentTargetSet = new Set();
825
- for (const key of selectedComponentKeys) {
799
+ const componentTargets = new Set();
800
+ for (const key of componentKeys) {
826
801
  const component = asRecord(components === null || components === void 0 ? void 0 : components[key]);
827
802
  const targetName = (_a = asString(component === null || component === void 0 ? void 0 : component.target)) === null || _a === void 0 ? void 0 : _a.toUpperCase();
828
- const target = targetName ? PROTOCOL_V2_TARGETS[targetName] : undefined;
829
803
  if (targetName === 'ROMLOADER') {
830
804
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 ROMLOADER requires its dedicated loader flow', { firmwareUpdateCode: 'FirmwarePlanInvalid' });
831
805
  }
806
+ const target = targetName ? PROTOCOL_V2_TARGETS[targetName] : undefined;
832
807
  if (!component || !target) {
833
808
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 component ${key} has an unsupported target`, { firmwareUpdateCode: 'FirmwarePlanInvalid' });
834
809
  }
835
- if (componentTargetSet.has(target)) {
810
+ if (componentTargets.has(target)) {
836
811
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 component ${key} duplicates target ${target}`, { firmwareUpdateCode: 'FirmwarePlanInvalid' });
837
812
  }
838
- componentTargetSet.add(target);
839
- const integrity = asIntegrity({
813
+ componentTargets.add(target);
814
+ artifacts.push(Object.assign(Object.assign({ artifactId: `component:${target}`, role: 'component', target, url: assertArtifactUrl(component.url, `Protocol V2 component ${key}`), container: 'raw', logicalName: key }, asIntegrity({
840
815
  size: component.expectedSize,
841
816
  sha256: component.fingerprint,
842
- });
843
- if (integrity.expectedSize === undefined || integrity.expectedSha256 === undefined) {
844
- planError(`Protocol V2 component ${key} integrity metadata is invalid`);
845
- }
846
- artifacts.push(Object.assign(Object.assign({ artifactId: `component:${target}`, role: 'component', target, url: assertArtifactUrl(component.url, `Protocol V2 component ${key}`), container: 'raw', logicalName: key }, integrity), (asVersion(component.version) ? { targetVersion: asVersion(component.version) } : {})));
817
+ })), (asVersion(component.version) ? { targetVersion: asVersion(component.version) } : {})));
847
818
  targets.push(target);
848
819
  }
820
+ const bundles = includeResources && Array.isArray(release.resourceBundles) ? release.resourceBundles : [];
821
+ const resourceBundleNames = new Set();
822
+ for (const value of bundles) {
823
+ const bundle = asRecord(value);
824
+ const name = asString(bundle === null || bundle === void 0 ? void 0 : bundle.name);
825
+ if (!bundle || !name) {
826
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 resource bundle is invalid', { firmwareUpdateCode: 'FirmwarePlanInvalid' });
827
+ }
828
+ if (resourceBundleNames.has(name)) {
829
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 resource bundle duplicates name ${name}`, { firmwareUpdateCode: 'FirmwarePlanInvalid' });
830
+ }
831
+ resourceBundleNames.add(name);
832
+ artifacts.push(Object.assign({ artifactId: `resourceBundle:${name}`, role: 'resourceBundle', target: 'resource', url: assertArtifactUrl(bundle.url, `Protocol V2 resource bundle ${name}`), container: 'raw', logicalName: name }, asIntegrity({
833
+ size: bundle.expectedSize,
834
+ sha256: bundle.fingerprint,
835
+ })));
836
+ }
837
+ if (bundles.length > 0) {
838
+ targets.push('resource');
839
+ }
849
840
  return { artifacts, targets: [...new Set(targets)] };
850
841
  };
851
842
  const isForcedTargetRepresented = ({ executor, forcedTarget, artifacts, targetsToUpdate, }) => {
@@ -874,95 +865,6 @@ const assertForcedTargetsRepresented = ({ executor, forcedTargets, artifacts, ta
874
865
  }
875
866
  }
876
867
  };
877
- const finalizeFirmwareUpdatePlan = ({ features, firmwareType, platform, artifacts, targetsToUpdate, }) => {
878
- const executor = getExecutor(features);
879
- const bootloaderMode = resolveDeviceBootloaderMode(features);
880
- const reportedIdentity = getDeviceUUID(features);
881
- const deviceIdentity = reportedIdentity === 'unavailable' ? '' : reportedIdentity;
882
- const allowsUnavailableIdentity = (bootloaderMode && executor === 'v2') || executor === 'v4';
883
- if (artifacts.length > 0 &&
884
- (platform === 'native' || platform === 'desktop') &&
885
- !deviceIdentity &&
886
- !allowsUnavailableIdentity) {
887
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Prepared firmware update requires a stable device identity', { firmwareUpdateCode: 'FirmwarePlanInvalid' });
888
- }
889
- const planWithoutDigest = {
890
- schemaVersion: 2,
891
- executor,
892
- deviceIdentity: deviceIdentity || 'unavailable',
893
- deviceModel: String(getDeviceType(features)),
894
- firmwareType,
895
- platform,
896
- artifacts,
897
- targetsToUpdate,
898
- };
899
- return assertFirmwareUpdatePlan(Object.assign(Object.assign({}, planWithoutDigest), { planDigest: digestFirmwareUpdatePlan(planWithoutDigest) }));
900
- };
901
- const buildProtocolV2LocalFirmwareUpdatePlan = ({ features, firmwareType, platform, artifacts, }) => {
902
- if (artifacts.length === 0) {
903
- return planError('Protocol V2 local firmware plan has no artifacts');
904
- }
905
- const plan = finalizeFirmwareUpdatePlan({
906
- features,
907
- firmwareType,
908
- platform,
909
- artifacts: artifacts.map(artifact => (Object.assign(Object.assign({}, artifact), { role: artifact.target === 'resource' ? 'resourceBundle' : 'component', url: `https://local-firmware.invalid/${encodeURIComponent(artifact.artifactId)}` }))),
910
- targetsToUpdate: artifacts.map(artifact => artifact.target),
911
- });
912
- if (plan.executor !== 'v4') {
913
- return planError('Protocol V2 local firmware plan requires executor v4');
914
- }
915
- return plan;
916
- };
917
- const buildProtocolV2FirmwareUpdatePlan = ({ features, firmwareType, platform, release, targetsToUpdate, forceUpdateTargets, resourceArchive, }) => {
918
- const validatedForceTargets = validateFirmwareUpdatePlanForceTargets(forceUpdateTargets);
919
- if (validatedForceTargets.some(target => target === 'ble' || target === 'bootloader')) {
920
- planError('Protocol V2 does not support forced BLE or legacy bootloader targets');
921
- }
922
- const requestedComponentTargets = new Set(targetsToUpdate.filter(target => target !== 'resource'));
923
- if (getDeviceType(features) === hdShared.EDeviceType.Neo &&
924
- (requestedComponentTargets.has('se03') || requestedComponentTargets.has('se04'))) {
925
- planError('Neo does not support Protocol V2 targets se03 or se04');
926
- }
927
- const protocolV2 = buildProtocolV2Artifacts(release !== null && release !== void 0 ? release : {}, {
928
- includeComponents: requestedComponentTargets.size > 0,
929
- componentTargets: requestedComponentTargets,
930
- });
931
- const resourceRequested = targetsToUpdate.includes('resource');
932
- if (resourceRequested) {
933
- const archive = resourceArchive;
934
- if (!archive) {
935
- return planError('Protocol V2 resource target has no resource archive');
936
- }
937
- const integrity = asIntegrity({
938
- size: archive.archiveSize,
939
- sha256: archive.archiveSha256,
940
- });
941
- if (integrity.expectedSize === undefined || integrity.expectedSha256 === undefined) {
942
- planError('Protocol V2 resource archive integrity metadata is invalid');
943
- }
944
- protocolV2.artifacts.push(Object.assign({ artifactId: 'resource:archive', role: 'resourceBundle', target: 'resource', url: assertArtifactUrl(archive.archiveUrl, 'Protocol V2 resource archive'), container: 'zip', logicalName: 'protocol-v2-resource-archive' }, integrity));
945
- protocolV2.targets.push('resource');
946
- }
947
- const representedTargets = new Set(protocolV2.targets);
948
- const missingTarget = Array.from(requestedComponentTargets).find(target => !representedTargets.has(target));
949
- if (missingTarget) {
950
- planError(`Protocol V2 release does not contain requested target ${missingTarget}`);
951
- }
952
- if (validatedForceTargets.includes('firmware') && protocolV2.targets.length === 0) {
953
- planError('Forced firmware update target firmware is not represented by the plan');
954
- }
955
- if (validatedForceTargets.includes('resource') && !resourceArchive) {
956
- planError('Forced firmware update target resource has no Protocol V2 resource archive');
957
- }
958
- return finalizeFirmwareUpdatePlan({
959
- features,
960
- firmwareType,
961
- platform,
962
- artifacts: protocolV2.artifacts,
963
- targetsToUpdate: protocolV2.targets,
964
- });
965
- };
966
868
  const buildFirmwareUpdatePlan = ({ features, firmwareType, platform, firmware, ble, bootloader, forceUpdateTargets, }) => {
967
869
  var _a, _b, _c, _d, _e, _f, _g;
968
870
  const executor = getExecutor(features);
@@ -984,6 +886,7 @@ const buildFirmwareUpdatePlan = ({ features, firmwareType, platform, firmware, b
984
886
  if (executor === 'v4' && (shouldUpdateFirmware || shouldUpdateResource)) {
985
887
  const protocolV2 = buildProtocolV2Artifacts(firmwareRelease !== null && firmwareRelease !== void 0 ? firmwareRelease : {}, {
986
888
  includeComponents: shouldUpdateFirmware,
889
+ includeResources: shouldUpdateResource,
987
890
  });
988
891
  artifacts = protocolV2.artifacts;
989
892
  targetsToUpdate = protocolV2.targets;
@@ -1048,13 +951,25 @@ const buildFirmwareUpdatePlan = ({ features, firmwareType, platform, firmware, b
1048
951
  artifacts,
1049
952
  targetsToUpdate,
1050
953
  });
1051
- return finalizeFirmwareUpdatePlan({
1052
- features,
954
+ const reportedIdentity = getDeviceUUID(features);
955
+ const deviceIdentity = reportedIdentity === 'unavailable' ? '' : reportedIdentity;
956
+ if (artifacts.length > 0 &&
957
+ (platform === 'native' || platform === 'desktop') &&
958
+ !deviceIdentity &&
959
+ !(bootloaderMode && executor === 'v2')) {
960
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Prepared firmware update requires a stable device identity', { firmwareUpdateCode: 'FirmwarePlanInvalid' });
961
+ }
962
+ const planWithoutDigest = {
963
+ schemaVersion: 2,
964
+ executor,
965
+ deviceIdentity: deviceIdentity || 'unavailable',
966
+ deviceModel: String(getDeviceType(features)),
1053
967
  firmwareType,
1054
968
  platform,
1055
969
  artifacts,
1056
970
  targetsToUpdate,
1057
- });
971
+ };
972
+ return assertFirmwareUpdatePlan(Object.assign(Object.assign({}, planWithoutDigest), { planDigest: digestFirmwareUpdatePlan(planWithoutDigest) }));
1058
973
  };
1059
974
 
1060
975
  const preparedPlanError = (message) => {
@@ -1175,7 +1090,7 @@ const prepareFirmwareUpdatePlan = ({ plan: value, leaseRef, artifacts, }) => {
1175
1090
  return Object.assign(Object.assign({}, planWithoutDigest), { preparedPlanDigest: digestPreparedPlan(planWithoutDigest) });
1176
1091
  };
1177
1092
  const validateFirmwareUpdatePreparedPlan = (value) => {
1178
- var _a, _b, _c, _d;
1093
+ var _a, _b, _c;
1179
1094
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
1180
1095
  return preparedPlanError('Firmware prepared plan must be an object');
1181
1096
  }
@@ -1255,13 +1170,7 @@ const validateFirmwareUpdatePreparedPlan = (value) => {
1255
1170
  artifactIds.add(artifact.artifactId);
1256
1171
  artifactTargets.add(artifact.target);
1257
1172
  assertFirmwareArtifactReference(artifact.artifact);
1258
- const materializedEntryNames = (_d = (_c = artifact.materializedEntries) === null || _c === void 0 ? void 0 : _c.map(entry => {
1259
- assertPreparedEntry(entry);
1260
- return getFirmwareUpdateResourceName(entry.entryName).toLowerCase();
1261
- })) !== null && _d !== void 0 ? _d : [];
1262
- if (new Set(materializedEntryNames).size !== materializedEntryNames.length) {
1263
- return preparedPlanError('Firmware prepared plan contains duplicate entry names');
1264
- }
1173
+ (_c = artifact.materializedEntries) === null || _c === void 0 ? void 0 : _c.forEach(assertPreparedEntry);
1265
1174
  }
1266
1175
  if (preparedPlan.targetsToUpdate.some(target => !FIRMWARE_UPDATE_PLAN_TARGETS.has(target)) ||
1267
1176
  new Set(preparedPlan.targetsToUpdate).size !== preparedPlan.targetsToUpdate.length ||
@@ -1295,7 +1204,7 @@ const assertFirmwareUpdatePreparedPlanDeviceIdentity = ({ preparedPlan: value, d
1295
1204
  }
1296
1205
  const pinnedIdentity = degradedPlanIdentityPins.get(preparedPlan.leaseRef);
1297
1206
  if (!deviceIdentity) {
1298
- if (preparedPlan.executor !== 'v4' && bootloaderMode !== true) {
1207
+ if (bootloaderMode !== true) {
1299
1208
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckDeviceIdError);
1300
1209
  }
1301
1210
  return preparedPlan;
@@ -1368,8 +1277,6 @@ class FirmwareHostBindingRegistry {
1368
1277
  register(binding) {
1369
1278
  var _a;
1370
1279
  if (!binding ||
1371
- typeof binding.preparedPlanDigest !== 'string' ||
1372
- !/^[0-9a-f]{64}$/i.test(binding.preparedPlanDigest) ||
1373
1280
  typeof ((_a = binding.artifactReader) === null || _a === void 0 ? void 0 : _a.open) !== 'function' ||
1374
1281
  typeof binding.artifactReader.read !== 'function' ||
1375
1282
  typeof binding.artifactReader.close !== 'function') {
@@ -1390,7 +1297,7 @@ class FirmwareHostBindingRegistry {
1390
1297
  getGeneration() {
1391
1298
  return this.generation;
1392
1299
  }
1393
- resolve(generation, preparedPlanDigest) {
1300
+ resolve(generation) {
1394
1301
  if (!Number.isSafeInteger(generation) ||
1395
1302
  generation <= 0 ||
1396
1303
  generation !== this.generation ||
@@ -1398,17 +1305,12 @@ class FirmwareHostBindingRegistry {
1398
1305
  return bindingError(`Firmware host binding generation ${generation} is stale`);
1399
1306
  }
1400
1307
  const { binding } = this;
1401
- if (preparedPlanDigest !== undefined &&
1402
- binding.preparedPlanDigest.toLowerCase() !== preparedPlanDigest.toLowerCase()) {
1403
- return bindingError(`Firmware host binding generation ${generation} does not match the prepared plan`);
1404
- }
1405
1308
  const assertCurrent = () => {
1406
1309
  if (generation !== this.generation || binding !== this.binding) {
1407
1310
  bindingError(`Firmware host binding generation ${generation} is stale`);
1408
1311
  }
1409
1312
  };
1410
1313
  return {
1411
- preparedPlanDigest: binding.preparedPlanDigest,
1412
1314
  artifactReader: {
1413
1315
  open: (input) => __awaiter(this, void 0, void 0, function* () {
1414
1316
  assertCurrent();
@@ -1441,7 +1343,7 @@ const firmwareHostBindingRegistry = new FirmwareHostBindingRegistry();
1441
1343
  const registerFirmwareUpdateHostBinding = (binding) => firmwareHostBindingRegistry.register(binding);
1442
1344
  const unregisterFirmwareUpdateHostBinding = (generation) => firmwareHostBindingRegistry.unregister(generation);
1443
1345
  const getFirmwareUpdateHostBindingGeneration = () => firmwareHostBindingRegistry.getGeneration();
1444
- const resolveFirmwareUpdateHostBinding = (generation, preparedPlanDigest) => firmwareHostBindingRegistry.resolve(generation !== null && generation !== void 0 ? generation : Number.NaN, preparedPlanDigest);
1346
+ const resolveFirmwareUpdateHostBinding = (generation) => firmwareHostBindingRegistry.resolve(generation !== null && generation !== void 0 ? generation : Number.NaN);
1445
1347
 
1446
1348
  const callbackManager = new Map();
1447
1349
  const generateCallbackId = () => `callback_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
@@ -40602,8 +40504,143 @@ const findLatestRelease = (releases) => {
40602
40504
  return leastRelease;
40603
40505
  };
40604
40506
 
40605
- const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH$1 = 'vol0:/loaders/bootloader/boot_resource.okpkg';
40507
+ const PROTOCOL_V2_RESOURCE_TYPES = [
40508
+ 'images',
40509
+ 'animation',
40510
+ 'wallpaper',
40511
+ 'translations',
40512
+ 'roobert',
40513
+ 'noto',
40514
+ 'firmware_logo',
40515
+ ];
40516
+ const PROTOCOL_V2_RESOURCE_DEVICE_PATHS = {
40517
+ images: 'vol0:/bundles/images/images.okpkg',
40518
+ animation: 'vol0:/bundles/images/animation.okpkg',
40519
+ wallpaper: 'vol0:/bundles/images/wallpaper.okpkg',
40520
+ translations: 'vol0:/bundles/translations/translations.okpkg',
40521
+ roobert: 'vol0:/bundles/font/roobert.okpkg',
40522
+ noto: 'vol0:/bundles/font/noto.okpkg',
40523
+ firmware_logo: 'vol0:/bundles/firmware_logo.okpkg',
40524
+ };
40525
+ const RESOURCE_TYPE_SET = new Set(PROTOCOL_V2_RESOURCE_TYPES);
40606
40526
  const SHA256_HEX_LENGTH = 64;
40527
+ const SHA3_512_HEX_LENGTH = 128;
40528
+ const PROTOCOL_V2_OKPP_HEADER_SIZE$1 = 0x52a0;
40529
+ const PROTOCOL_V2_OKPP_TYPE_OFFSET = 0x08;
40530
+ const PROTOCOL_V2_OKPP_HEADER_LENGTH_OFFSET = 0x0c;
40531
+ const PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET$1 = 0x240;
40532
+ const PROTOCOL_V2_OKPP_HASH_SIZE$1 = 64;
40533
+ const PROTOCOL_V2_RESOURCE_IDENTITY_READ_SIZE = PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET$1 + PROTOCOL_V2_OKPP_HASH_SIZE$1;
40534
+ const PROTOCOL_V2_MIN_FILE_READ_CHUNK_SIZE = 64;
40535
+ const PROTOCOL_V2_RESOURCE_INVENTORY_TIMEOUT_MS = 5 * 1000;
40536
+ function toFiniteNumber(value) {
40537
+ if (typeof value === 'number' && Number.isFinite(value))
40538
+ return value;
40539
+ if (typeof value === 'string') {
40540
+ const numeric = Number(value);
40541
+ return Number.isFinite(numeric) ? numeric : undefined;
40542
+ }
40543
+ if (value && typeof value === 'object') {
40544
+ const longLike = value;
40545
+ if (typeof longLike.toNumber === 'function') {
40546
+ const numeric = longLike.toNumber();
40547
+ return Number.isFinite(numeric) ? numeric : undefined;
40548
+ }
40549
+ }
40550
+ return undefined;
40551
+ }
40552
+ function toUint8Array(value) {
40553
+ if (value instanceof Uint8Array)
40554
+ return value;
40555
+ if (value instanceof ArrayBuffer)
40556
+ return new Uint8Array(value);
40557
+ if (ArrayBuffer.isView(value)) {
40558
+ return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
40559
+ }
40560
+ if (typeof value === 'string') {
40561
+ const hex = value.replace(/^0x/i, '');
40562
+ if (!hex || hex.length % 2 !== 0 || /[^0-9a-f]/i.test(hex)) {
40563
+ return new Uint8Array(0);
40564
+ }
40565
+ const bytes = new Uint8Array(hex.length / 2);
40566
+ for (let index = 0; index < bytes.length; index += 1) {
40567
+ bytes[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);
40568
+ }
40569
+ return bytes;
40570
+ }
40571
+ return new Uint8Array(0);
40572
+ }
40573
+ function readAscii(bytes, offset, length) {
40574
+ return Array.from(bytes.slice(offset, offset + length), byte => String.fromCharCode(byte)).join('');
40575
+ }
40576
+ function parseProtocolV2ResourceHeaderHash(bytes) {
40577
+ if (bytes.byteLength < PROTOCOL_V2_RESOURCE_IDENTITY_READ_SIZE)
40578
+ return undefined;
40579
+ if (readAscii(bytes, 0, 4) !== 'OKPP')
40580
+ return undefined;
40581
+ if (readAscii(bytes, PROTOCOL_V2_OKPP_TYPE_OFFSET, 4) !== 'RESC')
40582
+ return undefined;
40583
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
40584
+ if (view.getUint32(PROTOCOL_V2_OKPP_HEADER_LENGTH_OFFSET, true) !== PROTOCOL_V2_OKPP_HEADER_SIZE$1) {
40585
+ return undefined;
40586
+ }
40587
+ return bytesToHex$3(bytes.slice(PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET$1, PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET$1 + PROTOCOL_V2_OKPP_HASH_SIZE$1));
40588
+ }
40589
+ function readProtocolV2ResourceIdentity({ commands, resource, chunkSize, timeoutMs = PROTOCOL_V2_RESOURCE_INVENTORY_TIMEOUT_MS, }) {
40590
+ var _a, _b, _c, _d;
40591
+ return __awaiter(this, void 0, void 0, function* () {
40592
+ const path = PROTOCOL_V2_RESOURCE_DEVICE_PATHS[resource.type];
40593
+ const pathInfo = yield commands.typedCall('FilesystemPathInfoQuery', 'FilesystemPathInfo', { path }, { timeoutMs });
40594
+ const size = toFiniteNumber((_a = pathInfo.message) === null || _a === void 0 ? void 0 : _a.size);
40595
+ if (!((_b = pathInfo.message) === null || _b === void 0 ? void 0 : _b.exist) ||
40596
+ ((_c = pathInfo.message) === null || _c === void 0 ? void 0 : _c.directory) ||
40597
+ !Number.isSafeInteger(size) ||
40598
+ size !== resource.size ||
40599
+ size < PROTOCOL_V2_OKPP_HEADER_SIZE$1) {
40600
+ return undefined;
40601
+ }
40602
+ const header = new Uint8Array(PROTOCOL_V2_RESOURCE_IDENTITY_READ_SIZE);
40603
+ let offset = 0;
40604
+ while (offset < header.byteLength) {
40605
+ const readLength = Math.min(chunkSize, header.byteLength - offset);
40606
+ const response = yield commands.typedCall('FilesystemFileRead', 'FilesystemFile', {
40607
+ file: { path, offset, total_size: 0 },
40608
+ chunk_len: readLength,
40609
+ }, { timeoutMs });
40610
+ const data = toUint8Array((_d = response.message) === null || _d === void 0 ? void 0 : _d.data);
40611
+ if (data.byteLength === 0)
40612
+ return undefined;
40613
+ const copied = Math.min(data.byteLength, header.byteLength - offset);
40614
+ header.set(data.subarray(0, copied), offset);
40615
+ offset += copied;
40616
+ }
40617
+ const headerHash = parseProtocolV2ResourceHeaderHash(header);
40618
+ return headerHash ? { type: resource.type, size, headerHash } : undefined;
40619
+ });
40620
+ }
40621
+ function readProtocolV2ResourceInventory({ commands, resources, chunkSize = hdTransport.PROTOCOL_V2_BLE_FILE_READ_CHUNK_SIZE, timeoutMs = PROTOCOL_V2_RESOURCE_INVENTORY_TIMEOUT_MS, }) {
40622
+ return __awaiter(this, void 0, void 0, function* () {
40623
+ const normalizedChunkSize = Number.isFinite(chunkSize)
40624
+ ? Math.max(Math.floor(chunkSize), PROTOCOL_V2_MIN_FILE_READ_CHUNK_SIZE)
40625
+ : hdTransport.PROTOCOL_V2_BLE_FILE_READ_CHUNK_SIZE;
40626
+ const inventory = [];
40627
+ for (const resource of resources) {
40628
+ try {
40629
+ const item = yield readProtocolV2ResourceIdentity({
40630
+ commands,
40631
+ resource,
40632
+ chunkSize: normalizedChunkSize,
40633
+ timeoutMs,
40634
+ });
40635
+ if (item)
40636
+ inventory.push(item);
40637
+ }
40638
+ catch (_a) {
40639
+ }
40640
+ }
40641
+ return inventory;
40642
+ });
40643
+ }
40607
40644
  function normalizeHex$1(value, expectedLength, field) {
40608
40645
  if (typeof value !== 'string') {
40609
40646
  throw new Error(`Invalid Pro2 resource ${field}: expected a hexadecimal string`);
@@ -40614,158 +40651,132 @@ function normalizeHex$1(value, expectedLength, field) {
40614
40651
  }
40615
40652
  return normalized;
40616
40653
  }
40617
- function parseProtocolV2Resources(value) {
40618
- if (value === undefined)
40619
- return undefined;
40654
+ function validateResource(value, index) {
40620
40655
  if (!value || typeof value !== 'object') {
40621
- throw new Error('Invalid Pro2 resources config');
40622
- }
40623
- const { source } = value;
40624
- if (!source || typeof source !== 'object') {
40625
- throw new Error('Invalid Pro2 resources config: source is required');
40656
+ throw new Error(`Invalid Pro2 resource at stable[${index}]`);
40626
40657
  }
40627
- const { archiveUrl, archiveSha256, archiveSize } = source;
40628
- if (typeof archiveUrl !== 'string' || !archiveUrl.startsWith('https://')) {
40629
- throw new Error('Invalid Pro2 resources config: source.archiveUrl must use HTTPS');
40658
+ const resource = value;
40659
+ if (typeof resource.type !== 'string' || !RESOURCE_TYPE_SET.has(resource.type)) {
40660
+ throw new Error(`Invalid Pro2 resource type at stable[${index}]`);
40630
40661
  }
40631
- if (typeof archiveSha256 !== 'string' || !/^[0-9a-fA-F]{64}$/.test(archiveSha256)) {
40632
- throw new Error('Invalid Pro2 resources config: source.archiveSha256 must be a SHA-256 digest');
40662
+ if (typeof resource.url !== 'string' || !resource.url.startsWith('https://')) {
40663
+ throw new Error(`Invalid Pro2 resource url at stable[${index}]`);
40633
40664
  }
40634
- if (!Number.isSafeInteger(archiveSize) || archiveSize <= 0) {
40635
- throw new Error('Invalid Pro2 resources config: source.archiveSize must be a positive integer');
40665
+ if (!Number.isSafeInteger(resource.size) || Number(resource.size) <= 0) {
40666
+ throw new Error(`Invalid Pro2 resource size at stable[${index}]`);
40636
40667
  }
40637
40668
  return {
40638
- source: {
40639
- archiveUrl,
40640
- archiveSha256: archiveSha256.toLowerCase(),
40641
- archiveSize: archiveSize,
40642
- },
40669
+ type: resource.type,
40670
+ url: resource.url,
40671
+ size: Number(resource.size),
40672
+ fileHash: normalizeHex$1(resource.fileHash, SHA256_HEX_LENGTH, 'fileHash'),
40673
+ headerHash: normalizeHex$1(resource.headerHash, SHA3_512_HEX_LENGTH, 'headerHash'),
40643
40674
  };
40644
40675
  }
40645
- const PROTOCOL_V2_RESOURCE_MANIFEST_DEVICE_ROOTS = [
40646
- 'vol0:/bundles/',
40647
- 'vol0:/loaders/rom/',
40648
- ];
40649
- function isAllowedManifestDevicePath(path) {
40650
- if (!path.endsWith('.okpkg') ||
40651
- path.includes('\\') ||
40652
- path.includes('//') ||
40653
- path.split('/').some(part => part === '.' || part === '..')) {
40654
- return false;
40676
+ function validateBootResources(value) {
40677
+ if (!value || typeof value !== 'object') {
40678
+ throw new Error('Invalid Pro2 boot resources config');
40655
40679
  }
40656
- if (path === PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH$1) {
40657
- return true;
40680
+ const resource = value;
40681
+ if (resource.required !== false) {
40682
+ throw new Error('Invalid Pro2 boot resources required flag: expected false');
40658
40683
  }
40659
- return PROTOCOL_V2_RESOURCE_MANIFEST_DEVICE_ROOTS.some(root => path.startsWith(root));
40660
- }
40661
- function assertManifestString(value, field) {
40662
- if (typeof value !== 'string' || value.length === 0) {
40663
- throw new Error(`Invalid Pro2 resource manifest ${field}`);
40684
+ if (resource.target !== 'RES') {
40685
+ throw new Error('Invalid Pro2 boot resources target: expected RES');
40664
40686
  }
40665
- return value;
40666
- }
40667
- function assertManifestRelativePath(value, field) {
40668
- const path = assertManifestString(value, field);
40669
- if (path.startsWith('/') ||
40670
- path.includes('\\') ||
40671
- path.includes(':') ||
40672
- path.split('/').some(part => !part || part === '.' || part === '..')) {
40673
- throw new Error(`Invalid Pro2 resource manifest ${field}`);
40674
- }
40675
- return path;
40676
- }
40677
- function parseProtocolV2ResourceManifestFile(value, index) {
40678
- var _a;
40679
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
40680
- throw new Error(`Invalid Pro2 resource manifest files[${index}]`);
40687
+ if (resource.manifestUrl !== undefined &&
40688
+ (typeof resource.manifestUrl !== 'string' || !resource.manifestUrl.startsWith('https://'))) {
40689
+ throw new Error('Invalid Pro2 boot resources manifestUrl');
40681
40690
  }
40682
- const file = value;
40683
- const archivePath = assertManifestRelativePath(file.archive_path, `files[${index}].archive_path`);
40684
- const originalName = assertManifestRelativePath(file.original_name, `files[${index}].original_name`);
40685
- if (originalName.includes('/')) {
40686
- throw new Error(`Invalid Pro2 resource manifest files[${index}].original_name`);
40691
+ if (!Array.isArray(resource.files) || resource.files.length === 0) {
40692
+ throw new Error('Invalid Pro2 boot resources files');
40687
40693
  }
40688
- const devicePath = assertManifestString(file.device_path, `files[${index}].device_path`);
40689
- if (!isAllowedManifestDevicePath(devicePath)) {
40690
- throw new Error(`Invalid Pro2 resource manifest files[${index}].device_path`);
40694
+ const files = resource.files.map((value, index) => {
40695
+ if (!value || typeof value !== 'object') {
40696
+ throw new Error(`Invalid Pro2 boot resource file at files[${index}]`);
40697
+ }
40698
+ const file = value;
40699
+ if (typeof file.url !== 'string' || !file.url.startsWith('https://')) {
40700
+ throw new Error(`Invalid Pro2 boot resource url at files[${index}]`);
40701
+ }
40702
+ if (typeof file.devicePath !== 'string' ||
40703
+ !file.devicePath.startsWith('vol0:/') ||
40704
+ file.devicePath.includes('..') ||
40705
+ file.devicePath.includes('\\')) {
40706
+ throw new Error(`Invalid Pro2 boot resource devicePath at files[${index}]`);
40707
+ }
40708
+ if (!Number.isSafeInteger(file.size) || Number(file.size) <= 0) {
40709
+ throw new Error(`Invalid Pro2 boot resource size at files[${index}]`);
40710
+ }
40711
+ return Object.assign(Object.assign({}, (typeof file.name === 'string' && file.name ? { name: file.name } : undefined)), { url: file.url, devicePath: file.devicePath, size: Number(file.size), fileHash: normalizeHex$1(file.fileHash, SHA256_HEX_LENGTH, `boot files[${index}].fileHash`) });
40712
+ });
40713
+ if (new Set(files.map(file => file.devicePath)).size !== files.length) {
40714
+ throw new Error('Invalid Pro2 boot resources files: duplicate devicePath');
40691
40715
  }
40692
- if (!Number.isSafeInteger(file.size) || Number(file.size) <= 0) {
40693
- throw new Error(`Invalid Pro2 resource manifest files[${index}].size`);
40716
+ return Object.assign(Object.assign({ required: false, target: 'RES' }, (resource.manifestUrl ? { manifestUrl: resource.manifestUrl } : undefined)), { files });
40717
+ }
40718
+ function parseProtocolV2Resources(value) {
40719
+ if (value === undefined)
40720
+ return undefined;
40721
+ if (!value ||
40722
+ typeof value !== 'object' ||
40723
+ !Array.isArray(value.stable)) {
40724
+ throw new Error('Invalid Pro2 resources config: stable must be an array');
40694
40725
  }
40695
- const digest = normalizeHex$1(file.sha256, SHA256_HEX_LENGTH, `files[${index}].sha256`);
40696
- if (file.signed !== true) {
40697
- throw new Error(`Invalid Pro2 resource manifest files[${index}].signed`);
40726
+ const config = value;
40727
+ const stable = config.stable.map(validateResource);
40728
+ const types = new Set(stable.map(resource => resource.type));
40729
+ if (stable.length !== PROTOCOL_V2_RESOURCE_TYPES.length || types.size !== stable.length) {
40730
+ throw new Error(`Invalid Pro2 resources config: stable must contain ${PROTOCOL_V2_RESOURCE_TYPES.length} unique resource types`);
40698
40731
  }
40699
- if (file.sig_algo !== 'ed25519' && file.sig_algo !== 'mldsa65') {
40700
- throw new Error(`Invalid Pro2 resource manifest files[${index}].sig_algo`);
40732
+ for (const type of PROTOCOL_V2_RESOURCE_TYPES) {
40733
+ if (!types.has(type)) {
40734
+ throw new Error(`Invalid Pro2 resources config: stable is missing ${type}`);
40735
+ }
40701
40736
  }
40702
- if (file.payload_version !== null && typeof file.payload_version !== 'string') {
40703
- throw new Error(`Invalid Pro2 resource manifest files[${index}].payload_version`);
40737
+ const boot = config.boot === undefined ? undefined : validateBootResources(config.boot);
40738
+ return Object.assign({ stable: PROTOCOL_V2_RESOURCE_TYPES.map(type => {
40739
+ const resource = stable.find(item => item.type === type);
40740
+ if (!resource) {
40741
+ throw new Error(`Invalid Pro2 resources config: stable is missing ${type}`);
40742
+ }
40743
+ return resource;
40744
+ }) }, (boot ? { boot } : undefined));
40745
+ }
40746
+ function buildProtocolV2ResourceUpdatePlan({ resources, inventory, mode, forced = false, }) {
40747
+ if (forced) {
40748
+ return {
40749
+ status: resources.length > 0 ? 'outdated' : 'valid',
40750
+ resources: [...resources],
40751
+ };
40704
40752
  }
40705
- if (!archivePath.endsWith('.okpkg') || !originalName.endsWith('.okpkg')) {
40706
- throw new Error(`Invalid Pro2 resource manifest files[${index}] package extension`);
40753
+ if (!inventory) {
40754
+ return mode === 'bootloader-recovery'
40755
+ ? {
40756
+ status: resources.length > 0 ? 'outdated' : 'valid',
40757
+ resources: [...resources],
40758
+ }
40759
+ : { status: 'unknown', resources: [] };
40707
40760
  }
40761
+ const inventoryByType = new Map(inventory.map(item => [item.type, item]));
40762
+ const changedResources = resources.filter(resource => {
40763
+ const current = inventoryByType.get(resource.type);
40764
+ return (!current ||
40765
+ current.size !== resource.size ||
40766
+ current.headerHash.toLowerCase() !== resource.headerHash.toLowerCase());
40767
+ });
40708
40768
  return {
40709
- archive_path: archivePath,
40710
- original_name: originalName,
40711
- device_path: devicePath,
40712
- size: Number(file.size),
40713
- sha256: digest,
40714
- signed: true,
40715
- sig_algo: file.sig_algo,
40716
- payload_version: (_a = file.payload_version) !== null && _a !== void 0 ? _a : null,
40769
+ status: changedResources.length === 0 ? 'valid' : 'outdated',
40770
+ resources: changedResources,
40717
40771
  };
40718
40772
  }
40719
- function parseProtocolV2ResourceManifest(value) {
40720
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
40721
- throw new Error('Invalid Pro2 resource manifest');
40722
- }
40723
- const manifest = value;
40724
- if (manifest.schema !== 1 ||
40725
- manifest.variant !== 'resource' ||
40726
- manifest.device_root !== 'vol0:' ||
40727
- manifest.restore_mode !== 'bootloader_update' ||
40728
- !Array.isArray(manifest.trees) ||
40729
- !Array.isArray(manifest.files)) {
40730
- throw new Error('Invalid Pro2 resource manifest contract');
40731
- }
40732
- const files = manifest.files.map(parseProtocolV2ResourceManifestFile);
40733
- const devicePaths = new Set(files.map(file => file.device_path));
40734
- const archivePaths = new Set(files.map(file => file.archive_path));
40735
- if (files.length === 0 ||
40736
- devicePaths.size !== files.length ||
40737
- archivePaths.size !== files.length ||
40738
- !devicePaths.has(PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH$1) ||
40739
- !files.some(file => file.device_path.startsWith('vol0:/bundles/'))) {
40740
- throw new Error('Invalid Pro2 resource manifest file set');
40741
- }
40742
- return {
40743
- schema: 1,
40744
- artifact_name: assertManifestString(manifest.artifact_name, 'artifact_name'),
40745
- release_name: assertManifestString(manifest.release_name, 'release_name'),
40746
- variant: 'resource',
40747
- commit: assertManifestString(manifest.commit, 'commit'),
40748
- short_sha: assertManifestString(manifest.short_sha, 'short_sha'),
40749
- timestamp_utc: assertManifestString(manifest.timestamp_utc, 'timestamp_utc'),
40750
- core_version: assertManifestString(manifest.core_version, 'core_version'),
40751
- key_set: assertManifestString(manifest.key_set, 'key_set'),
40752
- device_root: 'vol0:',
40753
- restore_mode: 'bootloader_update',
40754
- trees: manifest.trees.map((tree, index) => {
40755
- if (!tree || typeof tree !== 'object') {
40756
- throw new Error(`Invalid Pro2 resource manifest trees[${index}]`);
40757
- }
40758
- const item = tree;
40759
- return {
40760
- path: assertManifestRelativePath(item.path, `trees[${index}].path`),
40761
- device: assertManifestString(item.device, `trees[${index}].device`),
40762
- };
40763
- }),
40764
- files,
40765
- };
40773
+ function bytesToHex$3(bytes) {
40774
+ return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');
40766
40775
  }
40767
- function selectProtocolV2ResourceManifestFiles({ manifest, targetsToUpdate, }) {
40768
- return targetsToUpdate.includes('resource') ? [...manifest.files] : [];
40776
+ function isProtocolV2ResourceFileValid(binary, resource) {
40777
+ if (binary.byteLength !== resource.size)
40778
+ return false;
40779
+ return bytesToHex$3(sha256.sha256(new Uint8Array(binary))) === resource.fileHash.toLowerCase();
40769
40780
  }
40770
40781
 
40771
40782
  var _a$1;
@@ -40826,7 +40837,6 @@ class DataManager {
40826
40837
  return __awaiter(this, void 0, void 0, function* () {
40827
40838
  this.settings = settings;
40828
40839
  this.protocolV2ResourcesConfigError = undefined;
40829
- this.protocolV2NeoResourcesConfigError = undefined;
40830
40840
  const manifestMode = (_b = settings.firmwareManifestMode) !== null && _b !== void 0 ? _b : (settings.fetchConfig ? 'sdk-managed' : undefined);
40831
40841
  if (settings.preloadedConfig) {
40832
40842
  this.applyRemoteConfig(settings.preloadedConfig);
@@ -40887,19 +40897,12 @@ class DataManager {
40887
40897
  let neoResources;
40888
40898
  try {
40889
40899
  pro2Resources = parseProtocolV2Resources((_b = data.pro2) === null || _b === void 0 ? void 0 : _b.resources);
40890
- }
40891
- catch (error) {
40892
- this.protocolV2ResourcesConfigError =
40893
- error instanceof Error ? error : new Error(String(error));
40894
- Log$k.warn('[DataConfig] Ignoring invalid Pro2 resources config:', error);
40895
- }
40896
- try {
40897
40900
  neoResources = parseProtocolV2Resources((_c = data.neo) === null || _c === void 0 ? void 0 : _c.resources);
40898
40901
  }
40899
40902
  catch (error) {
40900
- this.protocolV2NeoResourcesConfigError =
40903
+ this.protocolV2ResourcesConfigError =
40901
40904
  error instanceof Error ? error : new Error(String(error));
40902
- Log$k.warn('[DataConfig] Ignoring invalid Neo resources config:', error);
40905
+ Log$k.warn('[DataConfig] Ignoring invalid Protocol V2 resources config:', error);
40903
40906
  }
40904
40907
  const enrichedPro2Config = this.enrichFirmwareReleaseInfo(data.pro2);
40905
40908
  const enrichedNeoConfig = this.enrichFirmwareReleaseInfo(data.neo);
@@ -40937,20 +40940,16 @@ class DataManager {
40937
40940
  }
40938
40941
  });
40939
40942
  }
40940
- static forceReloadData({ requireResources = false, resourceDeviceType = hdShared.EDeviceType.Pro2, } = {}) {
40943
+ static forceReloadData({ requireResources = false, } = {}) {
40941
40944
  return __awaiter(this, void 0, void 0, function* () {
40942
- const resourceDeviceName = resourceDeviceType === hdShared.EDeviceType.Pro2 ? 'Pro2' : 'Neo';
40943
40945
  if (!this.settings) {
40944
40946
  throw new Error('Remote config settings are not initialized');
40945
40947
  }
40946
40948
  const hasFreshConfig = this.lastCheckTimestamp > 0 &&
40947
40949
  getTimeStamp() - this.lastCheckTimestamp <= FIRMWARE_UPDATE_CONFIG_FRESHNESS_MS;
40948
40950
  if (hasFreshConfig) {
40949
- const resourcesConfigError = resourceDeviceType === hdShared.EDeviceType.Pro2
40950
- ? this.protocolV2ResourcesConfigError
40951
- : this.protocolV2NeoResourcesConfigError;
40952
- if (requireResources && resourcesConfigError) {
40953
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareUpdateDownloadFailed, `Invalid ${resourceDeviceName} resources config: ${resourcesConfigError.message}`);
40951
+ if (requireResources && this.protocolV2ResourcesConfigError) {
40952
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareUpdateDownloadFailed, `Invalid Pro2 resources config: ${this.protocolV2ResourcesConfigError.message}`);
40954
40953
  }
40955
40954
  return;
40956
40955
  }
@@ -40958,18 +40957,19 @@ class DataManager {
40958
40957
  if (!loaded) {
40959
40958
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.NetworkError, 'Unable to refresh the latest remote config');
40960
40959
  }
40961
- const resourcesConfigError = resourceDeviceType === hdShared.EDeviceType.Pro2
40962
- ? this.protocolV2ResourcesConfigError
40963
- : this.protocolV2NeoResourcesConfigError;
40964
- if (requireResources && resourcesConfigError) {
40965
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareUpdateDownloadFailed, `Invalid ${resourceDeviceName} resources config: ${resourcesConfigError.message}`);
40960
+ if (requireResources && this.protocolV2ResourcesConfigError) {
40961
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareUpdateDownloadFailed, `Invalid Pro2 resources config: ${this.protocolV2ResourcesConfigError.message}`);
40966
40962
  }
40967
40963
  this.lastCheckTimestamp = getTimeStamp();
40968
40964
  });
40969
40965
  }
40970
- static getProtocolV2ResourceSource(deviceType = hdShared.EDeviceType.Pro2) {
40966
+ static getProtocolV2Resources(deviceType = hdShared.EDeviceType.Pro2) {
40967
+ var _b, _c;
40968
+ return (_c = (_b = this.deviceMap[deviceType]) === null || _b === void 0 ? void 0 : _b.resources) === null || _c === void 0 ? void 0 : _c.stable;
40969
+ }
40970
+ static getProtocolV2BootResources(deviceType = hdShared.EDeviceType.Pro2) {
40971
40971
  var _b, _c;
40972
- return (_c = (_b = this.deviceMap[deviceType]) === null || _b === void 0 ? void 0 : _b.resources) === null || _c === void 0 ? void 0 : _c.source;
40972
+ return (_c = (_b = this.deviceMap[deviceType]) === null || _b === void 0 ? void 0 : _b.resources) === null || _c === void 0 ? void 0 : _c.boot;
40973
40973
  }
40974
40974
  static getProtobufMessages(schema = 'v1CurrentSchema') {
40975
40975
  return this.messages[schema];
@@ -41006,10 +41006,12 @@ DataManager.deviceMap = {
41006
41006
  ble: [],
41007
41007
  },
41008
41008
  [hdShared.EDeviceType.Pro2]: {
41009
- 'firmware-v1': [],
41009
+ firmware: [],
41010
+ ble: [],
41010
41011
  },
41011
41012
  [hdShared.EDeviceType.Neo]: {
41012
- 'firmware-v1': [],
41013
+ firmware: [],
41014
+ ble: [],
41013
41015
  },
41014
41016
  [hdShared.EDeviceType.ClassicPure]: {
41015
41017
  firmware: [],
@@ -42006,7 +42008,7 @@ const getFirmwareUpdateField = ({ features, updateType, targetVersion, firmwareT
42006
42008
  if (deviceType === hdShared.EDeviceType.Pro) {
42007
42009
  return latestFirmwareField;
42008
42010
  }
42009
- if (deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo) {
42011
+ if (deviceType === hdShared.EDeviceType.Pro2) {
42010
42012
  return 'firmware-v1';
42011
42013
  }
42012
42014
  return 'firmware';
@@ -42038,7 +42040,7 @@ const getFirmwareUpdateFieldArray = (features, updateType) => {
42038
42040
  if (deviceType === 'pro') {
42039
42041
  return ['firmware-v8'];
42040
42042
  }
42041
- if (deviceType === 'pro2' || deviceType === 'neo') {
42043
+ if (deviceType === 'pro2') {
42042
42044
  return ['firmware-v1'];
42043
42045
  }
42044
42046
  return ['firmware'];
@@ -47381,93 +47383,76 @@ class ClearSessionCache extends BaseMethod {
47381
47383
  }
47382
47384
  }
47383
47385
 
47384
- const PROTOCOL_V2_MAIN_FIRMWARE_TARGETS = [
47385
- 'APPLICATION_P1',
47386
- 'APPLICATION_P2',
47387
- 'SE01',
47388
- 'SE02',
47389
- 'SE03',
47390
- 'SE04',
47391
- ];
47392
- const PROTOCOL_V2_BLE_TARGETS = [
47393
- 'COPROCESSOR',
47394
- ];
47395
- const PROTOCOL_V2_BOOTLOADER_TARGETS = [
47396
- 'BOOTLOADER',
47397
- ];
47398
- function loadProtocolV2FirmwareReleaseContext({ device, firmwareType: firmwareTypeParam, checkFirmwareHash = false, methodName, }) {
47399
- var _a;
47400
- return __awaiter(this, void 0, void 0, function* () {
47401
- const state = yield device.getDeviceState({
47402
- refreshSections: checkFirmwareHash
47403
- ? ['identity', 'versions', 'verification']
47404
- : ['identity', 'versions'],
47405
- });
47406
- if (state.identity.deviceType !== 'pro2' && state.identity.deviceType !== 'neo') {
47407
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotSupportMethod, `${methodName} requires a Pro2 or Neo device for Protocol V2`);
47408
- }
47409
- const { features } = device;
47410
- if (!features) {
47411
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `${methodName} requires initialized device features`);
47412
- }
47413
- const firmwareType = (_a = firmwareTypeParam !== null && firmwareTypeParam !== void 0 ? firmwareTypeParam : state.identity.firmwareType) !== null && _a !== void 0 ? _a : hdShared.EFirmwareType.Universal;
47414
- return {
47415
- state: state,
47416
- features,
47417
- firmwareType,
47418
- release: DataManager.getFirmwareLatestRelease(features, firmwareType),
47419
- };
47420
- });
47421
- }
47422
- function summarizeProtocolV2FirmwareRelease(plan, componentTargets) {
47423
- var _a;
47424
- const targetSet = new Set(componentTargets);
47425
- const components = plan.components.filter(component => targetSet.has(component.componentTarget));
47426
- const targetsToUpdate = Array.from(new Set(components.flatMap(component => component.status === 'outdated' && component.updateTarget ? [component.updateTarget] : [])));
47427
- const hasUpgrade = targetsToUpdate.length > 0;
47428
- const required = !!((_a = plan.release) === null || _a === void 0 ? void 0 : _a.required) && hasUpgrade;
47429
- let status = 'valid';
47430
- if (!plan.release || components.length === 0) {
47431
- status = 'unavailable';
47432
- }
47433
- else if (required) {
47434
- status = 'required';
47386
+ class CheckFirmwareRelease extends BaseMethod {
47387
+ init() {
47388
+ this.allowDeviceMode = [
47389
+ ...this.allowDeviceMode,
47390
+ UI_REQUEST.NOT_INITIALIZE,
47391
+ UI_REQUEST.BOOTLOADER,
47392
+ ];
47393
+ this.useDevicePassphraseState = false;
47394
+ this.skipForceUpdateCheck = true;
47435
47395
  }
47436
- else if (hasUpgrade) {
47437
- status = 'outdated';
47396
+ run() {
47397
+ var _a;
47398
+ const payload = this.payload;
47399
+ if (this.device.features) {
47400
+ const deviceFirmwareType = this.device.getCurrentFirmwareType();
47401
+ const firmwareType = (_a = payload.firmwareType) !== null && _a !== void 0 ? _a : deviceFirmwareType;
47402
+ const releaseInfo = getFirmwareReleaseInfo(this.device.features, firmwareType);
47403
+ return Promise.resolve(releaseInfo);
47404
+ }
47405
+ return Promise.resolve(null);
47438
47406
  }
47439
- else if (components.some(component => component.status === 'unknown')) {
47440
- status = 'unknown';
47407
+ }
47408
+
47409
+ class CheckBLEFirmwareRelease extends BaseMethod {
47410
+ init() {
47411
+ this.allowDeviceMode = [
47412
+ ...this.allowDeviceMode,
47413
+ UI_REQUEST.NOT_INITIALIZE,
47414
+ UI_REQUEST.BOOTLOADER,
47415
+ ];
47416
+ this.useDevicePassphraseState = false;
47417
+ this.skipForceUpdateCheck = true;
47441
47418
  }
47442
- else if (components.every(component => component.status === 'unsupported')) {
47443
- status = 'unavailable';
47419
+ run() {
47420
+ if (this.device.features) {
47421
+ const releaseInfo = getBleFirmwareReleaseInfo(this.device.features);
47422
+ return Promise.resolve(releaseInfo);
47423
+ }
47424
+ return Promise.resolve(null);
47444
47425
  }
47445
- return Object.assign(Object.assign({}, plan), { status,
47446
- hasUpgrade,
47447
- required,
47448
- components,
47449
- targetsToUpdate });
47450
47426
  }
47451
- function toProtocolV2FirmwareReleaseInfo({ plan, state, release, }) {
47452
- return {
47453
- shouldUpdate: plan.hasUpgrade,
47454
- status: plan.status === 'unavailable' ? 'unknown' : plan.status,
47455
- changelog: plan.release ? [plan.release.changelog] : [],
47456
- release,
47457
- bootloaderMode: state.status.mode === 'bootloader' || state.status.mode === 'romloader',
47458
- };
47459
- }
47460
- function getProtocolV2ComponentReleaseInfo(plan, componentTarget) {
47461
- var _a;
47462
- const componentRelease = plan.components.find(component => component.componentTarget === componentTarget);
47463
- if (!componentRelease || !plan.release) {
47464
- return undefined;
47427
+
47428
+ class CheckBridgeStatus extends BaseMethod {
47429
+ init() {
47430
+ this.useDevice = false;
47431
+ this.useDevicePassphraseState = false;
47432
+ this.skipForceUpdateCheck = true;
47465
47433
  }
47466
- const component = (_a = plan.release.components) === null || _a === void 0 ? void 0 : _a[componentRelease.configKey];
47467
- if (!component) {
47468
- return undefined;
47434
+ run() {
47435
+ return __awaiter(this, void 0, void 0, function* () {
47436
+ return new Promise((resolve, reject) => {
47437
+ axios__default["default"]
47438
+ .request({
47439
+ url: 'http://localhost:21320',
47440
+ method: 'POST',
47441
+ withCredentials: false,
47442
+ timeout: 3000,
47443
+ })
47444
+ .then(() => resolve(true))
47445
+ .catch(e => {
47446
+ if (e.code === 'ECONNABORTED') {
47447
+ reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BridgeTimeoutError));
47448
+ }
47449
+ else {
47450
+ resolve(false);
47451
+ }
47452
+ });
47453
+ });
47454
+ });
47469
47455
  }
47470
- return Object.assign(Object.assign({}, component), { protocol: 'V2', configKey: componentRelease.configKey, componentTarget, required: plan.release.required, changelog: plan.release.changelog });
47471
47456
  }
47472
47457
 
47473
47458
  const REQUIRED_BRIDGE_VERSION = '2.2.0';
@@ -47524,6 +47509,56 @@ function getBridgeReleaseInfo({ deviceType, currentFirmwareVersion, willUpdateFi
47524
47509
  });
47525
47510
  }
47526
47511
 
47512
+ class CheckBridgeRelease extends BaseMethod {
47513
+ init() {
47514
+ this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.BOOTLOADER];
47515
+ this.useDevicePassphraseState = false;
47516
+ this.skipForceUpdateCheck = true;
47517
+ }
47518
+ run() {
47519
+ return __awaiter(this, void 0, void 0, function* () {
47520
+ if (!this.device.features) {
47521
+ return null;
47522
+ }
47523
+ const { willUpdateFirmwareVersion } = this.payload;
47524
+ const { features } = this.device;
47525
+ const deviceType = getDeviceType(features);
47526
+ const currentFirmwareVersion = getDeviceFirmwareVersion(features).join('.');
47527
+ return getBridgeReleaseInfo({
47528
+ deviceType,
47529
+ currentFirmwareVersion,
47530
+ willUpdateFirmwareVersion,
47531
+ });
47532
+ });
47533
+ }
47534
+ }
47535
+
47536
+ class CheckBootloaderRelease extends BaseMethod {
47537
+ init() {
47538
+ this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.BOOTLOADER];
47539
+ this.useDevicePassphraseState = false;
47540
+ this.skipForceUpdateCheck = true;
47541
+ }
47542
+ run() {
47543
+ var _a;
47544
+ return __awaiter(this, void 0, void 0, function* () {
47545
+ if (!this.device.features) {
47546
+ return null;
47547
+ }
47548
+ const { features } = this.device;
47549
+ const payload = this.payload;
47550
+ const deviceFirmwareType = this.device.getCurrentFirmwareType();
47551
+ const firmwareType = (_a = payload.firmwareType) !== null && _a !== void 0 ? _a : deviceFirmwareType;
47552
+ const releaseInfo = getBootloaderReleaseInfo({
47553
+ features,
47554
+ willUpdateFirmwareVersion: payload.willUpdateFirmwareVersion,
47555
+ firmwareType,
47556
+ });
47557
+ return Promise.resolve(releaseInfo);
47558
+ });
47559
+ }
47560
+ }
47561
+
47527
47562
  const UPDATE_TARGET_BY_COMPONENT_TARGET = {
47528
47563
  BOOTLOADER: 'boot',
47529
47564
  APPLICATION_P1: 'app_v1',
@@ -47771,15 +47806,22 @@ class CheckAllFirmwareRelease extends BaseMethod {
47771
47806
  runProtocolV2() {
47772
47807
  var _a;
47773
47808
  return __awaiter(this, void 0, void 0, function* () {
47774
- const { checkFirmwareHash = false, firmwareType: firmwareTypeParam, platform, forceUpdateTargets, protocolV2ForceUpdateTargets, } = this.payload;
47775
- const validatedForceUpdateTargets = validateFirmwareUpdatePlanForceTargets(forceUpdateTargets);
47776
- const validatedProtocolV2ForceUpdateTargets = validateProtocolV2FirmwareUpdateTargets(protocolV2ForceUpdateTargets);
47777
- const { state, features, firmwareType, release } = yield loadProtocolV2FirmwareReleaseContext({
47778
- device: this.device,
47779
- firmwareType: firmwareTypeParam,
47780
- checkFirmwareHash,
47781
- methodName: 'checkAllFirmwareRelease',
47809
+ const { checkFirmwareHash = false, firmwareType: firmwareTypeParam } = this
47810
+ .payload;
47811
+ const state = yield this.device.getDeviceState({
47812
+ refreshSections: checkFirmwareHash
47813
+ ? ['identity', 'versions', 'verification']
47814
+ : ['identity', 'versions'],
47782
47815
  });
47816
+ if (state.identity.deviceType !== 'pro2' && state.identity.deviceType !== 'neo') {
47817
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotSupportMethod, 'checkAllFirmwareRelease requires a Pro2 or Neo device for Protocol V2');
47818
+ }
47819
+ const { features } = this.device;
47820
+ if (!features) {
47821
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'checkAllFirmwareRelease requires initialized device features');
47822
+ }
47823
+ const firmwareType = (_a = firmwareTypeParam !== null && firmwareTypeParam !== void 0 ? firmwareTypeParam : state.identity.firmwareType) !== null && _a !== void 0 ? _a : hdShared.EFirmwareType.Universal;
47824
+ const release = DataManager.getFirmwareLatestRelease(features, firmwareType);
47783
47825
  const plan = buildProtocolV2FirmwareRelease({
47784
47826
  currentVersions: state.versions,
47785
47827
  currentVerification: checkFirmwareHash ? state.verification : undefined,
@@ -47789,250 +47831,48 @@ class CheckAllFirmwareRelease extends BaseMethod {
47789
47831
  deviceType: state.identity.deviceType,
47790
47832
  });
47791
47833
  const resourceDeviceType = state.identity.deviceType === 'neo' ? hdShared.EDeviceType.Neo : hdShared.EDeviceType.Pro2;
47792
- const resourceSource = DataManager.getProtocolV2ResourceSource(resourceDeviceType);
47793
- const resourceStatus = 'unknown';
47794
- const detectedComponentTargets = validatedForceUpdateTargets.includes('firmware')
47795
- ? plan.components.flatMap(component => component.updateTarget ? [component.updateTarget] : [])
47796
- : plan.targetsToUpdate;
47797
- const componentTargetsToUpdate = Array.from(new Set([
47798
- ...detectedComponentTargets,
47799
- ...validatedProtocolV2ForceUpdateTargets.filter(target => target !== 'resource'),
47800
- ]));
47801
- const forceResourceUpdate = validatedForceUpdateTargets.includes('resource') ||
47802
- validatedProtocolV2ForceUpdateTargets.includes('resource');
47803
- const targetsToUpdate = Array.from(new Set([
47804
- ...componentTargetsToUpdate,
47805
- ...(forceResourceUpdate ? ['resource'] : []),
47806
- ]));
47807
- let firmwareUpdatePlan;
47808
- const shouldBuildFirmwareUpdatePlan = targetsToUpdate.length > 0;
47809
- const requestedPlatform = platform !== null && platform !== void 0 ? platform : 'web';
47810
- const requiresPreparedPlan = shouldBuildFirmwareUpdatePlan &&
47811
- (requestedPlatform === 'native' || requestedPlatform === 'desktop');
47812
- try {
47813
- if (shouldBuildFirmwareUpdatePlan) {
47814
- const validatedPlan = buildProtocolV2FirmwareUpdatePlan({
47815
- features,
47816
- firmwareType,
47817
- platform: requestedPlatform,
47818
- release,
47819
- targetsToUpdate,
47820
- forceUpdateTargets: validatedForceUpdateTargets,
47821
- resourceArchive: resourceSource,
47822
- });
47823
- firmwareUpdatePlan = validatedPlan;
47824
- }
47825
- else {
47826
- firmwareUpdatePlan = undefined;
47827
- }
47828
- }
47829
- catch (error) {
47830
- if (requiresPreparedPlan ||
47831
- validatedForceUpdateTargets.length > 0 ||
47832
- validatedProtocolV2ForceUpdateTargets.length > 0 ||
47833
- !(error instanceof hdShared.HardwareError) ||
47834
- ((_a = error.params) === null || _a === void 0 ? void 0 : _a.firmwareUpdateCode) !== 'FirmwarePlanInvalid') {
47835
- throw error;
47836
- }
47837
- Log$c.warn('[CheckAllFirmwareRelease] Optional Protocol V2 firmware Plan is unavailable; using the release result');
47838
- firmwareUpdatePlan = undefined;
47839
- }
47840
- const firmwarePlan = summarizeProtocolV2FirmwareRelease(plan, PROTOCOL_V2_MAIN_FIRMWARE_TARGETS);
47841
- const blePlan = summarizeProtocolV2FirmwareRelease(plan, PROTOCOL_V2_BLE_TARGETS);
47842
- const bootloaderPlan = summarizeProtocolV2FirmwareRelease(plan, PROTOCOL_V2_BOOTLOADER_TARGETS);
47843
- const { status } = plan;
47844
- return Object.assign(Object.assign({ firmware: toProtocolV2FirmwareReleaseInfo({ plan: firmwarePlan, state, release }), ble: toProtocolV2FirmwareReleaseInfo({
47845
- plan: blePlan,
47846
- state,
47847
- release: getProtocolV2ComponentReleaseInfo(plan, 'COPROCESSOR'),
47848
- }), bootloader: toProtocolV2FirmwareReleaseInfo({
47849
- plan: bootloaderPlan,
47850
- state,
47851
- release: getProtocolV2ComponentReleaseInfo(plan, 'BOOTLOADER'),
47852
- }), features, protocol: 'V2', deviceType: state.identity.deviceType }, plan), { status,
47853
- resourceStatus, resourceArchive: resourceSource, hasUpgrade: targetsToUpdate.length > 0, targetsToUpdate,
47854
- firmwareUpdatePlan });
47855
- });
47856
- }
47857
- }
47858
-
47859
- class CheckFirmwareRelease extends BaseMethod {
47860
- getSupportedProtocols() {
47861
- return ['V1', 'V2'];
47862
- }
47863
- init() {
47864
- this.allowDeviceMode = [
47865
- ...this.allowDeviceMode,
47866
- UI_REQUEST.NOT_INITIALIZE,
47867
- UI_REQUEST.BOOTLOADER,
47868
- ];
47869
- this.useDevicePassphraseState = false;
47870
- this.skipForceUpdateCheck = true;
47871
- }
47872
- run() {
47873
- var _a;
47874
- return __awaiter(this, void 0, void 0, function* () {
47875
- const payload = this.payload;
47876
- if (!this.device.features)
47877
- return null;
47878
- if (this.device.isProtocolV2()) {
47879
- const { state, firmwareType, release } = yield loadProtocolV2FirmwareReleaseContext({
47880
- device: this.device,
47881
- firmwareType: payload.firmwareType,
47882
- methodName: 'checkFirmwareRelease',
47883
- });
47884
- const plan = summarizeProtocolV2FirmwareRelease(buildProtocolV2FirmwareRelease({
47885
- currentVersions: state.versions,
47886
- firmwareType,
47887
- release,
47888
- deviceType: state.identity.deviceType,
47889
- }), PROTOCOL_V2_MAIN_FIRMWARE_TARGETS);
47890
- return toProtocolV2FirmwareReleaseInfo({ plan, state, release });
47891
- }
47892
- const deviceFirmwareType = this.device.getCurrentFirmwareType();
47893
- const firmwareType = (_a = payload.firmwareType) !== null && _a !== void 0 ? _a : deviceFirmwareType;
47894
- const releaseInfo = getFirmwareReleaseInfo(this.device.features, firmwareType);
47895
- return releaseInfo;
47896
- });
47897
- }
47898
- }
47899
-
47900
- class CheckBLEFirmwareRelease extends BaseMethod {
47901
- getSupportedProtocols() {
47902
- return ['V1', 'V2'];
47903
- }
47904
- init() {
47905
- this.allowDeviceMode = [
47906
- ...this.allowDeviceMode,
47907
- UI_REQUEST.NOT_INITIALIZE,
47908
- UI_REQUEST.BOOTLOADER,
47909
- ];
47910
- this.useDevicePassphraseState = false;
47911
- this.skipForceUpdateCheck = true;
47912
- }
47913
- run() {
47914
- return __awaiter(this, void 0, void 0, function* () {
47915
- if (!this.device.features)
47916
- return null;
47917
- if (this.device.isProtocolV2()) {
47918
- const { state, firmwareType, release } = yield loadProtocolV2FirmwareReleaseContext({
47919
- device: this.device,
47920
- methodName: 'checkBLEFirmwareRelease',
47921
- });
47922
- const plan = summarizeProtocolV2FirmwareRelease(buildProtocolV2FirmwareRelease({
47923
- currentVersions: state.versions,
47924
- firmwareType,
47925
- release,
47926
- deviceType: state.identity.deviceType,
47927
- }), PROTOCOL_V2_BLE_TARGETS);
47928
- return toProtocolV2FirmwareReleaseInfo({
47929
- plan,
47930
- state,
47931
- release: getProtocolV2ComponentReleaseInfo(plan, 'COPROCESSOR'),
47932
- });
47933
- }
47934
- const releaseInfo = getBleFirmwareReleaseInfo(this.device.features);
47935
- return releaseInfo;
47936
- });
47937
- }
47938
- }
47939
-
47940
- class CheckBridgeStatus extends BaseMethod {
47941
- init() {
47942
- this.useDevice = false;
47943
- this.useDevicePassphraseState = false;
47944
- this.skipForceUpdateCheck = true;
47945
- }
47946
- run() {
47947
- return __awaiter(this, void 0, void 0, function* () {
47948
- return new Promise((resolve, reject) => {
47949
- axios__default["default"]
47950
- .request({
47951
- url: 'http://localhost:21320',
47952
- method: 'POST',
47953
- withCredentials: false,
47954
- timeout: 3000,
47955
- })
47956
- .then(() => resolve(true))
47957
- .catch(e => {
47958
- if (e.code === 'ECONNABORTED') {
47959
- reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BridgeTimeoutError));
47834
+ const resources = DataManager.getProtocolV2Resources(resourceDeviceType);
47835
+ let resourceStatus = 'unknown';
47836
+ if (resources === null || resources === void 0 ? void 0 : resources.length) {
47837
+ const loaderMode = state.status.mode === 'bootloader' || state.status.mode === 'romloader';
47838
+ if (loaderMode) {
47839
+ try {
47840
+ const inventory = yield readProtocolV2ResourceInventory({
47841
+ commands: this.device.getCommands(),
47842
+ resources,
47843
+ });
47844
+ resourceStatus = buildProtocolV2ResourceUpdatePlan({
47845
+ resources,
47846
+ inventory,
47847
+ mode: 'bootloader-recovery',
47848
+ }).status;
47960
47849
  }
47961
- else {
47962
- resolve(false);
47850
+ catch (_b) {
47851
+ resourceStatus = buildProtocolV2ResourceUpdatePlan({
47852
+ resources,
47853
+ mode: 'bootloader-recovery',
47854
+ }).status;
47963
47855
  }
47964
- });
47965
- });
47966
- });
47967
- }
47968
- }
47969
-
47970
- class CheckBridgeRelease extends BaseMethod {
47971
- init() {
47972
- this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.BOOTLOADER];
47973
- this.useDevicePassphraseState = false;
47974
- this.skipForceUpdateCheck = true;
47975
- }
47976
- run() {
47977
- return __awaiter(this, void 0, void 0, function* () {
47978
- if (!this.device.features) {
47979
- return null;
47980
- }
47981
- const { willUpdateFirmwareVersion } = this.payload;
47982
- const { features } = this.device;
47983
- const deviceType = getDeviceType(features);
47984
- const currentFirmwareVersion = getDeviceFirmwareVersion(features).join('.');
47985
- return getBridgeReleaseInfo({
47986
- deviceType,
47987
- currentFirmwareVersion,
47988
- willUpdateFirmwareVersion,
47989
- });
47990
- });
47991
- }
47992
- }
47993
-
47994
- class CheckBootloaderRelease extends BaseMethod {
47995
- getSupportedProtocols() {
47996
- return ['V1', 'V2'];
47997
- }
47998
- init() {
47999
- this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.BOOTLOADER];
48000
- this.useDevicePassphraseState = false;
48001
- this.skipForceUpdateCheck = true;
48002
- }
48003
- run() {
48004
- var _a;
48005
- return __awaiter(this, void 0, void 0, function* () {
48006
- if (!this.device.features)
48007
- return null;
48008
- const { features } = this.device;
48009
- const payload = this.payload;
48010
- if (this.device.isProtocolV2()) {
48011
- const { state, firmwareType, release } = yield loadProtocolV2FirmwareReleaseContext({
48012
- device: this.device,
48013
- firmwareType: payload.firmwareType,
48014
- methodName: 'checkBootloaderRelease',
48015
- });
48016
- const plan = summarizeProtocolV2FirmwareRelease(buildProtocolV2FirmwareRelease({
48017
- currentVersions: state.versions,
48018
- firmwareType,
48019
- release,
48020
- deviceType: state.identity.deviceType,
48021
- }), PROTOCOL_V2_BOOTLOADER_TARGETS);
48022
- return toProtocolV2FirmwareReleaseInfo({
48023
- plan,
48024
- state,
48025
- release: getProtocolV2ComponentReleaseInfo(plan, 'BOOTLOADER'),
48026
- });
47856
+ }
48027
47857
  }
48028
- const deviceFirmwareType = this.device.getCurrentFirmwareType();
48029
- const firmwareType = (_a = payload.firmwareType) !== null && _a !== void 0 ? _a : deviceFirmwareType;
48030
- const releaseInfo = getBootloaderReleaseInfo({
48031
- features,
48032
- willUpdateFirmwareVersion: payload.willUpdateFirmwareVersion,
48033
- firmwareType,
48034
- });
48035
- return Promise.resolve(releaseInfo);
47858
+ const targetsToUpdate = [
47859
+ ...plan.targetsToUpdate,
47860
+ ...(resourceStatus === 'outdated' ? ['resource'] : []),
47861
+ ];
47862
+ const firmwareStatus = plan.status === 'unavailable' ? 'unknown' : plan.status;
47863
+ const emptyRelease = 'none';
47864
+ return Object.assign(Object.assign({ firmware: {
47865
+ status: firmwareStatus,
47866
+ changelog: release ? [release.changelog] : [],
47867
+ release: release !== null && release !== void 0 ? release : emptyRelease,
47868
+ bootloaderMode: state.status.mode === 'bootloader' || state.status.mode === 'romloader',
47869
+ }, ble: {
47870
+ status: 'valid',
47871
+ release: emptyRelease,
47872
+ }, bootloader: {
47873
+ status: 'valid',
47874
+ release: emptyRelease,
47875
+ }, features, protocol: 'V2', deviceType: state.identity.deviceType }, plan), { resourceStatus, hasUpgrade: plan.hasUpgrade || resourceStatus === 'outdated', targetsToUpdate });
48036
47876
  });
48037
47877
  }
48038
47878
  }
@@ -49404,6 +49244,8 @@ class FirmwareUpdateBaseMethod extends BaseMethod {
49404
49244
  !this.payload.skipWebDevicePrompt &&
49405
49245
  !hasPromptedWebDevice &&
49406
49246
  !isPromptingWebDevice) {
49247
+ clearInterval(intervalTimer);
49248
+ clearTimeout(timeoutTimer);
49407
49249
  isPromptingWebDevice = true;
49408
49250
  try {
49409
49251
  this.postTipMessage(exports.FirmwareUpdateTipMessage.SelectDeviceInBootloaderForWebDevice);
@@ -49777,35 +49619,24 @@ class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod {
49777
49619
  });
49778
49620
  }
49779
49621
  run() {
49780
- var _a, _b;
49622
+ var _a, _b, _c;
49781
49623
  return __awaiter(this, void 0, void 0, function* () {
49782
49624
  const { device } = this;
49783
49625
  const { features } = device;
49784
49626
  const payload = this.payload;
49785
- const hasPreparedPlan = payload.preparedPlan !== undefined;
49786
- const hasPreparedArtifact = payload.artifact !== undefined;
49787
- if (hasPreparedPlan !== hasPreparedArtifact) {
49788
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Prepared bootloader plans require exactly one prepared artifact');
49789
- }
49790
- if (payload.binary !== undefined && hasPreparedArtifact) {
49791
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Bootloader binary and prepared artifact are mutually exclusive');
49792
- }
49793
- const preparedPlan = hasPreparedArtifact
49794
- ? validateFirmwareUpdatePreparedPlan(payload.preparedPlan)
49627
+ const hostBinding = payload.artifact
49628
+ ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration)
49795
49629
  : undefined;
49796
- const artifactReader = preparedPlan
49797
- ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest).artifactReader
49798
- : payload.artifactReader;
49799
- const executionParams = Object.assign(Object.assign({}, payload), { artifactReader });
49630
+ const executionParams = Object.assign(Object.assign({}, payload), { artifactReader: (_a = hostBinding === null || hostBinding === void 0 ? void 0 : hostBinding.artifactReader) !== null && _a !== void 0 ? _a : payload.artifactReader });
49800
49631
  if (payload.artifact) {
49801
49632
  assertFirmwareUpdatePreparedPlanDeviceIdentity({
49802
- preparedPlan,
49633
+ preparedPlan: payload.preparedPlan,
49803
49634
  deviceIdentity: getDeviceUUID(features) || undefined,
49804
49635
  bootloaderMode: resolveDeviceBootloaderMode(features),
49805
49636
  deviceModel: String(getDeviceType(features)),
49806
49637
  });
49807
49638
  assertFirmwareUpdatePreparedPlanBinding({
49808
- preparedPlan,
49639
+ preparedPlan: payload.preparedPlan,
49809
49640
  executor: 'v2',
49810
49641
  scopeTargets: ['bootloader'],
49811
49642
  bindings: [
@@ -49825,7 +49656,7 @@ class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod {
49825
49656
  try {
49826
49657
  const deviceType = device.getCurrentDeviceType();
49827
49658
  const deviceFirmwareType = device.getCurrentFirmwareType();
49828
- const firmwareType = (_a = payload.firmwareType) !== null && _a !== void 0 ? _a : deviceFirmwareType;
49659
+ const firmwareType = (_b = payload.firmwareType) !== null && _b !== void 0 ? _b : deviceFirmwareType;
49829
49660
  if (DeviceModelToTypes.model_touch.includes(deviceType)) {
49830
49661
  return yield this.updateTouchBootloader({
49831
49662
  device,
@@ -49843,7 +49674,7 @@ class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod {
49843
49674
  const { binary } = payload;
49844
49675
  const deviceType = device.getCurrentDeviceType();
49845
49676
  const deviceFirmwareType = device.getCurrentFirmwareType();
49846
- const firmwareType = (_b = payload.firmwareType) !== null && _b !== void 0 ? _b : deviceFirmwareType;
49677
+ const firmwareType = (_c = payload.firmwareType) !== null && _c !== void 0 ? _c : deviceFirmwareType;
49847
49678
  if (DeviceModelToTypes.model_touch.includes(deviceType)) {
49848
49679
  return this.updateTouchBootloader({
49849
49680
  device,
@@ -50197,9 +50028,6 @@ class FirmwareUpdateV2 extends BaseMethod {
50197
50028
  payload.artifact !== undefined) {
50198
50029
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Firmware update binary and artifact are mutually exclusive');
50199
50030
  }
50200
- if (payload.preparedPlan !== undefined && payload.artifact === undefined) {
50201
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Prepared firmware plans require a prepared artifact');
50202
- }
50203
50031
  if (!payload.updateType) {
50204
50032
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'updateType is required');
50205
50033
  }
@@ -50215,8 +50043,7 @@ class FirmwareUpdateV2 extends BaseMethod {
50215
50043
  this.params = Object.assign(Object.assign({}, this.params), { binary: payload.binary });
50216
50044
  }
50217
50045
  if ('artifact' in payload) {
50218
- const preparedPlan = validateFirmwareUpdatePreparedPlan(payload.preparedPlan);
50219
- const hostBinding = resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest);
50046
+ const hostBinding = resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration);
50220
50047
  const target = payload.isUpdateBootloader ? 'bootloader' : payload.updateType;
50221
50048
  const resourceBindings = ((_a = payload.resourceEntries) !== null && _a !== void 0 ? _a : []).map((entry) => ({
50222
50049
  target: 'resource',
@@ -50224,13 +50051,13 @@ class FirmwareUpdateV2 extends BaseMethod {
50224
50051
  artifact: entry.artifact,
50225
50052
  }));
50226
50053
  assertFirmwareUpdatePreparedPlanBinding({
50227
- preparedPlan,
50054
+ preparedPlan: payload.preparedPlan,
50228
50055
  executor: 'v2',
50229
50056
  platform: payload.platform,
50230
50057
  scopeTargets: [target, ...(target === 'firmware' ? ['resource'] : [])],
50231
50058
  bindings: [{ target, artifact: payload.artifact }, ...resourceBindings],
50232
50059
  });
50233
- this.params = Object.assign(Object.assign({}, this.params), { preparedPlan, artifact: payload.artifact, resourceEntries: payload.resourceEntries, artifactReader: hostBinding.artifactReader });
50060
+ this.params = Object.assign(Object.assign({}, this.params), { preparedPlan: payload.preparedPlan, artifact: payload.artifact, resourceEntries: payload.resourceEntries, artifactReader: hostBinding.artifactReader });
50234
50061
  }
50235
50062
  }
50236
50063
  _promptDeviceInBootloaderForWebDevice() {
@@ -50575,7 +50402,7 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
50575
50402
  this.artifactSources = [];
50576
50403
  }
50577
50404
  init() {
50578
- var _a, _b, _c, _d, _e;
50405
+ var _a, _b, _c, _d, _e, _f;
50579
50406
  this.allowDeviceMode = [UI_REQUEST.BOOTLOADER, UI_REQUEST.NOT_INITIALIZE];
50580
50407
  this.requireDeviceMode = [];
50581
50408
  this.useDevicePassphraseState = false;
@@ -50593,15 +50420,12 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
50593
50420
  { name: 'firmwareType', type: 'string' },
50594
50421
  { name: 'platform', type: 'string' },
50595
50422
  ]);
50596
- const preparedPlan = payload.artifacts || payload.preparedPlan
50597
- ? validateFirmwareUpdatePreparedPlan(payload.preparedPlan)
50423
+ const hostBinding = payload.artifacts || payload.preparedPlan
50424
+ ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration)
50598
50425
  : undefined;
50599
- const artifactReader = preparedPlan
50600
- ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest).artifactReader
50601
- : payload.artifactReader;
50602
- if (preparedPlan) {
50426
+ if (hostBinding) {
50603
50427
  assertFirmwareUpdatePreparedPlanBinding({
50604
- preparedPlan,
50428
+ preparedPlan: payload.preparedPlan,
50605
50429
  executor: 'v3',
50606
50430
  platform: payload.platform,
50607
50431
  scopeTargets: ['bootloader', 'firmware', 'resource', 'ble'],
@@ -50639,7 +50463,7 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
50639
50463
  });
50640
50464
  }
50641
50465
  this.params = {
50642
- preparedPlan,
50466
+ preparedPlan: payload.preparedPlan,
50643
50467
  bleBinary: payload.bleBinary,
50644
50468
  firmwareBinary: payload.firmwareBinary,
50645
50469
  forcedUpdateRes: payload.forcedUpdateRes,
@@ -50650,7 +50474,7 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
50650
50474
  resourceBinary: payload.resourceBinary,
50651
50475
  firmwareType: payload.firmwareType,
50652
50476
  platform: payload.platform,
50653
- artifactReader,
50477
+ artifactReader: (_f = hostBinding === null || hostBinding === void 0 ? void 0 : hostBinding.artifactReader) !== null && _f !== void 0 ? _f : payload.artifactReader,
50654
50478
  artifacts: payload.artifacts,
50655
50479
  };
50656
50480
  }
@@ -51266,88 +51090,6 @@ const INSTALLABLE_FIRMWARE_TARGET_IDS = new Set([
51266
51090
  ]);
51267
51091
  new Map(Object.entries(ProtocolV2FirmwareTargetType).flatMap(([key, value]) => INSTALLABLE_FIRMWARE_TARGET_IDS.has(value) ? [[key, value]] : []));
51268
51092
 
51269
- let memoryHostSequence = 0;
51270
- const createReference = (binary, prefix) => {
51271
- const digest = utils.bytesToHex(sha256.sha256(new Uint8Array(binary)));
51272
- return {
51273
- artifactRef: `fwmem:${prefix}:${digest.slice(0, 32)}`,
51274
- size: binary.byteLength,
51275
- sha256: digest,
51276
- };
51277
- };
51278
- function prepareFirmwareUpdateV4MemoryHost({ sdk, plan, artifacts, }) {
51279
- if (plan.executor !== 'v4') {
51280
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Firmware memory host only supports V4 plans');
51281
- }
51282
- memoryHostSequence += 1;
51283
- const hostId = `${Date.now()}:${memoryHostSequence}`;
51284
- const binaries = new Map();
51285
- const inputs = artifacts.map((input, artifactIndex) => {
51286
- var _a;
51287
- const artifactBinary = new Uint8Array(input.binary).slice();
51288
- const artifact = createReference(artifactBinary.buffer, `${hostId}:artifact:${artifactIndex}`);
51289
- binaries.set(artifact.artifactRef, artifactBinary);
51290
- const materializedEntries = (_a = input.materializedEntries) === null || _a === void 0 ? void 0 : _a.map((entry, entryIndex) => {
51291
- const entryBinary = new Uint8Array(entry.binary).slice();
51292
- const entryArtifact = createReference(entryBinary.buffer, `${hostId}:entry:${artifactIndex}:${entryIndex}`);
51293
- binaries.set(entryArtifact.artifactRef, entryBinary);
51294
- return {
51295
- entryName: entry.entryName,
51296
- artifact: entryArtifact,
51297
- };
51298
- });
51299
- return Object.assign({ artifactId: input.artifactId, artifact }, ((materializedEntries === null || materializedEntries === void 0 ? void 0 : materializedEntries.length) ? { materializedEntries } : {}));
51300
- });
51301
- const preparedPlan = sdk.prepareFirmwareUpdatePlan({
51302
- plan,
51303
- leaseRef: `fwmemlease:${hostId}`,
51304
- artifacts: inputs,
51305
- });
51306
- const readers = new Map();
51307
- let readerSequence = 0;
51308
- const artifactReader = {
51309
- open({ artifactRef }) {
51310
- const binary = binaries.get(artifactRef);
51311
- if (!binary) {
51312
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Firmware memory artifact is unavailable');
51313
- }
51314
- readerSequence += 1;
51315
- const readerId = `fwmemreader:${hostId}:${readerSequence}`;
51316
- readers.set(readerId, binary);
51317
- return Promise.resolve({ readerId, size: binary.byteLength });
51318
- },
51319
- read({ readerId, offset, length }) {
51320
- const binary = readers.get(readerId);
51321
- if (!binary || offset < 0 || length <= 0 || offset + length > binary.byteLength) {
51322
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Firmware memory artifact read is invalid');
51323
- }
51324
- const data = binary.slice(offset, offset + length).buffer;
51325
- return Promise.resolve({
51326
- data,
51327
- bytesRead: data.byteLength,
51328
- eof: offset + length === binary.byteLength,
51329
- });
51330
- },
51331
- close({ readerId }) {
51332
- readers.delete(readerId);
51333
- return Promise.resolve();
51334
- },
51335
- };
51336
- const hostBindingGeneration = sdk.registerFirmwareUpdateHostBinding({
51337
- artifactReader,
51338
- preparedPlanDigest: preparedPlan.preparedPlanDigest,
51339
- });
51340
- return {
51341
- preparedPlan,
51342
- hostBindingGeneration,
51343
- release: () => {
51344
- sdk.unregisterFirmwareUpdateHostBinding(hostBindingGeneration);
51345
- readers.clear();
51346
- binaries.clear();
51347
- },
51348
- };
51349
- }
51350
-
51351
51093
  const Log$6 = getLogger(exports.LoggerNames.Method);
51352
51094
  const SESSION_ERROR$1 = 'session not found';
51353
51095
  const PROTOCOL_V2_BOOTLOADER_RECONNECT_TIMEOUT = 90 * 1000;
@@ -51374,24 +51116,7 @@ const PROTOCOL_V2_OKPP_HEADER_SIZE = 0x52a0;
51374
51116
  const PROTOCOL_V2_OKPP_PAYLOAD_HASH_OFFSET = 0x200;
51375
51117
  const PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET = 0x240;
51376
51118
  const PROTOCOL_V2_OKPP_HASH_SIZE = 64;
51377
- const PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES = 1024 * 1024;
51378
- const PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT = 512;
51379
- const PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES = 256 * 1024 * 1024;
51380
51119
  const PROTOCOL_V2_NEO_UNSUPPORTED_TARGETS = new Set(['se03', 'se04']);
51381
- const getProtocolV2ZipEntrySizes = (entry) => {
51382
- var _a;
51383
- const { compressedSize, uncompressedSize } = (_a = entry._data) !== null && _a !== void 0 ? _a : {};
51384
- if (!Number.isSafeInteger(compressedSize) ||
51385
- Number(compressedSize) < 0 ||
51386
- !Number.isSafeInteger(uncompressedSize) ||
51387
- Number(uncompressedSize) <= 0) {
51388
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource ZIP entry size is invalid: ${entry.name}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
51389
- }
51390
- return {
51391
- compressedSize: Number(compressedSize),
51392
- uncompressedSize: Number(uncompressedSize),
51393
- };
51394
- };
51395
51120
  function assertProtocolV2FirmwareTargetsSupported(deviceType, params) {
51396
51121
  var _a;
51397
51122
  const unsupportedTargets = new Set(((_a = params.targetsToUpdate) !== null && _a !== void 0 ? _a : []).filter(target => PROTOCOL_V2_NEO_UNSUPPORTED_TARGETS.has(target)));
@@ -51462,14 +51187,6 @@ const PROTOCOL_V2_REMOTE_COMPONENT_TARGETS = {
51462
51187
  },
51463
51188
  };
51464
51189
  const PROTOCOL_V2_FIRMWARE_STAGING_PATHS = new Set(Object.values(PROTOCOL_V2_REMOTE_COMPONENT_TARGETS).map(target => `${PROTOCOL_V2_FIRMWARE_STAGING_VOLUME}${target.fileName}`));
51465
- const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH = 'vol0:/loaders/bootloader/boot_resource.okpkg';
51466
- const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH = `${PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH}.staging`;
51467
- const resolveProtocolV2ResourceWritePath = (devicePath) => {
51468
- const normalizedPath = devicePath.replace(/^vol0:(?!\/)/i, 'vol0:/').toLowerCase();
51469
- return normalizedPath === PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH
51470
- ? PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH
51471
- : devicePath;
51472
- };
51473
51190
  const PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID = new Map([
51474
51191
  [ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_BOOTLOADER, 'boot'],
51475
51192
  [ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P1, 'app_v1'],
@@ -51480,10 +51197,6 @@ const PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID = new Map([
51480
51197
  [ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE03, 'se03'],
51481
51198
  [ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE04, 'se04'],
51482
51199
  ]);
51483
- const PROTOCOL_V2_INSTALL_TARGET_BY_UPDATE_TARGET = new Map(Object.values(PROTOCOL_V2_REMOTE_COMPONENT_TARGETS).map(target => [
51484
- PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(target.targetId),
51485
- target,
51486
- ]));
51487
51200
  const PROTOCOL_V2_ROMLOADER_UNSUPPORTED_MESSAGE = 'FW_MGMT_TARGET_ROMLOADER is not accepted by the current Pro2 bootloader update request. Flash romloader with the loader-specific flow instead of firmwareUpdateV4.';
51488
51201
  const PROTOCOL_V2_TARGET_ID_BY_DECODED_NAME = new Map(Object.entries(ProtocolV2FirmwareTargetType).map(([key, value]) => [key, value]));
51489
51202
  const PROTOCOL_V2_TARGET_STATUS_BY_DECODED_NAME = new Map([
@@ -51648,7 +51361,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51648
51361
  return ['V2'];
51649
51362
  }
51650
51363
  init() {
51651
- var _a, _b;
51364
+ var _a, _b, _c;
51652
51365
  this.allowDeviceMode = [UI_REQUEST.BOOTLOADER, UI_REQUEST.NOT_INITIALIZE];
51653
51366
  this.requireDeviceMode = [];
51654
51367
  this.unlockPolicy = 'unlock-before-run';
@@ -51679,85 +51392,54 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51679
51392
  { name: 'se02Binary', type: 'buffer' },
51680
51393
  { name: 'se03Binary', type: 'buffer' },
51681
51394
  { name: 'se04Binary', type: 'buffer' },
51682
- { name: 'resourceArchiveBinary', type: 'buffer' },
51683
51395
  { name: 'firmwareType', type: 'string' },
51684
51396
  { name: 'targetsToUpdate', type: 'array', allowEmpty: true },
51685
51397
  { name: 'platform', type: 'string' },
51686
51398
  { name: 'expectedDeviceId', type: 'string' },
51399
+ { name: 'resourceFiles', type: 'array', allowEmpty: true },
51687
51400
  ]);
51688
51401
  if (payload.expectedDeviceId !== undefined &&
51689
51402
  (payload.expectedDeviceId.length === 0 || payload.expectedDeviceId.length > 160)) {
51690
51403
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Protocol V2 expected device identity is invalid');
51691
51404
  }
51692
- const preparedPlan = payload.preparedPlan
51693
- ? validateFirmwareUpdatePreparedPlan(payload.preparedPlan)
51405
+ const hostBinding = payload.preparedPlan || payload.componentArtifacts || payload.resourceBundleArtifacts
51406
+ ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration)
51694
51407
  : undefined;
51695
- const hasLocalArtifacts = [
51696
- payload.bootloaderBinary,
51697
- payload.romloaderBinary,
51698
- payload.applicationP1Binary,
51699
- payload.applicationP2Binary,
51700
- payload.coprocessorBinary,
51701
- payload.se01Binary,
51702
- payload.se02Binary,
51703
- payload.se03Binary,
51704
- payload.se04Binary,
51705
- payload.resourceArchiveBinary,
51706
- ].some(Boolean);
51707
- if (preparedPlan && hasLocalArtifacts) {
51708
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Prepared firmware plans cannot be combined with legacy or local firmware inputs');
51709
- }
51710
- let { artifactReader } = payload;
51711
- if (preparedPlan) {
51712
- artifactReader = resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest).artifactReader;
51713
- }
51714
- else if (payload.hostBindingGeneration !== undefined) {
51715
- artifactReader = resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration).artifactReader;
51716
- }
51717
- if (preparedPlan) {
51408
+ if (hostBinding) {
51718
51409
  assertFirmwareUpdatePreparedPlanBinding({
51719
- preparedPlan,
51410
+ preparedPlan: payload.preparedPlan,
51720
51411
  executor: 'v4',
51721
51412
  platform: payload.platform,
51722
- scopeTargets: [],
51723
- bindings: [],
51413
+ scopeTargets: [
51414
+ 'boot',
51415
+ 'app_v1',
51416
+ 'app_v2',
51417
+ 'coprocessor',
51418
+ 'resource',
51419
+ 'se01',
51420
+ 'se02',
51421
+ 'se03',
51422
+ 'se04',
51423
+ ],
51424
+ bindings: [
51425
+ ...Object.entries((_a = payload.componentArtifacts) !== null && _a !== void 0 ? _a : {}).flatMap(([target, artifact]) => artifact
51426
+ ? [
51427
+ {
51428
+ target: target,
51429
+ artifact,
51430
+ },
51431
+ ]
51432
+ : []),
51433
+ ...((_b = payload.resourceBundleArtifacts) !== null && _b !== void 0 ? _b : []).map((entry) => ({
51434
+ target: 'resource',
51435
+ logicalName: entry.name,
51436
+ artifact: entry.artifact,
51437
+ })),
51438
+ ],
51724
51439
  });
51725
- if (payload.componentArtifacts) {
51726
- const componentBindings = Object.entries(payload.componentArtifacts).flatMap(([target, artifact]) => artifact
51727
- ? [
51728
- {
51729
- target: target,
51730
- artifact: artifact,
51731
- },
51732
- ]
51733
- : []);
51734
- assertFirmwareUpdatePreparedPlanBinding({
51735
- preparedPlan,
51736
- executor: 'v4',
51737
- platform: payload.platform,
51738
- scopeTargets: componentBindings.map(binding => binding.target),
51739
- bindings: componentBindings,
51740
- });
51741
- }
51742
- }
51743
- const preparedExpectedTargetVersions = preparedPlan === null || preparedPlan === void 0 ? void 0 : preparedPlan.artifacts.reduce((result, artifact) => {
51744
- if (artifact.role === 'component' &&
51745
- artifact.target !== 'resource' &&
51746
- artifact.targetVersion &&
51747
- PROTOCOL_V2_INSTALL_TARGET_BY_UPDATE_TARGET.has(artifact.target)) {
51748
- result[artifact.target] = artifact.targetVersion;
51749
- }
51750
- return result;
51751
- }, {});
51752
- const localTargetsToUpdate = (_a = payload.targetsToUpdate) === null || _a === void 0 ? void 0 : _a.map((target) => target === 'boot_resources' ? 'resource' : target);
51753
- if (payload.resourceArchiveBinary &&
51754
- localTargetsToUpdate &&
51755
- !localTargetsToUpdate.includes('resource')) {
51756
- localTargetsToUpdate.push('resource');
51757
51440
  }
51758
- const resolvedLocalTargetsToUpdate = localTargetsToUpdate !== null && localTargetsToUpdate !== void 0 ? localTargetsToUpdate : (payload.resourceArchiveBinary ? ['resource'] : undefined);
51759
51441
  this.params = {
51760
- preparedPlan,
51442
+ preparedPlan: payload.preparedPlan,
51761
51443
  chunkSize: payload.chunkSize,
51762
51444
  forcedUpdateRes: payload.forcedUpdateRes,
51763
51445
  bootloaderBinary: payload.bootloaderBinary,
@@ -51769,18 +51451,15 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51769
51451
  se02Binary: payload.se02Binary,
51770
51452
  se03Binary: payload.se03Binary,
51771
51453
  se04Binary: payload.se04Binary,
51772
- resourceArchiveBinary: payload.resourceArchiveBinary,
51773
- firmwareType: (_b = preparedPlan === null || preparedPlan === void 0 ? void 0 : preparedPlan.firmwareType) !== null && _b !== void 0 ? _b : payload.firmwareType,
51774
- targetsToUpdate: preparedPlan
51775
- ? [...preparedPlan.targetsToUpdate]
51776
- : resolvedLocalTargetsToUpdate,
51777
- expectedTargetVersions: preparedPlan
51778
- ? preparedExpectedTargetVersions
51779
- : payload.expectedTargetVersions,
51454
+ resourceFiles: payload.resourceFiles,
51455
+ firmwareType: payload.firmwareType,
51456
+ targetsToUpdate: payload.targetsToUpdate,
51457
+ expectedTargetVersions: payload.expectedTargetVersions,
51780
51458
  platform: payload.platform,
51781
51459
  expectedDeviceId: payload.expectedDeviceId,
51782
- artifactReader,
51783
- componentArtifacts: preparedPlan ? undefined : payload.componentArtifacts,
51460
+ artifactReader: (_c = hostBinding === null || hostBinding === void 0 ? void 0 : hostBinding.artifactReader) !== null && _c !== void 0 ? _c : payload.artifactReader,
51461
+ componentArtifacts: payload.componentArtifacts,
51462
+ resourceBundleArtifacts: payload.resourceBundleArtifacts,
51784
51463
  };
51785
51464
  }
51786
51465
  getProtocolV2FirmwareChunkSize(direction, filePath) {
@@ -51811,7 +51490,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51811
51490
  });
51812
51491
  }
51813
51492
  runProtocolV2() {
51814
- var _a, _b, _c, _d, _e, _f;
51493
+ var _a, _b, _c, _d, _e;
51815
51494
  return __awaiter(this, void 0, void 0, function* () {
51816
51495
  yield this.captureProtocolV2PhysicalIdentity();
51817
51496
  const deviceFeatures = yield this.getProtocolV2DeviceFeatures();
@@ -51823,80 +51502,85 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51823
51502
  const deviceFirmwareType = getFirmwareType(deviceFeatures);
51824
51503
  const firmwareType = (_a = this.params.firmwareType) !== null && _a !== void 0 ? _a : deviceFirmwareType;
51825
51504
  this.validateExpectedTargetVersions();
51826
- if (!this.params.preparedPlan &&
51827
- this.params.resourceArchiveBinary &&
51828
- ((_b = this.params.targetsToUpdate) === null || _b === void 0 ? void 0 : _b.includes('resource'))) {
51829
- const localMemoryHost = yield this.prepareProtocolV2LocalMemoryHost({
51830
- features: deviceFeatures,
51831
- firmwareType,
51832
- });
51833
- try {
51834
- return yield this.runProtocolV2PreparedArtifacts(deviceFeatures, firmwareType);
51835
- }
51836
- finally {
51837
- localMemoryHost.release();
51838
- }
51839
- }
51840
- const hasPreparedComponentArtifacts = Object.values((_c = this.params.componentArtifacts) !== null && _c !== void 0 ? _c : {}).some(Boolean);
51841
- if (this.params.preparedPlan || hasPreparedComponentArtifacts) {
51505
+ if ((this.params.componentArtifacts && Object.keys(this.params.componentArtifacts).length > 0) ||
51506
+ ((_b = this.params.resourceBundleArtifacts) === null || _b === void 0 ? void 0 : _b.length)) {
51842
51507
  return this.runProtocolV2PreparedArtifacts(deviceFeatures, firmwareType);
51843
51508
  }
51844
- const wantsResources = !!((_d = this.params.targetsToUpdate) === null || _d === void 0 ? void 0 : _d.includes('resource'));
51509
+ const hasExplicitResourceFiles = !!((_c = this.params.resourceFiles) === null || _c === void 0 ? void 0 : _c.length);
51510
+ const wantsStableResources = !!((_d = this.params.targetsToUpdate) === null || _d === void 0 ? void 0 : _d.includes('resource'));
51511
+ const wantsBootResources = !!((_e = this.params.targetsToUpdate) === null || _e === void 0 ? void 0 : _e.includes('boot_resources'));
51512
+ const needsRemoteResources = !hasExplicitResourceFiles && wantsStableResources;
51513
+ const needsRemoteBootResources = !hasExplicitResourceFiles && (wantsBootResources || wantsStableResources);
51845
51514
  let fwBinaryMap = [];
51846
51515
  let bootloaderBinary = null;
51847
51516
  let installItems;
51517
+ let resourceBundles;
51848
51518
  try {
51849
51519
  this.postTipMessage(exports.FirmwareUpdateTipMessage.StartDownloadFirmware);
51520
+ resourceBundles = this.prepareExplicitProtocolV2ResourceFiles();
51850
51521
  fwBinaryMap = this.collectExplicitTargetBinaries();
51851
51522
  bootloaderBinary = this.prepareBootloaderBinary();
51852
- const explicitInstallItems = this.buildProtocolV2InstallItems({
51853
- bootloaderBinary,
51854
- fwBinaryMap,
51855
- });
51856
- const missingFirmwareTargets = this.getMissingProtocolV2FirmwareTargets(explicitInstallItems);
51857
- const needsRemoteFirmware = ((_e = this.params.targetsToUpdate) === null || _e === void 0 ? void 0 : _e.length)
51858
- ? missingFirmwareTargets.length > 0
51859
- : explicitInstallItems.length === 0;
51860
- if (wantsResources) {
51861
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 resource archive must be provided through a local or external PreparedPlan', {
51862
- firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
51863
- });
51864
- }
51865
- if (needsRemoteFirmware &&
51523
+ const needsRemoteFirmware = !this.hasExplicitProtocolV2Payload(fwBinaryMap);
51524
+ if ((needsRemoteFirmware || needsRemoteResources || needsRemoteBootResources) &&
51866
51525
  (this.params.artifactReader ||
51867
51526
  DataManager.getSettings('firmwareManifestMode') === 'external-only')) {
51868
51527
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 firmware artifacts must be prepared by the external firmware host', {
51869
51528
  firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
51870
51529
  });
51871
51530
  }
51872
- if (needsRemoteFirmware) {
51873
- yield DataManager.forceReloadData();
51531
+ if (needsRemoteFirmware || needsRemoteResources || needsRemoteBootResources) {
51532
+ yield DataManager.forceReloadData({
51533
+ requireResources: needsRemoteResources || needsRemoteBootResources,
51534
+ });
51874
51535
  }
51875
51536
  if (needsRemoteFirmware) {
51876
- const remoteBinaries = yield this.prepareRemoteProtocolV2Binaries(firmwareType, deviceFeatures, explicitInstallItems);
51537
+ const remoteBinaries = yield this.prepareRemoteProtocolV2Binaries(firmwareType, deviceFeatures);
51877
51538
  bootloaderBinary = remoteBinaries.bootloaderBinary;
51878
51539
  fwBinaryMap = remoteBinaries.fwBinaryMap;
51879
51540
  installItems = remoteBinaries.installItems;
51880
51541
  }
51881
- this.postTipMessage(exports.FirmwareUpdateTipMessage.FinishDownloadFirmware);
51542
+ const bootResourceFiles = yield this.prepareProtocolV2BootResources();
51543
+ if (bootResourceFiles === null || bootResourceFiles === void 0 ? void 0 : bootResourceFiles.length) {
51544
+ resourceBundles = this.mergeProtocolV2ResourceBundles(resourceBundles, bootResourceFiles);
51545
+ }
51546
+ if (!needsRemoteResources) {
51547
+ this.postTipMessage(exports.FirmwareUpdateTipMessage.FinishDownloadFirmware);
51548
+ }
51882
51549
  }
51883
51550
  catch (err) {
51884
- if (typeof err === 'object' &&
51885
- err !== null &&
51886
- 'params' in err &&
51887
- ((_f = err.params) === null || _f === void 0 ? void 0 : _f.firmwareUpdateCode) === 'FirmwareArtifactsNotPrepared') {
51888
- throw err;
51889
- }
51890
51551
  if (err instanceof hdShared.HardwareError && err.errorCode === hdShared.HardwareErrorCode.NetworkError) {
51891
51552
  throw err;
51892
51553
  }
51893
51554
  throw normalizeFirmwarePreparationError(err);
51894
51555
  }
51895
- if (!bootloaderBinary && fwBinaryMap.length === 0 && !(installItems === null || installItems === void 0 ? void 0 : installItems.length)) {
51556
+ if (!bootloaderBinary &&
51557
+ fwBinaryMap.length === 0 &&
51558
+ !(installItems === null || installItems === void 0 ? void 0 : installItems.length) &&
51559
+ !(resourceBundles === null || resourceBundles === void 0 ? void 0 : resourceBundles.length) &&
51560
+ !needsRemoteResources) {
51896
51561
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareUpdateDownloadFailed, 'No firmware to update');
51897
51562
  }
51898
- return this.executeProtocolV2Update(Object.assign({ fwBinaryMap,
51899
- bootloaderBinary }, (installItems ? { installItems } : undefined)));
51563
+ if (needsRemoteResources) {
51564
+ const enteredBootloader = yield this.enterProtocolV2BootloaderMode();
51565
+ try {
51566
+ const stableResources = yield this.prepareProtocolV2ResourceBundles();
51567
+ resourceBundles = this.mergeProtocolV2ResourceBundles(resourceBundles, stableResources);
51568
+ this.postTipMessage(exports.FirmwareUpdateTipMessage.FinishDownloadFirmware);
51569
+ }
51570
+ catch (err) {
51571
+ if (enteredBootloader) {
51572
+ try {
51573
+ yield this.exitProtocolV2BootloaderToNormal();
51574
+ }
51575
+ catch (restoreError) {
51576
+ Log$6.warn('[FirmwareUpdateV4] failed to restore App mode after resource preparation error:', restoreError);
51577
+ }
51578
+ }
51579
+ throw normalizeFirmwarePreparationError(err);
51580
+ }
51581
+ }
51582
+ return this.executeProtocolV2Update(Object.assign(Object.assign({ fwBinaryMap,
51583
+ bootloaderBinary }, (installItems ? { installItems } : undefined)), ((resourceBundles === null || resourceBundles === void 0 ? void 0 : resourceBundles.length) ? { resourceBundles } : undefined)));
51900
51584
  });
51901
51585
  }
51902
51586
  openProtocolV2PreparedSource(artifact) {
@@ -51933,34 +51617,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51933
51617
  prepareProtocolV2InstallSources(firmwareType, features) {
51934
51618
  var _a, _b;
51935
51619
  return __awaiter(this, void 0, void 0, function* () {
51936
- if (this.params.preparedPlan) {
51937
- const requestedTargets = new Set(this.params.preparedPlan.targetsToUpdate.filter((target) => target !== 'resource'));
51938
- const installSources = [];
51939
- const preparedTargets = new Set();
51940
- for (const artifact of this.params.preparedPlan.artifacts) {
51941
- if (artifact.target !== 'resource') {
51942
- const target = artifact.target;
51943
- const installTarget = PROTOCOL_V2_INSTALL_TARGET_BY_UPDATE_TARGET.get(target);
51944
- if (!requestedTargets.has(target) ||
51945
- artifact.role !== 'component' ||
51946
- artifact.container !== 'raw' ||
51947
- !installTarget ||
51948
- preparedTargets.has(target)) {
51949
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 prepared component artifact is invalid: ${artifact.artifactId}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
51950
- }
51951
- installSources.push(Object.assign(Object.assign({}, installTarget), { source: yield this.openProtocolV2PreparedSource(artifact.artifact) }));
51952
- preparedTargets.add(target);
51953
- }
51954
- }
51955
- const missingTarget = Array.from(requestedTargets).find(target => !preparedTargets.has(target));
51956
- if (missingTarget) {
51957
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 ${missingTarget} artifact is not prepared`, {
51958
- firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
51959
- artifactName: missingTarget,
51960
- });
51961
- }
51962
- return installSources;
51963
- }
51964
51620
  const release = DataManager.getFirmwareLatestRelease(features, firmwareType);
51965
51621
  if (!release) {
51966
51622
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 firmware release is unavailable');
@@ -51991,278 +51647,39 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51991
51647
  return installSources;
51992
51648
  });
51993
51649
  }
51994
- prepareProtocolV2LocalMemoryHost({ features, firmwareType, }) {
51995
- var _a, _b;
51996
- return __awaiter(this, void 0, void 0, function* () {
51997
- const installItems = this.buildProtocolV2InstallItems({
51998
- bootloaderBinary: this.prepareBootloaderBinary(),
51999
- fwBinaryMap: this.collectExplicitTargetBinaries(),
52000
- });
52001
- const requestedComponentTargets = new Set(((_a = this.params.targetsToUpdate) !== null && _a !== void 0 ? _a : []).filter((target) => target !== 'resource' && target !== 'boot_resources'));
52002
- const localComponentTargets = new Set(installItems.flatMap(item => {
52003
- const target = PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(item.targetId);
52004
- return target ? [target] : [];
52005
- }));
52006
- const missingTarget = Array.from(requestedComponentTargets).find(target => !localComponentTargets.has(target));
52007
- if (missingTarget) {
52008
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local update has no binary for requested target ${missingTarget}`, {
52009
- firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
52010
- artifactName: missingTarget,
52011
- });
52012
- }
52013
- const planArtifacts = [];
52014
- const memoryArtifacts = [];
52015
- for (const item of installItems) {
52016
- const target = PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(item.targetId);
52017
- if (!target || item.binary.byteLength <= 0) {
52018
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local firmware artifact is invalid: ${item.fileName}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52019
- }
52020
- const artifactId = `component:${target}`;
52021
- planArtifacts.push(Object.assign({ artifactId,
52022
- target, container: 'raw', logicalName: item.fileName, expectedSize: item.binary.byteLength, expectedSha256: bytesToHex(sha256.sha256(new Uint8Array(item.binary))) }, (((_b = this.params.expectedTargetVersions) === null || _b === void 0 ? void 0 : _b[target])
52023
- ? { targetVersion: this.params.expectedTargetVersions[target] }
52024
- : {})));
52025
- memoryArtifacts.push({ artifactId, binary: item.binary });
52026
- }
52027
- const resourceArchive = yield this.prepareProtocolV2LocalResourceArchive(this.params.resourceArchiveBinary);
52028
- const resourceArtifactId = 'resource:archive';
52029
- planArtifacts.push({
52030
- artifactId: resourceArtifactId,
52031
- target: 'resource',
52032
- container: 'zip',
52033
- logicalName: 'protocol-v2-local-resource-archive',
52034
- expectedSize: resourceArchive.binary.byteLength,
52035
- expectedSha256: bytesToHex(sha256.sha256(new Uint8Array(resourceArchive.binary))),
52036
- });
52037
- memoryArtifacts.push({
52038
- artifactId: resourceArtifactId,
52039
- binary: resourceArchive.binary,
52040
- materializedEntries: resourceArchive.materializedEntries,
52041
- });
52042
- const plan = buildProtocolV2LocalFirmwareUpdatePlan({
52043
- features,
52044
- firmwareType,
52045
- platform: this.params.platform,
52046
- artifacts: planArtifacts,
52047
- });
52048
- let memoryHost;
52049
- try {
52050
- memoryHost = prepareFirmwareUpdateV4MemoryHost({
52051
- sdk: {
52052
- prepareFirmwareUpdatePlan,
52053
- registerFirmwareUpdateHostBinding,
52054
- unregisterFirmwareUpdateHostBinding,
52055
- },
52056
- plan,
52057
- artifacts: memoryArtifacts,
52058
- });
52059
- const preparedPlan = validateFirmwareUpdatePreparedPlan(memoryHost.preparedPlan);
52060
- assertFirmwareUpdatePreparedPlanBinding({
52061
- preparedPlan,
52062
- executor: 'v4',
52063
- platform: this.params.platform,
52064
- scopeTargets: [],
52065
- bindings: [],
52066
- });
52067
- assertFirmwareUpdatePreparedPlanDeviceIdentity({
52068
- preparedPlan,
52069
- deviceIdentity: this.protocolV2ExpectedSerialNumber,
52070
- deviceModel: this.getProtocolV2PreparedPlanDeviceModel(features),
52071
- });
52072
- const hostBinding = resolveFirmwareUpdateHostBinding(memoryHost.hostBindingGeneration, preparedPlan.preparedPlanDigest);
52073
- this.params.preparedPlan = preparedPlan;
52074
- this.params.targetsToUpdate = [...preparedPlan.targetsToUpdate];
52075
- this.params.artifactReader = hostBinding.artifactReader;
52076
- this.params.componentArtifacts = undefined;
52077
- return memoryHost;
52078
- }
52079
- catch (error) {
52080
- memoryHost === null || memoryHost === void 0 ? void 0 : memoryHost.release();
52081
- throw error;
52082
- }
52083
- });
52084
- }
52085
- prepareProtocolV2LocalResourceArchive(binary) {
52086
- var _a;
52087
- return __awaiter(this, void 0, void 0, function* () {
52088
- if (binary.byteLength <= 0 || binary.byteLength > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
52089
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP archive size is invalid', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52090
- }
52091
- const zip = yield JSZip__default["default"].loadAsync(binary);
52092
- const zipEntries = Object.values(zip.files);
52093
- if (zipEntries.some(entry => entry.unsafeOriginalName && entry.unsafeOriginalName !== entry.name)) {
52094
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP contains an unsafe entry path', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52095
- }
52096
- const entries = zipEntries.filter(entry => !entry.dir);
52097
- if (entries.length === 0 || entries.length > PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT + 1) {
52098
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP entry set is invalid', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52099
- }
52100
- let declaredUncompressedSize = 0;
52101
- let declaredCompressedSize = 0;
52102
- for (const entry of entries) {
52103
- const sizes = getProtocolV2ZipEntrySizes(entry);
52104
- declaredCompressedSize += sizes.compressedSize;
52105
- declaredUncompressedSize += sizes.uncompressedSize;
52106
- const entryLimit = entry.name === 'manifest.json'
52107
- ? PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES
52108
- : PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES;
52109
- if (sizes.uncompressedSize > entryLimit ||
52110
- declaredCompressedSize > binary.byteLength ||
52111
- declaredUncompressedSize >
52112
- PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES + PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES) {
52113
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP declared size exceeds the allowed limit', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52114
- }
52115
- }
52116
- const manifestEntry = zip.file('manifest.json');
52117
- if (!manifestEntry) {
52118
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP has no manifest.json', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52119
- }
52120
- const manifestBinary = yield manifestEntry.async('arraybuffer');
52121
- if (manifestBinary.byteLength <= 0 ||
52122
- manifestBinary.byteLength > PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES) {
52123
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource manifest size is invalid', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52124
- }
52125
- let manifestValue;
52126
- try {
52127
- manifestValue = JSON.parse(new TextDecoder().decode(manifestBinary));
52128
- }
52129
- catch (error) {
52130
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource manifest is invalid: ${String(error)}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52131
- }
52132
- const manifest = parseProtocolV2ResourceManifest(manifestValue);
52133
- const selectedFiles = selectProtocolV2ResourceManifestFiles({
52134
- manifest,
52135
- targetsToUpdate: (_a = this.params.targetsToUpdate) !== null && _a !== void 0 ? _a : [],
52136
- });
52137
- const expectedEntryNames = new Set([
52138
- 'manifest.json',
52139
- ...selectedFiles.map(file => file.archive_path),
52140
- ]);
52141
- if (entries.length !== expectedEntryNames.size ||
52142
- entries.some(entry => !expectedEntryNames.has(entry.name))) {
52143
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP contains an unexpected entry', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52144
- }
52145
- let totalSize = 0;
52146
- const materializedEntries = [
52147
- { entryName: 'manifest.json', binary: manifestBinary },
52148
- ];
52149
- for (const file of selectedFiles) {
52150
- const entry = zip.file(file.archive_path);
52151
- if (!entry) {
52152
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource ZIP is missing ${file.archive_path}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52153
- }
52154
- const { uncompressedSize } = getProtocolV2ZipEntrySizes(entry);
52155
- totalSize += uncompressedSize;
52156
- if (uncompressedSize !== file.size || totalSize > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
52157
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource file declared size is invalid: ${file.archive_path}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52158
- }
52159
- const fileBinary = yield entry.async('arraybuffer');
52160
- const digest = bytesToHex(sha256.sha256(new Uint8Array(fileBinary)));
52161
- if (fileBinary.byteLength !== file.size || digest !== file.sha256.toLowerCase()) {
52162
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource file does not match manifest: ${file.archive_path}`, { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52163
- }
52164
- materializedEntries.push({ entryName: file.archive_path, binary: fileBinary });
52165
- }
52166
- return { binary, materializedEntries };
52167
- });
52168
- }
52169
- prepareProtocolV2ResourceSources() {
52170
- var _a, _b;
51650
+ prepareProtocolV2ResourceSources(firmwareType, features) {
51651
+ var _a, _b, _c;
52171
51652
  return __awaiter(this, void 0, void 0, function* () {
52172
- const resourceRequested = (_b = (_a = this.params.targetsToUpdate) === null || _a === void 0 ? void 0 : _a.includes('resource')) !== null && _b !== void 0 ? _b : false;
51653
+ const preparedArtifacts = (_a = this.params.resourceBundleArtifacts) !== null && _a !== void 0 ? _a : [];
51654
+ const resourceRequested = ((_b = this.params.targetsToUpdate) === null || _b === void 0 ? void 0 : _b.includes('resource')) || preparedArtifacts.length > 0;
52173
51655
  if (!resourceRequested) {
52174
51656
  return [];
52175
51657
  }
52176
- const archiveSources = yield this.prepareProtocolV2ResourceArchiveSources();
52177
- if (archiveSources) {
52178
- return archiveSources;
52179
- }
52180
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 resource archive is not prepared', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52181
- });
52182
- }
52183
- prepareProtocolV2ResourceArchiveSources() {
52184
- var _a, _b, _c, _d;
52185
- return __awaiter(this, void 0, void 0, function* () {
52186
- const archiveArtifacts = (_b = (_a = this.params.preparedPlan) === null || _a === void 0 ? void 0 : _a.artifacts.filter(artifact => artifact.role === 'resourceBundle' &&
52187
- artifact.target === 'resource' &&
52188
- artifact.container === 'zip')) !== null && _b !== void 0 ? _b : [];
52189
- if (archiveArtifacts.length === 0) {
52190
- return undefined;
52191
- }
52192
- if (archiveArtifacts.length !== 1) {
52193
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared plan must contain exactly one resource archive', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52194
- }
52195
- const archiveArtifact = archiveArtifacts[0];
52196
- const archiveSource = yield this.openProtocolV2PreparedSource(archiveArtifact.artifact);
52197
- if (archiveSource.size > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
52198
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive exceeds the total size limit', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52199
- }
52200
- let archiveBinary;
52201
- try {
52202
- archiveBinary = yield readFirmwareByteSourceFully(archiveSource);
52203
- }
52204
- finally {
52205
- yield archiveSource.close();
52206
- }
52207
- const archiveDigest = bytesToHex(sha256.sha256(new Uint8Array(archiveBinary)));
52208
- if (archiveDigest !== archiveArtifact.artifact.sha256.toLowerCase()) {
52209
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive does not match its approved receipt', { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52210
- }
52211
- const verifiedArchive = yield this.prepareProtocolV2LocalResourceArchive(archiveBinary);
52212
- const entries = (_c = archiveArtifact.materializedEntries) !== null && _c !== void 0 ? _c : [];
52213
- const entriesByName = new Map(entries.map(entry => [entry.entryName, entry]));
52214
- if (entries.length !== verifiedArchive.materializedEntries.length ||
52215
- verifiedArchive.materializedEntries.some(entry => {
52216
- const preparedEntry = entriesByName.get(entry.entryName);
52217
- const digest = bytesToHex(sha256.sha256(new Uint8Array(entry.binary)));
52218
- return (!preparedEntry ||
52219
- preparedEntry.artifact.size !== entry.binary.byteLength ||
52220
- preparedEntry.artifact.sha256.toLowerCase() !== digest);
52221
- })) {
52222
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource entries do not match the approved archive', { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52223
- }
52224
- const verifiedEntriesByName = new Map(verifiedArchive.materializedEntries.map(entry => [entry.entryName, entry.binary]));
52225
- const manifestBinary = verifiedEntriesByName.get('manifest.json');
52226
- if (!manifestBinary) {
52227
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive has no valid manifest.json', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52228
- }
52229
- let manifestValue;
52230
- try {
52231
- manifestValue = JSON.parse(new TextDecoder().decode(manifestBinary));
52232
- }
52233
- catch (error) {
52234
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 prepared resource manifest is invalid: ${String(error)}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52235
- }
52236
- const manifest = parseProtocolV2ResourceManifest(manifestValue);
52237
- const selectedFiles = selectProtocolV2ResourceManifestFiles({
52238
- manifest,
52239
- targetsToUpdate: (_d = this.params.targetsToUpdate) !== null && _d !== void 0 ? _d : [],
52240
- });
52241
- if (selectedFiles.length > PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT) {
52242
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive contains too many files', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52243
- }
52244
- let totalSize = 0;
51658
+ const release = DataManager.getFirmwareLatestRelease(features, firmwareType);
51659
+ const descriptors = (_c = release === null || release === void 0 ? void 0 : release.resourceBundles) !== null && _c !== void 0 ? _c : [];
51660
+ const artifactByName = new Map(preparedArtifacts.map(item => [item.name, item.artifact]));
52245
51661
  const sources = [];
52246
- for (const [index, file] of selectedFiles.entries()) {
52247
- const binary = verifiedEntriesByName.get(file.archive_path);
52248
- if (!binary || binary.byteLength !== file.size) {
52249
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 prepared resource file does not match manifest: ${file.archive_path}`, { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52250
- }
52251
- totalSize += binary.byteLength;
52252
- if (totalSize > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
52253
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive exceeds the total size limit', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
51662
+ for (const descriptor of descriptors) {
51663
+ const artifact = artifactByName.get(descriptor.name);
51664
+ if (!artifact) {
51665
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 resource bundle ${descriptor.name} is not prepared`, {
51666
+ firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
51667
+ artifactName: descriptor.name,
51668
+ });
52254
51669
  }
52255
- const source = yield this.openProtocolV2MemorySource(binary);
52256
- const header = source.size >= PROTOCOL_V2_OKPP_HEADER_SIZE
52257
- ? parseProtocolV2OkppHeader(new Uint8Array(yield source.readAt(0, PROTOCOL_V2_OKPP_HEADER_SIZE)))
52258
- : null;
52259
- sources.push(Object.assign({ name: file.original_name || `resource-${index}`, source, devicePath: file.device_path }, (header
52260
- ? {
52261
- version: header.version,
52262
- payloadHash: header.payloadHash,
52263
- headerHash: header.headerHash,
52264
- }
52265
- : {})));
51670
+ const devicePath = validateProtocolV2FilesystemPath(descriptor.devicePath, 'resourceBundles[].devicePath');
51671
+ sources.push({
51672
+ name: descriptor.name,
51673
+ source: yield this.openProtocolV2PreparedSource(artifact),
51674
+ devicePath,
51675
+ version: descriptor.version,
51676
+ payloadHash: descriptor.payloadHash,
51677
+ headerHash: descriptor.headerHash,
51678
+ });
51679
+ artifactByName.delete(descriptor.name);
51680
+ }
51681
+ if (artifactByName.size > 0) {
51682
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 release does not contain resource bundle ${artifactByName.keys().next().value}`);
52266
51683
  }
52267
51684
  return sources;
52268
51685
  });
@@ -52272,7 +51689,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52272
51689
  try {
52273
51690
  this.postTipMessage(exports.FirmwareUpdateTipMessage.StartDownloadFirmware);
52274
51691
  const installSources = yield this.prepareProtocolV2InstallSources(firmwareType, features);
52275
- const resourceSources = yield this.prepareProtocolV2ResourceSources();
51692
+ const resourceSources = yield this.prepareProtocolV2ResourceSources(firmwareType, features);
52276
51693
  if (installSources.length === 0 && resourceSources.length === 0) {
52277
51694
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareUpdateDownloadFailed, 'No firmware to update');
52278
51695
  }
@@ -52356,15 +51773,15 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52356
51773
  }
52357
51774
  }
52358
51775
  getProtocolV2RequestedTargets() {
52359
- var _a, _b, _c;
51776
+ var _a, _b, _c, _d;
52360
51777
  if ((_a = this.params.targetsToUpdate) === null || _a === void 0 ? void 0 : _a.length) {
52361
51778
  return [...new Set(this.params.targetsToUpdate)];
52362
51779
  }
52363
- if ((_b = this.params.preparedPlan) === null || _b === void 0 ? void 0 : _b.targetsToUpdate.length) {
52364
- return [...new Set(this.params.preparedPlan.targetsToUpdate)];
52365
- }
52366
51780
  const targets = new Set();
52367
- Object.keys((_c = this.params.componentArtifacts) !== null && _c !== void 0 ? _c : {}).forEach(target => targets.add(target));
51781
+ Object.keys((_b = this.params.componentArtifacts) !== null && _b !== void 0 ? _b : {}).forEach(target => targets.add(target));
51782
+ if (((_c = this.params.resourceBundleArtifacts) === null || _c === void 0 ? void 0 : _c.length) || ((_d = this.params.resourceFiles) === null || _d === void 0 ? void 0 : _d.length)) {
51783
+ targets.add('resource');
51784
+ }
52368
51785
  if (this.params.bootloaderBinary)
52369
51786
  targets.add('boot');
52370
51787
  if (this.params.applicationP1Binary)
@@ -52401,26 +51818,8 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52401
51818
  const serialNumber = (_b = (_a = deviceInfo.hw) === null || _a === void 0 ? void 0 : _a.serial_no) === null || _b === void 0 ? void 0 : _b.trim();
52402
51819
  return serialNumber || undefined;
52403
51820
  }
52404
- getProtocolV2PreparedPlanDeviceModel(features) {
52405
- const currentDeviceType = this.device.getCurrentDeviceType();
52406
- const featureDeviceType = features ? getDeviceType(features) : undefined;
52407
- const deviceType = currentDeviceType === hdShared.EDeviceType.Pro2 || currentDeviceType === hdShared.EDeviceType.Neo
52408
- ? currentDeviceType
52409
- : featureDeviceType;
52410
- return deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo
52411
- ? String(deviceType)
52412
- : undefined;
52413
- }
52414
- getProtocolV2ConnectionRoute() {
52415
- var _a, _b, _c, _d, _e;
52416
- const descriptor = this.device.originalDescriptor;
52417
- return (((_a = descriptor === null || descriptor === void 0 ? void 0 : descriptor.path) === null || _a === void 0 ? void 0 : _a.trim()) ||
52418
- ((_d = (_c = (_b = this.device).getConnectId) === null || _c === void 0 ? void 0 : _c.call(_b)) === null || _d === void 0 ? void 0 : _d.trim()) ||
52419
- ((_e = descriptor === null || descriptor === void 0 ? void 0 : descriptor.id) === null || _e === void 0 ? void 0 : _e.trim()) ||
52420
- undefined);
52421
- }
52422
51821
  assertProtocolV2DeviceInfoIdentity(deviceInfo) {
52423
- assertProtocolV2ReconnectIdentity(this.protocolV2ExpectedSerialNumber, this.getProtocolV2SerialNumber(deviceInfo), this.protocolV2ExpectedPath, this.getProtocolV2ConnectionRoute());
51822
+ assertProtocolV2ReconnectIdentity(this.protocolV2ExpectedSerialNumber, this.getProtocolV2SerialNumber(deviceInfo), this.protocolV2ExpectedPath, this.device.originalDescriptor.path);
52424
51823
  }
52425
51824
  getProtocolV2DeviceInfoTimeout() {
52426
51825
  var _a;
@@ -52437,20 +51836,19 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52437
51836
  });
52438
51837
  }
52439
51838
  captureProtocolV2PhysicalIdentity() {
52440
- var _a, _b, _c;
51839
+ var _a, _b, _c, _d, _e;
52441
51840
  return __awaiter(this, void 0, void 0, function* () {
52442
51841
  const deviceInfo = yield this.requestProtocolV2PhysicalIdentity();
52443
51842
  const serialNumber = this.getProtocolV2SerialNumber(deviceInfo);
52444
- const path = this.getProtocolV2ConnectionRoute();
52445
- if ((_a = this.params) === null || _a === void 0 ? void 0 : _a.preparedPlan) {
51843
+ const path = ((_b = (_a = this.device.originalDescriptor) === null || _a === void 0 ? void 0 : _a.path) === null || _b === void 0 ? void 0 : _b.trim()) || undefined;
51844
+ if ((_c = this.params) === null || _c === void 0 ? void 0 : _c.preparedPlan) {
52446
51845
  assertFirmwareUpdatePreparedPlanDeviceIdentity({
52447
51846
  preparedPlan: this.params.preparedPlan,
52448
51847
  deviceIdentity: serialNumber,
52449
- deviceModel: this.getProtocolV2PreparedPlanDeviceModel(this.device.features),
52450
51848
  });
52451
51849
  }
52452
- else if ((_b = this.params) === null || _b === void 0 ? void 0 : _b.expectedDeviceId) {
52453
- assertProtocolV2ReconnectIdentity((_c = this.params) === null || _c === void 0 ? void 0 : _c.expectedDeviceId, serialNumber);
51850
+ else if ((_d = this.params) === null || _d === void 0 ? void 0 : _d.expectedDeviceId) {
51851
+ assertProtocolV2ReconnectIdentity((_e = this.params) === null || _e === void 0 ? void 0 : _e.expectedDeviceId, serialNumber);
52454
51852
  }
52455
51853
  else {
52456
51854
  assertProtocolV2ReconnectIdentity(serialNumber, serialNumber, path, path);
@@ -52470,15 +51868,11 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52470
51868
  var _a;
52471
51869
  return (_a = this.params.bootloaderBinary) !== null && _a !== void 0 ? _a : null;
52472
51870
  }
52473
- getMissingProtocolV2FirmwareTargets(installItems) {
51871
+ hasExplicitProtocolV2Payload(fwBinaryMap) {
52474
51872
  var _a;
52475
- const preparedTargets = new Set(installItems.flatMap(item => {
52476
- const target = PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(item.targetId);
52477
- return target ? [target] : [];
52478
- }));
52479
- return ((_a = this.params.targetsToUpdate) !== null && _a !== void 0 ? _a : [])
52480
- .filter((target) => target !== 'resource' && target !== 'boot_resources')
52481
- .filter(target => !preparedTargets.has(target));
51873
+ return (!!((_a = this.params.resourceFiles) === null || _a === void 0 ? void 0 : _a.length) ||
51874
+ !!this.params.bootloaderBinary ||
51875
+ fwBinaryMap.length > 0);
52482
51876
  }
52483
51877
  buildProtocolV2InstallItems({ bootloaderBinary, fwBinaryMap, }) {
52484
51878
  const installItems = [];
@@ -52527,17 +51921,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52527
51921
  if (!component.url) {
52528
51922
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Missing Protocol V2 firmware component url: ${key}/${component.target}`);
52529
51923
  }
52530
- const expectedFingerprint = normalizeProtocolV2Hex(component.fingerprint);
52531
- if (!Number.isSafeInteger(component.expectedSize) ||
52532
- Number(component.expectedSize) <= 0 ||
52533
- !expectedFingerprint ||
52534
- !/^[0-9a-f]{64}$/u.test(expectedFingerprint)) {
52535
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 firmware component integrity metadata is invalid: ${key}/${component.target}`, { firmwareUpdateCode: 'FirmwarePlanInvalid' });
52536
- }
52537
51924
  const { binary } = yield getSysResourceBinary(component.url);
52538
- if (binary.byteLength !== component.expectedSize) {
52539
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 firmware size mismatch: ${key}/${component.target}`, { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52540
- }
52541
51925
  if (!isProtocolV2FirmwareFingerprintValid(binary, component.fingerprint)) {
52542
51926
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 firmware fingerprint mismatch: ${key}/${component.target}`);
52543
51927
  }
@@ -52551,7 +51935,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52551
51935
  return Object.assign(Object.assign({}, target), { binary });
52552
51936
  });
52553
51937
  }
52554
- prepareRemoteProtocolV2Binaries(firmwareType, features, explicitInstallItems = []) {
51938
+ prepareRemoteProtocolV2Binaries(firmwareType, features) {
52555
51939
  var _a, _b;
52556
51940
  return __awaiter(this, void 0, void 0, function* () {
52557
51941
  const release = DataManager.getFirmwareLatestRelease(features, firmwareType);
@@ -52559,10 +51943,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52559
51943
  const fwBinaryMap = [];
52560
51944
  const installItems = [];
52561
51945
  if (!release) {
52562
- const missingFirmwareTargets = this.getMissingProtocolV2FirmwareTargets(explicitInstallItems);
52563
- if (missingFirmwareTargets.length > 0) {
52564
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 firmware release is unavailable for requested targets: ${missingFirmwareTargets.join(', ')}`);
52565
- }
52566
51946
  return {
52567
51947
  bootloaderBinary,
52568
51948
  fwBinaryMap,
@@ -52571,8 +51951,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52571
51951
  }
52572
51952
  const entries = this.getRemoteComponentEntries(release);
52573
51953
  const targetsToUpdate = new Set((_a = this.params.targetsToUpdate) !== null && _a !== void 0 ? _a : []);
52574
- const explicitInstallItemByTargetId = new Map(explicitInstallItems.map(item => [item.targetId, item]));
52575
- const preparedTargets = new Set();
52576
51954
  for (const [key, component] of entries) {
52577
51955
  const targetName = (_b = component.target) === null || _b === void 0 ? void 0 : _b.toUpperCase();
52578
51956
  const target = PROTOCOL_V2_REMOTE_COMPONENT_TARGETS[targetName];
@@ -52580,27 +51958,27 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52580
51958
  ? PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(target.targetId)
52581
51959
  : undefined;
52582
51960
  if (updateTarget && targetsToUpdate.has(updateTarget)) {
52583
- const explicitInstallItem = explicitInstallItemByTargetId.get(target.targetId);
52584
- const installItem = explicitInstallItem !== null && explicitInstallItem !== void 0 ? explicitInstallItem : (yield this.downloadRemoteProtocolV2Component(key, component));
52585
- if (installItem.kind === 'bootloader') {
52586
- bootloaderBinary = installItem.binary;
51961
+ const remoteBinary = yield this.downloadRemoteProtocolV2Component(key, component);
51962
+ if (remoteBinary.kind === 'bootloader') {
51963
+ bootloaderBinary = remoteBinary.binary;
51964
+ installItems.push({
51965
+ fileName: remoteBinary.fileName,
51966
+ binary: remoteBinary.binary,
51967
+ targetId: remoteBinary.targetId,
51968
+ kind: remoteBinary.kind,
51969
+ });
52587
51970
  }
52588
51971
  else {
52589
51972
  const binaryEntry = {
52590
- fileName: installItem.fileName,
52591
- binary: installItem.binary,
52592
- targetId: installItem.targetId,
51973
+ fileName: remoteBinary.fileName,
51974
+ binary: remoteBinary.binary,
51975
+ targetId: remoteBinary.targetId,
52593
51976
  };
52594
51977
  fwBinaryMap.push(binaryEntry);
51978
+ installItems.push(Object.assign(Object.assign({}, binaryEntry), { kind: remoteBinary.kind }));
52595
51979
  }
52596
- installItems.push(Object.assign({}, installItem));
52597
- preparedTargets.add(updateTarget);
52598
51980
  }
52599
51981
  }
52600
- const missingTarget = Array.from(targetsToUpdate).find(target => target !== 'resource' && !preparedTargets.has(target));
52601
- if (missingTarget) {
52602
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 release does not contain requested target ${missingTarget}`);
52603
- }
52604
51982
  return {
52605
51983
  bootloaderBinary,
52606
51984
  fwBinaryMap,
@@ -52608,6 +51986,178 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52608
51986
  };
52609
51987
  });
52610
51988
  }
51989
+ getProtocolV2DeviceType() {
51990
+ const deviceType = this.device.getCurrentDeviceType();
51991
+ if (deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo)
51992
+ return deviceType;
51993
+ throw new Error(`Unsupported Protocol V2 device type: ${deviceType}`);
51994
+ }
51995
+ prepareProtocolV2BootResources() {
51996
+ var _a, _b, _c, _d, _e;
51997
+ return __awaiter(this, void 0, void 0, function* () {
51998
+ const wantsStableResources = !!((_a = this.params.targetsToUpdate) === null || _a === void 0 ? void 0 : _a.includes('resource'));
51999
+ const wantsBootResources = !!((_b = this.params.targetsToUpdate) === null || _b === void 0 ? void 0 : _b.includes('boot_resources'));
52000
+ if (!wantsStableResources && !wantsBootResources) {
52001
+ return undefined;
52002
+ }
52003
+ if ((_c = this.params.resourceFiles) === null || _c === void 0 ? void 0 : _c.length) {
52004
+ return undefined;
52005
+ }
52006
+ const resource = DataManager.getProtocolV2BootResources(this.getProtocolV2DeviceType());
52007
+ if (!resource) {
52008
+ if (wantsBootResources) {
52009
+ throw new Error('Missing Protocol V2 boot resources configuration');
52010
+ }
52011
+ Log$6.debug('[FirmwareUpdateV4] no boot resources configured; continue with stable resources');
52012
+ return undefined;
52013
+ }
52014
+ const files = [];
52015
+ for (const file of resource.files) {
52016
+ const isCurrent = !this.params.forcedUpdateRes && (yield this.isProtocolV2BootResourceCurrent(file));
52017
+ if (isCurrent) {
52018
+ Log$6.log(`[FirmwareUpdateV4] boot resource unchanged, skipping ${file.devicePath}`);
52019
+ }
52020
+ else {
52021
+ Log$6.log(`[FirmwareUpdateV4] downloading boot resource ${file.devicePath}`);
52022
+ const { binary } = yield getSysResourceBinary(file.url);
52023
+ if (!isProtocolV2ResourceFileValid(binary, file)) {
52024
+ throw new Error(`Boot resource file verification failed: ${file.devicePath}`);
52025
+ }
52026
+ files.push({
52027
+ name: (_e = (_d = file.name) !== null && _d !== void 0 ? _d : file.devicePath.split('/').pop()) !== null && _e !== void 0 ? _e : file.devicePath,
52028
+ binary,
52029
+ devicePath: file.devicePath,
52030
+ });
52031
+ }
52032
+ }
52033
+ return files;
52034
+ });
52035
+ }
52036
+ isProtocolV2BootResourceCurrent(file) {
52037
+ var _a, _b, _c, _d;
52038
+ return __awaiter(this, void 0, void 0, function* () {
52039
+ try {
52040
+ const commands = this.device.getCommands();
52041
+ const pathInfo = yield commands.typedCall('FilesystemPathInfoQuery', 'FilesystemPathInfo', { path: file.devicePath }, { timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT });
52042
+ const size = toProtocolV2FiniteNumber((_a = pathInfo.message) === null || _a === void 0 ? void 0 : _a.size);
52043
+ if (!((_b = pathInfo.message) === null || _b === void 0 ? void 0 : _b.exist) ||
52044
+ ((_c = pathInfo.message) === null || _c === void 0 ? void 0 : _c.directory) ||
52045
+ !Number.isSafeInteger(size) ||
52046
+ size !== file.size) {
52047
+ return false;
52048
+ }
52049
+ const digest = sha256.sha256.create();
52050
+ const chunkSize = this.getProtocolV2FirmwareChunkSize('write');
52051
+ let offset = 0;
52052
+ while (offset < file.size) {
52053
+ const response = yield commands.typedCall('FilesystemFileRead', 'FilesystemFile', {
52054
+ file: { path: file.devicePath, offset, total_size: 0 },
52055
+ chunk_len: Math.min(chunkSize, file.size - offset),
52056
+ }, { timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT });
52057
+ const data = toProtocolV2Bytes((_d = response.message) === null || _d === void 0 ? void 0 : _d.data);
52058
+ if (data.byteLength === 0)
52059
+ return false;
52060
+ const consumed = data.subarray(0, Math.min(data.byteLength, file.size - offset));
52061
+ digest.update(consumed);
52062
+ offset += consumed.byteLength;
52063
+ }
52064
+ return bytesToHex(digest.digest()) === normalizeProtocolV2Hex(file.fileHash);
52065
+ }
52066
+ catch (error) {
52067
+ Log$6.debug(`[FirmwareUpdateV4] unable to compare boot resource ${file.devicePath}; scheduling rewrite`, error);
52068
+ return false;
52069
+ }
52070
+ });
52071
+ }
52072
+ mergeProtocolV2ResourceBundles(...groups) {
52073
+ const merged = groups.flatMap(group => group !== null && group !== void 0 ? group : []);
52074
+ if (!merged.length)
52075
+ return undefined;
52076
+ const seenPaths = new Set();
52077
+ for (const bundle of merged) {
52078
+ if (seenPaths.has(bundle.devicePath)) {
52079
+ throw new Error(`Duplicate Protocol V2 resource devicePath: ${bundle.devicePath}`);
52080
+ }
52081
+ seenPaths.add(bundle.devicePath);
52082
+ }
52083
+ return merged;
52084
+ }
52085
+ prepareExplicitProtocolV2ResourceFiles() {
52086
+ var _a;
52087
+ const files = (_a = this.params.resourceFiles) !== null && _a !== void 0 ? _a : [];
52088
+ if (!(files === null || files === void 0 ? void 0 : files.length))
52089
+ return undefined;
52090
+ const prepared = files.map((file, index) => {
52091
+ var _a;
52092
+ const devicePath = validateProtocolV2FilesystemPath(file.devicePath, `resourceFiles[${index}].devicePath`);
52093
+ const descriptor = file;
52094
+ if (descriptor.size !== undefined && descriptor.size !== file.binary.byteLength) {
52095
+ throw new Error(`resourceFiles[${index}] size mismatch`);
52096
+ }
52097
+ if (descriptor.fileHash &&
52098
+ !isProtocolV2ResourceFileValid(file.binary, {
52099
+ size: file.binary.byteLength,
52100
+ fileHash: descriptor.fileHash,
52101
+ })) {
52102
+ throw new Error(`resourceFiles[${index}] SHA-256 mismatch`);
52103
+ }
52104
+ return {
52105
+ name: (_a = devicePath.split('/').pop()) !== null && _a !== void 0 ? _a : devicePath,
52106
+ binary: file.binary,
52107
+ devicePath,
52108
+ };
52109
+ });
52110
+ if (new Set(prepared.map(file => file.devicePath)).size !== prepared.length) {
52111
+ throw new Error('resourceFiles contain duplicate devicePath values');
52112
+ }
52113
+ return prepared;
52114
+ }
52115
+ prepareProtocolV2ResourceBundles() {
52116
+ var _a;
52117
+ return __awaiter(this, void 0, void 0, function* () {
52118
+ if (!((_a = this.params.targetsToUpdate) === null || _a === void 0 ? void 0 : _a.includes('resource'))) {
52119
+ return undefined;
52120
+ }
52121
+ const resources = DataManager.getProtocolV2Resources(this.getProtocolV2DeviceType());
52122
+ if (!(resources === null || resources === void 0 ? void 0 : resources.length)) {
52123
+ throw new Error('Missing Pro2 stable resource configuration');
52124
+ }
52125
+ const inventory = this.params.forcedUpdateRes
52126
+ ? undefined
52127
+ : yield readProtocolV2ResourceInventory({
52128
+ commands: this.device.getCommands(),
52129
+ resources,
52130
+ chunkSize: this.getProtocolV2FirmwareChunkSize('write'),
52131
+ timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT,
52132
+ });
52133
+ const plan = buildProtocolV2ResourceUpdatePlan({
52134
+ resources,
52135
+ inventory,
52136
+ mode: 'bootloader-recovery',
52137
+ forced: this.params.forcedUpdateRes,
52138
+ });
52139
+ Log$6.log(`[FirmwareUpdateV4] Protocol V2 resource plan mode=bootloader-recovery status=${plan.status} count=${plan.resources.length}`);
52140
+ const bundles = [];
52141
+ for (const resource of plan.resources) {
52142
+ bundles.push(yield this.downloadProtocolV2Resource(resource));
52143
+ }
52144
+ return bundles;
52145
+ });
52146
+ }
52147
+ downloadProtocolV2Resource(resource) {
52148
+ return __awaiter(this, void 0, void 0, function* () {
52149
+ Log$6.log(`[FirmwareUpdateV4] downloading Pro2 resource ${resource.type}`);
52150
+ const { binary } = yield getSysResourceBinary(resource.url);
52151
+ if (!isProtocolV2ResourceFileValid(binary, resource)) {
52152
+ throw new Error(`Pro2 resource file verification failed: ${resource.type}`);
52153
+ }
52154
+ return {
52155
+ name: `${resource.type}.okpkg`,
52156
+ binary,
52157
+ devicePath: PROTOCOL_V2_RESOURCE_DEVICE_PATHS[resource.type],
52158
+ };
52159
+ });
52160
+ }
52611
52161
  getProtocolV2ResourceFilePath(path) {
52612
52162
  if (path.startsWith('vol'))
52613
52163
  return path;
@@ -52615,7 +52165,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52615
52165
  return `vol0:${path}`;
52616
52166
  return `vol0:/${path}`;
52617
52167
  }
52618
- readProtocolV2DeviceFileHeader(path, expectedSize) {
52168
+ readProtocolV2DeviceFileHeader(path) {
52619
52169
  var _a, _b, _c, _d;
52620
52170
  return __awaiter(this, void 0, void 0, function* () {
52621
52171
  const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
@@ -52627,8 +52177,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52627
52177
  if (!((_b = pathInfoRes.message) === null || _b === void 0 ? void 0 : _b.exist) ||
52628
52178
  ((_c = pathInfoRes.message) === null || _c === void 0 ? void 0 : _c.directory) ||
52629
52179
  fileSize === undefined ||
52630
- fileSize < PROTOCOL_V2_OKPP_HEADER_SIZE ||
52631
- (expectedSize !== undefined && fileSize !== expectedSize)) {
52180
+ fileSize < PROTOCOL_V2_OKPP_HEADER_SIZE) {
52632
52181
  return null;
52633
52182
  }
52634
52183
  const chunkSize = this.getProtocolV2FirmwareChunkSize('read');
@@ -52665,10 +52214,10 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52665
52214
  return __awaiter(this, void 0, void 0, function* () {
52666
52215
  if ((_a = this.params) === null || _a === void 0 ? void 0 : _a.forcedUpdateRes)
52667
52216
  return false;
52668
- if (!bundle.payloadHash || !bundle.headerHash)
52217
+ if (!bundle.version && !bundle.payloadHash)
52669
52218
  return false;
52670
52219
  try {
52671
- const header = yield this.readProtocolV2DeviceFileHeader(bundle.devicePath, bundle.source.size);
52220
+ const header = yield this.readProtocolV2DeviceFileHeader(bundle.devicePath);
52672
52221
  if (!header)
52673
52222
  return false;
52674
52223
  if (bundle.version) {
@@ -52676,12 +52225,16 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52676
52225
  if (cmp === undefined || cmp !== 0)
52677
52226
  return false;
52678
52227
  }
52679
- const expectedPayloadHash = normalizeProtocolV2Hex(bundle.payloadHash);
52680
- const expectedHeaderHash = normalizeProtocolV2Hex(bundle.headerHash);
52681
- if (!expectedPayloadHash || header.payloadHash !== expectedPayloadHash)
52682
- return false;
52683
- if (!expectedHeaderHash || header.headerHash !== expectedHeaderHash)
52684
- return false;
52228
+ if (bundle.payloadHash) {
52229
+ const expected = normalizeProtocolV2Hex(bundle.payloadHash);
52230
+ if (expected && header.payloadHash !== expected)
52231
+ return false;
52232
+ }
52233
+ if (bundle.headerHash) {
52234
+ const expected = normalizeProtocolV2Hex(bundle.headerHash);
52235
+ if (expected && header.headerHash !== expected)
52236
+ return false;
52237
+ }
52685
52238
  return true;
52686
52239
  }
52687
52240
  catch (error) {
@@ -52796,6 +52349,13 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52796
52349
  }
52797
52350
  buildProtocolV2ExecutionPhases({ installSources, resourceSources, }) {
52798
52351
  const phases = [];
52352
+ if (resourceSources.length > 0) {
52353
+ phases.push({
52354
+ kind: 'resource-sync',
52355
+ installSources: [],
52356
+ resourceSources,
52357
+ });
52358
+ }
52799
52359
  const bootloaderSources = installSources.filter(source => source.kind === 'bootloader');
52800
52360
  if (bootloaderSources.length > 0) {
52801
52361
  phases.push({
@@ -52808,13 +52368,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52808
52368
  resourceSources: [],
52809
52369
  });
52810
52370
  }
52811
- if (resourceSources.length > 0) {
52812
- phases.push({
52813
- kind: 'resource-sync',
52814
- installSources: [],
52815
- resourceSources,
52816
- });
52817
- }
52818
52371
  const componentSources = installSources.filter(source => source.kind !== 'bootloader');
52819
52372
  if (componentSources.length > 0) {
52820
52373
  phases.push({
@@ -52865,7 +52418,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52865
52418
  });
52866
52419
  });
52867
52420
  }
52868
- executeProtocolV2Update({ fwBinaryMap, bootloaderBinary, installItems, }) {
52421
+ executeProtocolV2Update({ fwBinaryMap, bootloaderBinary, installItems, resourceBundles, }) {
52869
52422
  return __awaiter(this, void 0, void 0, function* () {
52870
52423
  const memoryInstallItems = installItems !== null && installItems !== void 0 ? installItems : this.buildProtocolV2InstallItems({
52871
52424
  fwBinaryMap: fwBinaryMap !== null && fwBinaryMap !== void 0 ? fwBinaryMap : [],
@@ -52880,9 +52433,16 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52880
52433
  kind: item.kind,
52881
52434
  });
52882
52435
  })));
52436
+ const resourceSources = yield Promise.all((resourceBundles !== null && resourceBundles !== void 0 ? resourceBundles : []).map((bundle) => __awaiter(this, void 0, void 0, function* () {
52437
+ return ({
52438
+ name: bundle.name,
52439
+ source: yield this.openProtocolV2MemorySource(bundle.binary),
52440
+ devicePath: bundle.devicePath,
52441
+ });
52442
+ })));
52883
52443
  return yield this.executeProtocolV2Phases({
52884
52444
  installSources,
52885
- resourceSources: [],
52445
+ resourceSources,
52886
52446
  });
52887
52447
  }
52888
52448
  finally {
@@ -52906,14 +52466,13 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52906
52466
  this.postTipMessage(exports.FirmwareUpdateTipMessage.StartTransferData);
52907
52467
  let processedSize = 0;
52908
52468
  for (const resource of resourcesToSync) {
52909
- const writePath = resolveProtocolV2ResourceWritePath(resource.devicePath);
52910
52469
  processedSize = yield this.protocolV2SourceUpdateProcess({
52911
52470
  source: resource.source,
52912
- filePath: writePath,
52471
+ filePath: resource.devicePath,
52913
52472
  processedSize,
52914
52473
  totalSize,
52915
52474
  });
52916
- yield this.verifyProtocolV2StagedFile(writePath, resource.source.size);
52475
+ yield this.verifyProtocolV2StagedFile(resource.devicePath, resource.source.size);
52917
52476
  }
52918
52477
  const stagedInstallTargets = [];
52919
52478
  for (const item of installSources) {
@@ -53903,7 +53462,7 @@ class DeviceUploadWallpaper extends BaseMethod {
53903
53462
  }
53904
53463
 
53905
53464
  const FILESYSTEM_PATH_INFO_QUERY_MESSAGE_TYPE = 60802;
53906
- const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE$1 = 60805;
53465
+ const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
53907
53466
  const FILESYSTEM_DIR_LIST_MESSAGE_TYPE = 60808;
53908
53467
  const NFT_UPDATE_MESSAGE_TYPE = 61500;
53909
53468
  class DeviceUploadNft extends BaseMethod {
@@ -53932,7 +53491,7 @@ class DeviceUploadNft extends BaseMethod {
53932
53491
  assertCapabilities() {
53933
53492
  return __awaiter(this, void 0, void 0, function* () {
53934
53493
  const protocolInfo = yield this.device.ensureProtocolV2RuntimeContext();
53935
- const hasFileWrite = supportsProtocolV2Message(protocolInfo, FILESYSTEM_FILE_WRITE_MESSAGE_TYPE$1);
53494
+ const hasFileWrite = supportsProtocolV2Message(protocolInfo, FILESYSTEM_FILE_WRITE_MESSAGE_TYPE);
53936
53495
  const hasPathInfo = supportsProtocolV2Message(protocolInfo, FILESYSTEM_PATH_INFO_QUERY_MESSAGE_TYPE);
53937
53496
  const hasDirList = supportsProtocolV2Message(protocolInfo, FILESYSTEM_DIR_LIST_MESSAGE_TYPE);
53938
53497
  const hasNftUpdate = supportsProtocolV2Message(protocolInfo, NFT_UPDATE_MESSAGE_TYPE);
@@ -54067,8 +53626,6 @@ class FileWrite extends BaseMethod {
54067
53626
 
54068
53627
  const PORTFOLIO_PENDING_PATH = 'vol1:/portfolio/portfolio.okpkg.pending';
54069
53628
  const PORTFOLIO_CHUNK_SIZE = 2048;
54070
- const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
54071
- const PORTFOLIO_UPDATE_MESSAGE_TYPE = 61400;
54072
53629
  class UploadPortfolio extends FileWrite {
54073
53630
  init() {
54074
53631
  const { packageBytes, timeoutMs } = this.payload;
@@ -54082,12 +53639,6 @@ class UploadPortfolio extends FileWrite {
54082
53639
  run: { get: () => super.run }
54083
53640
  });
54084
53641
  return __awaiter(this, void 0, void 0, function* () {
54085
- const protocolInfo = yield this.device.ensureProtocolV2RuntimeContext();
54086
- const hasFileWrite = supportsProtocolV2Message(protocolInfo, FILESYSTEM_FILE_WRITE_MESSAGE_TYPE);
54087
- const hasPortfolioUpdate = supportsProtocolV2Message(protocolInfo, PORTFOLIO_UPDATE_MESSAGE_TYPE);
54088
- if (!hasFileWrite || !hasPortfolioUpdate) {
54089
- throw hdShared.createDeviceNotSupportMethodError(this.name, this.device.getCurrentFirmwareType());
54090
- }
54091
53642
  const stagedFile = yield _super.run.call(this);
54092
53643
  this.throwIfAborted();
54093
53644
  yield this.device.commands.typedCall('PortfolioUpdate', 'Success', {});
@@ -65629,14 +65180,11 @@ exports.normalizeSafetyCheckLevel = normalizeSafetyCheckLevel;
65629
65180
  exports.normalizeVersionArray = normalizeVersionArray;
65630
65181
  exports.parseConnectSettings = parseConnectSettings;
65631
65182
  exports.parseMessage = parseMessage;
65632
- exports.parseProtocolV2ResourceManifest = parseProtocolV2ResourceManifest;
65633
65183
  exports.patchFeatures = patchFeatures;
65634
65184
  exports.preloadSessionCache = preloadSessionCache;
65635
- exports.prepareFirmwareUpdateV4MemoryHost = prepareFirmwareUpdateV4MemoryHost;
65636
65185
  exports.projectDeviceStateFeatures = projectFeatures;
65637
65186
  exports.registerFirmwareUpdateHostBinding = registerFirmwareUpdateHostBinding;
65638
65187
  exports.safeThrowError = safeThrowError;
65639
- exports.selectProtocolV2ResourceManifestFiles = selectProtocolV2ResourceManifestFiles;
65640
65188
  exports.setLoggerPostMessage = setLoggerPostMessage;
65641
65189
  exports.supportInputPinOnSoftware = supportInputPinOnSoftware;
65642
65190
  exports.switchTransport = switchTransport;