@onekeyfe/hd-core 1.2.0-alpha.96 → 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 -1313
  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 +7 -29
  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 -469
  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() {
@@ -50593,27 +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 hasLegacyInputs = [
50600
- payload.bleVersion,
50601
- payload.bleBinary,
50602
- payload.firmwareVersion,
50603
- payload.firmwareBinary,
50604
- payload.resourceBinary,
50605
- payload.bootloaderVersion,
50606
- payload.bootloaderBinary,
50607
- ].some(input => input !== undefined);
50608
- if (preparedPlan && hasLegacyInputs) {
50609
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Prepared firmware plans cannot be combined with legacy firmware inputs');
50610
- }
50611
- const artifactReader = preparedPlan
50612
- ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest).artifactReader
50613
- : payload.artifactReader;
50614
- if (preparedPlan) {
50426
+ if (hostBinding) {
50615
50427
  assertFirmwareUpdatePreparedPlanBinding({
50616
- preparedPlan,
50428
+ preparedPlan: payload.preparedPlan,
50617
50429
  executor: 'v3',
50618
50430
  platform: payload.platform,
50619
50431
  scopeTargets: ['bootloader', 'firmware', 'resource', 'ble'],
@@ -50651,7 +50463,7 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
50651
50463
  });
50652
50464
  }
50653
50465
  this.params = {
50654
- preparedPlan,
50466
+ preparedPlan: payload.preparedPlan,
50655
50467
  bleBinary: payload.bleBinary,
50656
50468
  firmwareBinary: payload.firmwareBinary,
50657
50469
  forcedUpdateRes: payload.forcedUpdateRes,
@@ -50660,9 +50472,9 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
50660
50472
  bootloaderBinary: payload.bootloaderBinary,
50661
50473
  firmwareVersion: payload.firmwareVersion,
50662
50474
  resourceBinary: payload.resourceBinary,
50663
- firmwareType: (_f = preparedPlan === null || preparedPlan === void 0 ? void 0 : preparedPlan.firmwareType) !== null && _f !== void 0 ? _f : payload.firmwareType,
50475
+ firmwareType: payload.firmwareType,
50664
50476
  platform: payload.platform,
50665
- artifactReader,
50477
+ artifactReader: (_f = hostBinding === null || hostBinding === void 0 ? void 0 : hostBinding.artifactReader) !== null && _f !== void 0 ? _f : payload.artifactReader,
50666
50478
  artifacts: payload.artifacts,
50667
50479
  };
50668
50480
  }
@@ -51278,88 +51090,6 @@ const INSTALLABLE_FIRMWARE_TARGET_IDS = new Set([
51278
51090
  ]);
51279
51091
  new Map(Object.entries(ProtocolV2FirmwareTargetType).flatMap(([key, value]) => INSTALLABLE_FIRMWARE_TARGET_IDS.has(value) ? [[key, value]] : []));
51280
51092
 
51281
- let memoryHostSequence = 0;
51282
- const createReference = (binary, prefix) => {
51283
- const digest = utils.bytesToHex(sha256.sha256(new Uint8Array(binary)));
51284
- return {
51285
- artifactRef: `fwmem:${prefix}:${digest.slice(0, 32)}`,
51286
- size: binary.byteLength,
51287
- sha256: digest,
51288
- };
51289
- };
51290
- function prepareFirmwareUpdateV4MemoryHost({ sdk, plan, artifacts, }) {
51291
- if (plan.executor !== 'v4') {
51292
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Firmware memory host only supports V4 plans');
51293
- }
51294
- memoryHostSequence += 1;
51295
- const hostId = `${Date.now()}:${memoryHostSequence}`;
51296
- const binaries = new Map();
51297
- const inputs = artifacts.map((input, artifactIndex) => {
51298
- var _a;
51299
- const artifactBinary = new Uint8Array(input.binary).slice();
51300
- const artifact = createReference(artifactBinary.buffer, `${hostId}:artifact:${artifactIndex}`);
51301
- binaries.set(artifact.artifactRef, artifactBinary);
51302
- const materializedEntries = (_a = input.materializedEntries) === null || _a === void 0 ? void 0 : _a.map((entry, entryIndex) => {
51303
- const entryBinary = new Uint8Array(entry.binary).slice();
51304
- const entryArtifact = createReference(entryBinary.buffer, `${hostId}:entry:${artifactIndex}:${entryIndex}`);
51305
- binaries.set(entryArtifact.artifactRef, entryBinary);
51306
- return {
51307
- entryName: entry.entryName,
51308
- artifact: entryArtifact,
51309
- };
51310
- });
51311
- return Object.assign({ artifactId: input.artifactId, artifact }, ((materializedEntries === null || materializedEntries === void 0 ? void 0 : materializedEntries.length) ? { materializedEntries } : {}));
51312
- });
51313
- const preparedPlan = sdk.prepareFirmwareUpdatePlan({
51314
- plan,
51315
- leaseRef: `fwmemlease:${hostId}`,
51316
- artifacts: inputs,
51317
- });
51318
- const readers = new Map();
51319
- let readerSequence = 0;
51320
- const artifactReader = {
51321
- open({ artifactRef }) {
51322
- const binary = binaries.get(artifactRef);
51323
- if (!binary) {
51324
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Firmware memory artifact is unavailable');
51325
- }
51326
- readerSequence += 1;
51327
- const readerId = `fwmemreader:${hostId}:${readerSequence}`;
51328
- readers.set(readerId, binary);
51329
- return Promise.resolve({ readerId, size: binary.byteLength });
51330
- },
51331
- read({ readerId, offset, length }) {
51332
- const binary = readers.get(readerId);
51333
- if (!binary || offset < 0 || length <= 0 || offset + length > binary.byteLength) {
51334
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Firmware memory artifact read is invalid');
51335
- }
51336
- const data = binary.slice(offset, offset + length).buffer;
51337
- return Promise.resolve({
51338
- data,
51339
- bytesRead: data.byteLength,
51340
- eof: offset + length === binary.byteLength,
51341
- });
51342
- },
51343
- close({ readerId }) {
51344
- readers.delete(readerId);
51345
- return Promise.resolve();
51346
- },
51347
- };
51348
- const hostBindingGeneration = sdk.registerFirmwareUpdateHostBinding({
51349
- artifactReader,
51350
- preparedPlanDigest: preparedPlan.preparedPlanDigest,
51351
- });
51352
- return {
51353
- preparedPlan,
51354
- hostBindingGeneration,
51355
- release: () => {
51356
- sdk.unregisterFirmwareUpdateHostBinding(hostBindingGeneration);
51357
- readers.clear();
51358
- binaries.clear();
51359
- },
51360
- };
51361
- }
51362
-
51363
51093
  const Log$6 = getLogger(exports.LoggerNames.Method);
51364
51094
  const SESSION_ERROR$1 = 'session not found';
51365
51095
  const PROTOCOL_V2_BOOTLOADER_RECONNECT_TIMEOUT = 90 * 1000;
@@ -51386,24 +51116,7 @@ const PROTOCOL_V2_OKPP_HEADER_SIZE = 0x52a0;
51386
51116
  const PROTOCOL_V2_OKPP_PAYLOAD_HASH_OFFSET = 0x200;
51387
51117
  const PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET = 0x240;
51388
51118
  const PROTOCOL_V2_OKPP_HASH_SIZE = 64;
51389
- const PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES = 1024 * 1024;
51390
- const PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT = 512;
51391
- const PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES = 256 * 1024 * 1024;
51392
51119
  const PROTOCOL_V2_NEO_UNSUPPORTED_TARGETS = new Set(['se03', 'se04']);
51393
- const getProtocolV2ZipEntrySizes = (entry) => {
51394
- var _a;
51395
- const { compressedSize, uncompressedSize } = (_a = entry._data) !== null && _a !== void 0 ? _a : {};
51396
- if (!Number.isSafeInteger(compressedSize) ||
51397
- Number(compressedSize) < 0 ||
51398
- !Number.isSafeInteger(uncompressedSize) ||
51399
- Number(uncompressedSize) <= 0) {
51400
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource ZIP entry size is invalid: ${entry.name}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
51401
- }
51402
- return {
51403
- compressedSize: Number(compressedSize),
51404
- uncompressedSize: Number(uncompressedSize),
51405
- };
51406
- };
51407
51120
  function assertProtocolV2FirmwareTargetsSupported(deviceType, params) {
51408
51121
  var _a;
51409
51122
  const unsupportedTargets = new Set(((_a = params.targetsToUpdate) !== null && _a !== void 0 ? _a : []).filter(target => PROTOCOL_V2_NEO_UNSUPPORTED_TARGETS.has(target)));
@@ -51474,14 +51187,6 @@ const PROTOCOL_V2_REMOTE_COMPONENT_TARGETS = {
51474
51187
  },
51475
51188
  };
51476
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}`));
51477
- const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH = 'vol0:/loaders/bootloader/boot_resource.okpkg';
51478
- const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH = `${PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH}.staging`;
51479
- const resolveProtocolV2ResourceWritePath = (devicePath) => {
51480
- const normalizedPath = devicePath.replace(/^vol0:(?!\/)/i, 'vol0:/').toLowerCase();
51481
- return normalizedPath === PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH
51482
- ? PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH
51483
- : devicePath;
51484
- };
51485
51190
  const PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID = new Map([
51486
51191
  [ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_BOOTLOADER, 'boot'],
51487
51192
  [ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P1, 'app_v1'],
@@ -51492,10 +51197,6 @@ const PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID = new Map([
51492
51197
  [ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE03, 'se03'],
51493
51198
  [ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_SE04, 'se04'],
51494
51199
  ]);
51495
- const PROTOCOL_V2_INSTALL_TARGET_BY_UPDATE_TARGET = new Map(Object.values(PROTOCOL_V2_REMOTE_COMPONENT_TARGETS).map(target => [
51496
- PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(target.targetId),
51497
- target,
51498
- ]));
51499
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.';
51500
51201
  const PROTOCOL_V2_TARGET_ID_BY_DECODED_NAME = new Map(Object.entries(ProtocolV2FirmwareTargetType).map(([key, value]) => [key, value]));
51501
51202
  const PROTOCOL_V2_TARGET_STATUS_BY_DECODED_NAME = new Map([
@@ -51660,7 +51361,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51660
51361
  return ['V2'];
51661
51362
  }
51662
51363
  init() {
51663
- var _a, _b;
51364
+ var _a, _b, _c;
51664
51365
  this.allowDeviceMode = [UI_REQUEST.BOOTLOADER, UI_REQUEST.NOT_INITIALIZE];
51665
51366
  this.requireDeviceMode = [];
51666
51367
  this.unlockPolicy = 'unlock-before-run';
@@ -51691,85 +51392,54 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51691
51392
  { name: 'se02Binary', type: 'buffer' },
51692
51393
  { name: 'se03Binary', type: 'buffer' },
51693
51394
  { name: 'se04Binary', type: 'buffer' },
51694
- { name: 'resourceArchiveBinary', type: 'buffer' },
51695
51395
  { name: 'firmwareType', type: 'string' },
51696
51396
  { name: 'targetsToUpdate', type: 'array', allowEmpty: true },
51697
51397
  { name: 'platform', type: 'string' },
51698
51398
  { name: 'expectedDeviceId', type: 'string' },
51399
+ { name: 'resourceFiles', type: 'array', allowEmpty: true },
51699
51400
  ]);
51700
51401
  if (payload.expectedDeviceId !== undefined &&
51701
51402
  (payload.expectedDeviceId.length === 0 || payload.expectedDeviceId.length > 160)) {
51702
51403
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Protocol V2 expected device identity is invalid');
51703
51404
  }
51704
- const preparedPlan = payload.preparedPlan
51705
- ? validateFirmwareUpdatePreparedPlan(payload.preparedPlan)
51405
+ const hostBinding = payload.preparedPlan || payload.componentArtifacts || payload.resourceBundleArtifacts
51406
+ ? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration)
51706
51407
  : undefined;
51707
- const hasLocalArtifacts = [
51708
- payload.bootloaderBinary,
51709
- payload.romloaderBinary,
51710
- payload.applicationP1Binary,
51711
- payload.applicationP2Binary,
51712
- payload.coprocessorBinary,
51713
- payload.se01Binary,
51714
- payload.se02Binary,
51715
- payload.se03Binary,
51716
- payload.se04Binary,
51717
- payload.resourceArchiveBinary,
51718
- ].some(Boolean);
51719
- if (preparedPlan && hasLocalArtifacts) {
51720
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Prepared firmware plans cannot be combined with legacy or local firmware inputs');
51721
- }
51722
- let { artifactReader } = payload;
51723
- if (preparedPlan) {
51724
- artifactReader = resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest).artifactReader;
51725
- }
51726
- else if (payload.hostBindingGeneration !== undefined) {
51727
- artifactReader = resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration).artifactReader;
51728
- }
51729
- if (preparedPlan) {
51408
+ if (hostBinding) {
51730
51409
  assertFirmwareUpdatePreparedPlanBinding({
51731
- preparedPlan,
51410
+ preparedPlan: payload.preparedPlan,
51732
51411
  executor: 'v4',
51733
51412
  platform: payload.platform,
51734
- scopeTargets: [],
51735
- 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
+ ],
51736
51439
  });
51737
- if (payload.componentArtifacts) {
51738
- const componentBindings = Object.entries(payload.componentArtifacts).flatMap(([target, artifact]) => artifact
51739
- ? [
51740
- {
51741
- target: target,
51742
- artifact: artifact,
51743
- },
51744
- ]
51745
- : []);
51746
- assertFirmwareUpdatePreparedPlanBinding({
51747
- preparedPlan,
51748
- executor: 'v4',
51749
- platform: payload.platform,
51750
- scopeTargets: componentBindings.map(binding => binding.target),
51751
- bindings: componentBindings,
51752
- });
51753
- }
51754
- }
51755
- const preparedExpectedTargetVersions = preparedPlan === null || preparedPlan === void 0 ? void 0 : preparedPlan.artifacts.reduce((result, artifact) => {
51756
- if (artifact.role === 'component' &&
51757
- artifact.target !== 'resource' &&
51758
- artifact.targetVersion &&
51759
- PROTOCOL_V2_INSTALL_TARGET_BY_UPDATE_TARGET.has(artifact.target)) {
51760
- result[artifact.target] = artifact.targetVersion;
51761
- }
51762
- return result;
51763
- }, {});
51764
- const localTargetsToUpdate = (_a = payload.targetsToUpdate) === null || _a === void 0 ? void 0 : _a.map((target) => target === 'boot_resources' ? 'resource' : target);
51765
- if (payload.resourceArchiveBinary &&
51766
- localTargetsToUpdate &&
51767
- !localTargetsToUpdate.includes('resource')) {
51768
- localTargetsToUpdate.push('resource');
51769
51440
  }
51770
- const resolvedLocalTargetsToUpdate = localTargetsToUpdate !== null && localTargetsToUpdate !== void 0 ? localTargetsToUpdate : (payload.resourceArchiveBinary ? ['resource'] : undefined);
51771
51441
  this.params = {
51772
- preparedPlan,
51442
+ preparedPlan: payload.preparedPlan,
51773
51443
  chunkSize: payload.chunkSize,
51774
51444
  forcedUpdateRes: payload.forcedUpdateRes,
51775
51445
  bootloaderBinary: payload.bootloaderBinary,
@@ -51781,18 +51451,15 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51781
51451
  se02Binary: payload.se02Binary,
51782
51452
  se03Binary: payload.se03Binary,
51783
51453
  se04Binary: payload.se04Binary,
51784
- resourceArchiveBinary: payload.resourceArchiveBinary,
51785
- firmwareType: (_b = preparedPlan === null || preparedPlan === void 0 ? void 0 : preparedPlan.firmwareType) !== null && _b !== void 0 ? _b : payload.firmwareType,
51786
- targetsToUpdate: preparedPlan
51787
- ? [...preparedPlan.targetsToUpdate]
51788
- : resolvedLocalTargetsToUpdate,
51789
- expectedTargetVersions: preparedPlan
51790
- ? preparedExpectedTargetVersions
51791
- : payload.expectedTargetVersions,
51454
+ resourceFiles: payload.resourceFiles,
51455
+ firmwareType: payload.firmwareType,
51456
+ targetsToUpdate: payload.targetsToUpdate,
51457
+ expectedTargetVersions: payload.expectedTargetVersions,
51792
51458
  platform: payload.platform,
51793
51459
  expectedDeviceId: payload.expectedDeviceId,
51794
- artifactReader,
51795
- 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,
51796
51463
  };
51797
51464
  }
51798
51465
  getProtocolV2FirmwareChunkSize(direction, filePath) {
@@ -51823,7 +51490,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51823
51490
  });
51824
51491
  }
51825
51492
  runProtocolV2() {
51826
- var _a, _b, _c, _d, _e, _f;
51493
+ var _a, _b, _c, _d, _e;
51827
51494
  return __awaiter(this, void 0, void 0, function* () {
51828
51495
  yield this.captureProtocolV2PhysicalIdentity();
51829
51496
  const deviceFeatures = yield this.getProtocolV2DeviceFeatures();
@@ -51835,80 +51502,85 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51835
51502
  const deviceFirmwareType = getFirmwareType(deviceFeatures);
51836
51503
  const firmwareType = (_a = this.params.firmwareType) !== null && _a !== void 0 ? _a : deviceFirmwareType;
51837
51504
  this.validateExpectedTargetVersions();
51838
- if (!this.params.preparedPlan &&
51839
- this.params.resourceArchiveBinary &&
51840
- ((_b = this.params.targetsToUpdate) === null || _b === void 0 ? void 0 : _b.includes('resource'))) {
51841
- const localMemoryHost = yield this.prepareProtocolV2LocalMemoryHost({
51842
- features: deviceFeatures,
51843
- firmwareType,
51844
- });
51845
- try {
51846
- return yield this.runProtocolV2PreparedArtifacts(deviceFeatures, firmwareType);
51847
- }
51848
- finally {
51849
- localMemoryHost.release();
51850
- }
51851
- }
51852
- const hasPreparedComponentArtifacts = Object.values((_c = this.params.componentArtifacts) !== null && _c !== void 0 ? _c : {}).some(Boolean);
51853
- 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)) {
51854
51507
  return this.runProtocolV2PreparedArtifacts(deviceFeatures, firmwareType);
51855
51508
  }
51856
- 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);
51857
51514
  let fwBinaryMap = [];
51858
51515
  let bootloaderBinary = null;
51859
51516
  let installItems;
51517
+ let resourceBundles;
51860
51518
  try {
51861
51519
  this.postTipMessage(exports.FirmwareUpdateTipMessage.StartDownloadFirmware);
51520
+ resourceBundles = this.prepareExplicitProtocolV2ResourceFiles();
51862
51521
  fwBinaryMap = this.collectExplicitTargetBinaries();
51863
51522
  bootloaderBinary = this.prepareBootloaderBinary();
51864
- const explicitInstallItems = this.buildProtocolV2InstallItems({
51865
- bootloaderBinary,
51866
- fwBinaryMap,
51867
- });
51868
- const missingFirmwareTargets = this.getMissingProtocolV2FirmwareTargets(explicitInstallItems);
51869
- const needsRemoteFirmware = ((_e = this.params.targetsToUpdate) === null || _e === void 0 ? void 0 : _e.length)
51870
- ? missingFirmwareTargets.length > 0
51871
- : explicitInstallItems.length === 0;
51872
- if (wantsResources) {
51873
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 resource archive must be provided through a local or external PreparedPlan', {
51874
- firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
51875
- });
51876
- }
51877
- if (needsRemoteFirmware &&
51523
+ const needsRemoteFirmware = !this.hasExplicitProtocolV2Payload(fwBinaryMap);
51524
+ if ((needsRemoteFirmware || needsRemoteResources || needsRemoteBootResources) &&
51878
51525
  (this.params.artifactReader ||
51879
51526
  DataManager.getSettings('firmwareManifestMode') === 'external-only')) {
51880
51527
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 firmware artifacts must be prepared by the external firmware host', {
51881
51528
  firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
51882
51529
  });
51883
51530
  }
51884
- if (needsRemoteFirmware) {
51885
- yield DataManager.forceReloadData();
51531
+ if (needsRemoteFirmware || needsRemoteResources || needsRemoteBootResources) {
51532
+ yield DataManager.forceReloadData({
51533
+ requireResources: needsRemoteResources || needsRemoteBootResources,
51534
+ });
51886
51535
  }
51887
51536
  if (needsRemoteFirmware) {
51888
- const remoteBinaries = yield this.prepareRemoteProtocolV2Binaries(firmwareType, deviceFeatures, explicitInstallItems);
51537
+ const remoteBinaries = yield this.prepareRemoteProtocolV2Binaries(firmwareType, deviceFeatures);
51889
51538
  bootloaderBinary = remoteBinaries.bootloaderBinary;
51890
51539
  fwBinaryMap = remoteBinaries.fwBinaryMap;
51891
51540
  installItems = remoteBinaries.installItems;
51892
51541
  }
51893
- 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
+ }
51894
51549
  }
51895
51550
  catch (err) {
51896
- if (typeof err === 'object' &&
51897
- err !== null &&
51898
- 'params' in err &&
51899
- ((_f = err.params) === null || _f === void 0 ? void 0 : _f.firmwareUpdateCode) === 'FirmwareArtifactsNotPrepared') {
51900
- throw err;
51901
- }
51902
51551
  if (err instanceof hdShared.HardwareError && err.errorCode === hdShared.HardwareErrorCode.NetworkError) {
51903
51552
  throw err;
51904
51553
  }
51905
51554
  throw normalizeFirmwarePreparationError(err);
51906
51555
  }
51907
- 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) {
51908
51561
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareUpdateDownloadFailed, 'No firmware to update');
51909
51562
  }
51910
- return this.executeProtocolV2Update(Object.assign({ fwBinaryMap,
51911
- 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)));
51912
51584
  });
51913
51585
  }
51914
51586
  openProtocolV2PreparedSource(artifact) {
@@ -51945,34 +51617,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51945
51617
  prepareProtocolV2InstallSources(firmwareType, features) {
51946
51618
  var _a, _b;
51947
51619
  return __awaiter(this, void 0, void 0, function* () {
51948
- if (this.params.preparedPlan) {
51949
- const requestedTargets = new Set(this.params.preparedPlan.targetsToUpdate.filter((target) => target !== 'resource'));
51950
- const installSources = [];
51951
- const preparedTargets = new Set();
51952
- for (const artifact of this.params.preparedPlan.artifacts) {
51953
- if (artifact.target !== 'resource') {
51954
- const target = artifact.target;
51955
- const installTarget = PROTOCOL_V2_INSTALL_TARGET_BY_UPDATE_TARGET.get(target);
51956
- if (!requestedTargets.has(target) ||
51957
- artifact.role !== 'component' ||
51958
- artifact.container !== 'raw' ||
51959
- !installTarget ||
51960
- preparedTargets.has(target)) {
51961
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 prepared component artifact is invalid: ${artifact.artifactId}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
51962
- }
51963
- installSources.push(Object.assign(Object.assign({}, installTarget), { source: yield this.openProtocolV2PreparedSource(artifact.artifact) }));
51964
- preparedTargets.add(target);
51965
- }
51966
- }
51967
- const missingTarget = Array.from(requestedTargets).find(target => !preparedTargets.has(target));
51968
- if (missingTarget) {
51969
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 ${missingTarget} artifact is not prepared`, {
51970
- firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
51971
- artifactName: missingTarget,
51972
- });
51973
- }
51974
- return installSources;
51975
- }
51976
51620
  const release = DataManager.getFirmwareLatestRelease(features, firmwareType);
51977
51621
  if (!release) {
51978
51622
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 firmware release is unavailable');
@@ -52003,278 +51647,39 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52003
51647
  return installSources;
52004
51648
  });
52005
51649
  }
52006
- prepareProtocolV2LocalMemoryHost({ features, firmwareType, }) {
52007
- var _a, _b;
52008
- return __awaiter(this, void 0, void 0, function* () {
52009
- const installItems = this.buildProtocolV2InstallItems({
52010
- bootloaderBinary: this.prepareBootloaderBinary(),
52011
- fwBinaryMap: this.collectExplicitTargetBinaries(),
52012
- });
52013
- const requestedComponentTargets = new Set(((_a = this.params.targetsToUpdate) !== null && _a !== void 0 ? _a : []).filter((target) => target !== 'resource' && target !== 'boot_resources'));
52014
- const localComponentTargets = new Set(installItems.flatMap(item => {
52015
- const target = PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(item.targetId);
52016
- return target ? [target] : [];
52017
- }));
52018
- const missingTarget = Array.from(requestedComponentTargets).find(target => !localComponentTargets.has(target));
52019
- if (missingTarget) {
52020
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local update has no binary for requested target ${missingTarget}`, {
52021
- firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
52022
- artifactName: missingTarget,
52023
- });
52024
- }
52025
- const planArtifacts = [];
52026
- const memoryArtifacts = [];
52027
- for (const item of installItems) {
52028
- const target = PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(item.targetId);
52029
- if (!target || item.binary.byteLength <= 0) {
52030
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local firmware artifact is invalid: ${item.fileName}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52031
- }
52032
- const artifactId = `component:${target}`;
52033
- planArtifacts.push(Object.assign({ artifactId,
52034
- 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])
52035
- ? { targetVersion: this.params.expectedTargetVersions[target] }
52036
- : {})));
52037
- memoryArtifacts.push({ artifactId, binary: item.binary });
52038
- }
52039
- const resourceArchive = yield this.prepareProtocolV2LocalResourceArchive(this.params.resourceArchiveBinary);
52040
- const resourceArtifactId = 'resource:archive';
52041
- planArtifacts.push({
52042
- artifactId: resourceArtifactId,
52043
- target: 'resource',
52044
- container: 'zip',
52045
- logicalName: 'protocol-v2-local-resource-archive',
52046
- expectedSize: resourceArchive.binary.byteLength,
52047
- expectedSha256: bytesToHex(sha256.sha256(new Uint8Array(resourceArchive.binary))),
52048
- });
52049
- memoryArtifacts.push({
52050
- artifactId: resourceArtifactId,
52051
- binary: resourceArchive.binary,
52052
- materializedEntries: resourceArchive.materializedEntries,
52053
- });
52054
- const plan = buildProtocolV2LocalFirmwareUpdatePlan({
52055
- features,
52056
- firmwareType,
52057
- platform: this.params.platform,
52058
- artifacts: planArtifacts,
52059
- });
52060
- let memoryHost;
52061
- try {
52062
- memoryHost = prepareFirmwareUpdateV4MemoryHost({
52063
- sdk: {
52064
- prepareFirmwareUpdatePlan,
52065
- registerFirmwareUpdateHostBinding,
52066
- unregisterFirmwareUpdateHostBinding,
52067
- },
52068
- plan,
52069
- artifacts: memoryArtifacts,
52070
- });
52071
- const preparedPlan = validateFirmwareUpdatePreparedPlan(memoryHost.preparedPlan);
52072
- assertFirmwareUpdatePreparedPlanBinding({
52073
- preparedPlan,
52074
- executor: 'v4',
52075
- platform: this.params.platform,
52076
- scopeTargets: [],
52077
- bindings: [],
52078
- });
52079
- assertFirmwareUpdatePreparedPlanDeviceIdentity({
52080
- preparedPlan,
52081
- deviceIdentity: this.protocolV2ExpectedSerialNumber,
52082
- deviceModel: this.getProtocolV2PreparedPlanDeviceModel(features),
52083
- });
52084
- const hostBinding = resolveFirmwareUpdateHostBinding(memoryHost.hostBindingGeneration, preparedPlan.preparedPlanDigest);
52085
- this.params.preparedPlan = preparedPlan;
52086
- this.params.targetsToUpdate = [...preparedPlan.targetsToUpdate];
52087
- this.params.artifactReader = hostBinding.artifactReader;
52088
- this.params.componentArtifacts = undefined;
52089
- return memoryHost;
52090
- }
52091
- catch (error) {
52092
- memoryHost === null || memoryHost === void 0 ? void 0 : memoryHost.release();
52093
- throw error;
52094
- }
52095
- });
52096
- }
52097
- prepareProtocolV2LocalResourceArchive(binary) {
52098
- var _a;
52099
- return __awaiter(this, void 0, void 0, function* () {
52100
- if (binary.byteLength <= 0 || binary.byteLength > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
52101
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP archive size is invalid', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52102
- }
52103
- const zip = yield JSZip__default["default"].loadAsync(binary);
52104
- const zipEntries = Object.values(zip.files);
52105
- if (zipEntries.some(entry => entry.unsafeOriginalName && entry.unsafeOriginalName !== entry.name)) {
52106
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP contains an unsafe entry path', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52107
- }
52108
- const entries = zipEntries.filter(entry => !entry.dir);
52109
- if (entries.length === 0 || entries.length > PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT + 1) {
52110
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP entry set is invalid', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52111
- }
52112
- let declaredUncompressedSize = 0;
52113
- let declaredCompressedSize = 0;
52114
- for (const entry of entries) {
52115
- const sizes = getProtocolV2ZipEntrySizes(entry);
52116
- declaredCompressedSize += sizes.compressedSize;
52117
- declaredUncompressedSize += sizes.uncompressedSize;
52118
- const entryLimit = entry.name === 'manifest.json'
52119
- ? PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES
52120
- : PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES;
52121
- if (sizes.uncompressedSize > entryLimit ||
52122
- declaredCompressedSize > binary.byteLength ||
52123
- declaredUncompressedSize >
52124
- PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES + PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES) {
52125
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP declared size exceeds the allowed limit', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52126
- }
52127
- }
52128
- const manifestEntry = zip.file('manifest.json');
52129
- if (!manifestEntry) {
52130
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP has no manifest.json', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52131
- }
52132
- const manifestBinary = yield manifestEntry.async('arraybuffer');
52133
- if (manifestBinary.byteLength <= 0 ||
52134
- manifestBinary.byteLength > PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES) {
52135
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource manifest size is invalid', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52136
- }
52137
- let manifestValue;
52138
- try {
52139
- manifestValue = JSON.parse(new TextDecoder().decode(manifestBinary));
52140
- }
52141
- catch (error) {
52142
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource manifest is invalid: ${String(error)}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52143
- }
52144
- const manifest = parseProtocolV2ResourceManifest(manifestValue);
52145
- const selectedFiles = selectProtocolV2ResourceManifestFiles({
52146
- manifest,
52147
- targetsToUpdate: (_a = this.params.targetsToUpdate) !== null && _a !== void 0 ? _a : [],
52148
- });
52149
- const expectedEntryNames = new Set([
52150
- 'manifest.json',
52151
- ...selectedFiles.map(file => file.archive_path),
52152
- ]);
52153
- if (entries.length !== expectedEntryNames.size ||
52154
- entries.some(entry => !expectedEntryNames.has(entry.name))) {
52155
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 local resource ZIP contains an unexpected entry', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52156
- }
52157
- let totalSize = 0;
52158
- const materializedEntries = [
52159
- { entryName: 'manifest.json', binary: manifestBinary },
52160
- ];
52161
- for (const file of selectedFiles) {
52162
- const entry = zip.file(file.archive_path);
52163
- if (!entry) {
52164
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource ZIP is missing ${file.archive_path}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52165
- }
52166
- const { uncompressedSize } = getProtocolV2ZipEntrySizes(entry);
52167
- totalSize += uncompressedSize;
52168
- if (uncompressedSize !== file.size || totalSize > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
52169
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource file declared size is invalid: ${file.archive_path}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52170
- }
52171
- const fileBinary = yield entry.async('arraybuffer');
52172
- const digest = bytesToHex(sha256.sha256(new Uint8Array(fileBinary)));
52173
- if (fileBinary.byteLength !== file.size || digest !== file.sha256.toLowerCase()) {
52174
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 local resource file does not match manifest: ${file.archive_path}`, { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52175
- }
52176
- materializedEntries.push({ entryName: file.archive_path, binary: fileBinary });
52177
- }
52178
- return { binary, materializedEntries };
52179
- });
52180
- }
52181
- prepareProtocolV2ResourceSources() {
52182
- var _a, _b;
51650
+ prepareProtocolV2ResourceSources(firmwareType, features) {
51651
+ var _a, _b, _c;
52183
51652
  return __awaiter(this, void 0, void 0, function* () {
52184
- 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;
52185
51655
  if (!resourceRequested) {
52186
51656
  return [];
52187
51657
  }
52188
- const archiveSources = yield this.prepareProtocolV2ResourceArchiveSources();
52189
- if (archiveSources) {
52190
- return archiveSources;
52191
- }
52192
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 resource archive is not prepared', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52193
- });
52194
- }
52195
- prepareProtocolV2ResourceArchiveSources() {
52196
- var _a, _b, _c, _d;
52197
- return __awaiter(this, void 0, void 0, function* () {
52198
- const archiveArtifacts = (_b = (_a = this.params.preparedPlan) === null || _a === void 0 ? void 0 : _a.artifacts.filter(artifact => artifact.role === 'resourceBundle' &&
52199
- artifact.target === 'resource' &&
52200
- artifact.container === 'zip')) !== null && _b !== void 0 ? _b : [];
52201
- if (archiveArtifacts.length === 0) {
52202
- return undefined;
52203
- }
52204
- if (archiveArtifacts.length !== 1) {
52205
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared plan must contain exactly one resource archive', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52206
- }
52207
- const archiveArtifact = archiveArtifacts[0];
52208
- const archiveSource = yield this.openProtocolV2PreparedSource(archiveArtifact.artifact);
52209
- if (archiveSource.size > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
52210
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive exceeds the total size limit', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52211
- }
52212
- let archiveBinary;
52213
- try {
52214
- archiveBinary = yield readFirmwareByteSourceFully(archiveSource);
52215
- }
52216
- finally {
52217
- yield archiveSource.close();
52218
- }
52219
- const archiveDigest = bytesToHex(sha256.sha256(new Uint8Array(archiveBinary)));
52220
- if (archiveDigest !== archiveArtifact.artifact.sha256.toLowerCase()) {
52221
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive does not match its approved receipt', { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52222
- }
52223
- const verifiedArchive = yield this.prepareProtocolV2LocalResourceArchive(archiveBinary);
52224
- const entries = (_c = archiveArtifact.materializedEntries) !== null && _c !== void 0 ? _c : [];
52225
- const entriesByName = new Map(entries.map(entry => [entry.entryName, entry]));
52226
- if (entries.length !== verifiedArchive.materializedEntries.length ||
52227
- verifiedArchive.materializedEntries.some(entry => {
52228
- const preparedEntry = entriesByName.get(entry.entryName);
52229
- const digest = bytesToHex(sha256.sha256(new Uint8Array(entry.binary)));
52230
- return (!preparedEntry ||
52231
- preparedEntry.artifact.size !== entry.binary.byteLength ||
52232
- preparedEntry.artifact.sha256.toLowerCase() !== digest);
52233
- })) {
52234
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource entries do not match the approved archive', { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52235
- }
52236
- const verifiedEntriesByName = new Map(verifiedArchive.materializedEntries.map(entry => [entry.entryName, entry.binary]));
52237
- const manifestBinary = verifiedEntriesByName.get('manifest.json');
52238
- if (!manifestBinary) {
52239
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive has no valid manifest.json', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52240
- }
52241
- let manifestValue;
52242
- try {
52243
- manifestValue = JSON.parse(new TextDecoder().decode(manifestBinary));
52244
- }
52245
- catch (error) {
52246
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 prepared resource manifest is invalid: ${String(error)}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52247
- }
52248
- const manifest = parseProtocolV2ResourceManifest(manifestValue);
52249
- const selectedFiles = selectProtocolV2ResourceManifestFiles({
52250
- manifest,
52251
- targetsToUpdate: (_d = this.params.targetsToUpdate) !== null && _d !== void 0 ? _d : [],
52252
- });
52253
- if (selectedFiles.length > PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT) {
52254
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive contains too many files', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
52255
- }
52256
- 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]));
52257
51661
  const sources = [];
52258
- for (const [index, file] of selectedFiles.entries()) {
52259
- const binary = verifiedEntriesByName.get(file.archive_path);
52260
- if (!binary || binary.byteLength !== file.size) {
52261
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 prepared resource file does not match manifest: ${file.archive_path}`, { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52262
- }
52263
- totalSize += binary.byteLength;
52264
- if (totalSize > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
52265
- 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
+ });
52266
51669
  }
52267
- const source = yield this.openProtocolV2MemorySource(binary);
52268
- const header = source.size >= PROTOCOL_V2_OKPP_HEADER_SIZE
52269
- ? parseProtocolV2OkppHeader(new Uint8Array(yield source.readAt(0, PROTOCOL_V2_OKPP_HEADER_SIZE)))
52270
- : null;
52271
- sources.push(Object.assign({ name: file.original_name || `resource-${index}`, source, devicePath: file.device_path }, (header
52272
- ? {
52273
- version: header.version,
52274
- payloadHash: header.payloadHash,
52275
- headerHash: header.headerHash,
52276
- }
52277
- : {})));
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}`);
52278
51683
  }
52279
51684
  return sources;
52280
51685
  });
@@ -52284,7 +51689,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52284
51689
  try {
52285
51690
  this.postTipMessage(exports.FirmwareUpdateTipMessage.StartDownloadFirmware);
52286
51691
  const installSources = yield this.prepareProtocolV2InstallSources(firmwareType, features);
52287
- const resourceSources = yield this.prepareProtocolV2ResourceSources();
51692
+ const resourceSources = yield this.prepareProtocolV2ResourceSources(firmwareType, features);
52288
51693
  if (installSources.length === 0 && resourceSources.length === 0) {
52289
51694
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareUpdateDownloadFailed, 'No firmware to update');
52290
51695
  }
@@ -52368,15 +51773,15 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52368
51773
  }
52369
51774
  }
52370
51775
  getProtocolV2RequestedTargets() {
52371
- var _a, _b, _c;
51776
+ var _a, _b, _c, _d;
52372
51777
  if ((_a = this.params.targetsToUpdate) === null || _a === void 0 ? void 0 : _a.length) {
52373
51778
  return [...new Set(this.params.targetsToUpdate)];
52374
51779
  }
52375
- if ((_b = this.params.preparedPlan) === null || _b === void 0 ? void 0 : _b.targetsToUpdate.length) {
52376
- return [...new Set(this.params.preparedPlan.targetsToUpdate)];
52377
- }
52378
51780
  const targets = new Set();
52379
- 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
+ }
52380
51785
  if (this.params.bootloaderBinary)
52381
51786
  targets.add('boot');
52382
51787
  if (this.params.applicationP1Binary)
@@ -52413,26 +51818,8 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52413
51818
  const serialNumber = (_b = (_a = deviceInfo.hw) === null || _a === void 0 ? void 0 : _a.serial_no) === null || _b === void 0 ? void 0 : _b.trim();
52414
51819
  return serialNumber || undefined;
52415
51820
  }
52416
- getProtocolV2PreparedPlanDeviceModel(features) {
52417
- const currentDeviceType = this.device.getCurrentDeviceType();
52418
- const featureDeviceType = features ? getDeviceType(features) : undefined;
52419
- const deviceType = currentDeviceType === hdShared.EDeviceType.Pro2 || currentDeviceType === hdShared.EDeviceType.Neo
52420
- ? currentDeviceType
52421
- : featureDeviceType;
52422
- return deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo
52423
- ? String(deviceType)
52424
- : undefined;
52425
- }
52426
- getProtocolV2ConnectionRoute() {
52427
- var _a, _b, _c, _d, _e;
52428
- const descriptor = this.device.originalDescriptor;
52429
- return (((_a = descriptor === null || descriptor === void 0 ? void 0 : descriptor.path) === null || _a === void 0 ? void 0 : _a.trim()) ||
52430
- ((_d = (_c = (_b = this.device).getConnectId) === null || _c === void 0 ? void 0 : _c.call(_b)) === null || _d === void 0 ? void 0 : _d.trim()) ||
52431
- ((_e = descriptor === null || descriptor === void 0 ? void 0 : descriptor.id) === null || _e === void 0 ? void 0 : _e.trim()) ||
52432
- undefined);
52433
- }
52434
51821
  assertProtocolV2DeviceInfoIdentity(deviceInfo) {
52435
- assertProtocolV2ReconnectIdentity(this.protocolV2ExpectedSerialNumber, this.getProtocolV2SerialNumber(deviceInfo), this.protocolV2ExpectedPath, this.getProtocolV2ConnectionRoute());
51822
+ assertProtocolV2ReconnectIdentity(this.protocolV2ExpectedSerialNumber, this.getProtocolV2SerialNumber(deviceInfo), this.protocolV2ExpectedPath, this.device.originalDescriptor.path);
52436
51823
  }
52437
51824
  getProtocolV2DeviceInfoTimeout() {
52438
51825
  var _a;
@@ -52449,20 +51836,19 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52449
51836
  });
52450
51837
  }
52451
51838
  captureProtocolV2PhysicalIdentity() {
52452
- var _a, _b, _c;
51839
+ var _a, _b, _c, _d, _e;
52453
51840
  return __awaiter(this, void 0, void 0, function* () {
52454
51841
  const deviceInfo = yield this.requestProtocolV2PhysicalIdentity();
52455
51842
  const serialNumber = this.getProtocolV2SerialNumber(deviceInfo);
52456
- const path = this.getProtocolV2ConnectionRoute();
52457
- 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) {
52458
51845
  assertFirmwareUpdatePreparedPlanDeviceIdentity({
52459
51846
  preparedPlan: this.params.preparedPlan,
52460
51847
  deviceIdentity: serialNumber,
52461
- deviceModel: this.getProtocolV2PreparedPlanDeviceModel(this.device.features),
52462
51848
  });
52463
51849
  }
52464
- else if ((_b = this.params) === null || _b === void 0 ? void 0 : _b.expectedDeviceId) {
52465
- 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);
52466
51852
  }
52467
51853
  else {
52468
51854
  assertProtocolV2ReconnectIdentity(serialNumber, serialNumber, path, path);
@@ -52482,15 +51868,11 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52482
51868
  var _a;
52483
51869
  return (_a = this.params.bootloaderBinary) !== null && _a !== void 0 ? _a : null;
52484
51870
  }
52485
- getMissingProtocolV2FirmwareTargets(installItems) {
51871
+ hasExplicitProtocolV2Payload(fwBinaryMap) {
52486
51872
  var _a;
52487
- const preparedTargets = new Set(installItems.flatMap(item => {
52488
- const target = PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(item.targetId);
52489
- return target ? [target] : [];
52490
- }));
52491
- return ((_a = this.params.targetsToUpdate) !== null && _a !== void 0 ? _a : [])
52492
- .filter((target) => target !== 'resource' && target !== 'boot_resources')
52493
- .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);
52494
51876
  }
52495
51877
  buildProtocolV2InstallItems({ bootloaderBinary, fwBinaryMap, }) {
52496
51878
  const installItems = [];
@@ -52539,17 +51921,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52539
51921
  if (!component.url) {
52540
51922
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Missing Protocol V2 firmware component url: ${key}/${component.target}`);
52541
51923
  }
52542
- const expectedFingerprint = normalizeProtocolV2Hex(component.fingerprint);
52543
- if (!Number.isSafeInteger(component.expectedSize) ||
52544
- Number(component.expectedSize) <= 0 ||
52545
- !expectedFingerprint ||
52546
- !/^[0-9a-f]{64}$/u.test(expectedFingerprint)) {
52547
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 firmware component integrity metadata is invalid: ${key}/${component.target}`, { firmwareUpdateCode: 'FirmwarePlanInvalid' });
52548
- }
52549
51924
  const { binary } = yield getSysResourceBinary(component.url);
52550
- if (binary.byteLength !== component.expectedSize) {
52551
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 firmware size mismatch: ${key}/${component.target}`, { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
52552
- }
52553
51925
  if (!isProtocolV2FirmwareFingerprintValid(binary, component.fingerprint)) {
52554
51926
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 firmware fingerprint mismatch: ${key}/${component.target}`);
52555
51927
  }
@@ -52563,7 +51935,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52563
51935
  return Object.assign(Object.assign({}, target), { binary });
52564
51936
  });
52565
51937
  }
52566
- prepareRemoteProtocolV2Binaries(firmwareType, features, explicitInstallItems = []) {
51938
+ prepareRemoteProtocolV2Binaries(firmwareType, features) {
52567
51939
  var _a, _b;
52568
51940
  return __awaiter(this, void 0, void 0, function* () {
52569
51941
  const release = DataManager.getFirmwareLatestRelease(features, firmwareType);
@@ -52571,10 +51943,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52571
51943
  const fwBinaryMap = [];
52572
51944
  const installItems = [];
52573
51945
  if (!release) {
52574
- const missingFirmwareTargets = this.getMissingProtocolV2FirmwareTargets(explicitInstallItems);
52575
- if (missingFirmwareTargets.length > 0) {
52576
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 firmware release is unavailable for requested targets: ${missingFirmwareTargets.join(', ')}`);
52577
- }
52578
51946
  return {
52579
51947
  bootloaderBinary,
52580
51948
  fwBinaryMap,
@@ -52583,8 +51951,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52583
51951
  }
52584
51952
  const entries = this.getRemoteComponentEntries(release);
52585
51953
  const targetsToUpdate = new Set((_a = this.params.targetsToUpdate) !== null && _a !== void 0 ? _a : []);
52586
- const explicitInstallItemByTargetId = new Map(explicitInstallItems.map(item => [item.targetId, item]));
52587
- const preparedTargets = new Set();
52588
51954
  for (const [key, component] of entries) {
52589
51955
  const targetName = (_b = component.target) === null || _b === void 0 ? void 0 : _b.toUpperCase();
52590
51956
  const target = PROTOCOL_V2_REMOTE_COMPONENT_TARGETS[targetName];
@@ -52592,27 +51958,27 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52592
51958
  ? PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(target.targetId)
52593
51959
  : undefined;
52594
51960
  if (updateTarget && targetsToUpdate.has(updateTarget)) {
52595
- const explicitInstallItem = explicitInstallItemByTargetId.get(target.targetId);
52596
- const installItem = explicitInstallItem !== null && explicitInstallItem !== void 0 ? explicitInstallItem : (yield this.downloadRemoteProtocolV2Component(key, component));
52597
- if (installItem.kind === 'bootloader') {
52598
- 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
+ });
52599
51970
  }
52600
51971
  else {
52601
51972
  const binaryEntry = {
52602
- fileName: installItem.fileName,
52603
- binary: installItem.binary,
52604
- targetId: installItem.targetId,
51973
+ fileName: remoteBinary.fileName,
51974
+ binary: remoteBinary.binary,
51975
+ targetId: remoteBinary.targetId,
52605
51976
  };
52606
51977
  fwBinaryMap.push(binaryEntry);
51978
+ installItems.push(Object.assign(Object.assign({}, binaryEntry), { kind: remoteBinary.kind }));
52607
51979
  }
52608
- installItems.push(Object.assign({}, installItem));
52609
- preparedTargets.add(updateTarget);
52610
51980
  }
52611
51981
  }
52612
- const missingTarget = Array.from(targetsToUpdate).find(target => target !== 'resource' && !preparedTargets.has(target));
52613
- if (missingTarget) {
52614
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 release does not contain requested target ${missingTarget}`);
52615
- }
52616
51982
  return {
52617
51983
  bootloaderBinary,
52618
51984
  fwBinaryMap,
@@ -52620,6 +51986,178 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52620
51986
  };
52621
51987
  });
52622
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
+ }
52623
52161
  getProtocolV2ResourceFilePath(path) {
52624
52162
  if (path.startsWith('vol'))
52625
52163
  return path;
@@ -52627,7 +52165,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52627
52165
  return `vol0:${path}`;
52628
52166
  return `vol0:/${path}`;
52629
52167
  }
52630
- readProtocolV2DeviceFileHeader(path, expectedSize) {
52168
+ readProtocolV2DeviceFileHeader(path) {
52631
52169
  var _a, _b, _c, _d;
52632
52170
  return __awaiter(this, void 0, void 0, function* () {
52633
52171
  const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
@@ -52639,8 +52177,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52639
52177
  if (!((_b = pathInfoRes.message) === null || _b === void 0 ? void 0 : _b.exist) ||
52640
52178
  ((_c = pathInfoRes.message) === null || _c === void 0 ? void 0 : _c.directory) ||
52641
52179
  fileSize === undefined ||
52642
- fileSize < PROTOCOL_V2_OKPP_HEADER_SIZE ||
52643
- (expectedSize !== undefined && fileSize !== expectedSize)) {
52180
+ fileSize < PROTOCOL_V2_OKPP_HEADER_SIZE) {
52644
52181
  return null;
52645
52182
  }
52646
52183
  const chunkSize = this.getProtocolV2FirmwareChunkSize('read');
@@ -52677,10 +52214,10 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52677
52214
  return __awaiter(this, void 0, void 0, function* () {
52678
52215
  if ((_a = this.params) === null || _a === void 0 ? void 0 : _a.forcedUpdateRes)
52679
52216
  return false;
52680
- if (!bundle.payloadHash || !bundle.headerHash)
52217
+ if (!bundle.version && !bundle.payloadHash)
52681
52218
  return false;
52682
52219
  try {
52683
- const header = yield this.readProtocolV2DeviceFileHeader(bundle.devicePath, bundle.source.size);
52220
+ const header = yield this.readProtocolV2DeviceFileHeader(bundle.devicePath);
52684
52221
  if (!header)
52685
52222
  return false;
52686
52223
  if (bundle.version) {
@@ -52688,12 +52225,16 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52688
52225
  if (cmp === undefined || cmp !== 0)
52689
52226
  return false;
52690
52227
  }
52691
- const expectedPayloadHash = normalizeProtocolV2Hex(bundle.payloadHash);
52692
- const expectedHeaderHash = normalizeProtocolV2Hex(bundle.headerHash);
52693
- if (!expectedPayloadHash || header.payloadHash !== expectedPayloadHash)
52694
- return false;
52695
- if (!expectedHeaderHash || header.headerHash !== expectedHeaderHash)
52696
- 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
+ }
52697
52238
  return true;
52698
52239
  }
52699
52240
  catch (error) {
@@ -52808,6 +52349,13 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52808
52349
  }
52809
52350
  buildProtocolV2ExecutionPhases({ installSources, resourceSources, }) {
52810
52351
  const phases = [];
52352
+ if (resourceSources.length > 0) {
52353
+ phases.push({
52354
+ kind: 'resource-sync',
52355
+ installSources: [],
52356
+ resourceSources,
52357
+ });
52358
+ }
52811
52359
  const bootloaderSources = installSources.filter(source => source.kind === 'bootloader');
52812
52360
  if (bootloaderSources.length > 0) {
52813
52361
  phases.push({
@@ -52820,13 +52368,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52820
52368
  resourceSources: [],
52821
52369
  });
52822
52370
  }
52823
- if (resourceSources.length > 0) {
52824
- phases.push({
52825
- kind: 'resource-sync',
52826
- installSources: [],
52827
- resourceSources,
52828
- });
52829
- }
52830
52371
  const componentSources = installSources.filter(source => source.kind !== 'bootloader');
52831
52372
  if (componentSources.length > 0) {
52832
52373
  phases.push({
@@ -52877,7 +52418,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52877
52418
  });
52878
52419
  });
52879
52420
  }
52880
- executeProtocolV2Update({ fwBinaryMap, bootloaderBinary, installItems, }) {
52421
+ executeProtocolV2Update({ fwBinaryMap, bootloaderBinary, installItems, resourceBundles, }) {
52881
52422
  return __awaiter(this, void 0, void 0, function* () {
52882
52423
  const memoryInstallItems = installItems !== null && installItems !== void 0 ? installItems : this.buildProtocolV2InstallItems({
52883
52424
  fwBinaryMap: fwBinaryMap !== null && fwBinaryMap !== void 0 ? fwBinaryMap : [],
@@ -52892,9 +52433,16 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52892
52433
  kind: item.kind,
52893
52434
  });
52894
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
+ })));
52895
52443
  return yield this.executeProtocolV2Phases({
52896
52444
  installSources,
52897
- resourceSources: [],
52445
+ resourceSources,
52898
52446
  });
52899
52447
  }
52900
52448
  finally {
@@ -52918,14 +52466,13 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52918
52466
  this.postTipMessage(exports.FirmwareUpdateTipMessage.StartTransferData);
52919
52467
  let processedSize = 0;
52920
52468
  for (const resource of resourcesToSync) {
52921
- const writePath = resolveProtocolV2ResourceWritePath(resource.devicePath);
52922
52469
  processedSize = yield this.protocolV2SourceUpdateProcess({
52923
52470
  source: resource.source,
52924
- filePath: writePath,
52471
+ filePath: resource.devicePath,
52925
52472
  processedSize,
52926
52473
  totalSize,
52927
52474
  });
52928
- yield this.verifyProtocolV2StagedFile(writePath, resource.source.size);
52475
+ yield this.verifyProtocolV2StagedFile(resource.devicePath, resource.source.size);
52929
52476
  }
52930
52477
  const stagedInstallTargets = [];
52931
52478
  for (const item of installSources) {
@@ -53915,7 +53462,7 @@ class DeviceUploadWallpaper extends BaseMethod {
53915
53462
  }
53916
53463
 
53917
53464
  const FILESYSTEM_PATH_INFO_QUERY_MESSAGE_TYPE = 60802;
53918
- const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE$1 = 60805;
53465
+ const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
53919
53466
  const FILESYSTEM_DIR_LIST_MESSAGE_TYPE = 60808;
53920
53467
  const NFT_UPDATE_MESSAGE_TYPE = 61500;
53921
53468
  class DeviceUploadNft extends BaseMethod {
@@ -53944,7 +53491,7 @@ class DeviceUploadNft extends BaseMethod {
53944
53491
  assertCapabilities() {
53945
53492
  return __awaiter(this, void 0, void 0, function* () {
53946
53493
  const protocolInfo = yield this.device.ensureProtocolV2RuntimeContext();
53947
- const hasFileWrite = supportsProtocolV2Message(protocolInfo, FILESYSTEM_FILE_WRITE_MESSAGE_TYPE$1);
53494
+ const hasFileWrite = supportsProtocolV2Message(protocolInfo, FILESYSTEM_FILE_WRITE_MESSAGE_TYPE);
53948
53495
  const hasPathInfo = supportsProtocolV2Message(protocolInfo, FILESYSTEM_PATH_INFO_QUERY_MESSAGE_TYPE);
53949
53496
  const hasDirList = supportsProtocolV2Message(protocolInfo, FILESYSTEM_DIR_LIST_MESSAGE_TYPE);
53950
53497
  const hasNftUpdate = supportsProtocolV2Message(protocolInfo, NFT_UPDATE_MESSAGE_TYPE);
@@ -54079,8 +53626,6 @@ class FileWrite extends BaseMethod {
54079
53626
 
54080
53627
  const PORTFOLIO_PENDING_PATH = 'vol1:/portfolio/portfolio.okpkg.pending';
54081
53628
  const PORTFOLIO_CHUNK_SIZE = 2048;
54082
- const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
54083
- const PORTFOLIO_UPDATE_MESSAGE_TYPE = 61400;
54084
53629
  class UploadPortfolio extends FileWrite {
54085
53630
  init() {
54086
53631
  const { packageBytes, timeoutMs } = this.payload;
@@ -54094,12 +53639,6 @@ class UploadPortfolio extends FileWrite {
54094
53639
  run: { get: () => super.run }
54095
53640
  });
54096
53641
  return __awaiter(this, void 0, void 0, function* () {
54097
- const protocolInfo = yield this.device.ensureProtocolV2RuntimeContext();
54098
- const hasFileWrite = supportsProtocolV2Message(protocolInfo, FILESYSTEM_FILE_WRITE_MESSAGE_TYPE);
54099
- const hasPortfolioUpdate = supportsProtocolV2Message(protocolInfo, PORTFOLIO_UPDATE_MESSAGE_TYPE);
54100
- if (!hasFileWrite || !hasPortfolioUpdate) {
54101
- throw hdShared.createDeviceNotSupportMethodError(this.name, this.device.getCurrentFirmwareType());
54102
- }
54103
53642
  const stagedFile = yield _super.run.call(this);
54104
53643
  this.throwIfAborted();
54105
53644
  yield this.device.commands.typedCall('PortfolioUpdate', 'Success', {});
@@ -65641,14 +65180,11 @@ exports.normalizeSafetyCheckLevel = normalizeSafetyCheckLevel;
65641
65180
  exports.normalizeVersionArray = normalizeVersionArray;
65642
65181
  exports.parseConnectSettings = parseConnectSettings;
65643
65182
  exports.parseMessage = parseMessage;
65644
- exports.parseProtocolV2ResourceManifest = parseProtocolV2ResourceManifest;
65645
65183
  exports.patchFeatures = patchFeatures;
65646
65184
  exports.preloadSessionCache = preloadSessionCache;
65647
- exports.prepareFirmwareUpdateV4MemoryHost = prepareFirmwareUpdateV4MemoryHost;
65648
65185
  exports.projectDeviceStateFeatures = projectFeatures;
65649
65186
  exports.registerFirmwareUpdateHostBinding = registerFirmwareUpdateHostBinding;
65650
65187
  exports.safeThrowError = safeThrowError;
65651
- exports.selectProtocolV2ResourceManifestFiles = selectProtocolV2ResourceManifestFiles;
65652
65188
  exports.setLoggerPostMessage = setLoggerPostMessage;
65653
65189
  exports.supportInputPinOnSoftware = supportInputPinOnSoftware;
65654
65190
  exports.switchTransport = switchTransport;