@onekeyfe/hd-core 1.2.0-alpha.93 → 1.2.0-alpha.95
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__/firmware-update/firmware-prepared-host-digest.test.ts +239 -0
- package/__tests__/protocol-v2.test.ts +127 -33
- package/dist/api/FirmwareUpdateV2.d.ts +1 -0
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +1 -0
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +83 -40
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV2.ts +7 -0
- package/src/api/FirmwareUpdateV3.ts +5 -5
- package/src/api/FirmwareUpdateV4.ts +83 -38
- package/src/api/device/DeviceUpdateBootloader.ts +19 -5
- package/src/types/api/firmwareUpdate.ts +1 -0
|
@@ -2,6 +2,7 @@ import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
|
|
|
2
2
|
|
|
3
3
|
import FirmwareUpdateV2 from '../../src/api/FirmwareUpdateV2';
|
|
4
4
|
import FirmwareUpdateV3 from '../../src/api/FirmwareUpdateV3';
|
|
5
|
+
import FirmwareUpdateV4 from '../../src/api/FirmwareUpdateV4';
|
|
5
6
|
import DeviceUpdateBootloader from '../../src/api/device/DeviceUpdateBootloader';
|
|
6
7
|
import {
|
|
7
8
|
registerFirmwareUpdateHostBinding,
|
|
@@ -95,6 +96,47 @@ const registerMismatchedHost = () => {
|
|
|
95
96
|
return { artifactReader, hostBindingGeneration };
|
|
96
97
|
};
|
|
97
98
|
|
|
99
|
+
const createPreparedV4Plan = () => {
|
|
100
|
+
const sha256 = 'c'.repeat(64);
|
|
101
|
+
const artifact: FirmwareArtifactReference = {
|
|
102
|
+
artifactRef: `fw:${sha256}`,
|
|
103
|
+
size: 4,
|
|
104
|
+
sha256,
|
|
105
|
+
};
|
|
106
|
+
const plan = buildFirmwareUpdatePlan({
|
|
107
|
+
features: {
|
|
108
|
+
deviceType: EDeviceType.Pro2,
|
|
109
|
+
serialNo: 'pro2-device-id',
|
|
110
|
+
firmwareVersion: '1.0.0',
|
|
111
|
+
bootloaderVersion: '1.0.0',
|
|
112
|
+
} as Features,
|
|
113
|
+
firmwareType: EFirmwareType.Universal,
|
|
114
|
+
platform: 'desktop',
|
|
115
|
+
firmware: {
|
|
116
|
+
status: 'outdated',
|
|
117
|
+
release: {
|
|
118
|
+
components: {
|
|
119
|
+
applicationP1: {
|
|
120
|
+
target: 'APPLICATION_P1',
|
|
121
|
+
url: 'https://firmware.onekey.so/pro2/application-p1.bin',
|
|
122
|
+
expectedSize: artifact.size,
|
|
123
|
+
fingerprint: artifact.sha256,
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
ble: noUpdate,
|
|
129
|
+
bootloader: noUpdate,
|
|
130
|
+
});
|
|
131
|
+
expect(plan.executor).toBe('v4');
|
|
132
|
+
const preparedPlan = prepareFirmwareUpdatePlan({
|
|
133
|
+
plan,
|
|
134
|
+
leaseRef: 'fwlease:v4:app_v1',
|
|
135
|
+
artifacts: [{ artifactId: 'component:app_v1', artifact }],
|
|
136
|
+
});
|
|
137
|
+
return { artifact, preparedPlan };
|
|
138
|
+
};
|
|
139
|
+
|
|
98
140
|
describe('prepared firmware host digest binding', () => {
|
|
99
141
|
afterEach(() => {
|
|
100
142
|
unregisterFirmwareUpdateHostBinding();
|
|
@@ -123,6 +165,51 @@ describe('prepared firmware host digest binding', () => {
|
|
|
123
165
|
expect(artifactReader.open).not.toHaveBeenCalled();
|
|
124
166
|
});
|
|
125
167
|
|
|
168
|
+
test('FirmwareUpdateV2 rejects a direct reader when the prepared host generation is missing', () => {
|
|
169
|
+
const { artifact, preparedPlan } = createPreparedPlan({
|
|
170
|
+
executor: 'v2',
|
|
171
|
+
target: 'firmware',
|
|
172
|
+
});
|
|
173
|
+
const directArtifactReader = {
|
|
174
|
+
open: jest.fn(),
|
|
175
|
+
read: jest.fn(),
|
|
176
|
+
close: jest.fn(),
|
|
177
|
+
};
|
|
178
|
+
const method = new FirmwareUpdateV2({
|
|
179
|
+
id: 1,
|
|
180
|
+
payload: {
|
|
181
|
+
method: 'firmwareUpdateV2',
|
|
182
|
+
platform: 'desktop',
|
|
183
|
+
updateType: 'firmware',
|
|
184
|
+
artifact,
|
|
185
|
+
preparedPlan,
|
|
186
|
+
artifactReader: directArtifactReader,
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
expect(() => method.init()).toThrow('host binding generation NaN is stale');
|
|
191
|
+
expect(directArtifactReader.open).not.toHaveBeenCalled();
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test('FirmwareUpdateV2 does not treat a binary call carrying a prepared plan as legacy', () => {
|
|
195
|
+
const { preparedPlan } = createPreparedPlan({
|
|
196
|
+
executor: 'v2',
|
|
197
|
+
target: 'firmware',
|
|
198
|
+
});
|
|
199
|
+
const method = new FirmwareUpdateV2({
|
|
200
|
+
id: 1,
|
|
201
|
+
payload: {
|
|
202
|
+
method: 'firmwareUpdateV2',
|
|
203
|
+
platform: 'desktop',
|
|
204
|
+
updateType: 'firmware',
|
|
205
|
+
binary: new ArrayBuffer(4),
|
|
206
|
+
preparedPlan,
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
expect(() => method.init()).toThrow('Prepared firmware plans require a prepared artifact');
|
|
211
|
+
});
|
|
212
|
+
|
|
126
213
|
test('FirmwareUpdateV3 rejects a host registered for another prepared plan', () => {
|
|
127
214
|
const { artifact, preparedPlan } = createPreparedPlan({
|
|
128
215
|
executor: 'v3',
|
|
@@ -144,6 +231,31 @@ describe('prepared firmware host digest binding', () => {
|
|
|
144
231
|
expect(artifactReader.open).not.toHaveBeenCalled();
|
|
145
232
|
});
|
|
146
233
|
|
|
234
|
+
test('FirmwareUpdateV3 rejects a direct reader when the prepared host generation is missing', () => {
|
|
235
|
+
const { artifact, preparedPlan } = createPreparedPlan({
|
|
236
|
+
executor: 'v3',
|
|
237
|
+
target: 'firmware',
|
|
238
|
+
});
|
|
239
|
+
const directArtifactReader = {
|
|
240
|
+
open: jest.fn(),
|
|
241
|
+
read: jest.fn(),
|
|
242
|
+
close: jest.fn(),
|
|
243
|
+
};
|
|
244
|
+
const method = new FirmwareUpdateV3({
|
|
245
|
+
id: 1,
|
|
246
|
+
payload: {
|
|
247
|
+
method: 'firmwareUpdateV3',
|
|
248
|
+
platform: 'desktop',
|
|
249
|
+
artifacts: { firmware: artifact },
|
|
250
|
+
preparedPlan,
|
|
251
|
+
artifactReader: directArtifactReader,
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
expect(() => method.init()).toThrow('host binding generation NaN is stale');
|
|
256
|
+
expect(directArtifactReader.open).not.toHaveBeenCalled();
|
|
257
|
+
});
|
|
258
|
+
|
|
147
259
|
test('DeviceUpdateBootloader rejects a host registered for another prepared plan', async () => {
|
|
148
260
|
const { artifact, preparedPlan } = createPreparedPlan({
|
|
149
261
|
executor: 'v2',
|
|
@@ -170,6 +282,133 @@ describe('prepared firmware host digest binding', () => {
|
|
|
170
282
|
expect(artifactReader.open).not.toHaveBeenCalled();
|
|
171
283
|
});
|
|
172
284
|
|
|
285
|
+
test('DeviceUpdateBootloader rejects a direct reader when the prepared host generation is missing', async () => {
|
|
286
|
+
const { artifact, preparedPlan } = createPreparedPlan({
|
|
287
|
+
executor: 'v2',
|
|
288
|
+
target: 'bootloader',
|
|
289
|
+
});
|
|
290
|
+
const directArtifactReader = {
|
|
291
|
+
open: jest.fn(),
|
|
292
|
+
read: jest.fn(),
|
|
293
|
+
close: jest.fn(),
|
|
294
|
+
};
|
|
295
|
+
const method = new DeviceUpdateBootloader({
|
|
296
|
+
id: 1,
|
|
297
|
+
payload: {
|
|
298
|
+
method: 'deviceUpdateBootloader',
|
|
299
|
+
artifact,
|
|
300
|
+
preparedPlan,
|
|
301
|
+
artifactReader: directArtifactReader,
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
method.device = {
|
|
305
|
+
features: {
|
|
306
|
+
deviceType: EDeviceType.Classic1s,
|
|
307
|
+
serialNo: 'classic-device-id',
|
|
308
|
+
},
|
|
309
|
+
} as any;
|
|
310
|
+
|
|
311
|
+
await expect(method.run()).rejects.toThrow('host binding generation NaN is stale');
|
|
312
|
+
expect(directArtifactReader.open).not.toHaveBeenCalled();
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
test('DeviceUpdateBootloader does not treat a binary call carrying a prepared plan as legacy', async () => {
|
|
316
|
+
const { preparedPlan } = createPreparedPlan({
|
|
317
|
+
executor: 'v2',
|
|
318
|
+
target: 'bootloader',
|
|
319
|
+
});
|
|
320
|
+
const method = new DeviceUpdateBootloader({
|
|
321
|
+
id: 1,
|
|
322
|
+
payload: {
|
|
323
|
+
method: 'deviceUpdateBootloader',
|
|
324
|
+
binary: new ArrayBuffer(4),
|
|
325
|
+
preparedPlan,
|
|
326
|
+
},
|
|
327
|
+
});
|
|
328
|
+
method.device = { features: undefined } as any;
|
|
329
|
+
|
|
330
|
+
await expect(method.run()).rejects.toThrow(
|
|
331
|
+
'Prepared bootloader plans require exactly one prepared artifact'
|
|
332
|
+
);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
test('FirmwareUpdateV4 rejects a prepared plan without a host binding generation', () => {
|
|
336
|
+
const { preparedPlan } = createPreparedV4Plan();
|
|
337
|
+
const directArtifactReader = {
|
|
338
|
+
open: jest.fn(),
|
|
339
|
+
read: jest.fn(),
|
|
340
|
+
close: jest.fn(),
|
|
341
|
+
};
|
|
342
|
+
const method = new FirmwareUpdateV4({
|
|
343
|
+
id: 1,
|
|
344
|
+
payload: {
|
|
345
|
+
method: 'firmwareUpdateV4',
|
|
346
|
+
platform: 'desktop',
|
|
347
|
+
preparedPlan,
|
|
348
|
+
artifactReader: directArtifactReader,
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
expect(() => method.init()).toThrow('host binding generation NaN is stale');
|
|
353
|
+
expect(directArtifactReader.open).not.toHaveBeenCalled();
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
test('FirmwareUpdateV4 rejects a host registered for another prepared plan', () => {
|
|
357
|
+
const { preparedPlan } = createPreparedV4Plan();
|
|
358
|
+
const { artifactReader, hostBindingGeneration } = registerMismatchedHost();
|
|
359
|
+
const method = new FirmwareUpdateV4({
|
|
360
|
+
id: 1,
|
|
361
|
+
payload: {
|
|
362
|
+
method: 'firmwareUpdateV4',
|
|
363
|
+
platform: 'desktop',
|
|
364
|
+
preparedPlan,
|
|
365
|
+
hostBindingGeneration,
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
expect(() => method.init()).toThrow('does not match the prepared plan');
|
|
370
|
+
expect(artifactReader.open).not.toHaveBeenCalled();
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
test('FirmwareUpdateV4 obtains the prepared reader only from the digest-bound host', async () => {
|
|
374
|
+
const { artifact, preparedPlan } = createPreparedV4Plan();
|
|
375
|
+
const directArtifactReader = {
|
|
376
|
+
open: jest.fn(),
|
|
377
|
+
read: jest.fn(),
|
|
378
|
+
close: jest.fn(),
|
|
379
|
+
};
|
|
380
|
+
const boundArtifactReader = {
|
|
381
|
+
open: jest.fn().mockResolvedValue({ readerId: 'bound-reader', size: artifact.size }),
|
|
382
|
+
read: jest.fn(),
|
|
383
|
+
close: jest.fn(),
|
|
384
|
+
};
|
|
385
|
+
const hostBindingGeneration = registerFirmwareUpdateHostBinding({
|
|
386
|
+
preparedPlanDigest: preparedPlan.preparedPlanDigest,
|
|
387
|
+
artifactReader: boundArtifactReader,
|
|
388
|
+
});
|
|
389
|
+
const method = new FirmwareUpdateV4({
|
|
390
|
+
id: 1,
|
|
391
|
+
payload: {
|
|
392
|
+
method: 'firmwareUpdateV4',
|
|
393
|
+
platform: 'desktop',
|
|
394
|
+
preparedPlan,
|
|
395
|
+
hostBindingGeneration,
|
|
396
|
+
artifactReader: directArtifactReader,
|
|
397
|
+
},
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
method.init();
|
|
401
|
+
const executionReader = (
|
|
402
|
+
method as unknown as {
|
|
403
|
+
params: { artifactReader: typeof boundArtifactReader };
|
|
404
|
+
}
|
|
405
|
+
).params.artifactReader;
|
|
406
|
+
await executionReader.open({ artifactRef: artifact.artifactRef });
|
|
407
|
+
|
|
408
|
+
expect(boundArtifactReader.open).toHaveBeenCalledWith({ artifactRef: artifact.artifactRef });
|
|
409
|
+
expect(directArtifactReader.open).not.toHaveBeenCalled();
|
|
410
|
+
});
|
|
411
|
+
|
|
173
412
|
test('keeps non-prepared direct binary calls on the legacy paths', async () => {
|
|
174
413
|
const v2 = new FirmwareUpdateV2({
|
|
175
414
|
id: 1,
|
|
@@ -6159,8 +6159,8 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
6159
6159
|
});
|
|
6160
6160
|
const imagesBinary = createProtocolV2OkppBinary();
|
|
6161
6161
|
const bootBinary = createProtocolV2OkppBinary({ payloadHashByte: 0x33 });
|
|
6162
|
-
const imagesSha256 =
|
|
6163
|
-
const bootSha256 =
|
|
6162
|
+
const imagesSha256 = bytesToHex(sha256(new Uint8Array(imagesBinary)));
|
|
6163
|
+
const bootSha256 = bytesToHex(sha256(new Uint8Array(bootBinary)));
|
|
6164
6164
|
const manifest = {
|
|
6165
6165
|
schema: 1,
|
|
6166
6166
|
artifact_name: 'pro2-resource',
|
|
@@ -6198,11 +6198,38 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
6198
6198
|
],
|
|
6199
6199
|
};
|
|
6200
6200
|
const manifestBinary = new TextEncoder().encode(JSON.stringify(manifest)).buffer;
|
|
6201
|
-
const
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6201
|
+
const zip = new JSZip();
|
|
6202
|
+
zip.file('manifest.json', manifestBinary);
|
|
6203
|
+
zip.file('bundles/images/images.okpkg', imagesBinary);
|
|
6204
|
+
zip.file('loaders/bootloader/boot_resource.okpkg', bootBinary);
|
|
6205
|
+
const archiveBinary = await zip.generateAsync({ type: 'arraybuffer' });
|
|
6206
|
+
const preparedEntries = [
|
|
6207
|
+
{
|
|
6208
|
+
entryName: 'manifest.json',
|
|
6209
|
+
artifact: {
|
|
6210
|
+
artifactRef: 'manifest',
|
|
6211
|
+
size: manifestBinary.byteLength,
|
|
6212
|
+
sha256: bytesToHex(sha256(new Uint8Array(manifestBinary))),
|
|
6213
|
+
},
|
|
6214
|
+
},
|
|
6215
|
+
{
|
|
6216
|
+
entryName: 'bundles/images/images.okpkg',
|
|
6217
|
+
artifact: {
|
|
6218
|
+
artifactRef: 'images',
|
|
6219
|
+
size: imagesBinary.byteLength,
|
|
6220
|
+
sha256: imagesSha256,
|
|
6221
|
+
},
|
|
6222
|
+
},
|
|
6223
|
+
{
|
|
6224
|
+
entryName: 'loaders/bootloader/boot_resource.okpkg',
|
|
6225
|
+
artifact: {
|
|
6226
|
+
artifactRef: 'boot',
|
|
6227
|
+
size: bootBinary.byteLength,
|
|
6228
|
+
sha256: bootSha256,
|
|
6229
|
+
},
|
|
6230
|
+
},
|
|
6231
|
+
];
|
|
6232
|
+
const artifacts = new Map([['archive', archiveBinary]]);
|
|
6206
6233
|
(method as any).params = {
|
|
6207
6234
|
targetsToUpdate: ['resource'],
|
|
6208
6235
|
preparedPlan: {
|
|
@@ -6212,32 +6239,12 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
6212
6239
|
role: 'resourceBundle',
|
|
6213
6240
|
target: 'resource',
|
|
6214
6241
|
container: 'zip',
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
sha256: '0'.repeat(64),
|
|
6222
|
-
},
|
|
6223
|
-
},
|
|
6224
|
-
{
|
|
6225
|
-
entryName: 'bundles/images/images.okpkg',
|
|
6226
|
-
artifact: {
|
|
6227
|
-
artifactRef: 'images',
|
|
6228
|
-
size: imagesBinary.byteLength,
|
|
6229
|
-
sha256: imagesSha256,
|
|
6230
|
-
},
|
|
6231
|
-
},
|
|
6232
|
-
{
|
|
6233
|
-
entryName: 'loaders/bootloader/boot_resource.okpkg',
|
|
6234
|
-
artifact: {
|
|
6235
|
-
artifactRef: 'boot',
|
|
6236
|
-
size: bootBinary.byteLength,
|
|
6237
|
-
sha256: bootSha256,
|
|
6238
|
-
},
|
|
6239
|
-
},
|
|
6240
|
-
],
|
|
6242
|
+
artifact: {
|
|
6243
|
+
artifactRef: 'archive',
|
|
6244
|
+
size: archiveBinary.byteLength,
|
|
6245
|
+
sha256: bytesToHex(sha256(new Uint8Array(archiveBinary))),
|
|
6246
|
+
},
|
|
6247
|
+
materializedEntries: preparedEntries,
|
|
6241
6248
|
},
|
|
6242
6249
|
],
|
|
6243
6250
|
},
|
|
@@ -6264,6 +6271,11 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
6264
6271
|
}),
|
|
6265
6272
|
]);
|
|
6266
6273
|
await Promise.all(sources.map(source => source.source.close()));
|
|
6274
|
+
|
|
6275
|
+
preparedEntries[1].artifact.sha256 = 'f'.repeat(64);
|
|
6276
|
+
await expect((method as any).prepareProtocolV2ResourceArchiveSources()).rejects.toThrow(
|
|
6277
|
+
'entries do not match the approved archive'
|
|
6278
|
+
);
|
|
6267
6279
|
});
|
|
6268
6280
|
|
|
6269
6281
|
test('binds a prepared resource archive to the selected host generation', () => {
|
|
@@ -7754,6 +7766,88 @@ describe('Protocol V2 firmware reconnect identity', () => {
|
|
|
7754
7766
|
expect((method as any).protocolV2ExpectedPath).toBe('000000000000');
|
|
7755
7767
|
});
|
|
7756
7768
|
|
|
7769
|
+
test('executes a serial-less Pro2 prepared plan when the live model matches', async () => {
|
|
7770
|
+
const planWithoutDigest = {
|
|
7771
|
+
schemaVersion: 2 as const,
|
|
7772
|
+
executor: 'v4' as const,
|
|
7773
|
+
deviceIdentity: 'unavailable',
|
|
7774
|
+
deviceModel: 'pro2',
|
|
7775
|
+
firmwareType: EFirmwareType.Universal,
|
|
7776
|
+
platform: 'web' as const,
|
|
7777
|
+
targetsToUpdate: ['boot' as const],
|
|
7778
|
+
artifacts: [
|
|
7779
|
+
{
|
|
7780
|
+
artifactId: 'component:boot',
|
|
7781
|
+
role: 'component' as const,
|
|
7782
|
+
target: 'boot' as const,
|
|
7783
|
+
url: 'https://example.com/bootloader.bin',
|
|
7784
|
+
container: 'raw' as const,
|
|
7785
|
+
logicalName: 'bootloader',
|
|
7786
|
+
},
|
|
7787
|
+
],
|
|
7788
|
+
};
|
|
7789
|
+
const preparedPlan = prepareFirmwareUpdatePlan({
|
|
7790
|
+
plan: {
|
|
7791
|
+
...planWithoutDigest,
|
|
7792
|
+
planDigest: digestFirmwareUpdateContract(planWithoutDigest),
|
|
7793
|
+
},
|
|
7794
|
+
leaseRef: 'serial-less-v4-executor-test',
|
|
7795
|
+
artifacts: [
|
|
7796
|
+
{
|
|
7797
|
+
artifactId: 'component:boot',
|
|
7798
|
+
artifact: {
|
|
7799
|
+
artifactRef: 'serial-less-bootloader',
|
|
7800
|
+
size: 1,
|
|
7801
|
+
sha256: 'a'.repeat(64),
|
|
7802
|
+
},
|
|
7803
|
+
},
|
|
7804
|
+
],
|
|
7805
|
+
});
|
|
7806
|
+
const hostBindingGeneration = registerFirmwareUpdateHostBinding({
|
|
7807
|
+
preparedPlanDigest: preparedPlan.preparedPlanDigest,
|
|
7808
|
+
artifactReader: {
|
|
7809
|
+
open: jest.fn(),
|
|
7810
|
+
read: jest.fn(),
|
|
7811
|
+
close: jest.fn(),
|
|
7812
|
+
},
|
|
7813
|
+
});
|
|
7814
|
+
try {
|
|
7815
|
+
const method = new FirmwareUpdateV4({
|
|
7816
|
+
id: 1,
|
|
7817
|
+
payload: {
|
|
7818
|
+
method: 'firmwareUpdateV4',
|
|
7819
|
+
platform: 'web',
|
|
7820
|
+
preparedPlan,
|
|
7821
|
+
hostBindingGeneration,
|
|
7822
|
+
},
|
|
7823
|
+
});
|
|
7824
|
+
method.init();
|
|
7825
|
+
const typedCall = jest.fn().mockResolvedValue({
|
|
7826
|
+
type: 'DeviceInfo',
|
|
7827
|
+
message: { protocol_version: 1, hw: {} },
|
|
7828
|
+
});
|
|
7829
|
+
(method as any).device = stubDevice({
|
|
7830
|
+
originalDescriptor: { protocolType: 'V2', path: 'serial-less-pro2' },
|
|
7831
|
+
features: {
|
|
7832
|
+
deviceType: 'pro2',
|
|
7833
|
+
firmwareVersion: '1.0.0',
|
|
7834
|
+
capabilities: [],
|
|
7835
|
+
},
|
|
7836
|
+
getCommands: () => ({ typedCall }),
|
|
7837
|
+
});
|
|
7838
|
+
(method as any).runProtocolV2PreparedArtifacts = jest
|
|
7839
|
+
.fn()
|
|
7840
|
+
.mockResolvedValue('serial-less-result');
|
|
7841
|
+
|
|
7842
|
+
await expect(method.run()).resolves.toBe('serial-less-result');
|
|
7843
|
+
expect((method as any).runProtocolV2PreparedArtifacts).toHaveBeenCalled();
|
|
7844
|
+
expect((method as any).protocolV2ExpectedSerialNumber).toBeUndefined();
|
|
7845
|
+
expect((method as any).protocolV2ExpectedPath).toBe('serial-less-pro2');
|
|
7846
|
+
} finally {
|
|
7847
|
+
unregisterFirmwareUpdateHostBinding(hostBindingGeneration);
|
|
7848
|
+
}
|
|
7849
|
+
});
|
|
7850
|
+
|
|
7757
7851
|
test('uses the BLE read limit when reading an existing firmware bundle header', async () => {
|
|
7758
7852
|
const method = new FirmwareUpdateV4({
|
|
7759
7853
|
id: 1,
|
|
@@ -6,6 +6,7 @@ import type { FirmwareUpdatePreparedPlan } from '../types/api/firmwareUpdatePrep
|
|
|
6
6
|
type Params = {
|
|
7
7
|
binary?: ArrayBuffer;
|
|
8
8
|
artifact?: FirmwareArtifactReference;
|
|
9
|
+
hostBindingGeneration?: number;
|
|
9
10
|
resourceEntries?: Array<{
|
|
10
11
|
entryName: string;
|
|
11
12
|
artifact: FirmwareArtifactReference;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FirmwareUpdateV2.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV2.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EAEb,KAAK,aAAa,EAKnB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AA0B1C,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,UAAU,CAAC;AAEtD,OAAO,KAAK,EACV,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAE1F,KAAK,MAAM,GAAG;IACZ,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IACrC,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,yBAAyB,CAAC;KACrC,CAAC,CAAC;IACH,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,YAAY,CAAC,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,CAAC,EAAE,0BAA0B,CAAC,UAAU,CAAC,CAAC;IAClD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,UAAU,GAAG,KAAK,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,aAAa,CAAC;CAC9B,CAAC;AAkFF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,UAAU,CAAC,MAAM,CAAC;IAC9D,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAE1C,IAAI;
|
|
1
|
+
{"version":3,"file":"FirmwareUpdateV2.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV2.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EAEb,KAAK,aAAa,EAKnB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AA0B1C,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,UAAU,CAAC;AAEtD,OAAO,KAAK,EACV,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAE1F,KAAK,MAAM,GAAG;IACZ,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IACrC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,yBAAyB,CAAC;KACrC,CAAC,CAAC;IACH,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,YAAY,CAAC,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,CAAC,EAAE,0BAA0B,CAAC,UAAU,CAAC,CAAC;IAClD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,UAAU,GAAG,KAAK,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,aAAa,CAAC;CAC9B,CAAC;AAkFF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,UAAU,CAAC,MAAM,CAAC;IAC9D,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAQ;IAE1C,IAAI;IA6FJ,cAAc,YAAa,MAAM,UAS/B;YAEY,qCAAqC;IAkBnD,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;YA8FvC,4BAA4B;IAyB1C,qBAAqB;IAUrB,uBAAuB,CAAC,UAAU,EAAE,MAAM;IAc1C,gCAAgC,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAAE,YAAY,EAAE,aAAa;IAwBtF,GAAG;CAgQV"}
|
|
@@ -36,6 +36,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
36
36
|
private getProtocolV2RequestedTargets;
|
|
37
37
|
private getProtocolV2DeviceFeatures;
|
|
38
38
|
private getProtocolV2SerialNumber;
|
|
39
|
+
private getProtocolV2PreparedPlanDeviceModel;
|
|
39
40
|
private getProtocolV2ConnectionRoute;
|
|
40
41
|
private assertProtocolV2DeviceInfoIdentity;
|
|
41
42
|
private getProtocolV2DeviceInfoTimeout;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkD,MAAM,qBAAqB,CAAC;AAyBlG,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAkC/E,OAAO,KAAK,EAEV,sBAAsB,EAEvB,MAAM,6BAA6B,CAAC;AA2ErC,wBAAgB,wCAAwC,CACtD,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,EAC5C,MAAM,EAAE,sBAAsB,QAgB/B;AAgWD,eAAO,MAAM,oCAAoC,WACvC,WAAW,GAAG,UAAU,eACnB,MAAM,GAAG,SAAS,YAKhC,CAAC;AAEF,eAAO,MAAM,iCAAiC,0BACrB,MAAM,uBACR,MAAM,iBACZ,MAAM,eACR,MAAM,SAsBpB,CAAC;AAUF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,OAAO,CAAC,8BAA8B,CAAC,CAAS;IAEhD,OAAO,CAAC,sBAAsB,CAAC,CAAS;IAExC,qBAAqB;IAIrB,OAAO,CAAC,yBAAyB,CAA4B;IAE7D,OAAO,CAAC,2BAA2B,CAAS;IAE5C,OAAO,CAAC,iCAAiC,CAA6B;IAEtE,OAAO,CAAC,6BAA6B,CAAC,CAAW;IAEjD,OAAO,CAAC,6BAA6B,CAAS;IAE9C,IAAI;
|
|
1
|
+
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkD,MAAM,qBAAqB,CAAC;AAyBlG,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAkC/E,OAAO,KAAK,EAEV,sBAAsB,EAEvB,MAAM,6BAA6B,CAAC;AA2ErC,wBAAgB,wCAAwC,CACtD,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,EAC5C,MAAM,EAAE,sBAAsB,QAgB/B;AAgWD,eAAO,MAAM,oCAAoC,WACvC,WAAW,GAAG,UAAU,eACnB,MAAM,GAAG,SAAS,YAKhC,CAAC;AAEF,eAAO,MAAM,iCAAiC,0BACrB,MAAM,uBACR,MAAM,iBACZ,MAAM,eACR,MAAM,SAsBpB,CAAC;AAUF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,OAAO,CAAC,8BAA8B,CAAC,CAAS;IAEhD,OAAO,CAAC,sBAAsB,CAAC,CAAS;IAExC,qBAAqB;IAIrB,OAAO,CAAC,yBAAyB,CAA4B;IAE7D,OAAO,CAAC,2BAA2B,CAAS;IAE5C,OAAO,CAAC,iCAAiC,CAA6B;IAEtE,OAAO,CAAC,6BAA6B,CAAC,CAAW;IAEjD,OAAO,CAAC,6BAA6B,CAAS;IAE9C,IAAI;IA0KJ,OAAO,CAAC,8BAA8B;IAwBhC,GAAG;;;;;YAKK,aAAa;YAsHb,4BAA4B;YAkB5B,0BAA0B;YAY1B,8BAA8B;YAK9B,+BAA+B;YAqG/B,gCAAgC;YA+HhC,qCAAqC;YA0IrC,gCAAgC;YAgBhC,uCAAuC;YAmJvC,8BAA8B;IAsB5C,OAAO,CAAC,8BAA8B;IA0BtC,OAAO,CAAC,kCAAkC;IAc1C,OAAO,CAAC,gCAAgC;IAsDxC,OAAO,CAAC,6BAA6B;YAsBvB,2BAA2B;IAWzC,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,oCAAoC;IAY5C,OAAO,CAAC,4BAA4B;IAUpC,OAAO,CAAC,kCAAkC;IAS1C,OAAO,CAAC,8BAA8B;YAMxB,iCAAiC;YAOjC,iCAAiC;YAmBjC,iCAAiC;IAM/C,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,mCAAmC;IAe3C,OAAO,CAAC,2BAA2B;IAsBnC,OAAO,CAAC,yBAAyB;IAiBjC,OAAO,CAAC,wBAAwB;YAkBlB,iCAAiC;YAuDjC,+BAA+B;IA6E7C,OAAO,CAAC,6BAA6B;YAMvB,8BAA8B;YA+C9B,kCAAkC;IA+BhD,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,yBAAyB;IAc3B,6BAA6B;YAgCrB,+BAA+B;IAkD7C,OAAO,CAAC,6BAA6B;IAkCrC,OAAO,CAAC,8BAA8B;YA8CxB,uBAAuB;YAiCvB,6BAA6B;YAa7B,uBAAuB;YAiCvB,8BAA8B;YA8D9B,6BAA6B;IAuE3C,OAAO,CAAC,mCAAmC;YAI7B,0BAA0B;IAaxC,OAAO,CAAC,4BAA4B;IAyGpC,OAAO,CAAC,6BAA6B;YAcvB,uCAAuC;YA0JvC,gCAAgC;YAehC,yBAAyB;YAQzB,8BAA8B;IAQ5C,OAAO,CAAC,0BAA0B;YAkBpB,mCAAmC;YAWnC,qCAAqC;YAgDrC,yBAAyB;YA8DzB,8BAA8B;IAU5C,OAAO,CAAC,kCAAkC;YAQ5B,cAAc;YAuCd,6BAA6B;YAW7B,0BAA0B;YAS1B,6BAA6B;YAmB7B,gBAAgB;IAiB9B,OAAO,CAAC,qBAAqB;CAM9B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeviceUpdateBootloader.d.ts","sourceRoot":"","sources":["../../../src/api/device/DeviceUpdateBootloader.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAiBhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAE7E,MAAM,CAAC,OAAO,OAAO,sBAAuB,SAAQ,wBAAwB,CAAC,GAAG,CAAC;IAC/E,IAAI;IAOE,iCAAiC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;IAoBtE,2CAA2C,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB;IAcvF,qBAAqB,CAAC,EAC1B,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc,GACvB,EAAE;QACD,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,QAAQ,CAAC;QACpB,YAAY,EAAE,aAAa,CAAC;QAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,MAAM,CAAC,EAAE,kBAAkB,CAAC;KAC7B;IA0EK,GAAG;
|
|
1
|
+
{"version":3,"file":"DeviceUpdateBootloader.d.ts","sourceRoot":"","sources":["../../../src/api/device/DeviceUpdateBootloader.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAiBhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAE7E,MAAM,CAAC,OAAO,OAAO,sBAAuB,SAAQ,wBAAwB,CAAC,GAAG,CAAC;IAC/E,IAAI;IAOE,iCAAiC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;IAoBtE,2CAA2C,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB;IAcvF,qBAAqB,CAAC,EAC1B,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc,GACvB,EAAE;QACD,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,QAAQ,CAAC;QACpB,YAAY,EAAE,aAAa,CAAC;QAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,MAAM,CAAC,EAAE,kBAAkB,CAAC;KAC7B;IA0EK,GAAG;CA8FV"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1413,6 +1413,7 @@ type FirmwareUpdateV4Target = 'boot'
|
|
|
1413
1413
|
| 'boot_resources' | 'app_v1' | 'app_v2' | 'coprocessor' | 'resource' | 'se01' | 'se02' | 'se03' | 'se04';
|
|
1414
1414
|
interface FirmwareUpdateV4Params {
|
|
1415
1415
|
preparedPlan?: FirmwareUpdatePreparedPlan;
|
|
1416
|
+
/** Required whenever preparedPlan is present; Core resolves the reader from this digest-bound host. */
|
|
1416
1417
|
hostBindingGeneration?: number;
|
|
1417
1418
|
platform: IPlatform;
|
|
1418
1419
|
expectedDeviceId?: string;
|
package/dist/index.js
CHANGED
|
@@ -49777,18 +49777,26 @@ class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod {
|
|
|
49777
49777
|
});
|
|
49778
49778
|
}
|
|
49779
49779
|
run() {
|
|
49780
|
-
var _a, _b
|
|
49780
|
+
var _a, _b;
|
|
49781
49781
|
return __awaiter(this, void 0, void 0, function* () {
|
|
49782
49782
|
const { device } = this;
|
|
49783
49783
|
const { features } = device;
|
|
49784
49784
|
const payload = this.payload;
|
|
49785
|
-
const
|
|
49785
|
+
const hasPreparedPlan = payload.preparedPlan !== undefined;
|
|
49786
|
+
const hasPreparedArtifact = payload.artifact !== undefined;
|
|
49787
|
+
if (hasPreparedPlan !== hasPreparedArtifact) {
|
|
49788
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Prepared bootloader plans require exactly one prepared artifact');
|
|
49789
|
+
}
|
|
49790
|
+
if (payload.binary !== undefined && hasPreparedArtifact) {
|
|
49791
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Bootloader binary and prepared artifact are mutually exclusive');
|
|
49792
|
+
}
|
|
49793
|
+
const preparedPlan = hasPreparedArtifact
|
|
49786
49794
|
? validateFirmwareUpdatePreparedPlan(payload.preparedPlan)
|
|
49787
49795
|
: undefined;
|
|
49788
|
-
const
|
|
49789
|
-
? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest)
|
|
49790
|
-
:
|
|
49791
|
-
const executionParams = Object.assign(Object.assign({}, payload), { artifactReader
|
|
49796
|
+
const artifactReader = preparedPlan
|
|
49797
|
+
? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest).artifactReader
|
|
49798
|
+
: payload.artifactReader;
|
|
49799
|
+
const executionParams = Object.assign(Object.assign({}, payload), { artifactReader });
|
|
49792
49800
|
if (payload.artifact) {
|
|
49793
49801
|
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
49794
49802
|
preparedPlan,
|
|
@@ -49817,7 +49825,7 @@ class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod {
|
|
|
49817
49825
|
try {
|
|
49818
49826
|
const deviceType = device.getCurrentDeviceType();
|
|
49819
49827
|
const deviceFirmwareType = device.getCurrentFirmwareType();
|
|
49820
|
-
const firmwareType = (
|
|
49828
|
+
const firmwareType = (_a = payload.firmwareType) !== null && _a !== void 0 ? _a : deviceFirmwareType;
|
|
49821
49829
|
if (DeviceModelToTypes.model_touch.includes(deviceType)) {
|
|
49822
49830
|
return yield this.updateTouchBootloader({
|
|
49823
49831
|
device,
|
|
@@ -49835,7 +49843,7 @@ class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod {
|
|
|
49835
49843
|
const { binary } = payload;
|
|
49836
49844
|
const deviceType = device.getCurrentDeviceType();
|
|
49837
49845
|
const deviceFirmwareType = device.getCurrentFirmwareType();
|
|
49838
|
-
const firmwareType = (
|
|
49846
|
+
const firmwareType = (_b = payload.firmwareType) !== null && _b !== void 0 ? _b : deviceFirmwareType;
|
|
49839
49847
|
if (DeviceModelToTypes.model_touch.includes(deviceType)) {
|
|
49840
49848
|
return this.updateTouchBootloader({
|
|
49841
49849
|
device,
|
|
@@ -50189,6 +50197,9 @@ class FirmwareUpdateV2 extends BaseMethod {
|
|
|
50189
50197
|
payload.artifact !== undefined) {
|
|
50190
50198
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Firmware update binary and artifact are mutually exclusive');
|
|
50191
50199
|
}
|
|
50200
|
+
if (payload.preparedPlan !== undefined && payload.artifact === undefined) {
|
|
50201
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Prepared firmware plans require a prepared artifact');
|
|
50202
|
+
}
|
|
50192
50203
|
if (!payload.updateType) {
|
|
50193
50204
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'updateType is required');
|
|
50194
50205
|
}
|
|
@@ -50564,7 +50575,7 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
|
|
|
50564
50575
|
this.artifactSources = [];
|
|
50565
50576
|
}
|
|
50566
50577
|
init() {
|
|
50567
|
-
var _a, _b, _c, _d, _e
|
|
50578
|
+
var _a, _b, _c, _d, _e;
|
|
50568
50579
|
this.allowDeviceMode = [UI_REQUEST.BOOTLOADER, UI_REQUEST.NOT_INITIALIZE];
|
|
50569
50580
|
this.requireDeviceMode = [];
|
|
50570
50581
|
this.useDevicePassphraseState = false;
|
|
@@ -50585,10 +50596,10 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
|
|
|
50585
50596
|
const preparedPlan = payload.artifacts || payload.preparedPlan
|
|
50586
50597
|
? validateFirmwareUpdatePreparedPlan(payload.preparedPlan)
|
|
50587
50598
|
: undefined;
|
|
50588
|
-
const
|
|
50589
|
-
? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest)
|
|
50590
|
-
:
|
|
50591
|
-
if (
|
|
50599
|
+
const artifactReader = preparedPlan
|
|
50600
|
+
? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest).artifactReader
|
|
50601
|
+
: payload.artifactReader;
|
|
50602
|
+
if (preparedPlan) {
|
|
50592
50603
|
assertFirmwareUpdatePreparedPlanBinding({
|
|
50593
50604
|
preparedPlan,
|
|
50594
50605
|
executor: 'v3',
|
|
@@ -50639,7 +50650,7 @@ class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod {
|
|
|
50639
50650
|
resourceBinary: payload.resourceBinary,
|
|
50640
50651
|
firmwareType: payload.firmwareType,
|
|
50641
50652
|
platform: payload.platform,
|
|
50642
|
-
artifactReader
|
|
50653
|
+
artifactReader,
|
|
50643
50654
|
artifacts: payload.artifacts,
|
|
50644
50655
|
};
|
|
50645
50656
|
}
|
|
@@ -51637,7 +51648,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
51637
51648
|
return ['V2'];
|
|
51638
51649
|
}
|
|
51639
51650
|
init() {
|
|
51640
|
-
var _a, _b
|
|
51651
|
+
var _a, _b;
|
|
51641
51652
|
this.allowDeviceMode = [UI_REQUEST.BOOTLOADER, UI_REQUEST.NOT_INITIALIZE];
|
|
51642
51653
|
this.requireDeviceMode = [];
|
|
51643
51654
|
this.unlockPolicy = 'unlock-before-run';
|
|
@@ -51696,9 +51707,13 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
51696
51707
|
if (preparedPlan && hasLocalArtifacts) {
|
|
51697
51708
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Prepared firmware plans cannot be combined with legacy or local firmware inputs');
|
|
51698
51709
|
}
|
|
51699
|
-
|
|
51700
|
-
|
|
51701
|
-
|
|
51710
|
+
let { artifactReader } = payload;
|
|
51711
|
+
if (preparedPlan) {
|
|
51712
|
+
artifactReader = resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration, preparedPlan.preparedPlanDigest).artifactReader;
|
|
51713
|
+
}
|
|
51714
|
+
else if (payload.hostBindingGeneration !== undefined) {
|
|
51715
|
+
artifactReader = resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration).artifactReader;
|
|
51716
|
+
}
|
|
51702
51717
|
if (preparedPlan) {
|
|
51703
51718
|
assertFirmwareUpdatePreparedPlanBinding({
|
|
51704
51719
|
preparedPlan,
|
|
@@ -51764,7 +51779,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
51764
51779
|
: payload.expectedTargetVersions,
|
|
51765
51780
|
platform: payload.platform,
|
|
51766
51781
|
expectedDeviceId: payload.expectedDeviceId,
|
|
51767
|
-
artifactReader
|
|
51782
|
+
artifactReader,
|
|
51768
51783
|
componentArtifacts: preparedPlan ? undefined : payload.componentArtifacts,
|
|
51769
51784
|
};
|
|
51770
51785
|
}
|
|
@@ -52052,6 +52067,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
52052
52067
|
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
52053
52068
|
preparedPlan,
|
|
52054
52069
|
deviceIdentity: this.protocolV2ExpectedSerialNumber,
|
|
52070
|
+
deviceModel: this.getProtocolV2PreparedPlanDeviceModel(features),
|
|
52055
52071
|
});
|
|
52056
52072
|
const hostBinding = resolveFirmwareUpdateHostBinding(memoryHost.hostBindingGeneration, preparedPlan.preparedPlanDigest);
|
|
52057
52073
|
this.params.preparedPlan = preparedPlan;
|
|
@@ -52176,17 +52192,43 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
52176
52192
|
if (archiveArtifacts.length !== 1) {
|
|
52177
52193
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared plan must contain exactly one resource archive', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
|
|
52178
52194
|
}
|
|
52179
|
-
const
|
|
52180
|
-
const
|
|
52181
|
-
if (
|
|
52182
|
-
|
|
52183
|
-
|
|
52195
|
+
const archiveArtifact = archiveArtifacts[0];
|
|
52196
|
+
const archiveSource = yield this.openProtocolV2PreparedSource(archiveArtifact.artifact);
|
|
52197
|
+
if (archiveSource.size > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
|
|
52198
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive exceeds the total size limit', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
|
|
52199
|
+
}
|
|
52200
|
+
let archiveBinary;
|
|
52201
|
+
try {
|
|
52202
|
+
archiveBinary = yield readFirmwareByteSourceFully(archiveSource);
|
|
52203
|
+
}
|
|
52204
|
+
finally {
|
|
52205
|
+
yield archiveSource.close();
|
|
52206
|
+
}
|
|
52207
|
+
const archiveDigest = bytesToHex(sha256.sha256(new Uint8Array(archiveBinary)));
|
|
52208
|
+
if (archiveDigest !== archiveArtifact.artifact.sha256.toLowerCase()) {
|
|
52209
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive does not match its approved receipt', { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
|
|
52210
|
+
}
|
|
52211
|
+
const verifiedArchive = yield this.prepareProtocolV2LocalResourceArchive(archiveBinary);
|
|
52212
|
+
const entries = (_c = archiveArtifact.materializedEntries) !== null && _c !== void 0 ? _c : [];
|
|
52213
|
+
const entriesByName = new Map(entries.map(entry => [entry.entryName, entry]));
|
|
52214
|
+
if (entries.length !== verifiedArchive.materializedEntries.length ||
|
|
52215
|
+
verifiedArchive.materializedEntries.some(entry => {
|
|
52216
|
+
const preparedEntry = entriesByName.get(entry.entryName);
|
|
52217
|
+
const digest = bytesToHex(sha256.sha256(new Uint8Array(entry.binary)));
|
|
52218
|
+
return (!preparedEntry ||
|
|
52219
|
+
preparedEntry.artifact.size !== entry.binary.byteLength ||
|
|
52220
|
+
preparedEntry.artifact.sha256.toLowerCase() !== digest);
|
|
52221
|
+
})) {
|
|
52222
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource entries do not match the approved archive', { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
|
|
52223
|
+
}
|
|
52224
|
+
const verifiedEntriesByName = new Map(verifiedArchive.materializedEntries.map(entry => [entry.entryName, entry.binary]));
|
|
52225
|
+
const manifestBinary = verifiedEntriesByName.get('manifest.json');
|
|
52226
|
+
if (!manifestBinary) {
|
|
52184
52227
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive has no valid manifest.json', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
|
|
52185
52228
|
}
|
|
52186
|
-
const manifestSource = yield this.openProtocolV2PreparedSource(manifestEntry.artifact);
|
|
52187
52229
|
let manifestValue;
|
|
52188
52230
|
try {
|
|
52189
|
-
manifestValue = JSON.parse(new TextDecoder().decode(
|
|
52231
|
+
manifestValue = JSON.parse(new TextDecoder().decode(manifestBinary));
|
|
52190
52232
|
}
|
|
52191
52233
|
catch (error) {
|
|
52192
52234
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 prepared resource manifest is invalid: ${String(error)}`, { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
|
|
@@ -52199,28 +52241,18 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
52199
52241
|
if (selectedFiles.length > PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT) {
|
|
52200
52242
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive contains too many files', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
|
|
52201
52243
|
}
|
|
52202
|
-
const entriesByName = new Map(entries.map(entry => [entry.entryName, entry]));
|
|
52203
|
-
const expectedEntryNames = new Set([
|
|
52204
|
-
'manifest.json',
|
|
52205
|
-
...selectedFiles.map(file => file.archive_path),
|
|
52206
|
-
]);
|
|
52207
|
-
if (entries.some(entry => !expectedEntryNames.has(entry.entryName))) {
|
|
52208
|
-
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive contains an unexpected entry', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
|
|
52209
|
-
}
|
|
52210
52244
|
let totalSize = 0;
|
|
52211
52245
|
const sources = [];
|
|
52212
52246
|
for (const [index, file] of selectedFiles.entries()) {
|
|
52213
|
-
const
|
|
52214
|
-
if (!
|
|
52215
|
-
entry.artifact.size !== file.size ||
|
|
52216
|
-
entry.artifact.sha256.toLowerCase() !== file.sha256.toLowerCase()) {
|
|
52247
|
+
const binary = verifiedEntriesByName.get(file.archive_path);
|
|
52248
|
+
if (!binary || binary.byteLength !== file.size) {
|
|
52217
52249
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Protocol V2 prepared resource file does not match manifest: ${file.archive_path}`, { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' });
|
|
52218
52250
|
}
|
|
52219
|
-
totalSize +=
|
|
52251
|
+
totalSize += binary.byteLength;
|
|
52220
52252
|
if (totalSize > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
|
|
52221
52253
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 prepared resource archive exceeds the total size limit', { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' });
|
|
52222
52254
|
}
|
|
52223
|
-
const source = yield this.
|
|
52255
|
+
const source = yield this.openProtocolV2MemorySource(binary);
|
|
52224
52256
|
const header = source.size >= PROTOCOL_V2_OKPP_HEADER_SIZE
|
|
52225
52257
|
? parseProtocolV2OkppHeader(new Uint8Array(yield source.readAt(0, PROTOCOL_V2_OKPP_HEADER_SIZE)))
|
|
52226
52258
|
: null;
|
|
@@ -52369,6 +52401,16 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
52369
52401
|
const serialNumber = (_b = (_a = deviceInfo.hw) === null || _a === void 0 ? void 0 : _a.serial_no) === null || _b === void 0 ? void 0 : _b.trim();
|
|
52370
52402
|
return serialNumber || undefined;
|
|
52371
52403
|
}
|
|
52404
|
+
getProtocolV2PreparedPlanDeviceModel(features) {
|
|
52405
|
+
const currentDeviceType = this.device.getCurrentDeviceType();
|
|
52406
|
+
const featureDeviceType = features ? getDeviceType(features) : undefined;
|
|
52407
|
+
const deviceType = currentDeviceType === hdShared.EDeviceType.Pro2 || currentDeviceType === hdShared.EDeviceType.Neo
|
|
52408
|
+
? currentDeviceType
|
|
52409
|
+
: featureDeviceType;
|
|
52410
|
+
return deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo
|
|
52411
|
+
? String(deviceType)
|
|
52412
|
+
: undefined;
|
|
52413
|
+
}
|
|
52372
52414
|
getProtocolV2ConnectionRoute() {
|
|
52373
52415
|
var _a, _b, _c, _d, _e;
|
|
52374
52416
|
const descriptor = this.device.originalDescriptor;
|
|
@@ -52404,6 +52446,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
|
|
|
52404
52446
|
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
52405
52447
|
preparedPlan: this.params.preparedPlan,
|
|
52406
52448
|
deviceIdentity: serialNumber,
|
|
52449
|
+
deviceModel: this.getProtocolV2PreparedPlanDeviceModel(this.device.features),
|
|
52407
52450
|
});
|
|
52408
52451
|
}
|
|
52409
52452
|
else if ((_b = this.params) === null || _b === void 0 ? void 0 : _b.expectedDeviceId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"firmwareUpdate.d.ts","sourceRoot":"","sources":["../../../src/types/api/firmwareUpdate.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"firmwareUpdate.d.ts","sourceRoot":"","sources":["../../../src/types/api/firmwareUpdate.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.95",
|
|
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.95",
|
|
29
|
+
"@onekeyfe/hd-transport": "1.2.0-alpha.95",
|
|
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": "efd79360b765d83a31d12f2403da4e79ed2ccffc"
|
|
48
48
|
}
|
|
@@ -47,6 +47,7 @@ import type { FirmwareUpdatePreparedPlan } from '../types/api/firmwareUpdatePrep
|
|
|
47
47
|
type Params = {
|
|
48
48
|
binary?: ArrayBuffer;
|
|
49
49
|
artifact?: FirmwareArtifactReference;
|
|
50
|
+
hostBindingGeneration?: number;
|
|
50
51
|
resourceEntries?: Array<{
|
|
51
52
|
entryName: string;
|
|
52
53
|
artifact: FirmwareArtifactReference;
|
|
@@ -171,6 +172,12 @@ export default class FirmwareUpdateV2 extends BaseMethod<Params> {
|
|
|
171
172
|
'Firmware update binary and artifact are mutually exclusive'
|
|
172
173
|
);
|
|
173
174
|
}
|
|
175
|
+
if (payload.preparedPlan !== undefined && payload.artifact === undefined) {
|
|
176
|
+
throw ERRORS.TypedError(
|
|
177
|
+
HardwareErrorCode.CallMethodInvalidParameter,
|
|
178
|
+
'Prepared firmware plans require a prepared artifact'
|
|
179
|
+
);
|
|
180
|
+
}
|
|
174
181
|
|
|
175
182
|
if (!payload.updateType) {
|
|
176
183
|
throw ERRORS.TypedError(
|
|
@@ -82,13 +82,13 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
82
82
|
payload.artifacts || payload.preparedPlan
|
|
83
83
|
? validateFirmwareUpdatePreparedPlan(payload.preparedPlan)
|
|
84
84
|
: undefined;
|
|
85
|
-
const
|
|
85
|
+
const artifactReader = preparedPlan
|
|
86
86
|
? resolveFirmwareUpdateHostBinding(
|
|
87
87
|
payload.hostBindingGeneration,
|
|
88
88
|
preparedPlan.preparedPlanDigest
|
|
89
|
-
)
|
|
90
|
-
:
|
|
91
|
-
if (
|
|
89
|
+
).artifactReader
|
|
90
|
+
: payload.artifactReader;
|
|
91
|
+
if (preparedPlan) {
|
|
92
92
|
assertFirmwareUpdatePreparedPlanBinding({
|
|
93
93
|
preparedPlan,
|
|
94
94
|
executor: 'v3',
|
|
@@ -142,7 +142,7 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
142
142
|
resourceBinary: payload.resourceBinary,
|
|
143
143
|
firmwareType: payload.firmwareType,
|
|
144
144
|
platform: payload.platform,
|
|
145
|
-
artifactReader
|
|
145
|
+
artifactReader,
|
|
146
146
|
artifacts: payload.artifacts,
|
|
147
147
|
};
|
|
148
148
|
}
|
|
@@ -640,13 +640,17 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
640
640
|
'Prepared firmware plans cannot be combined with legacy or local firmware inputs'
|
|
641
641
|
);
|
|
642
642
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
643
|
+
let { artifactReader } = payload;
|
|
644
|
+
if (preparedPlan) {
|
|
645
|
+
artifactReader = resolveFirmwareUpdateHostBinding(
|
|
646
|
+
payload.hostBindingGeneration,
|
|
647
|
+
preparedPlan.preparedPlanDigest
|
|
648
|
+
).artifactReader;
|
|
649
|
+
} else if (payload.hostBindingGeneration !== undefined) {
|
|
650
|
+
artifactReader = resolveFirmwareUpdateHostBinding(
|
|
651
|
+
payload.hostBindingGeneration
|
|
652
|
+
).artifactReader;
|
|
653
|
+
}
|
|
650
654
|
if (preparedPlan) {
|
|
651
655
|
assertFirmwareUpdatePreparedPlanBinding({
|
|
652
656
|
preparedPlan,
|
|
@@ -731,7 +735,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
731
735
|
: payload.expectedTargetVersions,
|
|
732
736
|
platform: payload.platform,
|
|
733
737
|
expectedDeviceId: payload.expectedDeviceId,
|
|
734
|
-
artifactReader
|
|
738
|
+
artifactReader,
|
|
735
739
|
componentArtifacts: preparedPlan ? undefined : payload.componentArtifacts,
|
|
736
740
|
};
|
|
737
741
|
}
|
|
@@ -1129,6 +1133,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1129
1133
|
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
1130
1134
|
preparedPlan,
|
|
1131
1135
|
deviceIdentity: this.protocolV2ExpectedSerialNumber,
|
|
1136
|
+
deviceModel: this.getProtocolV2PreparedPlanDeviceModel(features),
|
|
1132
1137
|
});
|
|
1133
1138
|
const hostBinding = resolveFirmwareUpdateHostBinding(
|
|
1134
1139
|
memoryHost.hostBindingGeneration,
|
|
@@ -1320,13 +1325,59 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1320
1325
|
);
|
|
1321
1326
|
}
|
|
1322
1327
|
|
|
1323
|
-
const
|
|
1324
|
-
const
|
|
1328
|
+
const archiveArtifact = archiveArtifacts[0];
|
|
1329
|
+
const archiveSource = await this.openProtocolV2PreparedSource(archiveArtifact.artifact);
|
|
1330
|
+
if (archiveSource.size > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
|
|
1331
|
+
throw ERRORS.TypedError(
|
|
1332
|
+
HardwareErrorCode.RuntimeError,
|
|
1333
|
+
'Protocol V2 prepared resource archive exceeds the total size limit',
|
|
1334
|
+
{ firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' }
|
|
1335
|
+
);
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
let archiveBinary: ArrayBuffer;
|
|
1339
|
+
try {
|
|
1340
|
+
archiveBinary = await readFirmwareByteSourceFully(archiveSource);
|
|
1341
|
+
} finally {
|
|
1342
|
+
await archiveSource.close();
|
|
1343
|
+
}
|
|
1344
|
+
const archiveDigest = bytesToHex(sha256(new Uint8Array(archiveBinary)));
|
|
1345
|
+
if (archiveDigest !== archiveArtifact.artifact.sha256.toLowerCase()) {
|
|
1346
|
+
throw ERRORS.TypedError(
|
|
1347
|
+
HardwareErrorCode.RuntimeError,
|
|
1348
|
+
'Protocol V2 prepared resource archive does not match its approved receipt',
|
|
1349
|
+
{ firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' }
|
|
1350
|
+
);
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
// materializedEntries 由宿主生成,只有与获批 ZIP 的规范字节完全一致后才能使用。
|
|
1354
|
+
const verifiedArchive = await this.prepareProtocolV2LocalResourceArchive(archiveBinary);
|
|
1355
|
+
const entries = archiveArtifact.materializedEntries ?? [];
|
|
1356
|
+
const entriesByName = new Map(entries.map(entry => [entry.entryName, entry] as const));
|
|
1325
1357
|
if (
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1358
|
+
entries.length !== verifiedArchive.materializedEntries.length ||
|
|
1359
|
+
verifiedArchive.materializedEntries.some(entry => {
|
|
1360
|
+
const preparedEntry = entriesByName.get(entry.entryName);
|
|
1361
|
+
const digest = bytesToHex(sha256(new Uint8Array(entry.binary)));
|
|
1362
|
+
return (
|
|
1363
|
+
!preparedEntry ||
|
|
1364
|
+
preparedEntry.artifact.size !== entry.binary.byteLength ||
|
|
1365
|
+
preparedEntry.artifact.sha256.toLowerCase() !== digest
|
|
1366
|
+
);
|
|
1367
|
+
})
|
|
1329
1368
|
) {
|
|
1369
|
+
throw ERRORS.TypedError(
|
|
1370
|
+
HardwareErrorCode.RuntimeError,
|
|
1371
|
+
'Protocol V2 prepared resource entries do not match the approved archive',
|
|
1372
|
+
{ firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' }
|
|
1373
|
+
);
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
const verifiedEntriesByName = new Map(
|
|
1377
|
+
verifiedArchive.materializedEntries.map(entry => [entry.entryName, entry.binary] as const)
|
|
1378
|
+
);
|
|
1379
|
+
const manifestBinary = verifiedEntriesByName.get('manifest.json');
|
|
1380
|
+
if (!manifestBinary) {
|
|
1330
1381
|
throw ERRORS.TypedError(
|
|
1331
1382
|
HardwareErrorCode.RuntimeError,
|
|
1332
1383
|
'Protocol V2 prepared resource archive has no valid manifest.json',
|
|
@@ -1334,12 +1385,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1334
1385
|
);
|
|
1335
1386
|
}
|
|
1336
1387
|
|
|
1337
|
-
const manifestSource = await this.openProtocolV2PreparedSource(manifestEntry.artifact);
|
|
1338
1388
|
let manifestValue: unknown;
|
|
1339
1389
|
try {
|
|
1340
|
-
manifestValue = JSON.parse(
|
|
1341
|
-
new TextDecoder().decode(await readFirmwareByteSourceFully(manifestSource))
|
|
1342
|
-
);
|
|
1390
|
+
manifestValue = JSON.parse(new TextDecoder().decode(manifestBinary));
|
|
1343
1391
|
} catch (error) {
|
|
1344
1392
|
throw ERRORS.TypedError(
|
|
1345
1393
|
HardwareErrorCode.RuntimeError,
|
|
@@ -1360,35 +1408,18 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1360
1408
|
);
|
|
1361
1409
|
}
|
|
1362
1410
|
|
|
1363
|
-
const entriesByName = new Map(entries.map(entry => [entry.entryName, entry] as const));
|
|
1364
|
-
const expectedEntryNames = new Set([
|
|
1365
|
-
'manifest.json',
|
|
1366
|
-
...selectedFiles.map(file => file.archive_path),
|
|
1367
|
-
]);
|
|
1368
|
-
if (entries.some(entry => !expectedEntryNames.has(entry.entryName))) {
|
|
1369
|
-
throw ERRORS.TypedError(
|
|
1370
|
-
HardwareErrorCode.RuntimeError,
|
|
1371
|
-
'Protocol V2 prepared resource archive contains an unexpected entry',
|
|
1372
|
-
{ firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' }
|
|
1373
|
-
);
|
|
1374
|
-
}
|
|
1375
|
-
|
|
1376
1411
|
let totalSize = 0;
|
|
1377
1412
|
const sources: ProtocolV2ResourceBundleSource[] = [];
|
|
1378
1413
|
for (const [index, file] of selectedFiles.entries()) {
|
|
1379
|
-
const
|
|
1380
|
-
if (
|
|
1381
|
-
!entry ||
|
|
1382
|
-
entry.artifact.size !== file.size ||
|
|
1383
|
-
entry.artifact.sha256.toLowerCase() !== file.sha256.toLowerCase()
|
|
1384
|
-
) {
|
|
1414
|
+
const binary = verifiedEntriesByName.get(file.archive_path);
|
|
1415
|
+
if (!binary || binary.byteLength !== file.size) {
|
|
1385
1416
|
throw ERRORS.TypedError(
|
|
1386
1417
|
HardwareErrorCode.RuntimeError,
|
|
1387
1418
|
`Protocol V2 prepared resource file does not match manifest: ${file.archive_path}`,
|
|
1388
1419
|
{ firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' }
|
|
1389
1420
|
);
|
|
1390
1421
|
}
|
|
1391
|
-
totalSize +=
|
|
1422
|
+
totalSize += binary.byteLength;
|
|
1392
1423
|
if (totalSize > PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES) {
|
|
1393
1424
|
throw ERRORS.TypedError(
|
|
1394
1425
|
HardwareErrorCode.RuntimeError,
|
|
@@ -1396,7 +1427,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1396
1427
|
{ firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' }
|
|
1397
1428
|
);
|
|
1398
1429
|
}
|
|
1399
|
-
|
|
1430
|
+
// 使用从获批 ZIP 中提取的规范字节,避免宿主在校验后替换 entry reader 内容。
|
|
1431
|
+
const source = await this.openProtocolV2MemorySource(binary);
|
|
1400
1432
|
const header =
|
|
1401
1433
|
source.size >= PROTOCOL_V2_OKPP_HEADER_SIZE
|
|
1402
1434
|
? parseProtocolV2OkppHeader(
|
|
@@ -1573,6 +1605,18 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1573
1605
|
return serialNumber || undefined;
|
|
1574
1606
|
}
|
|
1575
1607
|
|
|
1608
|
+
private getProtocolV2PreparedPlanDeviceModel(features?: Features) {
|
|
1609
|
+
const currentDeviceType = this.device.getCurrentDeviceType();
|
|
1610
|
+
const featureDeviceType = features ? getDeviceType(features) : undefined;
|
|
1611
|
+
const deviceType =
|
|
1612
|
+
currentDeviceType === EDeviceType.Pro2 || currentDeviceType === EDeviceType.Neo
|
|
1613
|
+
? currentDeviceType
|
|
1614
|
+
: featureDeviceType;
|
|
1615
|
+
return deviceType === EDeviceType.Pro2 || deviceType === EDeviceType.Neo
|
|
1616
|
+
? String(deviceType)
|
|
1617
|
+
: undefined;
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1576
1620
|
private getProtocolV2ConnectionRoute() {
|
|
1577
1621
|
const descriptor = this.device.originalDescriptor;
|
|
1578
1622
|
return (
|
|
@@ -1613,6 +1657,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1613
1657
|
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
1614
1658
|
preparedPlan: this.params.preparedPlan,
|
|
1615
1659
|
deviceIdentity: serialNumber,
|
|
1660
|
+
deviceModel: this.getProtocolV2PreparedPlanDeviceModel(this.device.features),
|
|
1616
1661
|
});
|
|
1617
1662
|
} else if (this.params?.expectedDeviceId) {
|
|
1618
1663
|
assertProtocolV2ReconnectIdentity(this.params?.expectedDeviceId, serialNumber);
|
|
@@ -158,18 +158,32 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
|
|
|
158
158
|
const { features } = device;
|
|
159
159
|
|
|
160
160
|
const payload = this.payload as DeviceUpdateBootloaderParams;
|
|
161
|
-
const
|
|
161
|
+
const hasPreparedPlan = payload.preparedPlan !== undefined;
|
|
162
|
+
const hasPreparedArtifact = payload.artifact !== undefined;
|
|
163
|
+
if (hasPreparedPlan !== hasPreparedArtifact) {
|
|
164
|
+
throw ERRORS.TypedError(
|
|
165
|
+
HardwareErrorCode.CallMethodInvalidParameter,
|
|
166
|
+
'Prepared bootloader plans require exactly one prepared artifact'
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
if (payload.binary !== undefined && hasPreparedArtifact) {
|
|
170
|
+
throw ERRORS.TypedError(
|
|
171
|
+
HardwareErrorCode.CallMethodInvalidParameter,
|
|
172
|
+
'Bootloader binary and prepared artifact are mutually exclusive'
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
const preparedPlan = hasPreparedArtifact
|
|
162
176
|
? validateFirmwareUpdatePreparedPlan(payload.preparedPlan)
|
|
163
177
|
: undefined;
|
|
164
|
-
const
|
|
178
|
+
const artifactReader = preparedPlan
|
|
165
179
|
? resolveFirmwareUpdateHostBinding(
|
|
166
180
|
payload.hostBindingGeneration,
|
|
167
181
|
preparedPlan.preparedPlanDigest
|
|
168
|
-
)
|
|
169
|
-
:
|
|
182
|
+
).artifactReader
|
|
183
|
+
: payload.artifactReader;
|
|
170
184
|
const executionParams = {
|
|
171
185
|
...payload,
|
|
172
|
-
artifactReader
|
|
186
|
+
artifactReader,
|
|
173
187
|
};
|
|
174
188
|
if (payload.artifact) {
|
|
175
189
|
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
@@ -133,6 +133,7 @@ export type FirmwareUpdateV4Target =
|
|
|
133
133
|
|
|
134
134
|
export interface FirmwareUpdateV4Params {
|
|
135
135
|
preparedPlan?: FirmwareUpdatePreparedPlan;
|
|
136
|
+
/** Required whenever preparedPlan is present; Core resolves the reader from this digest-bound host. */
|
|
136
137
|
hostBindingGeneration?: number;
|
|
137
138
|
platform: IPlatform;
|
|
138
139
|
expectedDeviceId?: string;
|