@onekeyfe/hd-core 1.2.0-alpha.68 → 1.2.0-alpha.69
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 +28 -0
- package/__tests__/connectSettings.test.ts +5 -47
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +31 -59
- package/__tests__/protocol-v2-firmware-targets.test.ts +33 -1
- package/__tests__/protocol-v2-resources.test.ts +9 -6
- package/__tests__/protocol-v2.test.ts +174 -383
- package/__tests__/protocolV2FileWrite.test.ts +48 -7
- package/dist/api/CheckAllFirmwareRelease.d.ts +2 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdate.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +0 -10
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts +3 -7
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +6 -25
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +0 -8
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +0 -7
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/updateBootloader.d.ts +0 -2
- package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/uploadFirmware.d.ts +1 -9
- package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
- package/dist/data-manager/DataManager.d.ts +0 -1
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/connectSettings.d.ts.map +1 -1
- package/dist/device/Device.d.ts +0 -1
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/index.d.ts +2 -180
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1041 -3037
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/resources.d.ts +1 -1
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/topLevelInject.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +0 -4
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
- package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +1 -4
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +0 -68
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +1 -9
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/settings.d.ts +1 -14
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesCompat.d.ts +0 -1
- package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/CheckAllFirmwareRelease.ts +25 -61
- package/src/api/FirmwareUpdate.ts +1 -13
- package/src/api/FirmwareUpdateV2.ts +121 -296
- package/src/api/FirmwareUpdateV3.ts +57 -263
- package/src/api/FirmwareUpdateV4.ts +287 -865
- package/src/api/device/DeviceUpdateBootloader.ts +6 -125
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +1 -72
- package/src/api/firmware/updateBootloader.ts +4 -19
- package/src/api/firmware/uploadFirmware.ts +22 -140
- package/src/api/helpers/protocolV2FileWrite.ts +54 -4
- package/src/data-manager/DataManager.ts +54 -59
- package/src/data-manager/connectSettings.ts +0 -11
- package/src/device/Device.ts +1 -6
- package/src/index.ts +0 -5
- package/src/inject.ts +2 -22
- package/src/lowLevelInject.ts +1 -5
- package/src/protocols/protocol-v2/resources.ts +5 -1
- package/src/topLevelInject.ts +1 -5
- package/src/types/api/checkAllFirmwareRelease.ts +0 -4
- package/src/types/api/deviceUpdateBootloader.ts +0 -6
- package/src/types/api/export.ts +0 -18
- package/src/types/api/firmwareUpdate.ts +0 -75
- package/src/types/api/index.ts +0 -14
- package/src/types/settings.ts +2 -14
- package/src/utils/deviceFeaturesCompat.ts +0 -6
- package/__tests__/device-initialize-timeout.test.ts +0 -56
- package/__tests__/firmware-update/check-all-firmware-release.test.ts +0 -175
- package/__tests__/firmware-update/device-update-bootloader.test.ts +0 -87
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
- package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
- package/__tests__/firmware-update/firmware-preparation-error.test.ts +0 -27
- package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +0 -200
- package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
- package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +0 -394
- package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -593
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -231
- package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +0 -63
- package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
- package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -25
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
- package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
- package/dist/api/firmware/FirmwarePreparationError.d.ts +0 -3
- package/dist/api/firmware/FirmwarePreparationError.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -25
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -32
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
- package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdatePlan.d.ts +0 -28
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
- package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
- package/src/api/firmware/FirmwareHostBinding.ts +0 -100
- package/src/api/firmware/FirmwarePreparationError.ts +0 -12
- package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
- package/src/api/firmware/FirmwareUpdatePlan.ts +0 -772
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -449
- package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
- package/src/types/api/firmwareUpdatePlan.ts +0 -38
- package/src/types/api/firmwareUpdatePreparedPlan.ts +0 -53
|
@@ -5,24 +5,15 @@ import { UI_REQUEST } from '../../constants/ui-request';
|
|
|
5
5
|
import { FirmwareUpdateTipMessage } from '../../events/ui-request';
|
|
6
6
|
import { FirmwareUpdateBaseMethod } from '../firmware/FirmwareUpdateBaseMethod';
|
|
7
7
|
import { getSysResourceBinary } from '../firmware/getBinary';
|
|
8
|
-
import { updateBootloader
|
|
8
|
+
import { updateBootloader } from '../firmware/uploadFirmware';
|
|
9
9
|
import { DeviceModelToTypes } from '../../types';
|
|
10
10
|
import { DataManager } from '../../data-manager';
|
|
11
|
-
import { checkBootloaderLength
|
|
12
|
-
import { openFirmwareByteSource } from '../firmware/FirmwareArtifactSource';
|
|
13
|
-
import { resolveFirmwareUpdateHostBinding } from '../firmware/FirmwareHostBinding';
|
|
14
|
-
import {
|
|
15
|
-
assertFirmwareUpdatePreparedPlanBinding,
|
|
16
|
-
assertFirmwareUpdatePreparedPlanDeviceIdentity,
|
|
17
|
-
} from '../firmware/FirmwareUpdatePreparedPlan';
|
|
18
|
-
import { getDeviceType, getDeviceUUID } from '../../utils';
|
|
19
|
-
import { resolveDeviceBootloaderMode } from '../../utils/deviceFeaturesCompat';
|
|
11
|
+
import { checkBootloaderLength } from '../firmware/updateBootloader';
|
|
20
12
|
|
|
21
13
|
import type { DeviceUpdateBootloaderParams } from '../../types/api/deviceUpdateBootloader';
|
|
22
14
|
import type { EFirmwareType } from '@onekeyfe/hd-shared';
|
|
23
15
|
import type { Device } from '../../device/Device';
|
|
24
16
|
import type { Features } from '../../types';
|
|
25
|
-
import type { FirmwareByteSource } from '../firmware/FirmwareArtifactSource';
|
|
26
17
|
|
|
27
18
|
export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any> {
|
|
28
19
|
init() {
|
|
@@ -52,68 +43,17 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
|
|
|
52
43
|
return true;
|
|
53
44
|
}
|
|
54
45
|
|
|
55
|
-
async updateBootloaderWithEmmcFileWriteFromSource(_device: Device, source: FirmwareByteSource) {
|
|
56
|
-
const filePath = '0:boot/bootloader.bin';
|
|
57
|
-
|
|
58
|
-
this.postTipMessage(FirmwareUpdateTipMessage.StartTransferData);
|
|
59
|
-
await this.emmcCommonUpdateProcessFromSource({
|
|
60
|
-
source,
|
|
61
|
-
filePath,
|
|
62
|
-
});
|
|
63
|
-
this.postTipMessage(FirmwareUpdateTipMessage.ConfirmOnDevice);
|
|
64
|
-
await this.reboot(RebootType.Normal);
|
|
65
|
-
this.postTipMessage(FirmwareUpdateTipMessage.UpdateBootloaderSuccess);
|
|
66
|
-
return true;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
46
|
async updateTouchBootloader({
|
|
70
47
|
device,
|
|
71
48
|
features,
|
|
72
49
|
firmwareType,
|
|
73
|
-
binary: preparedBinary,
|
|
74
|
-
source: preparedSource,
|
|
75
50
|
}: {
|
|
76
51
|
device: Device;
|
|
77
52
|
features?: Features;
|
|
78
53
|
firmwareType: EFirmwareType;
|
|
79
|
-
binary?: ArrayBuffer;
|
|
80
|
-
source?: FirmwareByteSource;
|
|
81
54
|
}) {
|
|
82
|
-
|
|
83
|
-
if (!(await checkBootloaderSourceLength(preparedSource))) {
|
|
84
|
-
throw ERRORS.TypedError(HardwareErrorCode.CheckDownloadFileError);
|
|
85
|
-
}
|
|
86
|
-
if (features && device.isBootloader()) {
|
|
87
|
-
this.postTipMessage(FirmwareUpdateTipMessage.UpdateBootloader);
|
|
88
|
-
const result = await this.updateBootloaderWithEmmcFileWriteFromSource(
|
|
89
|
-
device,
|
|
90
|
-
preparedSource
|
|
91
|
-
);
|
|
92
|
-
return result;
|
|
93
|
-
}
|
|
94
|
-
if (features && !device.isBootloader()) {
|
|
95
|
-
await updateBootloaderFromSource(
|
|
96
|
-
this.device.getCommands().typedCall.bind(this.device.getCommands()),
|
|
97
|
-
this.postMessage,
|
|
98
|
-
device,
|
|
99
|
-
preparedSource
|
|
100
|
-
);
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
let binary = preparedBinary;
|
|
55
|
+
let { binary } = this.payload;
|
|
106
56
|
if (!binary) {
|
|
107
|
-
if (DataManager.getSettings('firmwareManifestMode') === 'external-only') {
|
|
108
|
-
throw ERRORS.TypedError(
|
|
109
|
-
HardwareErrorCode.RuntimeError,
|
|
110
|
-
'Bootloader must be prepared by the external firmware host',
|
|
111
|
-
{
|
|
112
|
-
firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
|
|
113
|
-
artifactName: 'bootloader',
|
|
114
|
-
}
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
57
|
this.postTipMessage(FirmwareUpdateTipMessage.CheckLatestUiResource);
|
|
118
58
|
const resourceUrl = features
|
|
119
59
|
? DataManager.getBootloaderResource(features, firmwareType)
|
|
@@ -128,7 +68,7 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
|
|
|
128
68
|
}
|
|
129
69
|
}
|
|
130
70
|
|
|
131
|
-
if (!
|
|
71
|
+
if (!checkBootloaderLength(binary)) {
|
|
132
72
|
throw ERRORS.TypedError(HardwareErrorCode.CheckDownloadFileError);
|
|
133
73
|
}
|
|
134
74
|
|
|
@@ -136,8 +76,7 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
|
|
|
136
76
|
if (features && device.isBootloader()) {
|
|
137
77
|
// Use emmcFileWrite + reboot logic for bootloader mode
|
|
138
78
|
this.postTipMessage(FirmwareUpdateTipMessage.UpdateBootloader);
|
|
139
|
-
|
|
140
|
-
return result;
|
|
79
|
+
return this.updateBootloaderWithEmmcFileWrite(device, binary);
|
|
141
80
|
}
|
|
142
81
|
|
|
143
82
|
if (features && !device.isBootloader()) {
|
|
@@ -157,71 +96,13 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
|
|
|
157
96
|
const { features } = device;
|
|
158
97
|
|
|
159
98
|
const payload = this.payload as DeviceUpdateBootloaderParams;
|
|
160
|
-
const hostBinding = payload.artifact
|
|
161
|
-
? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration)
|
|
162
|
-
: undefined;
|
|
163
|
-
const executionParams = {
|
|
164
|
-
...payload,
|
|
165
|
-
artifactReader: hostBinding?.artifactReader ?? payload.artifactReader,
|
|
166
|
-
};
|
|
167
|
-
if (payload.artifact) {
|
|
168
|
-
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
169
|
-
preparedPlan: payload.preparedPlan,
|
|
170
|
-
deviceIdentity: getDeviceUUID(features) || undefined,
|
|
171
|
-
bootloaderMode: resolveDeviceBootloaderMode(features),
|
|
172
|
-
deviceModel: String(getDeviceType(features)),
|
|
173
|
-
});
|
|
174
|
-
assertFirmwareUpdatePreparedPlanBinding({
|
|
175
|
-
preparedPlan: payload.preparedPlan,
|
|
176
|
-
executor: 'v2',
|
|
177
|
-
scopeTargets: ['bootloader'],
|
|
178
|
-
bindings: [
|
|
179
|
-
{
|
|
180
|
-
target: 'bootloader',
|
|
181
|
-
artifact: payload.artifact,
|
|
182
|
-
},
|
|
183
|
-
],
|
|
184
|
-
});
|
|
185
|
-
const source = await openFirmwareByteSource({
|
|
186
|
-
artifact: payload.artifact,
|
|
187
|
-
reader: executionParams.artifactReader,
|
|
188
|
-
});
|
|
189
|
-
if (!source) {
|
|
190
|
-
throw ERRORS.TypedError(
|
|
191
|
-
HardwareErrorCode.RuntimeError,
|
|
192
|
-
'Bootloader artifact is not prepared'
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
try {
|
|
196
|
-
const deviceType = device.getCurrentDeviceType();
|
|
197
|
-
const deviceFirmwareType = device.getCurrentFirmwareType();
|
|
198
|
-
const firmwareType = payload.firmwareType ?? deviceFirmwareType;
|
|
199
|
-
if (DeviceModelToTypes.model_touch.includes(deviceType)) {
|
|
200
|
-
return await this.updateTouchBootloader({
|
|
201
|
-
device,
|
|
202
|
-
features,
|
|
203
|
-
firmwareType,
|
|
204
|
-
source,
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
return true;
|
|
208
|
-
} finally {
|
|
209
|
-
await source.close().catch(() => undefined);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
99
|
|
|
213
|
-
const { binary } = payload;
|
|
214
100
|
const deviceType = device.getCurrentDeviceType();
|
|
215
101
|
const deviceFirmwareType = device.getCurrentFirmwareType();
|
|
216
102
|
const firmwareType = payload.firmwareType ?? deviceFirmwareType;
|
|
217
103
|
|
|
218
104
|
if (DeviceModelToTypes.model_touch.includes(deviceType)) {
|
|
219
|
-
return this.updateTouchBootloader({
|
|
220
|
-
device,
|
|
221
|
-
features,
|
|
222
|
-
firmwareType,
|
|
223
|
-
binary,
|
|
224
|
-
});
|
|
105
|
+
return this.updateTouchBootloader({ device, features, firmwareType });
|
|
225
106
|
}
|
|
226
107
|
|
|
227
108
|
return Promise.resolve(true);
|
|
@@ -13,7 +13,6 @@ import { DeviceModelToTypes } from '../../types';
|
|
|
13
13
|
import { DataManager } from '../../data-manager';
|
|
14
14
|
import { BaseMethod } from '../BaseMethod';
|
|
15
15
|
import { DEVICE } from '../../events';
|
|
16
|
-
import { writeFirmwareByteSource } from './FirmwareArtifactSource';
|
|
17
16
|
|
|
18
17
|
import type {
|
|
19
18
|
FirmwareProgress,
|
|
@@ -25,22 +24,11 @@ import type { RebootType } from '@onekeyfe/hd-transport';
|
|
|
25
24
|
import type { Deferred } from '@onekeyfe/hd-shared';
|
|
26
25
|
import type { KnownDevice } from '../../types';
|
|
27
26
|
import type { TypedResponseMessage } from '../../device/DeviceCommands';
|
|
28
|
-
import type { FirmwareByteSource } from './FirmwareArtifactSource';
|
|
29
27
|
|
|
30
28
|
const Log = getLogger(LoggerNames.Method);
|
|
31
29
|
const SESSION_ERROR = 'session not found';
|
|
32
30
|
const FIRMWARE_UPDATE_CONFIRM = 'Firmware install confirmed';
|
|
33
31
|
|
|
34
|
-
/**
|
|
35
|
-
* Response timeout for each Initialize probe while polling a rebooting device over BLE.
|
|
36
|
-
* Overlap safety comes from the poll's in-flight guard, not from this value. Keep it
|
|
37
|
-
* well below the 30s reboot budget so several attempts fit: a probe written into the
|
|
38
|
-
* dying pre-reboot connection is never answered, and its timeout tears that stale link
|
|
39
|
-
* down so the next tick reconnects fresh. Raise it only if a device model is proven to
|
|
40
|
-
* answer bootloader Initialize slower than this on a fresh connection.
|
|
41
|
-
*/
|
|
42
|
-
export const BOOTLOADER_POLL_INITIALIZE_TIMEOUT_MS = 5000;
|
|
43
|
-
|
|
44
32
|
type FirmwareTransferMetrics = Pick<
|
|
45
33
|
FirmwareProgress['payload'],
|
|
46
34
|
'transferredBytes' | 'totalBytes' | 'rateBytesPerSecond' | 'elapsedMs'
|
|
@@ -155,10 +143,6 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
|
|
|
155
143
|
this.checkPromise = createDeferred();
|
|
156
144
|
const env = DataManager.getSettings('env');
|
|
157
145
|
const isBleReconnect = connectId && DataManager.isBleConnect(env);
|
|
158
|
-
// Tracks the in-flight BLE probe so interval ticks never overlap: a superseded
|
|
159
|
-
// Initialize left pending on the V1 transport is exactly what later times out
|
|
160
|
-
// and used to tear down the connection mid-firmware-upload.
|
|
161
|
-
let bleProbeInFlight = false;
|
|
162
146
|
|
|
163
147
|
Log.log('FirmwareUpdateBaseMethod [checkDeviceToBootloader] isBleReconnect: ', isBleReconnect);
|
|
164
148
|
|
|
@@ -214,8 +198,6 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
|
|
|
214
198
|
}
|
|
215
199
|
|
|
216
200
|
if (isBleReconnect) {
|
|
217
|
-
if (bleProbeInFlight) return;
|
|
218
|
-
bleProbeInFlight = true;
|
|
219
201
|
try {
|
|
220
202
|
await this.device.deviceConnector?.acquire(
|
|
221
203
|
this.device.originalDescriptor.id,
|
|
@@ -223,10 +205,7 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
|
|
|
223
205
|
true,
|
|
224
206
|
this.payload.connectProtocol ?? this.device.originalDescriptor.protocolType
|
|
225
207
|
);
|
|
226
|
-
|
|
227
|
-
// frees the slot for the next tick instead of hanging into the
|
|
228
|
-
// 30s reboot budget.
|
|
229
|
-
await this.device.initialize({ timeoutMs: BOOTLOADER_POLL_INITIALIZE_TIMEOUT_MS });
|
|
208
|
+
await this.device.initialize();
|
|
230
209
|
if (this.device.isBootloader()) {
|
|
231
210
|
clearInterval(intervalTimer);
|
|
232
211
|
this.checkPromise?.resolve(true);
|
|
@@ -234,8 +213,6 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
|
|
|
234
213
|
} catch (e) {
|
|
235
214
|
// ignore error because of device is not connected
|
|
236
215
|
Log.log('catch Bluetooth error when device is restarting: ', e);
|
|
237
|
-
} finally {
|
|
238
|
-
bleProbeInFlight = false;
|
|
239
216
|
}
|
|
240
217
|
} else {
|
|
241
218
|
await this._checkDeviceInBootloaderMode(connectId, intervalTimer, timeoutTimer);
|
|
@@ -417,54 +394,6 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
|
|
|
417
394
|
return totalSize !== undefined ? (processedSize ?? 0) + payload.byteLength : 0;
|
|
418
395
|
}
|
|
419
396
|
|
|
420
|
-
async emmcCommonUpdateProcessFromSource({
|
|
421
|
-
source,
|
|
422
|
-
filePath,
|
|
423
|
-
processedSize,
|
|
424
|
-
totalSize,
|
|
425
|
-
}: {
|
|
426
|
-
source: FirmwareByteSource;
|
|
427
|
-
filePath: string;
|
|
428
|
-
processedSize?: number;
|
|
429
|
-
totalSize?: number;
|
|
430
|
-
}) {
|
|
431
|
-
if (!filePath.startsWith('0:')) {
|
|
432
|
-
throw new Error('filePath must start with 0:');
|
|
433
|
-
}
|
|
434
|
-
const env = DataManager.getSettings('env');
|
|
435
|
-
const chunkSize = 1024 * (DataManager.isBleConnect(env) ? 16 : 128);
|
|
436
|
-
|
|
437
|
-
await writeFirmwareByteSource({
|
|
438
|
-
source,
|
|
439
|
-
chunkSize,
|
|
440
|
-
write: async ({ data, sourceOffset, length, first }) => {
|
|
441
|
-
const progress =
|
|
442
|
-
totalSize !== undefined && processedSize !== undefined
|
|
443
|
-
? Math.min(Math.ceil(((processedSize + sourceOffset + length) / totalSize) * 100), 99)
|
|
444
|
-
: Math.min(Math.ceil(((sourceOffset + length) / source.size) * 100), 99);
|
|
445
|
-
const writeRes = await this.emmcFileWriteWithRetry(
|
|
446
|
-
filePath,
|
|
447
|
-
length,
|
|
448
|
-
sourceOffset,
|
|
449
|
-
data,
|
|
450
|
-
first,
|
|
451
|
-
progress
|
|
452
|
-
);
|
|
453
|
-
if (!writeRes) {
|
|
454
|
-
throw ERRORS.TypedError(
|
|
455
|
-
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
456
|
-
'transfer data error'
|
|
457
|
-
);
|
|
458
|
-
}
|
|
459
|
-
const processedBytes = Number(writeRes.message.processed_byte);
|
|
460
|
-
this.postProgressMessage(progress, 'transferData');
|
|
461
|
-
return Number.isFinite(processedBytes) ? processedBytes : length;
|
|
462
|
-
},
|
|
463
|
-
});
|
|
464
|
-
|
|
465
|
-
return totalSize !== undefined ? (processedSize ?? 0) + source.size : 0;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
397
|
async emmcFileWriteWithRetry(
|
|
469
398
|
filePath: string,
|
|
470
399
|
chunkLength: number,
|
|
@@ -8,7 +8,6 @@ import { shouldUpdateBootloaderForClassicAndMini } from './bootloaderHelper';
|
|
|
8
8
|
|
|
9
9
|
import type { Features } from '../../types';
|
|
10
10
|
import type { EFirmwareType } from '@onekeyfe/hd-shared';
|
|
11
|
-
import type { FirmwareByteSource } from './FirmwareArtifactSource';
|
|
12
11
|
|
|
13
12
|
export function checkNeedUpdateBootForTouch(features: Features, firmwareType: EFirmwareType) {
|
|
14
13
|
const deviceType = getDeviceType(features);
|
|
@@ -63,7 +62,8 @@ export function checkNeedUpdateBootForClassicAndMini({
|
|
|
63
62
|
}
|
|
64
63
|
|
|
65
64
|
const INIT_DATA_CHUNK_SIZE = 16 * 1024;
|
|
66
|
-
|
|
65
|
+
export function checkBootloaderLength(data: ArrayBuffer) {
|
|
66
|
+
const chunk = new Uint8Array(data.slice(0, Math.min(INIT_DATA_CHUNK_SIZE, data.byteLength)));
|
|
67
67
|
const buffer = ByteBuffer.wrap(chunk, undefined, undefined, true);
|
|
68
68
|
buffer.LE();
|
|
69
69
|
// byte 'O', 'K', 'T', 'B'
|
|
@@ -77,21 +77,6 @@ const readBootloaderLength = (chunk: Uint8Array) => {
|
|
|
77
77
|
buffer.readUint32();
|
|
78
78
|
// codelen
|
|
79
79
|
const codelen = buffer.readUint32();
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
export function checkBootloaderLength(data: ArrayBuffer) {
|
|
84
|
-
if (data.byteLength < 16) {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
const chunk = new Uint8Array(data.slice(0, Math.min(INIT_DATA_CHUNK_SIZE, data.byteLength)));
|
|
88
|
-
return readBootloaderLength(chunk) === data.byteLength;
|
|
80
|
+
const bootloaderLength = hdrlen + codelen;
|
|
81
|
+
return bootloaderLength === data.byteLength;
|
|
89
82
|
}
|
|
90
|
-
|
|
91
|
-
export const checkBootloaderSourceLength = async (source: FirmwareByteSource) => {
|
|
92
|
-
if (source.size < 16) {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
const chunk = new Uint8Array(await source.readAt(0, Math.min(INIT_DATA_CHUNK_SIZE, source.size)));
|
|
96
|
-
return readBootloaderLength(chunk) === source.size;
|
|
97
|
-
};
|
|
@@ -10,7 +10,6 @@ import { bytesToHex } from '../helpers/hexUtils';
|
|
|
10
10
|
import { DataManager } from '../../data-manager';
|
|
11
11
|
import { DevicePool } from '../../device/DevicePool';
|
|
12
12
|
import { buildProtocolV1FeaturesPayload } from '../../deviceProfile';
|
|
13
|
-
import { openFirmwareByteSource, readFirmwareByteSourceFully } from './FirmwareArtifactSource';
|
|
14
13
|
|
|
15
14
|
import type { KnownDevice } from '../../types';
|
|
16
15
|
import type { TypedCall, TypedResponseMessage } from '../../device/DeviceCommands';
|
|
@@ -18,7 +17,6 @@ import type { PROTO } from '../../constants';
|
|
|
18
17
|
import type { CoreMessage, IFirmwareUpdateProgressType } from '../../events';
|
|
19
18
|
import type { Success } from '@onekeyfe/hd-transport';
|
|
20
19
|
import type { Device } from '../../device/Device';
|
|
21
|
-
import type { FirmwareByteSource } from './FirmwareArtifactSource';
|
|
22
20
|
|
|
23
21
|
const NEW_BOOT_UPRATE_FIRMWARE_VERSION = '2.4.5';
|
|
24
22
|
const SESSION_ERROR = 'session not found';
|
|
@@ -90,20 +88,17 @@ export const waitBleInstall = async (updateType: string) => {
|
|
|
90
88
|
}
|
|
91
89
|
};
|
|
92
90
|
|
|
93
|
-
const
|
|
94
|
-
if (payload instanceof ArrayBuffer) {
|
|
95
|
-
return payload;
|
|
96
|
-
}
|
|
97
|
-
return new Uint8Array(payload.buffer, payload.byteOffset, payload.byteLength).slice().buffer;
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
export const uploadFirmwareFromSource = async (
|
|
91
|
+
export const uploadFirmware = async (
|
|
101
92
|
updateType: 'firmware' | 'ble',
|
|
102
93
|
typedCall: TypedCall,
|
|
103
94
|
postMessage: (message: CoreMessage) => void,
|
|
104
95
|
device: Device,
|
|
105
|
-
|
|
106
|
-
|
|
96
|
+
{
|
|
97
|
+
payload,
|
|
98
|
+
rebootOnSuccess,
|
|
99
|
+
}: PROTO.FirmwareUpload & {
|
|
100
|
+
rebootOnSuccess?: boolean;
|
|
101
|
+
},
|
|
107
102
|
isUpdateBootloader?: boolean
|
|
108
103
|
) => {
|
|
109
104
|
const deviceType = device.getCurrentDeviceType();
|
|
@@ -124,20 +119,20 @@ export const uploadFirmwareFromSource = async (
|
|
|
124
119
|
if (supportUpgradeFileHeader) {
|
|
125
120
|
// Extract and validate firmware header (first 1KB)
|
|
126
121
|
const HEADER_SIZE = 1024;
|
|
127
|
-
if (
|
|
122
|
+
if (payload.byteLength < HEADER_SIZE) {
|
|
128
123
|
throw ERRORS.TypedError(
|
|
129
124
|
HardwareErrorCode.RuntimeError,
|
|
130
|
-
`firmware payload too small: ${
|
|
125
|
+
`firmware payload too small: ${payload.byteLength} bytes, expected at least ${HEADER_SIZE} bytes`
|
|
131
126
|
);
|
|
132
127
|
}
|
|
133
128
|
|
|
134
129
|
Log.debug('Uploading firmware header:', {
|
|
135
130
|
size: HEADER_SIZE,
|
|
136
|
-
totalSize:
|
|
131
|
+
totalSize: payload.byteLength,
|
|
137
132
|
});
|
|
138
133
|
postProgressTip(device, 'UploadingFirmwareHeader', postMessage);
|
|
139
134
|
|
|
140
|
-
const header = new Uint8Array(
|
|
135
|
+
const header = new Uint8Array(payload.slice(0, HEADER_SIZE));
|
|
141
136
|
|
|
142
137
|
try {
|
|
143
138
|
const headerRes = await typedCall('UpgradeFileHeader', 'Success', {
|
|
@@ -174,9 +169,6 @@ export const uploadFirmwareFromSource = async (
|
|
|
174
169
|
postProgressMessage(device, 0, 'installingFirmware', postMessage);
|
|
175
170
|
let updateResponse: TypedResponseMessage<'Success'>;
|
|
176
171
|
try {
|
|
177
|
-
// Classic/Mini bootloaders accept one protobuf payload and do not expose
|
|
178
|
-
// a request-range protocol. Other device families remain fully streamed.
|
|
179
|
-
const payload = await readFirmwareByteSourceFully(source);
|
|
180
172
|
updateResponse = await typedCall('FirmwareUpload', 'Success', {
|
|
181
173
|
payload,
|
|
182
174
|
});
|
|
@@ -208,7 +200,9 @@ export const uploadFirmwareFromSource = async (
|
|
|
208
200
|
updateType,
|
|
209
201
|
postMessage,
|
|
210
202
|
device,
|
|
211
|
-
|
|
203
|
+
{
|
|
204
|
+
payload,
|
|
205
|
+
},
|
|
212
206
|
rebootOnSuccess
|
|
213
207
|
);
|
|
214
208
|
return response.message;
|
|
@@ -217,7 +211,7 @@ export const uploadFirmwareFromSource = async (
|
|
|
217
211
|
|
|
218
212
|
postConfirmationMessage(device);
|
|
219
213
|
postProgressTip(device, 'ConfirmOnDevice', postMessage);
|
|
220
|
-
const length =
|
|
214
|
+
const length = payload.byteLength;
|
|
221
215
|
|
|
222
216
|
let response = await typedCall('FirmwareErase', ['FirmwareRequest', 'Success'], { length });
|
|
223
217
|
postProgressTip(device, 'FirmwareEraseSuccess', postMessage);
|
|
@@ -226,7 +220,7 @@ export const uploadFirmwareFromSource = async (
|
|
|
226
220
|
const start = response.message.offset!;
|
|
227
221
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
228
222
|
const end = response.message.offset! + response.message.length!;
|
|
229
|
-
const chunk =
|
|
223
|
+
const chunk = payload.slice(start, end);
|
|
230
224
|
|
|
231
225
|
if (start > 0) {
|
|
232
226
|
postProgressMessage(
|
|
@@ -255,45 +249,11 @@ export const uploadFirmwareFromSource = async (
|
|
|
255
249
|
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'uploadFirmware: unknown device model');
|
|
256
250
|
};
|
|
257
251
|
|
|
258
|
-
export const uploadFirmware = async (
|
|
259
|
-
updateType: 'firmware' | 'ble',
|
|
260
|
-
typedCall: TypedCall,
|
|
261
|
-
postMessage: (message: CoreMessage) => void,
|
|
262
|
-
device: Device,
|
|
263
|
-
{
|
|
264
|
-
payload,
|
|
265
|
-
rebootOnSuccess,
|
|
266
|
-
}: PROTO.FirmwareUpload & {
|
|
267
|
-
rebootOnSuccess?: boolean;
|
|
268
|
-
},
|
|
269
|
-
isUpdateBootloader?: boolean
|
|
270
|
-
) => {
|
|
271
|
-
const source = await openFirmwareByteSource({
|
|
272
|
-
binary: toArrayBuffer(payload),
|
|
273
|
-
});
|
|
274
|
-
if (!source) {
|
|
275
|
-
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'firmware payload is empty');
|
|
276
|
-
}
|
|
277
|
-
try {
|
|
278
|
-
return await uploadFirmwareFromSource(
|
|
279
|
-
updateType,
|
|
280
|
-
typedCall,
|
|
281
|
-
postMessage,
|
|
282
|
-
device,
|
|
283
|
-
source,
|
|
284
|
-
rebootOnSuccess,
|
|
285
|
-
isUpdateBootloader
|
|
286
|
-
);
|
|
287
|
-
} finally {
|
|
288
|
-
await source.close();
|
|
289
|
-
}
|
|
290
|
-
};
|
|
291
|
-
|
|
292
252
|
const newTouchUpdateProcess = async (
|
|
293
253
|
updateType: 'firmware' | 'ble',
|
|
294
254
|
postMessage: (message: CoreMessage) => void,
|
|
295
255
|
device: Device,
|
|
296
|
-
|
|
256
|
+
{ payload }: PROTO.FirmwareUpload,
|
|
297
257
|
rebootOnSuccess = true
|
|
298
258
|
) => {
|
|
299
259
|
let typedCall = device.getCommands().typedCall.bind(device.getCommands());
|
|
@@ -303,13 +263,13 @@ const newTouchUpdateProcess = async (
|
|
|
303
263
|
const env = DataManager.getSettings('env');
|
|
304
264
|
const perPackageSize = DataManager.isBleConnect(env) ? 16 : 128;
|
|
305
265
|
const chunkSize = 1024 * perPackageSize;
|
|
306
|
-
const totalChunks = Math.ceil(
|
|
266
|
+
const totalChunks = Math.ceil(payload.byteLength / chunkSize);
|
|
307
267
|
let offset = 0;
|
|
308
268
|
for (let i = 0; i < totalChunks; i++) {
|
|
309
269
|
const chunkStart = i * chunkSize;
|
|
310
|
-
const chunkEnd = Math.min(chunkStart + chunkSize,
|
|
270
|
+
const chunkEnd = Math.min(chunkStart + chunkSize, payload.byteLength);
|
|
311
271
|
const chunkLength = chunkEnd - chunkStart;
|
|
312
|
-
const chunk =
|
|
272
|
+
const chunk = payload.slice(chunkStart, chunkEnd);
|
|
313
273
|
const overwrite = i === 0;
|
|
314
274
|
const progress = Math.round(((i + 1) / totalChunks) * 100);
|
|
315
275
|
const writeRes = await emmcFileWriteWithRetry(
|
|
@@ -543,67 +503,6 @@ export const updateResource = async (
|
|
|
543
503
|
return processResourceRequest(typedCall, res, data);
|
|
544
504
|
};
|
|
545
505
|
|
|
546
|
-
export const updateResourceFromSource = async (
|
|
547
|
-
typedCall: TypedCall,
|
|
548
|
-
fileName: string,
|
|
549
|
-
source: FirmwareByteSource,
|
|
550
|
-
onConfirmAfter?: () => void
|
|
551
|
-
) => {
|
|
552
|
-
const initialLength = Math.min(INIT_DATA_CHUNK_SIZE, source.size);
|
|
553
|
-
const initialChunk = new Uint8Array(await source.readAt(0, initialLength));
|
|
554
|
-
let response = await typedCall('ResourceUpdate', ['ResourceRequest', 'Success'], {
|
|
555
|
-
file_name: fileName,
|
|
556
|
-
data_length: source.size,
|
|
557
|
-
initial_data_chunk: bytesToHex(initialChunk),
|
|
558
|
-
hash: bytesToHex(blake2s(initialChunk)),
|
|
559
|
-
});
|
|
560
|
-
onConfirmAfter?.();
|
|
561
|
-
|
|
562
|
-
while (response.type !== 'Success') {
|
|
563
|
-
const { offset, data_length: dataLength } = response.message;
|
|
564
|
-
if (
|
|
565
|
-
!Number.isSafeInteger(offset) ||
|
|
566
|
-
offset === undefined ||
|
|
567
|
-
offset < 0 ||
|
|
568
|
-
!Number.isSafeInteger(dataLength) ||
|
|
569
|
-
dataLength === undefined ||
|
|
570
|
-
dataLength <= 0 ||
|
|
571
|
-
offset + dataLength > source.size
|
|
572
|
-
) {
|
|
573
|
-
throw ERRORS.TypedError(
|
|
574
|
-
HardwareErrorCode.RuntimeError,
|
|
575
|
-
'Device requested an invalid firmware resource range'
|
|
576
|
-
);
|
|
577
|
-
}
|
|
578
|
-
const chunk = new Uint8Array(await source.readAt(offset, dataLength));
|
|
579
|
-
response = await typedCall('ResourceAck', ['ResourceRequest', 'Success'], {
|
|
580
|
-
data_chunk: bytesToHex(chunk),
|
|
581
|
-
hash: bytesToHex(blake2s(chunk)),
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
return response.message;
|
|
585
|
-
};
|
|
586
|
-
|
|
587
|
-
export const updateResourcesFromSources = async (
|
|
588
|
-
typedCall: TypedCall,
|
|
589
|
-
postMessage: (message: CoreMessage) => void,
|
|
590
|
-
device: Device,
|
|
591
|
-
entries: ReadonlyArray<{ entryName: string; source: FirmwareByteSource }>
|
|
592
|
-
) => {
|
|
593
|
-
postProgressTip(device, 'UpdateSysResource', postMessage);
|
|
594
|
-
for (const [index, entry] of entries.entries()) {
|
|
595
|
-
await updateResourceFromSource(typedCall, entry.entryName, entry.source);
|
|
596
|
-
postProgressMessage(
|
|
597
|
-
device,
|
|
598
|
-
Math.floor(((index + 1) / entries.length) * 100),
|
|
599
|
-
'installingFirmware',
|
|
600
|
-
postMessage
|
|
601
|
-
);
|
|
602
|
-
}
|
|
603
|
-
postProgressTip(device, 'UpdateSysResourceSuccess', postMessage);
|
|
604
|
-
return true;
|
|
605
|
-
};
|
|
606
|
-
|
|
607
506
|
export const updateResources = async (
|
|
608
507
|
typedCall: TypedCall,
|
|
609
508
|
postMessage: (message: CoreMessage) => void,
|
|
@@ -638,28 +537,11 @@ export const updateBootloader = async (
|
|
|
638
537
|
typedCall: TypedCall,
|
|
639
538
|
postMessage: (message: CoreMessage) => void,
|
|
640
539
|
device: Device,
|
|
641
|
-
|
|
642
|
-
) => {
|
|
643
|
-
const source = await openFirmwareByteSource({ binary: data });
|
|
644
|
-
if (!source) {
|
|
645
|
-
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'bootloader payload is empty');
|
|
646
|
-
}
|
|
647
|
-
try {
|
|
648
|
-
return await updateBootloaderFromSource(typedCall, postMessage, device, source);
|
|
649
|
-
} finally {
|
|
650
|
-
await source.close();
|
|
651
|
-
}
|
|
652
|
-
};
|
|
653
|
-
|
|
654
|
-
export const updateBootloaderFromSource = async (
|
|
655
|
-
typedCall: TypedCall,
|
|
656
|
-
postMessage: (message: CoreMessage) => void,
|
|
657
|
-
device: Device,
|
|
658
|
-
source: FirmwareByteSource
|
|
540
|
+
source: ArrayBuffer
|
|
659
541
|
) => {
|
|
660
542
|
postProgressTip(device, 'UpdateBootloader', postMessage);
|
|
661
543
|
postProgressMessage(device, Math.floor(0), 'installingFirmware', postMessage);
|
|
662
|
-
await
|
|
544
|
+
await updateResource(typedCall, 'bootloader.bin', source, () => {
|
|
663
545
|
postProcessingMessage('resource', postMessage);
|
|
664
546
|
});
|
|
665
547
|
postProgressMessage(device, Math.floor(100), 'installingFirmware', postMessage);
|