@onekeyfe/hd-core 1.2.0-alpha.82 → 1.2.0-alpha.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/check-all-firmware-release-protocol-v2.test.ts +266 -0
- package/__tests__/check-firmware-release-protocol-v2.test.ts +6 -0
- package/__tests__/protocol-v2.test.ts +5 -2
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +33 -0
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
- package/dist/api/firmware/protocolV2Release.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +149 -29
- package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -0
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/CheckAllFirmwareRelease.ts +76 -5
- package/src/api/firmware/FirmwareUpdatePlan.ts +154 -37
- package/src/api/firmware/protocolV2Release.ts +2 -0
- package/src/types/api/checkAllFirmwareRelease.ts +1 -0
- package/src/utils/deviceFeaturesUtils.ts +2 -2
|
@@ -333,6 +333,15 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
333
333
|
resourceArchive: resourceSource,
|
|
334
334
|
resourcePreparationRequired: true,
|
|
335
335
|
targetsToUpdate: ['boot', 'app_v1', 'resource'],
|
|
336
|
+
firmwareUpdatePlan: {
|
|
337
|
+
executor: 'v4',
|
|
338
|
+
platform: 'web',
|
|
339
|
+
artifacts: [
|
|
340
|
+
{ artifactId: 'component:boot', target: 'boot' },
|
|
341
|
+
{ artifactId: 'component:app_v1', target: 'app_v1' },
|
|
342
|
+
],
|
|
343
|
+
targetsToUpdate: ['boot', 'app_v1'],
|
|
344
|
+
},
|
|
336
345
|
firmware: {
|
|
337
346
|
status: 'required',
|
|
338
347
|
},
|
|
@@ -344,6 +353,260 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
344
353
|
expect(method.getSupportedProtocols()).toEqual(['V1', 'V2']);
|
|
345
354
|
});
|
|
346
355
|
|
|
356
|
+
test('preserves platform and forced firmware targets in the Protocol V2 prepared plan', async () => {
|
|
357
|
+
const method = new CheckAllFirmwareRelease({
|
|
358
|
+
id: 1,
|
|
359
|
+
payload: {
|
|
360
|
+
method: 'checkAllFirmwareRelease',
|
|
361
|
+
firmwareType: EFirmwareType.Universal,
|
|
362
|
+
platform: 'native',
|
|
363
|
+
forceUpdateTargets: ['firmware'],
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
method.init();
|
|
367
|
+
method.device = {
|
|
368
|
+
isProtocolV2: () => true,
|
|
369
|
+
features: {
|
|
370
|
+
deviceType: 'pro2',
|
|
371
|
+
serialNo: 'pro2-device-id',
|
|
372
|
+
firmwareVersion: '1.0.0',
|
|
373
|
+
},
|
|
374
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
375
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
376
|
+
status: { mode: 'normal' },
|
|
377
|
+
versions: currentVersions,
|
|
378
|
+
}),
|
|
379
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
380
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
|
|
381
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
382
|
+
|
|
383
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
384
|
+
targetsToUpdate: ['boot', 'app_v1', 'se02', 'se03', 'resource'],
|
|
385
|
+
firmwareUpdatePlan: {
|
|
386
|
+
executor: 'v4',
|
|
387
|
+
deviceIdentity: 'pro2-device-id',
|
|
388
|
+
platform: 'native',
|
|
389
|
+
artifacts: [
|
|
390
|
+
{ artifactId: 'component:boot', target: 'boot' },
|
|
391
|
+
{ artifactId: 'component:app_v1', target: 'app_v1' },
|
|
392
|
+
{ artifactId: 'component:se02', target: 'se02' },
|
|
393
|
+
{ artifactId: 'component:se03', target: 'se03' },
|
|
394
|
+
],
|
|
395
|
+
targetsToUpdate: ['boot', 'app_v1', 'se02', 'se03'],
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
test('includes exact Protocol V2 developer force targets in the prepared plan', async () => {
|
|
401
|
+
const currentRelease: IFirmwareReleaseInfo = {
|
|
402
|
+
...release,
|
|
403
|
+
required: false,
|
|
404
|
+
version: [1, 0, 0],
|
|
405
|
+
installOrder: ['applicationP1', 'coprocessor'],
|
|
406
|
+
components: {
|
|
407
|
+
applicationP1: {
|
|
408
|
+
target: 'APPLICATION_P1',
|
|
409
|
+
url: 'https://example.com/application-p1.okpkg',
|
|
410
|
+
version: [1, 0, 0],
|
|
411
|
+
},
|
|
412
|
+
coprocessor: {
|
|
413
|
+
target: 'COPROCESSOR',
|
|
414
|
+
url: 'https://example.com/coprocessor.okpkg',
|
|
415
|
+
version: [1, 0, 0],
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
};
|
|
419
|
+
const method = new CheckAllFirmwareRelease({
|
|
420
|
+
id: 1,
|
|
421
|
+
payload: {
|
|
422
|
+
method: 'checkAllFirmwareRelease',
|
|
423
|
+
platform: 'desktop',
|
|
424
|
+
protocolV2ForceUpdateTargets: ['app_v1', 'coprocessor'],
|
|
425
|
+
},
|
|
426
|
+
});
|
|
427
|
+
method.init();
|
|
428
|
+
method.device = {
|
|
429
|
+
isProtocolV2: () => true,
|
|
430
|
+
features: {
|
|
431
|
+
deviceType: 'pro2',
|
|
432
|
+
serialNo: 'pro2-device-id',
|
|
433
|
+
firmwareVersion: '1.0.0',
|
|
434
|
+
},
|
|
435
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
436
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
437
|
+
status: { mode: 'normal' },
|
|
438
|
+
versions: { ...currentVersions, applicationP1: '1.0.0' },
|
|
439
|
+
}),
|
|
440
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
441
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(currentRelease);
|
|
442
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
443
|
+
|
|
444
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
445
|
+
targetsToUpdate: ['app_v1', 'coprocessor', 'resource'],
|
|
446
|
+
firmwareUpdatePlan: {
|
|
447
|
+
executor: 'v4',
|
|
448
|
+
platform: 'desktop',
|
|
449
|
+
artifacts: [
|
|
450
|
+
{ artifactId: 'component:app_v1', target: 'app_v1' },
|
|
451
|
+
{ artifactId: 'component:coprocessor', target: 'coprocessor' },
|
|
452
|
+
],
|
|
453
|
+
targetsToUpdate: ['app_v1', 'coprocessor'],
|
|
454
|
+
},
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
test('keeps exact force targets but omits a Desktop Plan without device identity', async () => {
|
|
459
|
+
const currentRelease: IFirmwareReleaseInfo = {
|
|
460
|
+
...release,
|
|
461
|
+
required: false,
|
|
462
|
+
version: [1, 0, 0],
|
|
463
|
+
installOrder: ['applicationP1'],
|
|
464
|
+
components: {
|
|
465
|
+
applicationP1: {
|
|
466
|
+
target: 'APPLICATION_P1',
|
|
467
|
+
url: 'https://example.com/application-p1.okpkg',
|
|
468
|
+
version: [1, 0, 0],
|
|
469
|
+
},
|
|
470
|
+
},
|
|
471
|
+
};
|
|
472
|
+
const method = new CheckAllFirmwareRelease({
|
|
473
|
+
id: 1,
|
|
474
|
+
payload: {
|
|
475
|
+
method: 'checkAllFirmwareRelease',
|
|
476
|
+
platform: 'desktop',
|
|
477
|
+
protocolV2ForceUpdateTargets: ['app_v1'],
|
|
478
|
+
},
|
|
479
|
+
});
|
|
480
|
+
method.init();
|
|
481
|
+
method.device = {
|
|
482
|
+
isProtocolV2: () => true,
|
|
483
|
+
features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
|
|
484
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
485
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
486
|
+
status: { mode: 'normal' },
|
|
487
|
+
versions: { ...currentVersions, applicationP1: '1.0.0' },
|
|
488
|
+
}),
|
|
489
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
490
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(currentRelease);
|
|
491
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
492
|
+
|
|
493
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
494
|
+
targetsToUpdate: ['app_v1', 'resource'],
|
|
495
|
+
firmwareUpdatePlan: undefined,
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
test('rejects Neo-only unsupported exact secure-element targets', async () => {
|
|
500
|
+
const neoRelease: IFirmwareReleaseInfo = {
|
|
501
|
+
...release,
|
|
502
|
+
required: false,
|
|
503
|
+
installOrder: ['se03'],
|
|
504
|
+
components: {
|
|
505
|
+
se03: {
|
|
506
|
+
target: 'SE03',
|
|
507
|
+
url: 'https://example.com/se03.okpkg',
|
|
508
|
+
version: [1, 0, 0],
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
};
|
|
512
|
+
const method = new CheckAllFirmwareRelease({
|
|
513
|
+
id: 1,
|
|
514
|
+
payload: {
|
|
515
|
+
method: 'checkAllFirmwareRelease',
|
|
516
|
+
protocolV2ForceUpdateTargets: ['se03'],
|
|
517
|
+
},
|
|
518
|
+
});
|
|
519
|
+
method.init();
|
|
520
|
+
method.device = {
|
|
521
|
+
isProtocolV2: () => true,
|
|
522
|
+
features: { deviceType: 'neo', firmwareVersion: '1.0.0' },
|
|
523
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
524
|
+
identity: { deviceType: 'neo', firmwareType: EFirmwareType.Universal },
|
|
525
|
+
status: { mode: 'normal' },
|
|
526
|
+
versions: currentVersions,
|
|
527
|
+
}),
|
|
528
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
529
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(neoRelease);
|
|
530
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
531
|
+
|
|
532
|
+
await expect(method.run()).rejects.toMatchObject({
|
|
533
|
+
params: { firmwareUpdateCode: 'FirmwarePlanInvalid' },
|
|
534
|
+
});
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
test('builds a V4 plan for Neo and excludes unsupported secure elements when forced', async () => {
|
|
538
|
+
const neoRelease: IFirmwareReleaseInfo = {
|
|
539
|
+
...release,
|
|
540
|
+
installOrder: ['se01', 'se02', 'se03', 'se04'],
|
|
541
|
+
components: {
|
|
542
|
+
se01: { target: 'SE01', url: 'https://example.com/se01.bin', version: [1, 0, 0] },
|
|
543
|
+
se02: { target: 'SE02', url: 'https://example.com/se02.bin', version: [2, 0, 0] },
|
|
544
|
+
se03: { target: 'SE03', url: 'https://example.com/se03.bin', version: [1, 0, 0] },
|
|
545
|
+
se04: { target: 'SE04', url: 'https://example.com/se04.bin', version: [1, 0, 0] },
|
|
546
|
+
},
|
|
547
|
+
};
|
|
548
|
+
const method = new CheckAllFirmwareRelease({
|
|
549
|
+
id: 1,
|
|
550
|
+
payload: {
|
|
551
|
+
method: 'checkAllFirmwareRelease',
|
|
552
|
+
platform: 'native',
|
|
553
|
+
forceUpdateTargets: ['firmware'],
|
|
554
|
+
},
|
|
555
|
+
});
|
|
556
|
+
method.init();
|
|
557
|
+
method.device = {
|
|
558
|
+
isProtocolV2: () => true,
|
|
559
|
+
features: {
|
|
560
|
+
deviceType: 'neo',
|
|
561
|
+
serialNo: 'neo-device-id',
|
|
562
|
+
firmwareVersion: '1.0.0',
|
|
563
|
+
},
|
|
564
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
565
|
+
identity: { deviceType: 'neo', firmwareType: EFirmwareType.Universal },
|
|
566
|
+
status: { mode: 'normal' },
|
|
567
|
+
versions: currentVersions,
|
|
568
|
+
}),
|
|
569
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
570
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(neoRelease);
|
|
571
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(resourceSource);
|
|
572
|
+
|
|
573
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
574
|
+
targetsToUpdate: ['se01', 'se02', 'resource'],
|
|
575
|
+
firmwareUpdatePlan: {
|
|
576
|
+
executor: 'v4',
|
|
577
|
+
deviceModel: 'neo',
|
|
578
|
+
platform: 'native',
|
|
579
|
+
targetsToUpdate: ['se01', 'se02'],
|
|
580
|
+
},
|
|
581
|
+
});
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
test('rejects a forced Protocol V2 resource target without a configured archive', async () => {
|
|
585
|
+
const method = new CheckAllFirmwareRelease({
|
|
586
|
+
id: 1,
|
|
587
|
+
payload: {
|
|
588
|
+
method: 'checkAllFirmwareRelease',
|
|
589
|
+
forceUpdateTargets: ['resource'],
|
|
590
|
+
},
|
|
591
|
+
});
|
|
592
|
+
method.init();
|
|
593
|
+
method.device = {
|
|
594
|
+
isProtocolV2: () => true,
|
|
595
|
+
features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
|
|
596
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
597
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
598
|
+
status: { mode: 'normal' },
|
|
599
|
+
versions: currentVersions,
|
|
600
|
+
}),
|
|
601
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
602
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
|
|
603
|
+
jest.spyOn(DataManager, 'getProtocolV2ResourceSource').mockReturnValue(undefined);
|
|
604
|
+
|
|
605
|
+
await expect(method.run()).rejects.toMatchObject({
|
|
606
|
+
params: { firmwareUpdateCode: 'FirmwarePlanInvalid' },
|
|
607
|
+
});
|
|
608
|
+
});
|
|
609
|
+
|
|
347
610
|
test('requests and compares firmware hashes only when explicitly enabled', async () => {
|
|
348
611
|
const packageSet: IFirmwareReleaseInfo = {
|
|
349
612
|
...release,
|
|
@@ -467,6 +730,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
467
730
|
resourceStatus: 'unknown',
|
|
468
731
|
resourcePreparationRequired: true,
|
|
469
732
|
targetsToUpdate: ['resource'],
|
|
733
|
+
firmwareUpdatePlan: undefined,
|
|
470
734
|
});
|
|
471
735
|
});
|
|
472
736
|
|
|
@@ -477,6 +741,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
477
741
|
await api.checkAllFirmwareRelease('pro2-connect-id', {
|
|
478
742
|
checkFirmwareHash: true,
|
|
479
743
|
firmwareType: EFirmwareType.Universal,
|
|
744
|
+
protocolV2ForceUpdateTargets: ['app_v1'],
|
|
480
745
|
retryCount: 0,
|
|
481
746
|
});
|
|
482
747
|
|
|
@@ -484,6 +749,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
484
749
|
connectId: 'pro2-connect-id',
|
|
485
750
|
checkFirmwareHash: true,
|
|
486
751
|
firmwareType: EFirmwareType.Universal,
|
|
752
|
+
protocolV2ForceUpdateTargets: ['app_v1'],
|
|
487
753
|
retryCount: 0,
|
|
488
754
|
method: 'checkAllFirmwareRelease',
|
|
489
755
|
});
|
|
@@ -22,6 +22,10 @@ const release: IFirmwareReleaseInfo = {
|
|
|
22
22
|
'zh-CN': '更新',
|
|
23
23
|
'en-US': 'Update',
|
|
24
24
|
},
|
|
25
|
+
bootloaderChangelog: {
|
|
26
|
+
'zh-CN': '旧版 Bootloader 更新',
|
|
27
|
+
'en-US': 'Legacy bootloader update',
|
|
28
|
+
},
|
|
25
29
|
installOrder: ['bootloader', 'applicationP1', 'coprocessor'],
|
|
26
30
|
components: {
|
|
27
31
|
bootloader: {
|
|
@@ -127,6 +131,7 @@ describe.each(['pro2', 'neo'] as const)('Protocol V2 release checks for %s', dev
|
|
|
127
131
|
await expect(bootloaderMethod.run()).resolves.toMatchObject({
|
|
128
132
|
status: 'outdated',
|
|
129
133
|
shouldUpdate: true,
|
|
134
|
+
changelog: [release.changelog],
|
|
130
135
|
release: {
|
|
131
136
|
protocol: 'V2',
|
|
132
137
|
configKey: 'bootloader',
|
|
@@ -134,6 +139,7 @@ describe.each(['pro2', 'neo'] as const)('Protocol V2 release checks for %s', dev
|
|
|
134
139
|
target: 'BOOTLOADER',
|
|
135
140
|
url: 'https://example.com/bootloader.okpkg',
|
|
136
141
|
version: [2, 0, 0],
|
|
142
|
+
changelog: release.changelog,
|
|
137
143
|
},
|
|
138
144
|
});
|
|
139
145
|
await expect(allMethod.run()).resolves.toMatchObject({
|
|
@@ -2778,9 +2778,12 @@ describe('Protocol V2 feature adapter', () => {
|
|
|
2778
2778
|
expect(checkedTypes).toEqual(['pro2', 'model_pro2']);
|
|
2779
2779
|
});
|
|
2780
2780
|
|
|
2781
|
-
test(
|
|
2781
|
+
test.each([
|
|
2782
|
+
['Pro2', DeviceType.PRO2],
|
|
2783
|
+
['Neo', DeviceType.NEO],
|
|
2784
|
+
] as const)('uses firmware-v1 as the %s remote firmware config field', (_name, deviceType) => {
|
|
2782
2785
|
const features = normalizeProtocolV2Features({ ...descriptor, protocolType: 'V2' } as any, {
|
|
2783
|
-
hw: { Device_type:
|
|
2786
|
+
hw: { Device_type: deviceType },
|
|
2784
2787
|
});
|
|
2785
2788
|
|
|
2786
2789
|
expect(
|
|
@@ -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;
|
|
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,7 +1,30 @@
|
|
|
1
1
|
import { EFirmwareType } from '@onekeyfe/hd-shared';
|
|
2
|
+
import type { FirmwareUpdateV4Target } from '../../types/api/firmwareUpdate';
|
|
2
3
|
import type { FirmwareUpdatePlan, FirmwareUpdatePlanForceTarget, FirmwareUpdatePlanTarget } from '../../types/api/firmwareUpdatePlan';
|
|
3
4
|
import type { Features } from '../../types';
|
|
4
5
|
type FirmwareUpdatePlatform = 'native' | 'desktop' | 'ext' | 'web' | 'web-embed';
|
|
6
|
+
type ReleaseRecord = {
|
|
7
|
+
url?: unknown;
|
|
8
|
+
webUpdate?: unknown;
|
|
9
|
+
resource?: unknown;
|
|
10
|
+
fullResource?: unknown;
|
|
11
|
+
fullResourceRange?: unknown;
|
|
12
|
+
bootloaderResource?: unknown;
|
|
13
|
+
version?: unknown;
|
|
14
|
+
components?: unknown;
|
|
15
|
+
installOrder?: unknown;
|
|
16
|
+
resourceBundles?: unknown;
|
|
17
|
+
fingerprint?: unknown;
|
|
18
|
+
fingerprintWeb?: unknown;
|
|
19
|
+
expectedSize?: unknown;
|
|
20
|
+
resourceFingerprint?: unknown;
|
|
21
|
+
resourceExpectedSize?: unknown;
|
|
22
|
+
fullResourceFingerprint?: unknown;
|
|
23
|
+
fullResourceExpectedSize?: unknown;
|
|
24
|
+
bootloaderFingerprint?: unknown;
|
|
25
|
+
bootloaderExpectedSize?: unknown;
|
|
26
|
+
bootloaderVersion?: unknown;
|
|
27
|
+
};
|
|
5
28
|
type ReleaseSelection = {
|
|
6
29
|
shouldUpdate?: boolean;
|
|
7
30
|
status?: unknown;
|
|
@@ -9,9 +32,19 @@ type ReleaseSelection = {
|
|
|
9
32
|
};
|
|
10
33
|
export declare const digestFirmwareUpdateContract: (value: unknown) => string;
|
|
11
34
|
export declare const validateFirmwareUpdatePlanForceTargets: (value: unknown) => FirmwareUpdatePlanForceTarget[];
|
|
35
|
+
export declare const validateProtocolV2FirmwareUpdateTargets: (value: unknown) => FirmwareUpdateV4Target[];
|
|
12
36
|
export declare const FIRMWARE_UPDATE_PLAN_TARGETS: Set<FirmwareUpdatePlanTarget>;
|
|
13
37
|
export declare const FIRMWARE_UPDATE_PLAN_ROLES: Set<string>;
|
|
14
38
|
export declare const assertFirmwareUpdatePlan: (value: unknown) => FirmwareUpdatePlan;
|
|
39
|
+
export declare const buildProtocolV2FirmwareUpdatePlan: ({ features, firmwareType, platform, release, targetsToUpdate, forceUpdateTargets, resourceArchiveAvailable, }: {
|
|
40
|
+
features: Features;
|
|
41
|
+
firmwareType: EFirmwareType;
|
|
42
|
+
platform: FirmwareUpdatePlatform;
|
|
43
|
+
release: ReleaseRecord | undefined;
|
|
44
|
+
targetsToUpdate: readonly FirmwareUpdateV4Target[];
|
|
45
|
+
forceUpdateTargets?: FirmwareUpdatePlanForceTarget[] | undefined;
|
|
46
|
+
resourceArchiveAvailable: boolean;
|
|
47
|
+
}) => FirmwareUpdatePlan;
|
|
15
48
|
export declare const buildFirmwareUpdatePlan: ({ features, firmwareType, platform, firmware, ble, bootloader, forceUpdateTargets, }: {
|
|
16
49
|
features: Features;
|
|
17
50
|
firmwareType: EFirmwareType;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FirmwareUpdatePlan.d.ts","sourceRoot":"","sources":["../../../src/api/firmware/FirmwareUpdatePlan.ts"],"names":[],"mappings":"AAEA,OAAO,EAAe,aAAa,EAA6B,MAAM,qBAAqB,CAAC;AAU5F,OAAO,KAAK,EACV,kBAAkB,EAElB,6BAA6B,EAC7B,wBAAwB,EACzB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,KAAK,sBAAsB,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"FirmwareUpdatePlan.d.ts","sourceRoot":"","sources":["../../../src/api/firmware/FirmwareUpdatePlan.ts"],"names":[],"mappings":"AAEA,OAAO,EAAe,aAAa,EAA6B,MAAM,qBAAqB,CAAC;AAU5F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,KAAK,EACV,kBAAkB,EAElB,6BAA6B,EAC7B,wBAAwB,EACzB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,KAAK,sBAAsB,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG,WAAW,CAAC;AAEjF,KAAK,aAAa,GAAG;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AA+GF,eAAO,MAAM,4BAA4B,UAAW,OAAO,KAAG,MAG3D,CAAC;AAkBJ,eAAO,MAAM,sCAAsC,UAC1C,OAAO,KACb,6BAA6B,EAa/B,CAAC;AAEF,eAAO,MAAM,uCAAuC,UAC3C,OAAO,KACb,sBAAsB,EAaxB,CAAC;AAuBF,eAAO,MAAM,4BAA4B,+BAavC,CAAC;AAEH,eAAO,MAAM,0BAA0B,aAOrC,CAAC;AAYH,eAAO,MAAM,wBAAwB,UAAW,OAAO,KAAG,kBAyHzD,CAAC;AA0RF,eAAO,MAAM,iCAAiC;cASlC,QAAQ;kBACJ,aAAa;cACjB,sBAAsB;aACvB,aAAa,GAAG,SAAS;qBACjB,SAAS,sBAAsB,EAAE;;8BAExB,OAAO;MAC/B,kBA2CH,CAAC;AAEF,eAAO,MAAM,uBAAuB;cASxB,QAAQ;kBACJ,aAAa;cACjB,sBAAsB;cACtB,gBAAgB;SACrB,gBAAgB;;;MAGnB,kBAyIH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocolV2Release.d.ts","sourceRoot":"","sources":["../../../src/api/firmware/protocolV2Release.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA6B,MAAM,qBAAqB,CAAC;AAI/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EACR,oBAAoB,EACpB,kCAAkC,EACnC,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,0BAA0B,EAC1B,8BAA8B,EAE/B,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AAEhF,eAAO,MAAM,iCAAiC,EAAE,SAAS,kCAAkC,EAO1F,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,SAAS,kCAAkC,EAEhF,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,SAAS,kCAAkC,EAEvF,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC7C,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,GAAG;QACrC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC,GAAG;YACtD,UAAU,EAAE,WAAW,CAAC,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC;SAChD,CAAC;KACH,CAAC;IACF,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,aAAa,CAAC;IAC5B,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF,wBAAsB,oCAAoC,CAAC,EACzD,MAAM,EACN,YAAY,EAAE,iBAAiB,EAC/B,iBAAyB,EACzB,UAAU,GACX,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,gCAAgC,CAAC,CA4B5C;AAED,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,6BAA6B,EACnC,gBAAgB,EAAE,SAAS,kCAAkC,EAAE,GAC9D,6BAA6B,CAiC/B;AAED,wBAAgB,+BAA+B,CAAC,EAC9C,IAAI,EACJ,KAAK,EACL,OAAO,GACR,EAAE;IACD,IAAI,EAAE,6BAA6B,CAAC;IACpC,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,0BAA0B,CAAC,SAAS,CAAC,CAAC;CAChD,GAAG,0BAA0B,
|
|
1
|
+
{"version":3,"file":"protocolV2Release.d.ts","sourceRoot":"","sources":["../../../src/api/firmware/protocolV2Release.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA6B,MAAM,qBAAqB,CAAC;AAI/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EACR,oBAAoB,EACpB,kCAAkC,EACnC,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,0BAA0B,EAC1B,8BAA8B,EAE/B,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AAEhF,eAAO,MAAM,iCAAiC,EAAE,SAAS,kCAAkC,EAO1F,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,SAAS,kCAAkC,EAEhF,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,SAAS,kCAAkC,EAEvF,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC7C,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,GAAG;QACrC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC,GAAG;YACtD,UAAU,EAAE,WAAW,CAAC,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC;SAChD,CAAC;KACH,CAAC;IACF,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,aAAa,CAAC;IAC5B,OAAO,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF,wBAAsB,oCAAoC,CAAC,EACzD,MAAM,EACN,YAAY,EAAE,iBAAiB,EAC/B,iBAAyB,EACzB,UAAU,GACX,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,gCAAgC,CAAC,CA4B5C;AAED,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,6BAA6B,EACnC,gBAAgB,EAAE,SAAS,kCAAkC,EAAE,GAC9D,6BAA6B,CAiC/B;AAED,wBAAgB,+BAA+B,CAAC,EAC9C,IAAI,EACJ,KAAK,EACL,OAAO,GACR,EAAE;IACD,IAAI,EAAE,6BAA6B,CAAC;IACpC,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,0BAA0B,CAAC,SAAS,CAAC,CAAC;CAChD,GAAG,0BAA0B,CAU7B;AAED,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,6BAA6B,EACnC,eAAe,EAAE,kCAAkC,GAClD,8BAA8B,GAAG,SAAS,CAmB5C"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1542,6 +1542,7 @@ type CheckAllFirmwareReleaseParams = {
|
|
|
1542
1542
|
firmwareType?: EFirmwareType;
|
|
1543
1543
|
platform?: 'native' | 'desktop' | 'ext' | 'web' | 'web-embed';
|
|
1544
1544
|
forceUpdateTargets?: FirmwareUpdatePlanForceTarget[];
|
|
1545
|
+
protocolV2ForceUpdateTargets?: FirmwareUpdateV4Target[];
|
|
1545
1546
|
};
|
|
1546
1547
|
declare function checkAllFirmwareRelease(connectId?: string, params?: CommonParams & CheckAllFirmwareReleaseParams): Response<AllFirmwareRelease>;
|
|
1547
1548
|
|
package/dist/index.js
CHANGED
|
@@ -522,6 +522,10 @@ 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
|
+
]);
|
|
525
529
|
const asRecord = (value) => value && typeof value === 'object' && !Array.isArray(value)
|
|
526
530
|
? value
|
|
527
531
|
: undefined;
|
|
@@ -609,6 +613,18 @@ const validateFirmwareUpdatePlanForceTargets = (value) => {
|
|
|
609
613
|
}
|
|
610
614
|
return [...value];
|
|
611
615
|
};
|
|
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
|
+
};
|
|
612
628
|
const assertExactKeys = (value, required, optional = []) => {
|
|
613
629
|
const allowed = new Set([...required, ...optional]);
|
|
614
630
|
if (required.some(key => !Object.prototype.hasOwnProperty.call(value, key)) ||
|
|
@@ -773,7 +789,7 @@ const selectResourceUrl = ({ release, features, platform, }) => {
|
|
|
773
789
|
};
|
|
774
790
|
const getExecutor = (features) => {
|
|
775
791
|
const deviceType = getDeviceType(features);
|
|
776
|
-
if (deviceType === hdShared.EDeviceType.Pro2) {
|
|
792
|
+
if (deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo) {
|
|
777
793
|
return 'v4';
|
|
778
794
|
}
|
|
779
795
|
if (deviceType === hdShared.EDeviceType.Pro &&
|
|
@@ -782,7 +798,7 @@ const getExecutor = (features) => {
|
|
|
782
798
|
}
|
|
783
799
|
return 'v2';
|
|
784
800
|
};
|
|
785
|
-
const buildProtocolV2Artifacts = (release, { includeComponents = true, includeResources = true, } = {}) => {
|
|
801
|
+
const buildProtocolV2Artifacts = (release, { includeComponents = true, includeResources = true, componentTargets: selectedComponentTargets, } = {}) => {
|
|
786
802
|
var _a;
|
|
787
803
|
const components = asRecord(release.components);
|
|
788
804
|
if (includeComponents && !components) {
|
|
@@ -794,23 +810,32 @@ const buildProtocolV2Artifacts = (release, { includeComponents = true, includeRe
|
|
|
794
810
|
const componentKeys = includeComponents && components
|
|
795
811
|
? [...installOrder, ...Object.keys(components).filter(key => !installOrder.includes(key))]
|
|
796
812
|
: [];
|
|
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;
|
|
797
822
|
const artifacts = [];
|
|
798
823
|
const targets = [];
|
|
799
|
-
const
|
|
800
|
-
for (const key of
|
|
824
|
+
const componentTargetSet = new Set();
|
|
825
|
+
for (const key of selectedComponentKeys) {
|
|
801
826
|
const component = asRecord(components === null || components === void 0 ? void 0 : components[key]);
|
|
802
827
|
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;
|
|
803
829
|
if (targetName === 'ROMLOADER') {
|
|
804
830
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 ROMLOADER requires its dedicated loader flow', { firmwareUpdateCode: 'FirmwarePlanInvalid' });
|
|
805
831
|
}
|
|
806
|
-
const target = targetName ? PROTOCOL_V2_TARGETS[targetName] : undefined;
|
|
807
832
|
if (!component || !target) {
|
|
808
833
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 component ${key} has an unsupported target`, { firmwareUpdateCode: 'FirmwarePlanInvalid' });
|
|
809
834
|
}
|
|
810
|
-
if (
|
|
835
|
+
if (componentTargetSet.has(target)) {
|
|
811
836
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 component ${key} duplicates target ${target}`, { firmwareUpdateCode: 'FirmwarePlanInvalid' });
|
|
812
837
|
}
|
|
813
|
-
|
|
838
|
+
componentTargetSet.add(target);
|
|
814
839
|
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({
|
|
815
840
|
size: component.expectedSize,
|
|
816
841
|
sha256: component.fingerprint,
|
|
@@ -865,6 +890,63 @@ const assertForcedTargetsRepresented = ({ executor, forcedTargets, artifacts, ta
|
|
|
865
890
|
}
|
|
866
891
|
}
|
|
867
892
|
};
|
|
893
|
+
const finalizeFirmwareUpdatePlan = ({ features, firmwareType, platform, artifacts, targetsToUpdate, }) => {
|
|
894
|
+
const executor = getExecutor(features);
|
|
895
|
+
const bootloaderMode = resolveDeviceBootloaderMode(features);
|
|
896
|
+
const reportedIdentity = getDeviceUUID(features);
|
|
897
|
+
const deviceIdentity = reportedIdentity === 'unavailable' ? '' : reportedIdentity;
|
|
898
|
+
if (artifacts.length > 0 &&
|
|
899
|
+
(platform === 'native' || platform === 'desktop') &&
|
|
900
|
+
!deviceIdentity &&
|
|
901
|
+
!(bootloaderMode && executor === 'v2')) {
|
|
902
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Prepared firmware update requires a stable device identity', { firmwareUpdateCode: 'FirmwarePlanInvalid' });
|
|
903
|
+
}
|
|
904
|
+
const planWithoutDigest = {
|
|
905
|
+
schemaVersion: 2,
|
|
906
|
+
executor,
|
|
907
|
+
deviceIdentity: deviceIdentity || 'unavailable',
|
|
908
|
+
deviceModel: String(getDeviceType(features)),
|
|
909
|
+
firmwareType,
|
|
910
|
+
platform,
|
|
911
|
+
artifacts,
|
|
912
|
+
targetsToUpdate,
|
|
913
|
+
};
|
|
914
|
+
return assertFirmwareUpdatePlan(Object.assign(Object.assign({}, planWithoutDigest), { planDigest: digestFirmwareUpdatePlan(planWithoutDigest) }));
|
|
915
|
+
};
|
|
916
|
+
const buildProtocolV2FirmwareUpdatePlan = ({ features, firmwareType, platform, release, targetsToUpdate, forceUpdateTargets, resourceArchiveAvailable, }) => {
|
|
917
|
+
const validatedForceTargets = validateFirmwareUpdatePlanForceTargets(forceUpdateTargets);
|
|
918
|
+
if (validatedForceTargets.some(target => target === 'ble' || target === 'bootloader')) {
|
|
919
|
+
planError('Protocol V2 does not support forced BLE or legacy bootloader targets');
|
|
920
|
+
}
|
|
921
|
+
const requestedComponentTargets = new Set(targetsToUpdate.filter(target => target !== 'resource'));
|
|
922
|
+
if (getDeviceType(features) === hdShared.EDeviceType.Neo &&
|
|
923
|
+
(requestedComponentTargets.has('se03') || requestedComponentTargets.has('se04'))) {
|
|
924
|
+
planError('Neo does not support Protocol V2 targets se03 or se04');
|
|
925
|
+
}
|
|
926
|
+
const protocolV2 = buildProtocolV2Artifacts(release !== null && release !== void 0 ? release : {}, {
|
|
927
|
+
includeComponents: requestedComponentTargets.size > 0,
|
|
928
|
+
includeResources: false,
|
|
929
|
+
componentTargets: requestedComponentTargets,
|
|
930
|
+
});
|
|
931
|
+
const representedTargets = new Set(protocolV2.targets);
|
|
932
|
+
const missingTarget = Array.from(requestedComponentTargets).find(target => !representedTargets.has(target));
|
|
933
|
+
if (missingTarget) {
|
|
934
|
+
planError(`Protocol V2 release does not contain requested target ${missingTarget}`);
|
|
935
|
+
}
|
|
936
|
+
if (validatedForceTargets.includes('firmware') && protocolV2.targets.length === 0) {
|
|
937
|
+
planError('Forced firmware update target firmware is not represented by the plan');
|
|
938
|
+
}
|
|
939
|
+
if (validatedForceTargets.includes('resource') && !resourceArchiveAvailable) {
|
|
940
|
+
planError('Forced firmware update target resource has no Protocol V2 resource archive');
|
|
941
|
+
}
|
|
942
|
+
return finalizeFirmwareUpdatePlan({
|
|
943
|
+
features,
|
|
944
|
+
firmwareType,
|
|
945
|
+
platform,
|
|
946
|
+
artifacts: protocolV2.artifacts,
|
|
947
|
+
targetsToUpdate: protocolV2.targets,
|
|
948
|
+
});
|
|
949
|
+
};
|
|
868
950
|
const buildFirmwareUpdatePlan = ({ features, firmwareType, platform, firmware, ble, bootloader, forceUpdateTargets, }) => {
|
|
869
951
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
870
952
|
const executor = getExecutor(features);
|
|
@@ -951,25 +1033,13 @@ const buildFirmwareUpdatePlan = ({ features, firmwareType, platform, firmware, b
|
|
|
951
1033
|
artifacts,
|
|
952
1034
|
targetsToUpdate,
|
|
953
1035
|
});
|
|
954
|
-
|
|
955
|
-
|
|
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)),
|
|
1036
|
+
return finalizeFirmwareUpdatePlan({
|
|
1037
|
+
features,
|
|
967
1038
|
firmwareType,
|
|
968
1039
|
platform,
|
|
969
1040
|
artifacts,
|
|
970
1041
|
targetsToUpdate,
|
|
971
|
-
};
|
|
972
|
-
return assertFirmwareUpdatePlan(Object.assign(Object.assign({}, planWithoutDigest), { planDigest: digestFirmwareUpdatePlan(planWithoutDigest) }));
|
|
1042
|
+
});
|
|
973
1043
|
};
|
|
974
1044
|
|
|
975
1045
|
const preparedPlanError = (message) => {
|
|
@@ -41925,7 +41995,7 @@ const getFirmwareUpdateField = ({ features, updateType, targetVersion, firmwareT
|
|
|
41925
41995
|
if (deviceType === hdShared.EDeviceType.Pro) {
|
|
41926
41996
|
return latestFirmwareField;
|
|
41927
41997
|
}
|
|
41928
|
-
if (deviceType === hdShared.EDeviceType.Pro2) {
|
|
41998
|
+
if (deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo) {
|
|
41929
41999
|
return 'firmware-v1';
|
|
41930
42000
|
}
|
|
41931
42001
|
return 'firmware';
|
|
@@ -41957,7 +42027,7 @@ const getFirmwareUpdateFieldArray = (features, updateType) => {
|
|
|
41957
42027
|
if (deviceType === 'pro') {
|
|
41958
42028
|
return ['firmware-v8'];
|
|
41959
42029
|
}
|
|
41960
|
-
if (deviceType === 'pro2') {
|
|
42030
|
+
if (deviceType === 'pro2' || deviceType === 'neo') {
|
|
41961
42031
|
return ['firmware-v1'];
|
|
41962
42032
|
}
|
|
41963
42033
|
return ['firmware'];
|
|
@@ -47688,9 +47758,11 @@ class CheckAllFirmwareRelease extends BaseMethod {
|
|
|
47688
47758
|
});
|
|
47689
47759
|
}
|
|
47690
47760
|
runProtocolV2() {
|
|
47761
|
+
var _a;
|
|
47691
47762
|
return __awaiter(this, void 0, void 0, function* () {
|
|
47692
|
-
const { checkFirmwareHash = false, firmwareType: firmwareTypeParam } = this
|
|
47693
|
-
|
|
47763
|
+
const { checkFirmwareHash = false, firmwareType: firmwareTypeParam, platform, forceUpdateTargets, protocolV2ForceUpdateTargets, } = this.payload;
|
|
47764
|
+
const validatedForceUpdateTargets = validateFirmwareUpdatePlanForceTargets(forceUpdateTargets);
|
|
47765
|
+
const validatedProtocolV2ForceUpdateTargets = validateProtocolV2FirmwareUpdateTargets(protocolV2ForceUpdateTargets);
|
|
47694
47766
|
const { state, features, firmwareType, release } = yield loadProtocolV2FirmwareReleaseContext({
|
|
47695
47767
|
device: this.device,
|
|
47696
47768
|
firmwareType: firmwareTypeParam,
|
|
@@ -47709,10 +47781,57 @@ class CheckAllFirmwareRelease extends BaseMethod {
|
|
|
47709
47781
|
const resourceSource = DataManager.getProtocolV2ResourceSource(resourceDeviceType);
|
|
47710
47782
|
const resourceStatus = 'unknown';
|
|
47711
47783
|
const resourcePreparationRequired = !!resourceSource;
|
|
47784
|
+
const detectedComponentTargets = validatedForceUpdateTargets.includes('firmware')
|
|
47785
|
+
? plan.components.flatMap(component => component.updateTarget ? [component.updateTarget] : [])
|
|
47786
|
+
: plan.targetsToUpdate;
|
|
47787
|
+
const componentTargetsToUpdate = Array.from(new Set([
|
|
47788
|
+
...detectedComponentTargets,
|
|
47789
|
+
...validatedProtocolV2ForceUpdateTargets.filter(target => target !== 'resource'),
|
|
47790
|
+
]));
|
|
47791
|
+
const forceResourceUpdate = validatedForceUpdateTargets.includes('resource') ||
|
|
47792
|
+
validatedProtocolV2ForceUpdateTargets.includes('resource');
|
|
47712
47793
|
const targetsToUpdate = Array.from(new Set([
|
|
47713
|
-
...
|
|
47714
|
-
...(resourcePreparationRequired ? ['resource'] : []),
|
|
47794
|
+
...componentTargetsToUpdate,
|
|
47795
|
+
...(resourcePreparationRequired || forceResourceUpdate ? ['resource'] : []),
|
|
47715
47796
|
]));
|
|
47797
|
+
let firmwareUpdatePlan;
|
|
47798
|
+
try {
|
|
47799
|
+
const shouldBuildFirmwareUpdatePlan = componentTargetsToUpdate.length > 0 ||
|
|
47800
|
+
validatedForceUpdateTargets.some(target => target !== 'resource') ||
|
|
47801
|
+
validatedProtocolV2ForceUpdateTargets.some(target => target !== 'resource') ||
|
|
47802
|
+
(forceResourceUpdate && !resourcePreparationRequired);
|
|
47803
|
+
const requestedPlatform = platform !== null && platform !== void 0 ? platform : 'web';
|
|
47804
|
+
const requiresDeviceIdentity = requestedPlatform === 'native' || requestedPlatform === 'desktop';
|
|
47805
|
+
const canBindPreparedPlan = !requiresDeviceIdentity || !!getDeviceSerialNo(features);
|
|
47806
|
+
if (shouldBuildFirmwareUpdatePlan) {
|
|
47807
|
+
const validatedPlan = buildProtocolV2FirmwareUpdatePlan({
|
|
47808
|
+
features,
|
|
47809
|
+
firmwareType,
|
|
47810
|
+
platform: canBindPreparedPlan ? requestedPlatform : 'web',
|
|
47811
|
+
release,
|
|
47812
|
+
targetsToUpdate,
|
|
47813
|
+
forceUpdateTargets: validatedForceUpdateTargets,
|
|
47814
|
+
resourceArchiveAvailable: resourcePreparationRequired,
|
|
47815
|
+
});
|
|
47816
|
+
firmwareUpdatePlan = canBindPreparedPlan ? validatedPlan : undefined;
|
|
47817
|
+
if (!canBindPreparedPlan) {
|
|
47818
|
+
Log$c.warn('[CheckAllFirmwareRelease] Protocol V2 device identity is unavailable; using the release result without a prepared Plan');
|
|
47819
|
+
}
|
|
47820
|
+
}
|
|
47821
|
+
else {
|
|
47822
|
+
firmwareUpdatePlan = undefined;
|
|
47823
|
+
}
|
|
47824
|
+
}
|
|
47825
|
+
catch (error) {
|
|
47826
|
+
if (validatedForceUpdateTargets.length > 0 ||
|
|
47827
|
+
validatedProtocolV2ForceUpdateTargets.length > 0 ||
|
|
47828
|
+
!(error instanceof hdShared.HardwareError) ||
|
|
47829
|
+
((_a = error.params) === null || _a === void 0 ? void 0 : _a.firmwareUpdateCode) !== 'FirmwarePlanInvalid') {
|
|
47830
|
+
throw error;
|
|
47831
|
+
}
|
|
47832
|
+
Log$c.warn('[CheckAllFirmwareRelease] Optional Protocol V2 firmware Plan is unavailable; using the release result');
|
|
47833
|
+
firmwareUpdatePlan = undefined;
|
|
47834
|
+
}
|
|
47716
47835
|
const firmwarePlan = summarizeProtocolV2FirmwareRelease(plan, PROTOCOL_V2_MAIN_FIRMWARE_TARGETS);
|
|
47717
47836
|
const blePlan = summarizeProtocolV2FirmwareRelease(plan, PROTOCOL_V2_BLE_TARGETS);
|
|
47718
47837
|
const bootloaderPlan = summarizeProtocolV2FirmwareRelease(plan, PROTOCOL_V2_BOOTLOADER_TARGETS);
|
|
@@ -47728,7 +47847,8 @@ class CheckAllFirmwareRelease extends BaseMethod {
|
|
|
47728
47847
|
state,
|
|
47729
47848
|
release: getProtocolV2ComponentReleaseInfo(plan, 'BOOTLOADER'),
|
|
47730
47849
|
}), features, protocol: 'V2', deviceType: state.identity.deviceType }, plan), { status,
|
|
47731
|
-
resourceStatus, resourceArchive: resourceSource, resourcePreparationRequired, hasUpgrade:
|
|
47850
|
+
resourceStatus, resourceArchive: resourceSource, resourcePreparationRequired, hasUpgrade: targetsToUpdate.length > 0, targetsToUpdate,
|
|
47851
|
+
firmwareUpdatePlan });
|
|
47732
47852
|
});
|
|
47733
47853
|
}
|
|
47734
47854
|
}
|
|
@@ -62,6 +62,7 @@ export type CheckAllFirmwareReleaseParams = {
|
|
|
62
62
|
firmwareType?: EFirmwareType;
|
|
63
63
|
platform?: 'native' | 'desktop' | 'ext' | 'web' | 'web-embed';
|
|
64
64
|
forceUpdateTargets?: FirmwareUpdatePlanForceTarget[];
|
|
65
|
+
protocolV2ForceUpdateTargets?: FirmwareUpdateV4Target[];
|
|
65
66
|
};
|
|
66
67
|
export declare function checkAllFirmwareRelease(connectId?: string, params?: CommonParams & CheckAllFirmwareReleaseParams): Response<AllFirmwareRelease>;
|
|
67
68
|
//# sourceMappingURL=checkAllFirmwareRelease.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkAllFirmwareRelease.d.ts","sourceRoot":"","sources":["../../../src/types/api/checkAllFirmwareRelease.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"checkAllFirmwareRelease.d.ts","sourceRoot":"","sources":["../../../src/types/api/checkAllFirmwareRelease.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-core",
|
|
3
|
-
"version": "1.2.0-alpha.
|
|
3
|
+
"version": "1.2.0-alpha.84",
|
|
4
4
|
"description": "Core processes and APIs for communicating with OneKey hardware devices.",
|
|
5
5
|
"author": "OneKey",
|
|
6
6
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@onekeyfe/hd-shared": "1.2.0-alpha.
|
|
29
|
-
"@onekeyfe/hd-transport": "1.2.0-alpha.
|
|
28
|
+
"@onekeyfe/hd-shared": "1.2.0-alpha.84",
|
|
29
|
+
"@onekeyfe/hd-transport": "1.2.0-alpha.84",
|
|
30
30
|
"axios": "1.15.2",
|
|
31
31
|
"bignumber.js": "^9.0.2",
|
|
32
32
|
"bytebuffer": "^5.0.1",
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"@types/w3c-web-usb": "^1.0.10",
|
|
45
45
|
"@types/web-bluetooth": "^0.0.21"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "577746142ef64d2c97de487c7a9cc8a5a0422e0b"
|
|
48
48
|
}
|
|
@@ -11,7 +11,9 @@ import {
|
|
|
11
11
|
} from './firmware/releaseHelper';
|
|
12
12
|
import {
|
|
13
13
|
buildFirmwareUpdatePlan,
|
|
14
|
+
buildProtocolV2FirmwareUpdatePlan,
|
|
14
15
|
validateFirmwareUpdatePlanForceTargets,
|
|
16
|
+
validateProtocolV2FirmwareUpdateTargets,
|
|
15
17
|
} from './firmware/FirmwareUpdatePlan';
|
|
16
18
|
import {
|
|
17
19
|
PROTOCOL_V2_BLE_TARGETS,
|
|
@@ -26,6 +28,7 @@ import { getBridgeReleaseInfo } from '../utils/bridgeUpdate';
|
|
|
26
28
|
import {
|
|
27
29
|
LoggerNames,
|
|
28
30
|
getDeviceFirmwareVersion,
|
|
31
|
+
getDeviceSerialNo,
|
|
29
32
|
getDeviceType,
|
|
30
33
|
getFirmwareType,
|
|
31
34
|
getLogger,
|
|
@@ -384,8 +387,17 @@ export default class CheckAllFirmwareRelease extends BaseMethod {
|
|
|
384
387
|
}
|
|
385
388
|
|
|
386
389
|
private async runProtocolV2(): Promise<AllFirmwareRelease> {
|
|
387
|
-
const {
|
|
388
|
-
|
|
390
|
+
const {
|
|
391
|
+
checkFirmwareHash = false,
|
|
392
|
+
firmwareType: firmwareTypeParam,
|
|
393
|
+
platform,
|
|
394
|
+
forceUpdateTargets,
|
|
395
|
+
protocolV2ForceUpdateTargets,
|
|
396
|
+
} = this.payload as CheckAllFirmwareReleaseParams;
|
|
397
|
+
const validatedForceUpdateTargets = validateFirmwareUpdatePlanForceTargets(forceUpdateTargets);
|
|
398
|
+
const validatedProtocolV2ForceUpdateTargets = validateProtocolV2FirmwareUpdateTargets(
|
|
399
|
+
protocolV2ForceUpdateTargets
|
|
400
|
+
);
|
|
389
401
|
const { state, features, firmwareType, release } = await loadProtocolV2FirmwareReleaseContext({
|
|
390
402
|
device: this.device,
|
|
391
403
|
firmwareType: firmwareTypeParam,
|
|
@@ -405,12 +417,70 @@ export default class CheckAllFirmwareRelease extends BaseMethod {
|
|
|
405
417
|
const resourceSource = DataManager.getProtocolV2ResourceSource(resourceDeviceType);
|
|
406
418
|
const resourceStatus = 'unknown' as const;
|
|
407
419
|
const resourcePreparationRequired = !!resourceSource;
|
|
420
|
+
const detectedComponentTargets = validatedForceUpdateTargets.includes('firmware')
|
|
421
|
+
? plan.components.flatMap(component =>
|
|
422
|
+
component.updateTarget ? [component.updateTarget] : []
|
|
423
|
+
)
|
|
424
|
+
: plan.targetsToUpdate;
|
|
425
|
+
const componentTargetsToUpdate = Array.from(
|
|
426
|
+
new Set([
|
|
427
|
+
...detectedComponentTargets,
|
|
428
|
+
...validatedProtocolV2ForceUpdateTargets.filter(target => target !== 'resource'),
|
|
429
|
+
])
|
|
430
|
+
);
|
|
431
|
+
const forceResourceUpdate =
|
|
432
|
+
validatedForceUpdateTargets.includes('resource') ||
|
|
433
|
+
validatedProtocolV2ForceUpdateTargets.includes('resource');
|
|
408
434
|
const targetsToUpdate = Array.from(
|
|
409
435
|
new Set([
|
|
410
|
-
...
|
|
411
|
-
...(resourcePreparationRequired ? (['resource'] as const) : []),
|
|
436
|
+
...componentTargetsToUpdate,
|
|
437
|
+
...(resourcePreparationRequired || forceResourceUpdate ? (['resource'] as const) : []),
|
|
412
438
|
])
|
|
413
439
|
);
|
|
440
|
+
let firmwareUpdatePlan: FirmwareUpdatePlan | undefined;
|
|
441
|
+
try {
|
|
442
|
+
const shouldBuildFirmwareUpdatePlan =
|
|
443
|
+
componentTargetsToUpdate.length > 0 ||
|
|
444
|
+
validatedForceUpdateTargets.some(target => target !== 'resource') ||
|
|
445
|
+
validatedProtocolV2ForceUpdateTargets.some(target => target !== 'resource') ||
|
|
446
|
+
(forceResourceUpdate && !resourcePreparationRequired);
|
|
447
|
+
const requestedPlatform = platform ?? 'web';
|
|
448
|
+
const requiresDeviceIdentity =
|
|
449
|
+
requestedPlatform === 'native' || requestedPlatform === 'desktop';
|
|
450
|
+
const canBindPreparedPlan = !requiresDeviceIdentity || !!getDeviceSerialNo(features);
|
|
451
|
+
if (shouldBuildFirmwareUpdatePlan) {
|
|
452
|
+
const validatedPlan = buildProtocolV2FirmwareUpdatePlan({
|
|
453
|
+
features,
|
|
454
|
+
firmwareType,
|
|
455
|
+
platform: canBindPreparedPlan ? requestedPlatform : 'web',
|
|
456
|
+
release,
|
|
457
|
+
targetsToUpdate,
|
|
458
|
+
forceUpdateTargets: validatedForceUpdateTargets,
|
|
459
|
+
resourceArchiveAvailable: resourcePreparationRequired,
|
|
460
|
+
});
|
|
461
|
+
firmwareUpdatePlan = canBindPreparedPlan ? validatedPlan : undefined;
|
|
462
|
+
if (!canBindPreparedPlan) {
|
|
463
|
+
Log.warn(
|
|
464
|
+
'[CheckAllFirmwareRelease] Protocol V2 device identity is unavailable; using the release result without a prepared Plan'
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
} else {
|
|
468
|
+
firmwareUpdatePlan = undefined;
|
|
469
|
+
}
|
|
470
|
+
} catch (error) {
|
|
471
|
+
if (
|
|
472
|
+
validatedForceUpdateTargets.length > 0 ||
|
|
473
|
+
validatedProtocolV2ForceUpdateTargets.length > 0 ||
|
|
474
|
+
!(error instanceof HardwareError) ||
|
|
475
|
+
error.params?.firmwareUpdateCode !== 'FirmwarePlanInvalid'
|
|
476
|
+
) {
|
|
477
|
+
throw error;
|
|
478
|
+
}
|
|
479
|
+
Log.warn(
|
|
480
|
+
'[CheckAllFirmwareRelease] Optional Protocol V2 firmware Plan is unavailable; using the release result'
|
|
481
|
+
);
|
|
482
|
+
firmwareUpdatePlan = undefined;
|
|
483
|
+
}
|
|
414
484
|
const firmwarePlan = summarizeProtocolV2FirmwareRelease(
|
|
415
485
|
plan,
|
|
416
486
|
PROTOCOL_V2_MAIN_FIRMWARE_TARGETS
|
|
@@ -442,8 +512,9 @@ export default class CheckAllFirmwareRelease extends BaseMethod {
|
|
|
442
512
|
resourceStatus,
|
|
443
513
|
resourceArchive: resourceSource,
|
|
444
514
|
resourcePreparationRequired,
|
|
445
|
-
hasUpgrade:
|
|
515
|
+
hasUpgrade: targetsToUpdate.length > 0,
|
|
446
516
|
targetsToUpdate,
|
|
517
|
+
firmwareUpdatePlan,
|
|
447
518
|
};
|
|
448
519
|
}
|
|
449
520
|
}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
getDeviceFirmwareVersion,
|
|
11
11
|
} from '../../utils/deviceVersionUtils';
|
|
12
12
|
|
|
13
|
+
import type { FirmwareUpdateV4Target } from '../../types/api/firmwareUpdate';
|
|
13
14
|
import type {
|
|
14
15
|
FirmwareUpdatePlan,
|
|
15
16
|
FirmwareUpdatePlanArtifact,
|
|
@@ -62,6 +63,11 @@ const PROTOCOL_V2_TARGETS: Readonly<
|
|
|
62
63
|
SE04: 'se04',
|
|
63
64
|
};
|
|
64
65
|
|
|
66
|
+
const PROTOCOL_V2_FIRMWARE_UPDATE_TARGETS = new Set<FirmwareUpdateV4Target>([
|
|
67
|
+
...Object.values(PROTOCOL_V2_TARGETS),
|
|
68
|
+
'resource',
|
|
69
|
+
]);
|
|
70
|
+
|
|
65
71
|
const asRecord = (value: unknown): Record<string, unknown> | undefined =>
|
|
66
72
|
value && typeof value === 'object' && !Array.isArray(value)
|
|
67
73
|
? (value as Record<string, unknown>)
|
|
@@ -191,6 +197,23 @@ export const validateFirmwareUpdatePlanForceTargets = (
|
|
|
191
197
|
return [...value] as FirmwareUpdatePlanForceTarget[];
|
|
192
198
|
};
|
|
193
199
|
|
|
200
|
+
export const validateProtocolV2FirmwareUpdateTargets = (
|
|
201
|
+
value: unknown
|
|
202
|
+
): FirmwareUpdateV4Target[] => {
|
|
203
|
+
if (value === undefined) {
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
if (
|
|
207
|
+
!Array.isArray(value) ||
|
|
208
|
+
value.length > PROTOCOL_V2_FIRMWARE_UPDATE_TARGETS.size ||
|
|
209
|
+
value.some(target => !PROTOCOL_V2_FIRMWARE_UPDATE_TARGETS.has(target)) ||
|
|
210
|
+
new Set(value).size !== value.length
|
|
211
|
+
) {
|
|
212
|
+
return planError('Protocol V2 firmware update targets are invalid');
|
|
213
|
+
}
|
|
214
|
+
return [...value] as FirmwareUpdateV4Target[];
|
|
215
|
+
};
|
|
216
|
+
|
|
194
217
|
const assertExactKeys = (
|
|
195
218
|
value: Record<string, unknown>,
|
|
196
219
|
required: readonly string[],
|
|
@@ -405,7 +428,7 @@ const selectResourceUrl = ({
|
|
|
405
428
|
|
|
406
429
|
const getExecutor = (features: Features): FirmwareUpdatePlan['executor'] => {
|
|
407
430
|
const deviceType = getDeviceType(features);
|
|
408
|
-
if (deviceType === EDeviceType.Pro2) {
|
|
431
|
+
if (deviceType === EDeviceType.Pro2 || deviceType === EDeviceType.Neo) {
|
|
409
432
|
return 'v4';
|
|
410
433
|
}
|
|
411
434
|
if (
|
|
@@ -422,9 +445,11 @@ const buildProtocolV2Artifacts = (
|
|
|
422
445
|
{
|
|
423
446
|
includeComponents = true,
|
|
424
447
|
includeResources = true,
|
|
448
|
+
componentTargets: selectedComponentTargets,
|
|
425
449
|
}: {
|
|
426
450
|
includeComponents?: boolean;
|
|
427
451
|
includeResources?: boolean;
|
|
452
|
+
componentTargets?: ReadonlySet<FirmwareUpdatePlanTarget>;
|
|
428
453
|
} = {}
|
|
429
454
|
): {
|
|
430
455
|
artifacts: FirmwareUpdatePlanArtifact[];
|
|
@@ -445,12 +470,21 @@ const buildProtocolV2Artifacts = (
|
|
|
445
470
|
includeComponents && components
|
|
446
471
|
? [...installOrder, ...Object.keys(components).filter(key => !installOrder.includes(key))]
|
|
447
472
|
: [];
|
|
473
|
+
const selectedComponentKeys = selectedComponentTargets
|
|
474
|
+
? componentKeys.filter(key => {
|
|
475
|
+
const component = asRecord(components?.[key]);
|
|
476
|
+
const targetName = asString(component?.target)?.toUpperCase();
|
|
477
|
+
const target = targetName ? PROTOCOL_V2_TARGETS[targetName] : undefined;
|
|
478
|
+
return !!target && selectedComponentTargets.has(target);
|
|
479
|
+
})
|
|
480
|
+
: componentKeys;
|
|
448
481
|
const artifacts: FirmwareUpdatePlanArtifact[] = [];
|
|
449
482
|
const targets: FirmwareUpdatePlanTarget[] = [];
|
|
450
|
-
const
|
|
451
|
-
for (const key of
|
|
483
|
+
const componentTargetSet = new Set<FirmwareUpdatePlanTarget>();
|
|
484
|
+
for (const key of selectedComponentKeys) {
|
|
452
485
|
const component = asRecord(components?.[key]);
|
|
453
486
|
const targetName = asString(component?.target)?.toUpperCase();
|
|
487
|
+
const target = targetName ? PROTOCOL_V2_TARGETS[targetName] : undefined;
|
|
454
488
|
if (targetName === 'ROMLOADER') {
|
|
455
489
|
throw ERRORS.TypedError(
|
|
456
490
|
HardwareErrorCode.RuntimeError,
|
|
@@ -458,7 +492,6 @@ const buildProtocolV2Artifacts = (
|
|
|
458
492
|
{ firmwareUpdateCode: 'FirmwarePlanInvalid' }
|
|
459
493
|
);
|
|
460
494
|
}
|
|
461
|
-
const target = targetName ? PROTOCOL_V2_TARGETS[targetName] : undefined;
|
|
462
495
|
if (!component || !target) {
|
|
463
496
|
throw ERRORS.TypedError(
|
|
464
497
|
HardwareErrorCode.RuntimeError,
|
|
@@ -466,14 +499,14 @@ const buildProtocolV2Artifacts = (
|
|
|
466
499
|
{ firmwareUpdateCode: 'FirmwarePlanInvalid' }
|
|
467
500
|
);
|
|
468
501
|
}
|
|
469
|
-
if (
|
|
502
|
+
if (componentTargetSet.has(target)) {
|
|
470
503
|
throw ERRORS.TypedError(
|
|
471
504
|
HardwareErrorCode.RuntimeError,
|
|
472
505
|
`Protocol V2 component ${key} duplicates target ${target}`,
|
|
473
506
|
{ firmwareUpdateCode: 'FirmwarePlanInvalid' }
|
|
474
507
|
);
|
|
475
508
|
}
|
|
476
|
-
|
|
509
|
+
componentTargetSet.add(target);
|
|
477
510
|
artifacts.push({
|
|
478
511
|
artifactId: `component:${target}`,
|
|
479
512
|
role: 'component',
|
|
@@ -587,6 +620,119 @@ const assertForcedTargetsRepresented = ({
|
|
|
587
620
|
}
|
|
588
621
|
};
|
|
589
622
|
|
|
623
|
+
const finalizeFirmwareUpdatePlan = ({
|
|
624
|
+
features,
|
|
625
|
+
firmwareType,
|
|
626
|
+
platform,
|
|
627
|
+
artifacts,
|
|
628
|
+
targetsToUpdate,
|
|
629
|
+
}: {
|
|
630
|
+
features: Features;
|
|
631
|
+
firmwareType: EFirmwareType;
|
|
632
|
+
platform: FirmwareUpdatePlatform;
|
|
633
|
+
artifacts: FirmwareUpdatePlanArtifact[];
|
|
634
|
+
targetsToUpdate: FirmwareUpdatePlanTarget[];
|
|
635
|
+
}): FirmwareUpdatePlan => {
|
|
636
|
+
const executor = getExecutor(features);
|
|
637
|
+
const bootloaderMode = resolveDeviceBootloaderMode(features);
|
|
638
|
+
// 'unavailable' is the reserved degraded-identity sentinel; a device-reported
|
|
639
|
+
// serial must never be able to collide with it.
|
|
640
|
+
const reportedIdentity = getDeviceUUID(features);
|
|
641
|
+
const deviceIdentity = reportedIdentity === 'unavailable' ? '' : reportedIdentity;
|
|
642
|
+
// Bootloader-mode classic-family devices (executor v2, e.g. classic1s) cannot report
|
|
643
|
+
// a serial number, so their recovery plans fall back to the degraded 'unavailable'
|
|
644
|
+
// identity. Binding is then enforced against the live device at install time instead
|
|
645
|
+
// (assertFirmwareUpdatePreparedPlanDeviceIdentity), and plan integrity by the digest.
|
|
646
|
+
// Pro (v3), Pro2, and Neo (v4) report a serial even in loader mode and stay strict.
|
|
647
|
+
if (
|
|
648
|
+
artifacts.length > 0 &&
|
|
649
|
+
(platform === 'native' || platform === 'desktop') &&
|
|
650
|
+
!deviceIdentity &&
|
|
651
|
+
!(bootloaderMode && executor === 'v2')
|
|
652
|
+
) {
|
|
653
|
+
throw ERRORS.TypedError(
|
|
654
|
+
HardwareErrorCode.RuntimeError,
|
|
655
|
+
'Prepared firmware update requires a stable device identity',
|
|
656
|
+
{ firmwareUpdateCode: 'FirmwarePlanInvalid' }
|
|
657
|
+
);
|
|
658
|
+
}
|
|
659
|
+
const planWithoutDigest: Omit<FirmwareUpdatePlan, 'planDigest'> = {
|
|
660
|
+
schemaVersion: 2,
|
|
661
|
+
executor,
|
|
662
|
+
deviceIdentity: deviceIdentity || 'unavailable',
|
|
663
|
+
deviceModel: String(getDeviceType(features)),
|
|
664
|
+
firmwareType,
|
|
665
|
+
platform,
|
|
666
|
+
artifacts,
|
|
667
|
+
targetsToUpdate,
|
|
668
|
+
};
|
|
669
|
+
return assertFirmwareUpdatePlan({
|
|
670
|
+
...planWithoutDigest,
|
|
671
|
+
planDigest: digestFirmwareUpdatePlan(planWithoutDigest),
|
|
672
|
+
});
|
|
673
|
+
};
|
|
674
|
+
|
|
675
|
+
export const buildProtocolV2FirmwareUpdatePlan = ({
|
|
676
|
+
features,
|
|
677
|
+
firmwareType,
|
|
678
|
+
platform,
|
|
679
|
+
release,
|
|
680
|
+
targetsToUpdate,
|
|
681
|
+
forceUpdateTargets,
|
|
682
|
+
resourceArchiveAvailable,
|
|
683
|
+
}: {
|
|
684
|
+
features: Features;
|
|
685
|
+
firmwareType: EFirmwareType;
|
|
686
|
+
platform: FirmwareUpdatePlatform;
|
|
687
|
+
release: ReleaseRecord | undefined;
|
|
688
|
+
targetsToUpdate: readonly FirmwareUpdateV4Target[];
|
|
689
|
+
forceUpdateTargets?: FirmwareUpdatePlanForceTarget[];
|
|
690
|
+
resourceArchiveAvailable: boolean;
|
|
691
|
+
}): FirmwareUpdatePlan => {
|
|
692
|
+
const validatedForceTargets = validateFirmwareUpdatePlanForceTargets(forceUpdateTargets);
|
|
693
|
+
if (validatedForceTargets.some(target => target === 'ble' || target === 'bootloader')) {
|
|
694
|
+
planError('Protocol V2 does not support forced BLE or legacy bootloader targets');
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
const requestedComponentTargets = new Set<FirmwareUpdatePlanTarget>(
|
|
698
|
+
targetsToUpdate.filter(target => target !== 'resource')
|
|
699
|
+
);
|
|
700
|
+
if (
|
|
701
|
+
getDeviceType(features) === EDeviceType.Neo &&
|
|
702
|
+
(requestedComponentTargets.has('se03') || requestedComponentTargets.has('se04'))
|
|
703
|
+
) {
|
|
704
|
+
planError('Neo does not support Protocol V2 targets se03 or se04');
|
|
705
|
+
}
|
|
706
|
+
const protocolV2 = buildProtocolV2Artifacts(release ?? {}, {
|
|
707
|
+
includeComponents: requestedComponentTargets.size > 0,
|
|
708
|
+
includeResources: false,
|
|
709
|
+
componentTargets: requestedComponentTargets,
|
|
710
|
+
});
|
|
711
|
+
const representedTargets = new Set(protocolV2.targets);
|
|
712
|
+
const missingTarget = Array.from(requestedComponentTargets).find(
|
|
713
|
+
target => !representedTargets.has(target)
|
|
714
|
+
);
|
|
715
|
+
if (missingTarget) {
|
|
716
|
+
planError(`Protocol V2 release does not contain requested target ${missingTarget}`);
|
|
717
|
+
}
|
|
718
|
+
if (validatedForceTargets.includes('firmware') && protocolV2.targets.length === 0) {
|
|
719
|
+
planError('Forced firmware update target firmware is not represented by the plan');
|
|
720
|
+
}
|
|
721
|
+
if (validatedForceTargets.includes('resource') && !resourceArchiveAvailable) {
|
|
722
|
+
planError('Forced firmware update target resource has no Protocol V2 resource archive');
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// Protocol V2 resource archives are materialized by the host into explicit
|
|
726
|
+
// resourceFiles. The prepared artifact plan therefore binds firmware components only.
|
|
727
|
+
return finalizeFirmwareUpdatePlan({
|
|
728
|
+
features,
|
|
729
|
+
firmwareType,
|
|
730
|
+
platform,
|
|
731
|
+
artifacts: protocolV2.artifacts,
|
|
732
|
+
targetsToUpdate: protocolV2.targets,
|
|
733
|
+
});
|
|
734
|
+
};
|
|
735
|
+
|
|
590
736
|
export const buildFirmwareUpdatePlan = ({
|
|
591
737
|
features,
|
|
592
738
|
firmwareType,
|
|
@@ -733,40 +879,11 @@ export const buildFirmwareUpdatePlan = ({
|
|
|
733
879
|
artifacts,
|
|
734
880
|
targetsToUpdate,
|
|
735
881
|
});
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
// serial must never be able to collide with it.
|
|
739
|
-
const reportedIdentity = getDeviceUUID(features);
|
|
740
|
-
const deviceIdentity = reportedIdentity === 'unavailable' ? '' : reportedIdentity;
|
|
741
|
-
// Bootloader-mode classic-family devices (executor v2, e.g. classic1s) cannot report
|
|
742
|
-
// a serial number, so their recovery plans fall back to the degraded 'unavailable'
|
|
743
|
-
// identity. Binding is then enforced against the live device at install time instead
|
|
744
|
-
// (assertFirmwareUpdatePreparedPlanDeviceIdentity), and plan integrity by the digest.
|
|
745
|
-
// Pro (v3) and Pro2 (v4) report a serial even in bootloader mode and stay strict.
|
|
746
|
-
if (
|
|
747
|
-
artifacts.length > 0 &&
|
|
748
|
-
(platform === 'native' || platform === 'desktop') &&
|
|
749
|
-
!deviceIdentity &&
|
|
750
|
-
!(bootloaderMode && executor === 'v2')
|
|
751
|
-
) {
|
|
752
|
-
throw ERRORS.TypedError(
|
|
753
|
-
HardwareErrorCode.RuntimeError,
|
|
754
|
-
'Prepared firmware update requires a stable device identity',
|
|
755
|
-
{ firmwareUpdateCode: 'FirmwarePlanInvalid' }
|
|
756
|
-
);
|
|
757
|
-
}
|
|
758
|
-
const planWithoutDigest: Omit<FirmwareUpdatePlan, 'planDigest'> = {
|
|
759
|
-
schemaVersion: 2,
|
|
760
|
-
executor,
|
|
761
|
-
deviceIdentity: deviceIdentity || 'unavailable',
|
|
762
|
-
deviceModel: String(getDeviceType(features)),
|
|
882
|
+
return finalizeFirmwareUpdatePlan({
|
|
883
|
+
features,
|
|
763
884
|
firmwareType,
|
|
764
885
|
platform,
|
|
765
886
|
artifacts,
|
|
766
887
|
targetsToUpdate,
|
|
767
|
-
};
|
|
768
|
-
return assertFirmwareUpdatePlan({
|
|
769
|
-
...planWithoutDigest,
|
|
770
|
-
planDigest: digestFirmwareUpdatePlan(planWithoutDigest),
|
|
771
888
|
});
|
|
772
889
|
};
|
|
@@ -135,6 +135,8 @@ export function toProtocolV2FirmwareReleaseInfo({
|
|
|
135
135
|
return {
|
|
136
136
|
shouldUpdate: plan.hasUpgrade,
|
|
137
137
|
status: plan.status === 'unavailable' ? 'unknown' : plan.status,
|
|
138
|
+
// Protocol V2 components share package-set release notes. The optional
|
|
139
|
+
// bootloaderChangelog field belongs to the legacy Protocol V1 release model.
|
|
138
140
|
changelog: plan.release ? [plan.release.changelog] : [],
|
|
139
141
|
release,
|
|
140
142
|
bootloaderMode: state.status.mode === 'bootloader' || state.status.mode === 'romloader',
|
|
@@ -89,6 +89,7 @@ export type CheckAllFirmwareReleaseParams = {
|
|
|
89
89
|
firmwareType?: EFirmwareType;
|
|
90
90
|
platform?: 'native' | 'desktop' | 'ext' | 'web' | 'web-embed';
|
|
91
91
|
forceUpdateTargets?: FirmwareUpdatePlanForceTarget[];
|
|
92
|
+
protocolV2ForceUpdateTargets?: FirmwareUpdateV4Target[];
|
|
92
93
|
};
|
|
93
94
|
|
|
94
95
|
export declare function checkAllFirmwareRelease(
|
|
@@ -328,7 +328,7 @@ export const getFirmwareUpdateField = ({
|
|
|
328
328
|
if (deviceType === EDeviceType.Pro) {
|
|
329
329
|
return latestFirmwareField;
|
|
330
330
|
}
|
|
331
|
-
if (deviceType === EDeviceType.Pro2) {
|
|
331
|
+
if (deviceType === EDeviceType.Pro2 || deviceType === EDeviceType.Neo) {
|
|
332
332
|
return 'firmware-v1';
|
|
333
333
|
}
|
|
334
334
|
return 'firmware';
|
|
@@ -374,7 +374,7 @@ export const getFirmwareUpdateFieldArray = (
|
|
|
374
374
|
return ['firmware-v8'];
|
|
375
375
|
}
|
|
376
376
|
|
|
377
|
-
if (deviceType === 'pro2') {
|
|
377
|
+
if (deviceType === 'pro2' || deviceType === 'neo') {
|
|
378
378
|
return ['firmware-v1'];
|
|
379
379
|
}
|
|
380
380
|
|