@onekeyfe/hd-core 1.2.0-alpha.97 → 1.2.0-alpha.99
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 +411 -86
- package/__tests__/check-firmware-release-protocol-v2.test.ts +199 -0
- package/__tests__/firmware-memory-host.test.ts +126 -0
- package/__tests__/firmware-update/device-update-bootloader.test.ts +14 -2
- package/__tests__/firmware-update/firmware-host-binding.test.ts +9 -0
- package/__tests__/firmware-update/firmware-prepared-host-digest.test.ts +573 -0
- package/__tests__/firmware-update/firmware-prepared-resource-archive.test.ts +150 -0
- package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +65 -2
- package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +80 -0
- package/__tests__/firmware-update/firmware-update-plan.test.ts +293 -71
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +53 -1
- package/__tests__/firmware-update/firmware-update-prepared-resource-executors.test.ts +326 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +2 -2
- package/__tests__/protocol-v2-firmware-targets.test.ts +16 -0
- package/__tests__/protocol-v2-resources.test.ts +148 -232
- package/__tests__/protocol-v2.test.ts +1326 -510
- package/dist/api/CheckAllFirmwareRelease.d.ts +2 -3
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/CheckBLEFirmwareRelease.d.ts +3 -2
- package/dist/api/CheckBLEFirmwareRelease.d.ts.map +1 -1
- package/dist/api/CheckBootloaderRelease.d.ts +2 -1
- package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
- package/dist/api/CheckFirmwareRelease.d.ts +3 -2
- package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +1 -0
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +11 -9
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/UploadPortfolio.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareHostBinding.d.ts +1 -1
- package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareMemoryHost.d.ts +22 -0
- package/dist/api/firmware/FirmwareMemoryHost.d.ts.map +1 -0
- package/dist/api/firmware/FirmwarePreparedResourceArchive.d.ts +11 -0
- package/dist/api/firmware/FirmwarePreparedResourceArchive.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +48 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +7 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +0 -1
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/protocolV2Release.d.ts +33 -0
- package/dist/api/firmware/protocolV2Release.d.ts.map +1 -0
- package/dist/data-manager/DataManager.d.ts +4 -3
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/index.d.ts +108 -114
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1825 -1006
- package/dist/protocols/protocol-v2/resources.d.ts +10 -28
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +20 -8
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/checkBLEFirmwareRelease.d.ts +2 -13
- package/dist/types/api/checkBLEFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/checkBootloaderRelease.d.ts +2 -6
- package/dist/types/api/checkBootloaderRelease.d.ts.map +1 -1
- package/dist/types/api/checkFirmwareRelease.d.ts +2 -13
- package/dist/types/api/checkFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/checkFirmwareTypeAvailable.d.ts +2 -2
- package/dist/types/api/checkFirmwareTypeAvailable.d.ts.map +1 -1
- package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +1 -1
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +4 -12
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdatePlan.d.ts +2 -2
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -1
- package/dist/types/settings.d.ts +35 -36
- package/dist/types/settings.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/CheckAllFirmwareRelease.ts +113 -80
- package/src/api/CheckBLEFirmwareRelease.ts +37 -5
- package/src/api/CheckBootloaderRelease.ts +35 -3
- package/src/api/CheckFirmwareRelease.ts +35 -7
- package/src/api/FirmwareUpdateV2.ts +231 -138
- package/src/api/FirmwareUpdateV3.ts +101 -56
- package/src/api/FirmwareUpdateV4.ts +936 -408
- package/src/api/UploadPortfolio.ts +18 -0
- package/src/api/device/DeviceUpdateBootloader.ts +37 -11
- package/src/api/firmware/FirmwareHostBinding.ts +26 -3
- package/src/api/firmware/FirmwareMemoryHost.ts +143 -0
- package/src/api/firmware/FirmwarePreparedResourceArchive.ts +207 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +122 -73
- package/src/api/firmware/FirmwareUpdatePlan.ts +295 -122
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +49 -12
- package/src/api/firmware/protocolV2Release.ts +168 -0
- package/src/data-manager/DataManager.ts +35 -19
- package/src/index.ts +10 -0
- package/src/protocols/protocol-v2/resources.ts +157 -341
- package/src/types/api/checkAllFirmwareRelease.ts +27 -12
- package/src/types/api/checkBLEFirmwareRelease.ts +4 -13
- package/src/types/api/checkBootloaderRelease.ts +2 -6
- package/src/types/api/checkFirmwareRelease.ts +2 -13
- package/src/types/api/checkFirmwareTypeAvailable.ts +2 -2
- package/src/types/api/deviceUpdateBootloader.ts +1 -0
- package/src/types/api/export.ts +6 -1
- package/src/types/api/firmwareUpdate.ts +12 -17
- package/src/types/api/firmwareUpdatePlan.ts +2 -2
- package/src/types/settings.ts +35 -61
- package/src/utils/deviceFeaturesUtils.ts +2 -2
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
2
|
+
import { bytesToHex } from '@noble/hashes/utils';
|
|
3
|
+
import { EFirmwareType } from '@onekeyfe/hd-shared';
|
|
4
|
+
import JSZip from 'jszip';
|
|
5
|
+
|
|
6
|
+
import { readVerifiedPreparedResourceArchive } from '../../src/api/firmware/FirmwarePreparedResourceArchive';
|
|
7
|
+
import { prepareFirmwareUpdatePlan } from '../../src/api/firmware/FirmwareUpdatePreparedPlan';
|
|
8
|
+
import { digestFirmwareUpdateContract } from '../../src/api/firmware/FirmwareUpdatePlan';
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
FirmwareArtifactReader,
|
|
12
|
+
FirmwareArtifactReference,
|
|
13
|
+
} from '../../src/types/api/firmwareUpdate';
|
|
14
|
+
import type { FirmwareUpdatePlan } from '../../src/types/api/firmwareUpdatePlan';
|
|
15
|
+
|
|
16
|
+
jest.mock('../../src/data/config', () => ({
|
|
17
|
+
getSDKVersion: jest.fn(() => '1.0.0'),
|
|
18
|
+
DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
const createReference = (artifactRef: string, binary: ArrayBuffer): FirmwareArtifactReference => ({
|
|
22
|
+
artifactRef,
|
|
23
|
+
size: binary.byteLength,
|
|
24
|
+
sha256: bytesToHex(sha256(new Uint8Array(binary))),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const createReader = (artifacts: Map<string, ArrayBuffer>): FirmwareArtifactReader => {
|
|
28
|
+
const opened = new Map<string, ArrayBuffer>();
|
|
29
|
+
let sequence = 0;
|
|
30
|
+
return {
|
|
31
|
+
open({ artifactRef }) {
|
|
32
|
+
const binary = artifacts.get(artifactRef);
|
|
33
|
+
if (!binary) throw new Error(`missing artifact: ${artifactRef}`);
|
|
34
|
+
sequence += 1;
|
|
35
|
+
const readerId = `reader-${sequence}`;
|
|
36
|
+
opened.set(readerId, binary);
|
|
37
|
+
return Promise.resolve({ readerId, size: binary.byteLength });
|
|
38
|
+
},
|
|
39
|
+
read({ readerId, offset, length }) {
|
|
40
|
+
const binary = opened.get(readerId);
|
|
41
|
+
if (!binary) throw new Error(`missing reader: ${readerId}`);
|
|
42
|
+
const data = binary.slice(offset, offset + length);
|
|
43
|
+
return Promise.resolve({
|
|
44
|
+
data,
|
|
45
|
+
bytesRead: data.byteLength,
|
|
46
|
+
eof: offset + length === binary.byteLength,
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
close({ readerId }) {
|
|
50
|
+
opened.delete(readerId);
|
|
51
|
+
return Promise.resolve();
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const createPreparedResourcePlan = ({
|
|
57
|
+
executor,
|
|
58
|
+
archiveBinary,
|
|
59
|
+
entryBinary,
|
|
60
|
+
}: {
|
|
61
|
+
executor: 'v2' | 'v3';
|
|
62
|
+
archiveBinary: ArrayBuffer;
|
|
63
|
+
entryBinary: ArrayBuffer;
|
|
64
|
+
}) => {
|
|
65
|
+
const archiveArtifact = createReference('resource-archive', archiveBinary);
|
|
66
|
+
const entryArtifact = createReference('resource-entry', entryBinary);
|
|
67
|
+
const planWithoutDigest: Omit<FirmwareUpdatePlan, 'planDigest'> = {
|
|
68
|
+
schemaVersion: 2,
|
|
69
|
+
executor,
|
|
70
|
+
deviceIdentity: `${executor}-device`,
|
|
71
|
+
deviceModel: executor === 'v2' ? 'TOUCH' : 'PRO',
|
|
72
|
+
firmwareType: EFirmwareType.Universal,
|
|
73
|
+
platform: 'desktop',
|
|
74
|
+
artifacts: [
|
|
75
|
+
{
|
|
76
|
+
artifactId: 'resource',
|
|
77
|
+
role: 'resource',
|
|
78
|
+
target: 'resource',
|
|
79
|
+
url: 'https://firmware.onekey.so/resource.zip',
|
|
80
|
+
container: 'zip',
|
|
81
|
+
expectedSize: archiveArtifact.size,
|
|
82
|
+
expectedSha256: archiveArtifact.sha256,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
targetsToUpdate: ['resource'],
|
|
86
|
+
};
|
|
87
|
+
const plan: FirmwareUpdatePlan = {
|
|
88
|
+
...planWithoutDigest,
|
|
89
|
+
planDigest: digestFirmwareUpdateContract(planWithoutDigest),
|
|
90
|
+
};
|
|
91
|
+
return {
|
|
92
|
+
archiveArtifact,
|
|
93
|
+
preparedPlan: prepareFirmwareUpdatePlan({
|
|
94
|
+
plan,
|
|
95
|
+
leaseRef: `${executor}-resource-lease`,
|
|
96
|
+
artifacts: [
|
|
97
|
+
{
|
|
98
|
+
artifactId: 'resource',
|
|
99
|
+
artifact: archiveArtifact,
|
|
100
|
+
materializedEntries: [{ entryName: 'images/logo.bin', artifact: entryArtifact }],
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
}),
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
describe.each(['v2', 'v3'] as const)('%s prepared resource archive binding', executor => {
|
|
108
|
+
test('uses canonical bytes extracted from the approved ZIP', async () => {
|
|
109
|
+
const entryBinary = Uint8Array.from([1, 2, 3, 4]).buffer;
|
|
110
|
+
const zip = new JSZip();
|
|
111
|
+
zip.file('images/logo.bin', entryBinary);
|
|
112
|
+
const archiveBinary = await zip.generateAsync({ type: 'arraybuffer' });
|
|
113
|
+
const { archiveArtifact, preparedPlan } = createPreparedResourcePlan({
|
|
114
|
+
executor,
|
|
115
|
+
archiveBinary,
|
|
116
|
+
entryBinary,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const result = await readVerifiedPreparedResourceArchive({
|
|
120
|
+
preparedPlan,
|
|
121
|
+
reader: createReader(new Map([[archiveArtifact.artifactRef, archiveBinary]])),
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
expect(result).toHaveLength(1);
|
|
125
|
+
expect(result[0].entryName).toBe('logo.bin');
|
|
126
|
+
expect(new Uint8Array(result[0].binary)).toEqual(new Uint8Array(entryBinary));
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('rejects entries that are not derived from the approved ZIP', async () => {
|
|
130
|
+
const approvedEntry = Uint8Array.from([1, 2, 3, 4]).buffer;
|
|
131
|
+
const substitutedEntry = Uint8Array.from([9, 9, 9, 9]).buffer;
|
|
132
|
+
const zip = new JSZip();
|
|
133
|
+
zip.file('images/logo.bin', approvedEntry);
|
|
134
|
+
const archiveBinary = await zip.generateAsync({ type: 'arraybuffer' });
|
|
135
|
+
const { archiveArtifact, preparedPlan } = createPreparedResourcePlan({
|
|
136
|
+
executor,
|
|
137
|
+
archiveBinary,
|
|
138
|
+
entryBinary: substitutedEntry,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
await expect(
|
|
142
|
+
readVerifiedPreparedResourceArchive({
|
|
143
|
+
preparedPlan,
|
|
144
|
+
reader: createReader(new Map([[archiveArtifact.artifactRef, archiveBinary]])),
|
|
145
|
+
})
|
|
146
|
+
).rejects.toMatchObject({
|
|
147
|
+
params: { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' },
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -231,7 +231,7 @@ describe.each([
|
|
|
231
231
|
jest.restoreAllMocks();
|
|
232
232
|
});
|
|
233
233
|
|
|
234
|
-
test('
|
|
234
|
+
test('resumes bounded polling after browser authorization returns an empty enumeration', async () => {
|
|
235
235
|
jest.spyOn(DataManager, 'getSettings').mockReturnValue('webusb' as never);
|
|
236
236
|
jest.spyOn(DataManager, 'isBleConnect').mockReturnValue(false);
|
|
237
237
|
jest.spyOn(DataManager, 'isBrowserWebUsb').mockReturnValue(true);
|
|
@@ -300,13 +300,76 @@ describe.each([
|
|
|
300
300
|
}
|
|
301
301
|
expect(rejected).not.toHaveBeenCalled();
|
|
302
302
|
|
|
303
|
-
permissionGranted = true;
|
|
304
303
|
resolvePrompt('bootloader-device');
|
|
305
304
|
await flush();
|
|
306
305
|
await flush();
|
|
307
306
|
|
|
307
|
+
// The chooser may resolve before the newly authorized device appears in the
|
|
308
|
+
// next WebUSB enumeration. That transient empty result must not strand the
|
|
309
|
+
// deferred check after its original interval and timeout were cleared.
|
|
310
|
+
expect(resolved).not.toHaveBeenCalled();
|
|
311
|
+
expect(rejected).not.toHaveBeenCalled();
|
|
312
|
+
|
|
313
|
+
permissionGranted = true;
|
|
314
|
+
for (let elapsed = 0; elapsed < 5000; elapsed += 500) {
|
|
315
|
+
jest.advanceTimersByTime(500);
|
|
316
|
+
// eslint-disable-next-line no-await-in-loop
|
|
317
|
+
await flush();
|
|
318
|
+
if (resolved.mock.calls.length) break;
|
|
319
|
+
}
|
|
320
|
+
|
|
308
321
|
expect(resolved).toHaveBeenCalledWith(true);
|
|
309
322
|
expect(updateFromCache).toHaveBeenCalledWith(bootloaderDevice);
|
|
310
323
|
expect(commands.disposed).toBe(false);
|
|
311
324
|
});
|
|
325
|
+
|
|
326
|
+
test('rejects after the fresh deadline when the authorized device never appears', async () => {
|
|
327
|
+
jest.spyOn(DataManager, 'getSettings').mockReturnValue('webusb' as never);
|
|
328
|
+
jest.spyOn(DataManager, 'isBleConnect').mockReturnValue(false);
|
|
329
|
+
jest.spyOn(DataManager, 'isBrowserWebUsb').mockReturnValue(true);
|
|
330
|
+
jest.spyOn(DevicePool, 'getDevices').mockResolvedValue({ devices: {}, deviceList: [] });
|
|
331
|
+
|
|
332
|
+
const method = buildMethod();
|
|
333
|
+
method.device = {
|
|
334
|
+
originalDescriptor: {
|
|
335
|
+
id: WEBUSB_ID,
|
|
336
|
+
path: WEBUSB_ID,
|
|
337
|
+
protocolType: 'V1',
|
|
338
|
+
},
|
|
339
|
+
deviceConnector: {
|
|
340
|
+
enumerate: jest.fn().mockResolvedValue({ descriptors: [] }),
|
|
341
|
+
},
|
|
342
|
+
commands: { disposed: true },
|
|
343
|
+
updateFromCache: jest.fn(),
|
|
344
|
+
getCurrentDeviceType: jest.fn(() => EDeviceType.Pro),
|
|
345
|
+
} as unknown as Device;
|
|
346
|
+
method.postTipMessage = jest.fn();
|
|
347
|
+
const prompt = jest
|
|
348
|
+
.spyOn(method as any, '_promptDeviceInBootloaderForWebDevice')
|
|
349
|
+
.mockResolvedValue('bootloader-device');
|
|
350
|
+
|
|
351
|
+
method.checkDeviceToBootloader(WEBUSB_ID);
|
|
352
|
+
const resolved = jest.fn();
|
|
353
|
+
const rejected = jest.fn();
|
|
354
|
+
method.checkPromise?.promise.then(resolved, rejected);
|
|
355
|
+
|
|
356
|
+
for (let elapsed = 0; elapsed < 15000; elapsed += 500) {
|
|
357
|
+
jest.advanceTimersByTime(500);
|
|
358
|
+
// eslint-disable-next-line no-await-in-loop
|
|
359
|
+
await flush();
|
|
360
|
+
if (prompt.mock.calls.length) break;
|
|
361
|
+
}
|
|
362
|
+
expect(prompt).toHaveBeenCalledTimes(1);
|
|
363
|
+
|
|
364
|
+
for (let elapsed = 0; elapsed < 31000; elapsed += 500) {
|
|
365
|
+
jest.advanceTimersByTime(500);
|
|
366
|
+
// eslint-disable-next-line no-await-in-loop
|
|
367
|
+
await flush();
|
|
368
|
+
if (rejected.mock.calls.length) break;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
expect(resolved).not.toHaveBeenCalled();
|
|
372
|
+
expect(rejected).toHaveBeenCalledTimes(1);
|
|
373
|
+
expect(prompt).toHaveBeenCalledTimes(1);
|
|
374
|
+
});
|
|
312
375
|
});
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
|
|
2
2
|
|
|
3
3
|
import { buildFirmwareUpdatePlan } from '../../src/api/firmware/FirmwareUpdatePlan';
|
|
4
|
+
import {
|
|
5
|
+
registerFirmwareUpdateHostBinding,
|
|
6
|
+
unregisterFirmwareUpdateHostBinding,
|
|
7
|
+
} from '../../src/api/firmware/FirmwareHostBinding';
|
|
4
8
|
import {
|
|
5
9
|
assertFirmwareUpdatePreparedPlanDeviceIdentity,
|
|
6
10
|
prepareFirmwareUpdatePlan,
|
|
@@ -179,6 +183,19 @@ describe('firmware update plan identity in bootloader mode', () => {
|
|
|
179
183
|
],
|
|
180
184
|
});
|
|
181
185
|
};
|
|
186
|
+
const createBinding = (preparedPlanDigest: string) => ({
|
|
187
|
+
preparedPlanDigest,
|
|
188
|
+
artifactReader: {
|
|
189
|
+
open: () => Promise.resolve({ readerId: 'unused', size: 0 }),
|
|
190
|
+
read: () =>
|
|
191
|
+
Promise.resolve({
|
|
192
|
+
data: new ArrayBuffer(0),
|
|
193
|
+
bytesRead: 0,
|
|
194
|
+
eof: true,
|
|
195
|
+
}),
|
|
196
|
+
close: () => Promise.resolve(),
|
|
197
|
+
},
|
|
198
|
+
});
|
|
182
199
|
|
|
183
200
|
test('accepts the phase that runs after the device reboots and reports a serial', () => {
|
|
184
201
|
const preparedPlan = prepareRecoveryPlan();
|
|
@@ -250,6 +267,69 @@ describe('firmware update plan identity in bootloader mode', () => {
|
|
|
250
267
|
})
|
|
251
268
|
).not.toThrow();
|
|
252
269
|
});
|
|
270
|
+
|
|
271
|
+
test('releases the identity pin when the digest-bound host workflow ends', () => {
|
|
272
|
+
const preparedPlan = prepareRecoveryPlan();
|
|
273
|
+
const firstGeneration = registerFirmwareUpdateHostBinding(
|
|
274
|
+
createBinding(preparedPlan.preparedPlanDigest)
|
|
275
|
+
);
|
|
276
|
+
try {
|
|
277
|
+
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
278
|
+
preparedPlan,
|
|
279
|
+
deviceIdentity: 'CLA45F0023',
|
|
280
|
+
bootloaderMode: false,
|
|
281
|
+
deviceModel: String(EDeviceType.Classic1s),
|
|
282
|
+
});
|
|
283
|
+
} finally {
|
|
284
|
+
expect(unregisterFirmwareUpdateHostBinding(firstGeneration)).toBe(true);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const secondGeneration = registerFirmwareUpdateHostBinding(
|
|
288
|
+
createBinding(preparedPlan.preparedPlanDigest)
|
|
289
|
+
);
|
|
290
|
+
try {
|
|
291
|
+
expect(() =>
|
|
292
|
+
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
293
|
+
preparedPlan,
|
|
294
|
+
deviceIdentity: 'CLA99Z9999',
|
|
295
|
+
bootloaderMode: false,
|
|
296
|
+
deviceModel: String(EDeviceType.Classic1s),
|
|
297
|
+
})
|
|
298
|
+
).not.toThrow();
|
|
299
|
+
} finally {
|
|
300
|
+
expect(unregisterFirmwareUpdateHostBinding(secondGeneration)).toBe(true);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
test('a stale unregister cannot release the active workflow identity pin', () => {
|
|
305
|
+
const stalePlan = prepareRecoveryPlan();
|
|
306
|
+
const staleGeneration = registerFirmwareUpdateHostBinding(
|
|
307
|
+
createBinding(stalePlan.preparedPlanDigest)
|
|
308
|
+
);
|
|
309
|
+
const activePlan = prepareRecoveryPlan();
|
|
310
|
+
const activeGeneration = registerFirmwareUpdateHostBinding(
|
|
311
|
+
createBinding(activePlan.preparedPlanDigest)
|
|
312
|
+
);
|
|
313
|
+
try {
|
|
314
|
+
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
315
|
+
preparedPlan: activePlan,
|
|
316
|
+
deviceIdentity: 'CLA45F0023',
|
|
317
|
+
bootloaderMode: false,
|
|
318
|
+
deviceModel: String(EDeviceType.Classic1s),
|
|
319
|
+
});
|
|
320
|
+
expect(unregisterFirmwareUpdateHostBinding(staleGeneration)).toBe(false);
|
|
321
|
+
expect(() =>
|
|
322
|
+
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
323
|
+
preparedPlan: activePlan,
|
|
324
|
+
deviceIdentity: 'CLA99Z9999',
|
|
325
|
+
bootloaderMode: false,
|
|
326
|
+
deviceModel: String(EDeviceType.Classic1s),
|
|
327
|
+
})
|
|
328
|
+
).toThrow();
|
|
329
|
+
} finally {
|
|
330
|
+
expect(unregisterFirmwareUpdateHostBinding(activeGeneration)).toBe(true);
|
|
331
|
+
}
|
|
332
|
+
});
|
|
253
333
|
});
|
|
254
334
|
|
|
255
335
|
describe('prepared plan device identity assertion', () => {
|