@onekeyfe/hd-core 1.2.0-alpha.84 → 1.2.0-alpha.86

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 (58) hide show
  1. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +69 -26
  2. package/__tests__/check-firmware-release-protocol-v2.test.ts +1 -2
  3. package/__tests__/firmware-memory-host.test.ts +108 -0
  4. package/__tests__/firmware-update/device-update-bootloader.test.ts +4 -1
  5. package/__tests__/firmware-update/firmware-host-binding.test.ts +9 -0
  6. package/__tests__/firmware-update/firmware-update-plan.test.ts +15 -70
  7. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +53 -1
  8. package/__tests__/protocol-v2-resources.test.ts +59 -39
  9. package/__tests__/protocol-v2.test.ts +255 -306
  10. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  11. package/dist/api/FirmwareUpdateV4.d.ts +1 -2
  12. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  13. package/dist/api/firmware/FirmwareHostBinding.d.ts +1 -1
  14. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -1
  15. package/dist/api/firmware/FirmwareMemoryHost.d.ts +27 -0
  16. package/dist/api/firmware/FirmwareMemoryHost.d.ts.map +1 -0
  17. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +3 -4
  18. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
  19. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -1
  20. package/dist/api/firmware/getBinary.d.ts +0 -1
  21. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  22. package/dist/data-manager/DataManager.d.ts +3 -1
  23. package/dist/data-manager/DataManager.d.ts.map +1 -1
  24. package/dist/index.d.ts +32 -70
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +450 -390
  27. package/dist/inject.d.ts.map +1 -1
  28. package/dist/protocols/protocol-v2/resources.d.ts +0 -17
  29. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
  30. package/dist/types/api/checkAllFirmwareRelease.d.ts +0 -1
  31. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  32. package/dist/types/api/export.d.ts +0 -1
  33. package/dist/types/api/export.d.ts.map +1 -1
  34. package/dist/types/api/firmwareUpdate.d.ts +1 -10
  35. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  36. package/dist/types/api/index.d.ts +0 -2
  37. package/dist/types/api/index.d.ts.map +1 -1
  38. package/dist/types/settings.d.ts +3 -15
  39. package/dist/types/settings.d.ts.map +1 -1
  40. package/package.json +4 -4
  41. package/src/api/CheckAllFirmwareRelease.ts +4 -13
  42. package/src/api/FirmwareUpdateV4.ts +166 -170
  43. package/src/api/firmware/FirmwareHostBinding.ts +16 -3
  44. package/src/api/firmware/FirmwareMemoryHost.ts +174 -0
  45. package/src/api/firmware/FirmwareUpdatePlan.ts +28 -48
  46. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +8 -1
  47. package/src/data-manager/DataManager.ts +33 -13
  48. package/src/index.ts +6 -1
  49. package/src/inject.ts +0 -2
  50. package/src/protocols/protocol-v2/resources.ts +0 -47
  51. package/src/types/api/checkAllFirmwareRelease.ts +0 -1
  52. package/src/types/api/export.ts +0 -4
  53. package/src/types/api/firmwareUpdate.ts +2 -15
  54. package/src/types/api/index.ts +0 -2
  55. package/src/types/settings.ts +3 -25
  56. package/dist/types/api/protocolV2ResourceManifest.d.ts +0 -17
  57. package/dist/types/api/protocolV2ResourceManifest.d.ts.map +0 -1
  58. package/src/types/api/protocolV2ResourceManifest.ts +0 -19
@@ -100,6 +100,12 @@ import {
100
100
  } from '../src/utils';
101
101
  import { getDeviceFirmwareVersion } from '../src/utils/deviceVersionUtils';
102
102
  import { openFirmwareByteSource } from '../src/api/firmware/FirmwareArtifactSource';
103
+ import {
104
+ registerFirmwareUpdateHostBinding,
105
+ unregisterFirmwareUpdateHostBinding,
106
+ } from '../src/api/firmware/FirmwareHostBinding';
107
+ import { prepareFirmwareUpdatePlan } from '../src/api/firmware/FirmwareUpdatePreparedPlan';
108
+ import { digestFirmwareUpdateContract } from '../src/api/firmware/FirmwareUpdatePlan';
103
109
  import {
104
110
  getPassphraseState,
105
111
  getPassphraseStateWithRefreshDeviceInfo,
@@ -5579,23 +5585,31 @@ describe('Protocol V2 firmware update targets', () => {
5579
5585
  .mockResolvedValue(undefined);
5580
5586
  (method as any).isProtocolV2ResourceBundleUpToDate = jest.fn().mockResolvedValue(false);
5581
5587
 
5582
- await (method as any).executeProtocolV2Update({
5583
- resourceBundles: [
5588
+ await (method as any).executeProtocolV2SourceUpdate({
5589
+ resourceSources: [
5584
5590
  {
5585
5591
  name: 'images.okpkg',
5586
- binary: new Uint8Array([1, 2]).buffer,
5592
+ source: {
5593
+ size: 2,
5594
+ readAt: jest.fn(),
5595
+ close: jest.fn(),
5596
+ },
5587
5597
  devicePath: 'vol0:/bundles/images/images.okpkg',
5588
5598
  version: [1, 2, 3],
5589
5599
  payloadHash: '11'.repeat(64),
5590
5600
  headerHash: '22'.repeat(64),
5591
5601
  },
5592
5602
  ],
5593
- bootloaderBinary: null,
5594
- fwBinaryMap: [
5603
+ installSources: [
5595
5604
  {
5596
5605
  fileName: 'application_p1.bin',
5597
- binary: new Uint8Array([3]).buffer,
5606
+ source: {
5607
+ size: 1,
5608
+ readAt: jest.fn(),
5609
+ close: jest.fn(),
5610
+ },
5598
5611
  targetId: 4,
5612
+ kind: 'firmware',
5599
5613
  },
5600
5614
  ],
5601
5615
  });
@@ -6101,56 +6115,218 @@ describe('Protocol V2 firmware update targets', () => {
6101
6115
  });
6102
6116
  });
6103
6117
 
6104
- test('rejects prepared RESC bundle paths before opening an artifact source', async () => {
6118
+ test('maps a prepared resource archive manifest to artifact-backed resource sources', async () => {
6105
6119
  const method = new FirmwareUpdateV4({
6106
6120
  id: 1,
6107
6121
  payload: {
6108
6122
  method: 'firmwareUpdateV4',
6109
6123
  },
6110
6124
  });
6111
- const openPreparedSource = jest.fn();
6125
+ const imagesBinary = createProtocolV2OkppBinary();
6126
+ const bootBinary = createProtocolV2OkppBinary({ payloadHashByte: 0x33 });
6127
+ const imagesSha256 = '1'.repeat(64);
6128
+ const bootSha256 = '2'.repeat(64);
6129
+ const manifest = {
6130
+ schema: 1,
6131
+ artifact_name: 'pro2-resource',
6132
+ release_name: 'test-release',
6133
+ variant: 'resource',
6134
+ commit: 'abc123',
6135
+ short_sha: 'abc123',
6136
+ timestamp_utc: '2026-08-09T00:00:00Z',
6137
+ core_version: '1.0.0',
6138
+ key_set: 'production',
6139
+ device_root: 'vol0:',
6140
+ restore_mode: 'bootloader_update',
6141
+ trees: [{ path: 'bundles', device: 'pro2' }],
6142
+ files: [
6143
+ {
6144
+ archive_path: 'bundles/images/images.okpkg',
6145
+ original_name: 'images.okpkg',
6146
+ device_path: 'vol0:/bundles/images/images.okpkg',
6147
+ size: imagesBinary.byteLength,
6148
+ sha256: imagesSha256,
6149
+ signed: true,
6150
+ sig_algo: 'ed25519',
6151
+ payload_version: '1.2.3',
6152
+ },
6153
+ {
6154
+ archive_path: 'loaders/bootloader/boot_resource.okpkg',
6155
+ original_name: 'boot_resource.okpkg',
6156
+ device_path: 'vol0:/loaders/bootloader/boot_resource.okpkg',
6157
+ size: bootBinary.byteLength,
6158
+ sha256: bootSha256,
6159
+ signed: true,
6160
+ sig_algo: 'ed25519',
6161
+ payload_version: '1.2.3',
6162
+ },
6163
+ ],
6164
+ };
6165
+ const manifestBinary = new TextEncoder().encode(JSON.stringify(manifest)).buffer;
6166
+ const artifacts = new Map([
6167
+ ['manifest', manifestBinary],
6168
+ ['images', imagesBinary],
6169
+ ['boot', bootBinary],
6170
+ ]);
6112
6171
  (method as any).params = {
6113
6172
  targetsToUpdate: ['resource'],
6114
- resourceBundleArtifacts: [
6173
+ preparedPlan: {
6174
+ artifacts: [
6175
+ {
6176
+ artifactId: 'resource:archive',
6177
+ role: 'resourceBundle',
6178
+ target: 'resource',
6179
+ container: 'zip',
6180
+ materializedEntries: [
6181
+ {
6182
+ entryName: 'manifest.json',
6183
+ artifact: {
6184
+ artifactRef: 'manifest',
6185
+ size: manifestBinary.byteLength,
6186
+ sha256: '0'.repeat(64),
6187
+ },
6188
+ },
6189
+ {
6190
+ entryName: 'bundles/images/images.okpkg',
6191
+ artifact: {
6192
+ artifactRef: 'images',
6193
+ size: imagesBinary.byteLength,
6194
+ sha256: imagesSha256,
6195
+ },
6196
+ },
6197
+ {
6198
+ entryName: 'loaders/bootloader/boot_resource.okpkg',
6199
+ artifact: {
6200
+ artifactRef: 'boot',
6201
+ size: bootBinary.byteLength,
6202
+ sha256: bootSha256,
6203
+ },
6204
+ },
6205
+ ],
6206
+ },
6207
+ ],
6208
+ },
6209
+ };
6210
+ (method as any).openProtocolV2PreparedSource = jest.fn(async artifact => {
6211
+ const binary = artifacts.get(artifact.artifactRef);
6212
+ if (!binary) throw new Error(`Unknown artifact: ${artifact.artifactRef}`);
6213
+ return openFirmwareByteSource({ binary });
6214
+ });
6215
+
6216
+ const sources = await (method as any).prepareProtocolV2ResourceArchiveSources();
6217
+
6218
+ expect(sources).toHaveLength(2);
6219
+ expect(sources).toEqual([
6220
+ expect.objectContaining({
6221
+ name: 'images.okpkg',
6222
+ devicePath: 'vol0:/bundles/images/images.okpkg',
6223
+ version: [1, 2, 3],
6224
+ }),
6225
+ expect.objectContaining({
6226
+ name: 'boot_resource.okpkg',
6227
+ devicePath: 'vol0:/loaders/bootloader/boot_resource.okpkg',
6228
+ version: [1, 2, 3],
6229
+ }),
6230
+ ]);
6231
+ await Promise.all(sources.map(source => source.source.close()));
6232
+ });
6233
+
6234
+ test('binds a prepared resource archive to the selected host generation', () => {
6235
+ const planWithoutDigest = {
6236
+ schemaVersion: 2 as const,
6237
+ executor: 'v4' as const,
6238
+ deviceIdentity: 'PRO2-SERIAL',
6239
+ deviceModel: 'pro2',
6240
+ firmwareType: EFirmwareType.Universal,
6241
+ platform: 'web' as const,
6242
+ targetsToUpdate: ['resource' as const],
6243
+ artifacts: [
6244
+ {
6245
+ artifactId: 'resource:archive',
6246
+ role: 'resourceBundle' as const,
6247
+ target: 'resource' as const,
6248
+ url: 'https://example.com/resource.zip',
6249
+ container: 'zip' as const,
6250
+ logicalName: 'protocol-v2-resource-archive',
6251
+ },
6252
+ ],
6253
+ };
6254
+ const plan = {
6255
+ ...planWithoutDigest,
6256
+ planDigest: digestFirmwareUpdateContract(planWithoutDigest),
6257
+ };
6258
+ const preparedPlan = prepareFirmwareUpdatePlan({
6259
+ plan,
6260
+ leaseRef: 'resource-archive-test',
6261
+ artifacts: [
6115
6262
  {
6116
- name: 'images',
6263
+ artifactId: 'resource:archive',
6117
6264
  artifact: {
6118
- artifactRef: `fw:${'a'.repeat(64)}`,
6119
- size: 1,
6265
+ artifactRef: 'resource-archive',
6266
+ size: 3,
6120
6267
  sha256: 'a'.repeat(64),
6121
6268
  },
6269
+ materializedEntries: [
6270
+ {
6271
+ entryName: 'manifest.json',
6272
+ artifact: {
6273
+ artifactRef: 'resource-manifest',
6274
+ size: 2,
6275
+ sha256: 'b'.repeat(64),
6276
+ },
6277
+ },
6278
+ ],
6122
6279
  },
6123
6280
  ],
6124
- };
6125
- (method as any).openProtocolV2PreparedSource = openPreparedSource;
6126
- const getFirmwareLatestReleaseSpy = jest
6127
- .spyOn(DataManager, 'getFirmwareLatestRelease')
6128
- .mockReturnValue({
6129
- required: false,
6130
- version: [1, 0, 0],
6131
- url: '',
6132
- resourceBundles: [
6133
- {
6134
- name: 'images',
6135
- url: 'https://example.com/images.okpkg',
6136
- devicePath: 'vol0:/resource/../images.okpkg',
6137
- },
6138
- ],
6139
- fingerprint: '',
6140
- changelog: {
6141
- 'zh-CN': '',
6142
- 'en-US': '',
6281
+ });
6282
+ const mismatchedHostBindingGeneration = registerFirmwareUpdateHostBinding({
6283
+ preparedPlanDigest: 'c'.repeat(64),
6284
+ artifactReader: {
6285
+ open: jest.fn(),
6286
+ read: jest.fn(),
6287
+ close: jest.fn(),
6288
+ },
6289
+ });
6290
+ try {
6291
+ const mismatchedMethod = new FirmwareUpdateV4({
6292
+ id: 1,
6293
+ payload: {
6294
+ method: 'firmwareUpdateV4',
6295
+ platform: 'web',
6296
+ targetsToUpdate: ['resource'],
6297
+ preparedPlan,
6298
+ hostBindingGeneration: mismatchedHostBindingGeneration,
6143
6299
  },
6144
6300
  });
6145
6301
 
6146
- await expect(
6147
- (method as any).prepareProtocolV2ResourceSources('universal', {
6148
- deviceType: 'pro2',
6149
- })
6150
- ).rejects.toThrow('resourceBundles[].devicePath');
6151
- expect(openPreparedSource).not.toHaveBeenCalled();
6302
+ expect(() => mismatchedMethod.init()).toThrow('does not match the prepared plan');
6303
+ } finally {
6304
+ unregisterFirmwareUpdateHostBinding(mismatchedHostBindingGeneration);
6305
+ }
6306
+ const hostBindingGeneration = registerFirmwareUpdateHostBinding({
6307
+ preparedPlanDigest: preparedPlan.preparedPlanDigest,
6308
+ artifactReader: {
6309
+ open: jest.fn(),
6310
+ read: jest.fn(),
6311
+ close: jest.fn(),
6312
+ },
6313
+ });
6314
+ try {
6315
+ const method = new FirmwareUpdateV4({
6316
+ id: 1,
6317
+ payload: {
6318
+ method: 'firmwareUpdateV4',
6319
+ platform: 'web',
6320
+ targetsToUpdate: ['resource'],
6321
+ preparedPlan,
6322
+ hostBindingGeneration,
6323
+ },
6324
+ });
6152
6325
 
6153
- getFirmwareLatestReleaseSpy.mockRestore();
6326
+ expect(() => method.init()).not.toThrow();
6327
+ } finally {
6328
+ unregisterFirmwareUpdateHostBinding(hostBindingGeneration);
6329
+ }
6154
6330
  });
6155
6331
 
6156
6332
  test('stops a remote update before reboot when the latest config cannot be refreshed', async () => {
@@ -6219,252 +6395,7 @@ describe('Protocol V2 firmware update targets', () => {
6219
6395
  });
6220
6396
  });
6221
6397
 
6222
- test('treats manual resource files as authoritative payload for resource', async () => {
6223
- const resourceBundle = createProtocolV2OkppBinary();
6224
- const method = new FirmwareUpdateV4({
6225
- id: 1,
6226
- payload: {
6227
- method: 'firmwareUpdateV4',
6228
- platform: 'web',
6229
- targetsToUpdate: ['resource'],
6230
- resourceFiles: [
6231
- {
6232
- binary: resourceBundle,
6233
- devicePath: ' VOL0:/resource/images/images.okpkg ',
6234
- },
6235
- ],
6236
- },
6237
- });
6238
- method.init();
6239
- (method as any).captureProtocolV2PhysicalIdentity = jest.fn().mockResolvedValue(undefined);
6240
- (method as any).device = stubDevice({
6241
- originalDescriptor: { protocolType: 'V2' },
6242
- features: { deviceType: 'pro2', firmwareVersion: '0.0.0', capabilities: [] },
6243
- });
6244
- (method as any).prepareRemoteProtocolV2Binaries = jest.fn();
6245
- (method as any).enterProtocolV2BootloaderMode = jest.fn().mockResolvedValue(true);
6246
- (method as any).executeProtocolV2Update = jest.fn().mockResolvedValue(undefined);
6247
- (method as any).exitProtocolV2BootloaderToNormal = jest.fn().mockResolvedValue(undefined);
6248
- (method as any).waitForProtocolV2FinalFeatures = jest.fn().mockResolvedValue({
6249
- bootloaderVersion: '1.0.0',
6250
- bleVersion: '0.0.0',
6251
- firmwareVersion: '1.0.0',
6252
- });
6253
- method.postTipMessage = jest.fn();
6254
-
6255
- await method.run();
6256
-
6257
- expect(forceReloadDataSpy).not.toHaveBeenCalled();
6258
- expect((method as any).prepareRemoteProtocolV2Binaries).not.toHaveBeenCalled();
6259
- expect((method as any).executeProtocolV2Update).toHaveBeenCalledWith(
6260
- expect.objectContaining({
6261
- resourceBundles: [
6262
- {
6263
- name: 'images.okpkg',
6264
- binary: resourceBundle,
6265
- devicePath: 'vol0:/resource/images/images.okpkg',
6266
- version: [1, 2, 3],
6267
- payloadHash: '11'.repeat(64),
6268
- headerHash: '22'.repeat(64),
6269
- },
6270
- ],
6271
- })
6272
- );
6273
- });
6274
-
6275
- test('downloads every missing firmware target when manifest resources are already prepared', async () => {
6276
- const resourceBundle = createProtocolV2OkppBinary();
6277
- const applicationBinary = new Uint8Array([7]).buffer;
6278
- const remoteBinaries = {
6279
- bootloaderBinary: null,
6280
- fwBinaryMap: [
6281
- {
6282
- fileName: 'application_p1.bin',
6283
- binary: applicationBinary,
6284
- targetId: 4,
6285
- },
6286
- ],
6287
- installItems: [
6288
- {
6289
- fileName: 'application_p1.bin',
6290
- binary: applicationBinary,
6291
- targetId: 4,
6292
- kind: 'firmware',
6293
- },
6294
- ],
6295
- };
6296
- const method = new FirmwareUpdateV4({
6297
- id: 1,
6298
- payload: {
6299
- method: 'firmwareUpdateV4',
6300
- platform: 'web',
6301
- targetsToUpdate: ['app_v1', 'resource'],
6302
- resourceFiles: [
6303
- {
6304
- binary: resourceBundle,
6305
- devicePath: 'vol0:/bundles/images/images.okpkg',
6306
- },
6307
- ],
6308
- },
6309
- });
6310
- method.init();
6311
- (method as any).captureProtocolV2PhysicalIdentity = jest.fn().mockResolvedValue(undefined);
6312
- (method as any).device = stubDevice({
6313
- originalDescriptor: { protocolType: 'V2' },
6314
- features: { deviceType: 'pro2', firmwareVersion: '0.0.0', capabilities: [] },
6315
- });
6316
- (method as any).prepareRemoteProtocolV2Binaries = jest.fn().mockResolvedValue(remoteBinaries);
6317
- (method as any).executeProtocolV2Update = jest.fn().mockResolvedValue(undefined);
6318
- method.postTipMessage = jest.fn();
6319
-
6320
- await method.run();
6321
-
6322
- expect(forceReloadDataSpy).toHaveBeenCalledTimes(1);
6323
- expect((method as any).prepareRemoteProtocolV2Binaries).toHaveBeenCalledWith(
6324
- 'universal',
6325
- expect.objectContaining({ deviceType: 'pro2' }),
6326
- []
6327
- );
6328
- expect((method as any).executeProtocolV2Update).toHaveBeenCalledWith({
6329
- bootloaderBinary: null,
6330
- fwBinaryMap: remoteBinaries.fwBinaryMap,
6331
- installItems: remoteBinaries.installItems,
6332
- resourceBundles: [
6333
- {
6334
- name: 'images.okpkg',
6335
- binary: resourceBundle,
6336
- devicePath: 'vol0:/bundles/images/images.okpkg',
6337
- version: [1, 2, 3],
6338
- payloadHash: '11'.repeat(64),
6339
- headerHash: '22'.repeat(64),
6340
- },
6341
- ],
6342
- });
6343
- });
6344
-
6345
- test('rejects a mixed resource plan when the requested firmware release is unavailable', async () => {
6346
- const resourceBundle = createProtocolV2OkppBinary();
6347
- const method = new FirmwareUpdateV4({
6348
- id: 1,
6349
- payload: {
6350
- method: 'firmwareUpdateV4',
6351
- platform: 'web',
6352
- targetsToUpdate: ['app_v1', 'resource'],
6353
- resourceFiles: [
6354
- {
6355
- binary: resourceBundle,
6356
- devicePath: 'vol0:/bundles/images/images.okpkg',
6357
- },
6358
- ],
6359
- },
6360
- });
6361
- method.init();
6362
- (method as any).captureProtocolV2PhysicalIdentity = jest.fn().mockResolvedValue(undefined);
6363
- (method as any).device = stubDevice({
6364
- originalDescriptor: { protocolType: 'V2' },
6365
- features: { deviceType: 'pro2', firmwareVersion: '0.0.0', capabilities: [] },
6366
- });
6367
- jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(undefined);
6368
- (method as any).executeProtocolV2Update = jest.fn();
6369
- method.postTipMessage = jest.fn();
6370
-
6371
- await expect(method.run()).rejects.toThrow(
6372
- 'Protocol V2 firmware release is unavailable for requested targets: app_v1'
6373
- );
6374
- expect((method as any).executeProtocolV2Update).not.toHaveBeenCalled();
6375
- });
6376
-
6377
- test('combines prepared firmware components with explicit manifest resource files', async () => {
6378
- const resourceBundle = createProtocolV2OkppBinary();
6379
- const method = new FirmwareUpdateV4({
6380
- id: 1,
6381
- payload: {
6382
- method: 'firmwareUpdateV4',
6383
- platform: 'web',
6384
- },
6385
- });
6386
- method.init();
6387
- (method as any).params = {
6388
- targetsToUpdate: ['app_v1', 'resource'],
6389
- resourceFiles: [
6390
- {
6391
- binary: resourceBundle,
6392
- devicePath: 'vol0:/bundles/images/images.okpkg',
6393
- },
6394
- ],
6395
- };
6396
- const firmwareSource = { size: 10 };
6397
- const resourceSource = { size: resourceBundle.byteLength };
6398
- (method as any).prepareProtocolV2InstallSources = jest.fn().mockResolvedValue([
6399
- {
6400
- fileName: 'application_p1.bin',
6401
- source: firmwareSource,
6402
- targetId: 4,
6403
- kind: 'firmware',
6404
- },
6405
- ]);
6406
- (method as any).prepareProtocolV2ResourceSources = jest.fn();
6407
- (method as any).openProtocolV2MemorySource = jest.fn().mockResolvedValue(resourceSource);
6408
- (method as any).executeProtocolV2SourceUpdate = jest.fn().mockResolvedValue(undefined);
6409
- (method as any).closeProtocolV2PreparedSources = jest.fn().mockResolvedValue(undefined);
6410
- method.postTipMessage = jest.fn();
6411
-
6412
- await (method as any).runProtocolV2PreparedArtifacts({ deviceType: 'pro2' }, 'universal');
6413
-
6414
- expect((method as any).prepareProtocolV2ResourceSources).not.toHaveBeenCalled();
6415
- expect((method as any).executeProtocolV2SourceUpdate).toHaveBeenCalledWith({
6416
- installSources: [
6417
- {
6418
- fileName: 'application_p1.bin',
6419
- source: firmwareSource,
6420
- targetId: 4,
6421
- kind: 'firmware',
6422
- },
6423
- ],
6424
- resourceSources: [
6425
- {
6426
- name: 'images.okpkg',
6427
- source: resourceSource,
6428
- devicePath: 'vol0:/bundles/images/images.okpkg',
6429
- version: [1, 2, 3],
6430
- payloadHash: '11'.repeat(64),
6431
- headerHash: '22'.repeat(64),
6432
- },
6433
- ],
6434
- });
6435
- });
6436
-
6437
- test('rejects manual RESC bundle paths before bootloader entry', async () => {
6438
- const method = new FirmwareUpdateV4({
6439
- id: 1,
6440
- payload: {
6441
- method: 'firmwareUpdateV4',
6442
- platform: 'web',
6443
- resourceFiles: [
6444
- {
6445
- binary: new Uint8Array([1, 2, 3]).buffer,
6446
- devicePath: 'vol2:/resource/images/images.okpkg',
6447
- },
6448
- ],
6449
- },
6450
- });
6451
- method.init();
6452
- (method as any).captureProtocolV2PhysicalIdentity = jest.fn().mockResolvedValue(undefined);
6453
-
6454
- (method as any).device = stubDevice({
6455
- originalDescriptor: { protocolType: 'V2' },
6456
- features: { deviceType: 'pro2', firmwareVersion: '0.0.0', capabilities: [] },
6457
- });
6458
- (method as any).prepareRemoteProtocolV2Binaries = jest.fn();
6459
- (method as any).enterProtocolV2BootloaderMode = jest.fn();
6460
- method.postTipMessage = jest.fn();
6461
-
6462
- await expect(method.run()).rejects.toThrow('resourceFiles[0].devicePath');
6463
- expect((method as any).prepareRemoteProtocolV2Binaries).not.toHaveBeenCalled();
6464
- expect((method as any).enterProtocolV2BootloaderMode).not.toHaveBeenCalled();
6465
- });
6466
-
6467
- test('syncs resource bundles without sending a firmware install request', async () => {
6398
+ test('syncs prepared resource sources without sending a firmware install request', async () => {
6468
6399
  const method = new FirmwareUpdateV4({
6469
6400
  id: 1,
6470
6401
  payload: {
@@ -6481,16 +6412,19 @@ describe('Protocol V2 firmware update targets', () => {
6481
6412
  (method as any).protocolV2StartFirmwareUpdate = jest.fn();
6482
6413
  (method as any).waitForProtocolV2FirmwareUpdateComplete = jest.fn();
6483
6414
 
6484
- await (method as any).executeProtocolV2Update({
6485
- resourceBundles: [
6415
+ await (method as any).executeProtocolV2SourceUpdate({
6416
+ installSources: [],
6417
+ resourceSources: [
6486
6418
  {
6487
6419
  name: 'images.okpkg',
6488
- binary: new Uint8Array([1, 2, 3]).buffer,
6420
+ source: {
6421
+ size: 3,
6422
+ readAt: jest.fn(),
6423
+ close: jest.fn(),
6424
+ },
6489
6425
  devicePath: 'vol0:/resource/images/images.okpkg',
6490
6426
  },
6491
6427
  ],
6492
- bootloaderBinary: null,
6493
- fwBinaryMap: [],
6494
6428
  });
6495
6429
 
6496
6430
  expect((method as any).protocolV2SourceUpdateProcess).toHaveBeenCalledTimes(1);
@@ -6520,16 +6454,19 @@ describe('Protocol V2 firmware update targets', () => {
6520
6454
  (method as any).completeProtocolV2FinalVerification = jest.fn().mockResolvedValue({});
6521
6455
  (method as any).verifyProtocolV2StagedFile = jest.fn().mockResolvedValue(undefined);
6522
6456
 
6523
- await (method as any).executeProtocolV2Update({
6524
- resourceBundles: [
6457
+ await (method as any).executeProtocolV2SourceUpdate({
6458
+ installSources: [],
6459
+ resourceSources: [
6525
6460
  {
6526
6461
  name: 'boot_resource.okpkg',
6527
- binary: new Uint8Array([1, 2, 3]).buffer,
6462
+ source: {
6463
+ size: 3,
6464
+ readAt: jest.fn(),
6465
+ close: jest.fn(),
6466
+ },
6528
6467
  devicePath: 'vol0:/loaders/bootloader/boot_resource.okpkg',
6529
6468
  },
6530
6469
  ],
6531
- bootloaderBinary: null,
6532
- fwBinaryMap: [],
6533
6470
  });
6534
6471
 
6535
6472
  const stagingPath = 'vol0:/loaders/bootloader/boot_resource.okpkg.staging';
@@ -7411,27 +7348,39 @@ describe('Protocol V2 firmware reconnect identity', () => {
7411
7348
  expect((method as any).protocolV2SourceUpdateProcess).not.toHaveBeenCalled();
7412
7349
  });
7413
7350
 
7414
- test('rejects a manually supplied resource file when its manifest hash does not match', () => {
7351
+ test('updates a resource when the installed file size differs despite matching headers', async () => {
7415
7352
  const method = new FirmwareUpdateV4({
7416
7353
  id: 1,
7417
7354
  payload: {
7418
7355
  method: 'firmwareUpdateV4',
7419
7356
  platform: 'web',
7420
- resourceFiles: [
7421
- {
7422
- binary: new Uint8Array([1, 2, 3]).buffer,
7423
- devicePath: 'vol0:/assets/loaders/boot.staging/graphics/bootloader_crest.bin',
7424
- size: 3,
7425
- fileHash: '00'.repeat(32),
7426
- },
7427
- ],
7428
7357
  },
7429
7358
  });
7430
7359
  method.init();
7360
+ const installedBinary = new Uint8Array(createProtocolV2OkppBinary());
7361
+ const typedCall = jest.fn((requestType: string) => {
7362
+ if (requestType === 'FilesystemPathInfoQuery') {
7363
+ return Promise.resolve({
7364
+ message: { exist: true, directory: false, size: installedBinary.byteLength + 1 },
7365
+ });
7366
+ }
7367
+ throw new Error(`Unexpected request: ${requestType}`);
7368
+ });
7369
+ (method as any).device = stubDevice({
7370
+ getCommands: () => ({ typedCall }),
7371
+ });
7431
7372
 
7432
- expect(() => (method as any).prepareExplicitProtocolV2ResourceFiles()).toThrow(
7433
- 'SHA-256 mismatch'
7434
- );
7373
+ await expect(
7374
+ (method as any).isProtocolV2ResourceBundleUpToDate({
7375
+ name: 'images.okpkg',
7376
+ source: { size: installedBinary.byteLength },
7377
+ devicePath: 'vol0:/bundles/images/images.okpkg',
7378
+ version: [1, 2, 3],
7379
+ payloadHash: '11'.repeat(64),
7380
+ headerHash: '22'.repeat(64),
7381
+ })
7382
+ ).resolves.toBe(false);
7383
+ expect(typedCall).toHaveBeenCalledTimes(1);
7435
7384
  });
7436
7385
  });
7437
7386
 
@@ -1 +1 @@
1
- {"version":3,"file":"CheckAllFirmwareRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckAllFirmwareRelease.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAiC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EACV,kBAAkB,EAElB,kCAAkC,EAClC,+BAA+B,EAChC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EAGrB,MAAM,UAAU,CAAC;AAgIlB,MAAM,MAAM,6BAA6B,GAAG;IAC1C,YAAY,EAAE,aAAa,CAAC;IAC5B,MAAM,EAAE,+BAA+B,CAAC;IACxC,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,mBAAmB,CAAC;IACrC,UAAU,EAAE,kCAAkC,EAAE,CAAC;IACjD,eAAe,EAAE,sBAAsB,EAAE,CAAC;IAC1C,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF,wBAAgB,8BAA8B,CAAC,EAC7C,eAAe,EACf,mBAAwB,EACxB,iBAAyB,EACzB,mBAAwB,EACxB,YAAY,EACZ,OAAO,EACP,UAAU,GACX,EAAE;IACD,eAAe,EAAE,mBAAmB,CAAC;IACrC,mBAAmB,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACpD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IAC9D,YAAY,EAAE,aAAa,CAAC;IAC5B,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC7B,GAAG,6BAA6B,CAiFhC;AAID,MAAM,CAAC,OAAO,OAAO,uBAAwB,SAAQ,UAAU;IAC7D,qBAAqB;IAIrB,IAAI;IAME,GAAG;YAuFK,aAAa;CAmI5B"}
1
+ {"version":3,"file":"CheckAllFirmwareRelease.d.ts","sourceRoot":"","sources":["../../src/api/CheckAllFirmwareRelease.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAiC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EACV,kBAAkB,EAElB,kCAAkC,EAClC,+BAA+B,EAChC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EAGrB,MAAM,UAAU,CAAC;AAgIlB,MAAM,MAAM,6BAA6B,GAAG;IAC1C,YAAY,EAAE,aAAa,CAAC;IAC5B,MAAM,EAAE,+BAA+B,CAAC;IACxC,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,mBAAmB,CAAC;IACrC,UAAU,EAAE,kCAAkC,EAAE,CAAC;IACjD,eAAe,EAAE,sBAAsB,EAAE,CAAC;IAC1C,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF,wBAAgB,8BAA8B,CAAC,EAC7C,eAAe,EACf,mBAAwB,EACxB,iBAAyB,EACzB,mBAAwB,EACxB,YAAY,EACZ,OAAO,EACP,UAAU,GACX,EAAE;IACD,eAAe,EAAE,mBAAmB,CAAC;IACrC,mBAAmB,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACpD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IAC9D,YAAY,EAAE,aAAa,CAAC;IAC5B,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC7B,GAAG,6BAA6B,CAiFhC;AAID,MAAM,CAAC,OAAO,OAAO,uBAAwB,SAAQ,UAAU;IAC7D,qBAAqB;IAIrB,IAAI;IAME,GAAG;YAuFK,aAAa;CA0H5B"}
@@ -26,6 +26,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
26
26
  private closeProtocolV2PreparedSources;
27
27
  private prepareProtocolV2InstallSources;
28
28
  private prepareProtocolV2ResourceSources;
29
+ private prepareProtocolV2ResourceArchiveSources;
29
30
  private runProtocolV2PreparedArtifacts;
30
31
  private validateExpectedTargetVersions;
31
32
  private getExpectedProtocolV2TargetVersion;
@@ -39,14 +40,12 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
39
40
  private captureProtocolV2PhysicalIdentity;
40
41
  private verifyProtocolV2ReconnectIdentity;
41
42
  private prepareBootloaderBinary;
42
- private hasExplicitProtocolV2Payload;
43
43
  private getMissingProtocolV2FirmwareTargets;
44
44
  private buildProtocolV2InstallItems;
45
45
  private getRemoteComponentEntries;
46
46
  private getRemoteComponentTarget;
47
47
  private downloadRemoteProtocolV2Component;
48
48
  private prepareRemoteProtocolV2Binaries;
49
- private prepareExplicitProtocolV2ResourceFiles;
50
49
  private getProtocolV2ResourceFilePath;
51
50
  private readProtocolV2DeviceFileHeader;
52
51
  private isProtocolV2ResourceBundleUpToDate;