@onekeyfe/hd-core 1.2.8-alpha.128 → 1.2.8-alpha.129
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__/device-lifecycle-events.test.ts +96 -0
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +11 -0
- package/__tests__/protocol-v2-resources.test.ts +14 -0
- package/__tests__/protocol-v2.test.ts +306 -14
- package/__tests__/protocolV2FileWrite.test.ts +434 -7
- package/dist/api/FileWrite.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +0 -1
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +5 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/device/Device.d.ts +1 -0
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +1 -0
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +616 -382
- package/dist/protocols/protocol-v2/resources.d.ts +1 -0
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/FileWrite.ts +7 -1
- package/src/api/FirmwareUpdateV4.ts +56 -30
- package/src/api/firmware/FirmwareArtifactSource.ts +12 -3
- package/src/api/helpers/protocolV2FileWrite.ts +375 -111
- package/src/api/protocol-v2/DeviceUploadNft.ts +6 -1
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +15 -1
- package/src/device/Device.ts +18 -2
- package/src/events/ui-request.ts +1 -0
- package/src/protocols/protocol-v2/resources.ts +6 -1
|
@@ -3,6 +3,7 @@ export declare const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH = "vol0:/loaders/boo
|
|
|
3
3
|
export declare const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH: string;
|
|
4
4
|
export declare const PROTOCOL_V2_ROM_PARAMS_PACKAGE_PATH = "vol0:/loaders/rom/params.okpkg";
|
|
5
5
|
export declare const PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_SIZE = 24464;
|
|
6
|
+
export declare const PROTOCOL_V2_RESOURCE_PACKAGE_COMPARE_SIZE = 640;
|
|
6
7
|
export declare function parseProtocolV2Resources(value: unknown): IProtocolV2Resources | undefined;
|
|
7
8
|
export declare function isProtocolV2ResourceArchiveEntryName(entryName: string): boolean;
|
|
8
9
|
export type ProtocolV2ResourcePackageHeader = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/resources.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEvE,eAAO,MAAM,sCAAsC,iDACH,CAAC;AACjD,eAAO,MAAM,8CAA8C,QAAsD,CAAC;AAClH,eAAO,MAAM,mCAAmC,mCAAmC,CAAC;AACpF,eAAO,MAAM,wCAAwC,QAAS,CAAC;AAW/D,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,GAAG,SAAS,CA8BzF;AAED,wBAAgB,oCAAoC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAoB/E;AA0CD,MAAM,MAAM,+BAA+B,GAAG;IAC5C,OAAO,EAAE,aAAa,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,oCAAoC,CAClD,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,MAAM,GAClB,+BAA+B,CAyCjC;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,WAAW,GAAG,UAAU,GAC/B,+BAA+B,
|
|
1
|
+
{"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/resources.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEvE,eAAO,MAAM,sCAAsC,iDACH,CAAC;AACjD,eAAO,MAAM,8CAA8C,QAAsD,CAAC;AAClH,eAAO,MAAM,mCAAmC,mCAAmC,CAAC;AACpF,eAAO,MAAM,wCAAwC,QAAS,CAAC;AAE/D,eAAO,MAAM,yCAAyC,MAAQ,CAAC;AAW/D,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,GAAG,SAAS,CA8BzF;AAED,wBAAgB,oCAAoC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAoB/E;AA0CD,MAAM,MAAM,+BAA+B,GAAG;IAC5C,OAAO,EAAE,aAAa,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,oCAAoC,CAClD,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,MAAM,GAClB,+BAA+B,CAyCjC;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,WAAW,GAAG,UAAU,GAC/B,+BAA+B,CAMjC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-core",
|
|
3
|
-
"version": "1.2.8-alpha.
|
|
3
|
+
"version": "1.2.8-alpha.129",
|
|
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.8-alpha.
|
|
29
|
-
"@onekeyfe/hd-transport": "1.2.8-alpha.
|
|
28
|
+
"@onekeyfe/hd-shared": "1.2.8-alpha.129",
|
|
29
|
+
"@onekeyfe/hd-transport": "1.2.8-alpha.129",
|
|
30
30
|
"axios": "1.15.2",
|
|
31
31
|
"bignumber.js": "^9.0.2",
|
|
32
32
|
"buffer": "^6.0.3",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"@types/w3c-web-usb": "^1.0.10",
|
|
47
47
|
"@types/web-bluetooth": "^0.0.21"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "e340d9447b375a9d79afd737bec50ff8c5a46aba"
|
|
50
50
|
}
|
package/src/api/FileWrite.ts
CHANGED
|
@@ -6,7 +6,10 @@ import {
|
|
|
6
6
|
validateProtocolV2FilesystemPath,
|
|
7
7
|
validateRequiredData,
|
|
8
8
|
} from './helpers/filesystemValidation';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
createProtocolV2AssetFileWriteRecovery,
|
|
11
|
+
writeProtocolV2File,
|
|
12
|
+
} from './helpers/protocolV2FileWrite';
|
|
10
13
|
import { UI_REQUEST, createUiMessage } from '../events/ui-request';
|
|
11
14
|
|
|
12
15
|
export type FileWriteParams = {
|
|
@@ -63,6 +66,9 @@ export default class FileWrite extends BaseMethod<FileWriteParams> {
|
|
|
63
66
|
append: this.params.append,
|
|
64
67
|
uiPercentage: this.params.uiPercentage,
|
|
65
68
|
timeoutMs: this.params.timeoutMs === undefined ? undefined : Number(this.params.timeoutMs),
|
|
69
|
+
...(this.name === 'uploadPortfolio'
|
|
70
|
+
? { maxChunkRetries: 3, recoverConnection: createProtocolV2AssetFileWriteRecovery(this) }
|
|
71
|
+
: {}),
|
|
66
72
|
throwIfAborted: () => this.throwIfAborted(),
|
|
67
73
|
onProgress: payload => {
|
|
68
74
|
if (this.params.emitProgress && typeof this.postMessage === 'function') {
|
|
@@ -36,6 +36,7 @@ import { requestProtocolV2DeviceInfo } from '../protocols/protocol-v2/features';
|
|
|
36
36
|
import {
|
|
37
37
|
PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH,
|
|
38
38
|
PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH,
|
|
39
|
+
PROTOCOL_V2_RESOURCE_PACKAGE_COMPARE_SIZE,
|
|
39
40
|
PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_SIZE,
|
|
40
41
|
type ProtocolV2ResourcePackageHeader,
|
|
41
42
|
isProtocolV2ResourceArchiveEntryName,
|
|
@@ -77,6 +78,7 @@ import type {
|
|
|
77
78
|
import type { FirmwareByteSource } from './firmware/FirmwareArtifactSource';
|
|
78
79
|
|
|
79
80
|
const Log = getLogger(LoggerNames.Method);
|
|
81
|
+
const TransferLog = getLogger(LoggerNames.Core);
|
|
80
82
|
|
|
81
83
|
// Restored after a rebase dropped the declaration while keeping its use in
|
|
82
84
|
// fileWriteChunk; without it that error branch throws ReferenceError instead of
|
|
@@ -112,6 +114,7 @@ const PROTOCOL_V2_RESOURCE_HEADER_RECOVERY_LIMIT = 2;
|
|
|
112
114
|
// window. Set it to undefined to keep every transfer serial.
|
|
113
115
|
const PROTOCOL_V2_BLE_FILE_WRITE_WINDOW_MIN_BOOTLOADER_VERSION: string | undefined = '1.0.3';
|
|
114
116
|
const PROTOCOL_V2_TRANSFER_PROGRESS_HEARTBEAT_MS = 1000;
|
|
117
|
+
const PROTOCOL_V2_TRANSFER_LOG_INTERVAL_MS = 10_000;
|
|
115
118
|
const PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE = 'FirmwareInstallStatusConflict';
|
|
116
119
|
const PROTOCOL_V2_INSTALL_FAILED_CODE = 'FirmwareInstallFailed';
|
|
117
120
|
const PROTOCOL_V2_INSTALL_TIMEOUT_CODE = 'FirmwareInstallTimeout';
|
|
@@ -631,9 +634,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
631
634
|
|
|
632
635
|
private protocolV2LastTransferredBytes = 0;
|
|
633
636
|
|
|
634
|
-
/** Set when a windowed FileWrite attempt fails: the rest of this update writes serially. */
|
|
635
|
-
private protocolV2FileWriteWindowDisabled = false;
|
|
636
|
-
|
|
637
637
|
init() {
|
|
638
638
|
this.allowDeviceMode = [UI_REQUEST.BOOTLOADER, UI_REQUEST.NOT_INITIALIZE];
|
|
639
639
|
this.requireDeviceMode = [];
|
|
@@ -1868,8 +1868,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1868
1868
|
const chunkSize = this.getProtocolV2FirmwareChunkSize('read');
|
|
1869
1869
|
const chunks: Uint8Array[] = [];
|
|
1870
1870
|
let offset = 0;
|
|
1871
|
-
while (offset <
|
|
1872
|
-
const readLen = Math.min(chunkSize,
|
|
1871
|
+
while (offset < PROTOCOL_V2_RESOURCE_PACKAGE_COMPARE_SIZE) {
|
|
1872
|
+
const readLen = Math.min(chunkSize, PROTOCOL_V2_RESOURCE_PACKAGE_COMPARE_SIZE - offset);
|
|
1873
1873
|
const res = await typedCall('FilesystemFileRead', 'FilesystemFile', {
|
|
1874
1874
|
file: {
|
|
1875
1875
|
path: filePath,
|
|
@@ -1880,7 +1880,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1880
1880
|
ui_percentage: undefined,
|
|
1881
1881
|
});
|
|
1882
1882
|
const data = toProtocolV2Bytes(res.message?.data);
|
|
1883
|
-
if (data.byteLength === 0) return null;
|
|
1883
|
+
if (data.byteLength === 0 || data.byteLength > readLen) return null;
|
|
1884
1884
|
chunks.push(data);
|
|
1885
1885
|
offset += data.byteLength;
|
|
1886
1886
|
}
|
|
@@ -1995,6 +1995,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1995
1995
|
this.postTipMessage(FirmwareUpdateTipMessage.AutoRebootToBootloader);
|
|
1996
1996
|
await this.protocolV2Reboot(DeviceRebootType.Bootloader);
|
|
1997
1997
|
await wait(1000);
|
|
1998
|
+
if (this.isBleReconnect()) {
|
|
1999
|
+
await this.device.deviceConnector?.disconnect(this.device.originalDescriptor.id);
|
|
2000
|
+
}
|
|
1998
2001
|
await this.waitForProtocolV2BootloaderMode();
|
|
1999
2002
|
this.protocolV2ExecutionInLoader = true;
|
|
2000
2003
|
this.postTipMessage(FirmwareUpdateTipMessage.GoToBootloaderSuccess);
|
|
@@ -2037,12 +2040,19 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2037
2040
|
while (Date.now() - startTime < timeout) {
|
|
2038
2041
|
try {
|
|
2039
2042
|
if (shouldReconnect) {
|
|
2040
|
-
|
|
2043
|
+
if (this.isBleReconnect()) {
|
|
2044
|
+
await this.reconnectProtocolV2Device({ skipProtocolProbe: true });
|
|
2045
|
+
} else {
|
|
2046
|
+
await this.reconnectProtocolV2Device();
|
|
2047
|
+
}
|
|
2041
2048
|
shouldReconnect = false;
|
|
2042
2049
|
}
|
|
2043
2050
|
const deviceInfo = await requestProtocolV2DeviceInfo({
|
|
2044
2051
|
commands: this.device.getCommands(),
|
|
2045
|
-
timeoutMs:
|
|
2052
|
+
timeoutMs: Math.min(
|
|
2053
|
+
this.getProtocolV2DeviceInfoTimeout(),
|
|
2054
|
+
PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT
|
|
2055
|
+
),
|
|
2046
2056
|
});
|
|
2047
2057
|
this.assertProtocolV2DeviceInfoIdentity(deviceInfo);
|
|
2048
2058
|
const features = await this.device.probeProtocolV2RuntimeState(
|
|
@@ -2335,10 +2345,37 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2335
2345
|
this.throwIfAborted();
|
|
2336
2346
|
const attemptStartedAt = Date.now();
|
|
2337
2347
|
let windowed = false;
|
|
2348
|
+
let chunkSize = 0;
|
|
2349
|
+
let confirmedBytes = 0;
|
|
2350
|
+
let lastMetricsAt = attemptStartedAt;
|
|
2351
|
+
const logTransfer = (status: 'started' | 'progress' | 'completed' | 'failed') => {
|
|
2352
|
+
const elapsedMs = getProtocolV2ElapsedMs(attemptStartedAt);
|
|
2353
|
+
TransferLog.log('[FirmwareUpdateV4] FileWrite metrics', {
|
|
2354
|
+
status,
|
|
2355
|
+
path: filePath,
|
|
2356
|
+
fileWriteWindow: windowed ? PROTOCOL_V2_FILE_WRITE_PIPELINE_WINDOW : 1,
|
|
2357
|
+
chunkSize,
|
|
2358
|
+
attempt,
|
|
2359
|
+
retryCount: attempt - 1,
|
|
2360
|
+
transferredBytes: confirmedBytes,
|
|
2361
|
+
totalBytes: source.size,
|
|
2362
|
+
elapsedMs,
|
|
2363
|
+
rateBytesPerSecond: getProtocolV2TransferRate(confirmedBytes, elapsedMs),
|
|
2364
|
+
});
|
|
2365
|
+
};
|
|
2366
|
+
const reportAttemptChunk = (chunkEnd: number) => {
|
|
2367
|
+
confirmedBytes = chunkEnd;
|
|
2368
|
+
reportConfirmedChunk(chunkEnd);
|
|
2369
|
+
const now = Date.now();
|
|
2370
|
+
if (now - lastMetricsAt >= PROTOCOL_V2_TRANSFER_LOG_INTERVAL_MS && chunkEnd < source.size) {
|
|
2371
|
+
logTransfer('progress');
|
|
2372
|
+
lastMetricsAt = now;
|
|
2373
|
+
}
|
|
2374
|
+
};
|
|
2338
2375
|
try {
|
|
2339
|
-
windowed =
|
|
2340
|
-
|
|
2341
|
-
|
|
2376
|
+
windowed = this.shouldUseProtocolV2BleFileWriteWindow();
|
|
2377
|
+
chunkSize = this.getProtocolV2FirmwareChunkSize('write', filePath, windowed);
|
|
2378
|
+
logTransfer('started');
|
|
2342
2379
|
if (windowed) {
|
|
2343
2380
|
await this.writeProtocolV2SourceWindowed({
|
|
2344
2381
|
source,
|
|
@@ -2346,7 +2383,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2346
2383
|
chunkSize,
|
|
2347
2384
|
processedSize,
|
|
2348
2385
|
totalSize,
|
|
2349
|
-
onChunkConfirmed:
|
|
2386
|
+
onChunkConfirmed: reportAttemptChunk,
|
|
2350
2387
|
});
|
|
2351
2388
|
} else {
|
|
2352
2389
|
await writeFirmwareByteSource({
|
|
@@ -2377,23 +2414,18 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
2377
2414
|
`invalid processed_byte ${rawProcessedByte} for offset ${sourceOffset}`
|
|
2378
2415
|
);
|
|
2379
2416
|
}
|
|
2380
|
-
|
|
2417
|
+
reportAttemptChunk(chunkEnd);
|
|
2381
2418
|
return length;
|
|
2382
2419
|
},
|
|
2383
2420
|
});
|
|
2384
2421
|
}
|
|
2385
|
-
|
|
2386
|
-
path: filePath,
|
|
2387
|
-
bytes: source.size,
|
|
2388
|
-
elapsedMs: getProtocolV2ElapsedMs(attemptStartedAt),
|
|
2389
|
-
attempt,
|
|
2390
|
-
fileWriteWindow: windowed ? PROTOCOL_V2_FILE_WRITE_PIPELINE_WINDOW : 1,
|
|
2391
|
-
});
|
|
2422
|
+
logTransfer('completed');
|
|
2392
2423
|
return processedSize + source.size;
|
|
2393
2424
|
} catch (error) {
|
|
2394
2425
|
this.throwIfAborted();
|
|
2395
2426
|
lastError = error;
|
|
2396
|
-
|
|
2427
|
+
logTransfer('failed');
|
|
2428
|
+
TransferLog.debug('[FirmwareUpdateV4] Protocol V2 file transfer attempt failed', {
|
|
2397
2429
|
path: filePath,
|
|
2398
2430
|
attempt,
|
|
2399
2431
|
fileWriteWindow: windowed ? PROTOCOL_V2_FILE_WRITE_PIPELINE_WINDOW : 1,
|
|
@@ -3346,7 +3378,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
3346
3378
|
// parsed version keeps major.minor.patch only, so a 1.0.3 prerelease counts as 1.0.3.
|
|
3347
3379
|
const bootloaderVersion = getDeviceBootloaderVersion(this.device.features).join('.');
|
|
3348
3380
|
const enabled = supportsProtocolV2BleFileWriteWindow(bootloaderVersion, minBootloaderVersion);
|
|
3349
|
-
|
|
3381
|
+
TransferLog.debug('[FirmwareUpdateV4] BLE FileWrite window', {
|
|
3350
3382
|
enabled,
|
|
3351
3383
|
bootloaderVersion,
|
|
3352
3384
|
bootloaderBuildId: this.device.features?.verify?.bootloaderBuildId,
|
|
@@ -3406,9 +3438,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
3406
3438
|
if (source.size === 0) return;
|
|
3407
3439
|
const firstRequest = await readRequest();
|
|
3408
3440
|
|
|
3409
|
-
//
|
|
3410
|
-
//
|
|
3411
|
-
// nothing about the bootloader and keep the window.
|
|
3441
|
+
// Core retries the whole overwriting file after a verified reconnect. Keep the same
|
|
3442
|
+
// window on retries and subsequent files; the running bootloader version gates support.
|
|
3412
3443
|
const response = await this.device
|
|
3413
3444
|
.getCommands()
|
|
3414
3445
|
.typedCall('FilesystemFileWrite', 'FilesystemFile', firstRequest, {
|
|
@@ -3422,16 +3453,11 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
3422
3453
|
onChunkConfirmed(Number(confirmed.message.processed_byte));
|
|
3423
3454
|
},
|
|
3424
3455
|
},
|
|
3425
|
-
})
|
|
3426
|
-
.catch((error: unknown) => {
|
|
3427
|
-
this.protocolV2FileWriteWindowDisabled = true;
|
|
3428
|
-
throw error;
|
|
3429
3456
|
});
|
|
3430
3457
|
this.throwIfAborted();
|
|
3431
3458
|
if (sourceError) throw sourceError;
|
|
3432
3459
|
const rawProcessedByte = response.message.processed_byte;
|
|
3433
3460
|
if (Number(rawProcessedByte) !== source.size) {
|
|
3434
|
-
this.protocolV2FileWriteWindowDisabled = true;
|
|
3435
3461
|
throw ERRORS.TypedError(
|
|
3436
3462
|
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
3437
3463
|
`invalid processed_byte ${rawProcessedByte} for file size ${source.size}`
|
|
@@ -212,17 +212,26 @@ export const readVerifiedFirmwareArtifact = async ({
|
|
|
212
212
|
}): Promise<ArrayBuffer> => {
|
|
213
213
|
assertFirmwareArtifactReference(artifact);
|
|
214
214
|
const source = await ReaderFirmwareByteSource.open(artifact, reader);
|
|
215
|
+
const hasher = sha256.create();
|
|
215
216
|
try {
|
|
216
|
-
const
|
|
217
|
-
|
|
217
|
+
const bytes = new Uint8Array(source.size);
|
|
218
|
+
let offset = 0;
|
|
219
|
+
while (offset < source.size) {
|
|
220
|
+
const length = Math.min(MAX_FIRMWARE_ARTIFACT_READ_BYTES, source.size - offset);
|
|
221
|
+
bytes.set(new Uint8Array(await source.readAt(offset, length)), offset);
|
|
222
|
+
hasher.update(bytes.subarray(offset, offset + length));
|
|
223
|
+
offset += length;
|
|
224
|
+
}
|
|
225
|
+
const actualSha256 = bytesToHex(hasher.digest());
|
|
218
226
|
if (actualSha256 !== artifact.sha256.toLowerCase()) {
|
|
219
227
|
return artifactError(
|
|
220
228
|
'FirmwareArtifactReceiptMismatch',
|
|
221
229
|
'Firmware artifact bytes do not match the approved SHA-256 receipt'
|
|
222
230
|
);
|
|
223
231
|
}
|
|
224
|
-
return
|
|
232
|
+
return bytes.buffer;
|
|
225
233
|
} finally {
|
|
234
|
+
hasher.destroy();
|
|
226
235
|
await source.close().catch(() => undefined);
|
|
227
236
|
}
|
|
228
237
|
};
|