@onekeyfe/hd-core 1.2.0-alpha.30 → 1.2.0-alpha.32
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 +251 -0
- package/__tests__/connectSettings.test.ts +5 -47
- package/__tests__/device-state-mapper.test.ts +10 -1
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +31 -59
- package/__tests__/networkUtils.test.ts +20 -0
- package/__tests__/open-wallet-session.test.ts +19 -5
- package/__tests__/protocol-v2-firmware-targets.test.ts +18 -0
- package/__tests__/protocol-v2.test.ts +58 -240
- package/__tests__/public-device-state-api.test.ts +10 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts +24 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +0 -11
- 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 -22
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/PromptWebDeviceAccess.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 -7
- 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/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/DeviceStateMapper.d.ts.map +1 -1
- package/dist/index.d.ts +43 -179
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1048 -2606
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/topLevelInject.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +25 -7
- 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 +2 -4
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +0 -69
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +3 -10
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/openWalletSession.d.ts +9 -3
- package/dist/types/api/openWalletSession.d.ts.map +1 -1
- package/dist/types/device.d.ts +6 -0
- package/dist/types/device.d.ts.map +1 -1
- package/dist/types/settings.d.ts +1 -13
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/networkUtils.d.ts +1 -0
- package/dist/utils/networkUtils.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/CheckAllFirmwareRelease.ts +368 -50
- package/src/api/FirmwareUpdateV2.ts +120 -298
- package/src/api/FirmwareUpdateV3.ts +56 -258
- package/src/api/FirmwareUpdateV4.ts +328 -765
- package/src/api/OpenWalletSession.ts +12 -8
- package/src/api/PromptWebDeviceAccess.ts +2 -6
- package/src/api/device/DeviceUpdateBootloader.ts +6 -122
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +0 -50
- package/src/api/firmware/updateBootloader.ts +4 -19
- package/src/api/firmware/uploadFirmware.ts +22 -140
- package/src/data/messages/messages-protocol-v2.json +4 -0
- package/src/data-manager/DataManager.ts +33 -33
- package/src/data-manager/connectSettings.ts +0 -11
- package/src/device/DeviceStateMapper.ts +6 -0
- package/src/index.ts +0 -5
- package/src/inject.ts +2 -22
- package/src/lowLevelInject.ts +1 -5
- package/src/protocols/protocol-v2/walletSession.ts +2 -1
- package/src/topLevelInject.ts +1 -5
- package/src/types/api/checkAllFirmwareRelease.ts +46 -7
- package/src/types/api/deviceUpdateBootloader.ts +0 -6
- package/src/types/api/export.ts +5 -18
- package/src/types/api/firmwareUpdate.ts +0 -76
- package/src/types/api/index.ts +6 -15
- package/src/types/api/openWalletSession.ts +12 -3
- package/src/types/device.ts +6 -0
- package/src/types/settings.ts +3 -13
- package/src/utils/networkUtils.ts +5 -3
- package/__tests__/firmware-update/check-all-firmware-release.test.ts +0 -174
- 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-capabilities.test.ts +0 -13
- package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -593
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -213
- 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 -30
- 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 -745
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -392
- 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,6 +5,7 @@ import { getProtocolV2WalletSession } from '../protocols/protocol-v2/walletSessi
|
|
|
5
5
|
import { getPassphraseStateWithRefreshDeviceInfo } from '../utils/deviceFeaturesUtils';
|
|
6
6
|
import { BaseMethod } from './BaseMethod';
|
|
7
7
|
import { invalidParameter } from './helpers/paramsValidator';
|
|
8
|
+
import { OpenWalletSessionMode } from '../types/api/openWalletSession';
|
|
8
9
|
|
|
9
10
|
import type {
|
|
10
11
|
OpenWalletSessionParams,
|
|
@@ -44,9 +45,9 @@ const normalizeParams = (payload: Record<string, unknown>): OpenWalletSessionPar
|
|
|
44
45
|
throw invalidParameter('Parameter [mode] is required.');
|
|
45
46
|
}
|
|
46
47
|
if (
|
|
47
|
-
payload.mode !==
|
|
48
|
-
payload.mode !==
|
|
49
|
-
payload.mode !==
|
|
48
|
+
payload.mode !== OpenWalletSessionMode.Standard &&
|
|
49
|
+
payload.mode !== OpenWalletSessionMode.SelectHidden &&
|
|
50
|
+
payload.mode !== OpenWalletSessionMode.ResumeHidden
|
|
50
51
|
) {
|
|
51
52
|
throw invalidParameter(
|
|
52
53
|
'Parameter [mode] must be one of standard, select-hidden, or resume-hidden.'
|
|
@@ -57,7 +58,10 @@ const normalizeParams = (payload: Record<string, unknown>): OpenWalletSessionPar
|
|
|
57
58
|
'Legacy parameters [useEmptyPassphrase] and [initSession] are not supported by openWalletSession.'
|
|
58
59
|
);
|
|
59
60
|
}
|
|
60
|
-
if (
|
|
61
|
+
if (
|
|
62
|
+
payload.mode === OpenWalletSessionMode.Standard ||
|
|
63
|
+
payload.mode === OpenWalletSessionMode.SelectHidden
|
|
64
|
+
) {
|
|
61
65
|
if (payload.deviceId !== undefined || payload.passphraseState !== undefined) {
|
|
62
66
|
throw invalidParameter(
|
|
63
67
|
'Parameters [deviceId] and [passphraseState] are only allowed with mode [resume-hidden].'
|
|
@@ -66,7 +70,7 @@ const normalizeParams = (payload: Record<string, unknown>): OpenWalletSessionPar
|
|
|
66
70
|
return { mode: payload.mode };
|
|
67
71
|
}
|
|
68
72
|
return {
|
|
69
|
-
mode:
|
|
73
|
+
mode: OpenWalletSessionMode.ResumeHidden,
|
|
70
74
|
deviceId: requiredString(payload.deviceId, 'deviceId'),
|
|
71
75
|
passphraseState: requiredString(payload.passphraseState, 'passphraseState'),
|
|
72
76
|
};
|
|
@@ -81,7 +85,7 @@ export default class OpenWalletSession extends BaseMethod<OpenWalletSessionParam
|
|
|
81
85
|
this.useDevicePassphraseState = false;
|
|
82
86
|
this.skipForceUpdateCheck = true;
|
|
83
87
|
this.params = normalizeParams(this.payload as unknown as Record<string, unknown>);
|
|
84
|
-
this.payload.useEmptyPassphrase = this.params.mode ===
|
|
88
|
+
this.payload.useEmptyPassphrase = this.params.mode === OpenWalletSessionMode.Standard;
|
|
85
89
|
}
|
|
86
90
|
|
|
87
91
|
async run(): Promise<OpenWalletSessionPayload> {
|
|
@@ -102,7 +106,7 @@ export default class OpenWalletSession extends BaseMethod<OpenWalletSessionParam
|
|
|
102
106
|
|
|
103
107
|
const protocol = isProtocolV2 ? 'V2' : 'V1';
|
|
104
108
|
|
|
105
|
-
if (this.params.mode ===
|
|
109
|
+
if (this.params.mode === OpenWalletSessionMode.Standard) {
|
|
106
110
|
this.device.passphraseState = undefined;
|
|
107
111
|
const session = isProtocolV2
|
|
108
112
|
? await getProtocolV2WalletSession(this.device, { onlyMainPin: true })
|
|
@@ -129,7 +133,7 @@ export default class OpenWalletSession extends BaseMethod<OpenWalletSessionParam
|
|
|
129
133
|
};
|
|
130
134
|
}
|
|
131
135
|
|
|
132
|
-
if (this.params.mode ===
|
|
136
|
+
if (this.params.mode === OpenWalletSessionMode.ResumeHidden) {
|
|
133
137
|
if (isProtocolV2) {
|
|
134
138
|
if (this.device.features?.unlocked === false) {
|
|
135
139
|
await this.device.unlockDevice();
|
|
@@ -52,13 +52,9 @@ export default class PromptWebDeviceAccess extends BaseMethod {
|
|
|
52
52
|
|
|
53
53
|
if (isWebUsbEnv) {
|
|
54
54
|
const usbDevice = device as USBDevice;
|
|
55
|
-
|
|
55
|
+
const path = usbDevice.serialNumber;
|
|
56
56
|
if (!path) {
|
|
57
|
-
|
|
58
|
-
// session-stable mock path, which is recovered by USBDevice identity here.
|
|
59
|
-
const diff = await this.connector?.enumerate();
|
|
60
|
-
const matched = diff?.descriptors?.find(d => (d as any).device === usbDevice);
|
|
61
|
-
path = matched?.path ?? '';
|
|
57
|
+
throw ERRORS.TypedError(HardwareErrorCode.WebDevicePromptAccessError);
|
|
62
58
|
}
|
|
63
59
|
devicesDescriptor = [
|
|
64
60
|
{
|
|
@@ -5,23 +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 { getDeviceUUID } from '../../utils';
|
|
11
|
+
import { checkBootloaderLength } from '../firmware/updateBootloader';
|
|
19
12
|
|
|
20
13
|
import type { DeviceUpdateBootloaderParams } from '../../types/api/deviceUpdateBootloader';
|
|
21
14
|
import type { EFirmwareType } from '@onekeyfe/hd-shared';
|
|
22
15
|
import type { Device } from '../../device/Device';
|
|
23
16
|
import type { Features } from '../../types';
|
|
24
|
-
import type { FirmwareByteSource } from '../firmware/FirmwareArtifactSource';
|
|
25
17
|
|
|
26
18
|
export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any> {
|
|
27
19
|
init() {
|
|
@@ -51,68 +43,17 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
|
|
|
51
43
|
return true;
|
|
52
44
|
}
|
|
53
45
|
|
|
54
|
-
async updateBootloaderWithEmmcFileWriteFromSource(_device: Device, source: FirmwareByteSource) {
|
|
55
|
-
const filePath = '0:boot/bootloader.bin';
|
|
56
|
-
|
|
57
|
-
this.postTipMessage(FirmwareUpdateTipMessage.StartTransferData);
|
|
58
|
-
await this.emmcCommonUpdateProcessFromSource({
|
|
59
|
-
source,
|
|
60
|
-
filePath,
|
|
61
|
-
});
|
|
62
|
-
this.postTipMessage(FirmwareUpdateTipMessage.ConfirmOnDevice);
|
|
63
|
-
await this.reboot(RebootType.Normal);
|
|
64
|
-
this.postTipMessage(FirmwareUpdateTipMessage.UpdateBootloaderSuccess);
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
46
|
async updateTouchBootloader({
|
|
69
47
|
device,
|
|
70
48
|
features,
|
|
71
49
|
firmwareType,
|
|
72
|
-
binary: preparedBinary,
|
|
73
|
-
source: preparedSource,
|
|
74
50
|
}: {
|
|
75
51
|
device: Device;
|
|
76
52
|
features?: Features;
|
|
77
53
|
firmwareType: EFirmwareType;
|
|
78
|
-
binary?: ArrayBuffer;
|
|
79
|
-
source?: FirmwareByteSource;
|
|
80
54
|
}) {
|
|
81
|
-
|
|
82
|
-
if (!(await checkBootloaderSourceLength(preparedSource))) {
|
|
83
|
-
throw ERRORS.TypedError(HardwareErrorCode.CheckDownloadFileError);
|
|
84
|
-
}
|
|
85
|
-
if (features && device.isBootloader()) {
|
|
86
|
-
this.postTipMessage(FirmwareUpdateTipMessage.UpdateBootloader);
|
|
87
|
-
const result = await this.updateBootloaderWithEmmcFileWriteFromSource(
|
|
88
|
-
device,
|
|
89
|
-
preparedSource
|
|
90
|
-
);
|
|
91
|
-
return result;
|
|
92
|
-
}
|
|
93
|
-
if (features && !device.isBootloader()) {
|
|
94
|
-
await updateBootloaderFromSource(
|
|
95
|
-
this.device.getCommands().typedCall.bind(this.device.getCommands()),
|
|
96
|
-
this.postMessage,
|
|
97
|
-
device,
|
|
98
|
-
preparedSource
|
|
99
|
-
);
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
let binary = preparedBinary;
|
|
55
|
+
let { binary } = this.payload;
|
|
105
56
|
if (!binary) {
|
|
106
|
-
if (DataManager.getSettings('firmwareManifestMode') === 'external-only') {
|
|
107
|
-
throw ERRORS.TypedError(
|
|
108
|
-
HardwareErrorCode.RuntimeError,
|
|
109
|
-
'Bootloader must be prepared by the external firmware host',
|
|
110
|
-
{
|
|
111
|
-
firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
|
|
112
|
-
artifactName: 'bootloader',
|
|
113
|
-
}
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
57
|
this.postTipMessage(FirmwareUpdateTipMessage.CheckLatestUiResource);
|
|
117
58
|
const resourceUrl = features
|
|
118
59
|
? DataManager.getBootloaderResource(features, firmwareType)
|
|
@@ -127,7 +68,7 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
|
|
|
127
68
|
}
|
|
128
69
|
}
|
|
129
70
|
|
|
130
|
-
if (!
|
|
71
|
+
if (!checkBootloaderLength(binary)) {
|
|
131
72
|
throw ERRORS.TypedError(HardwareErrorCode.CheckDownloadFileError);
|
|
132
73
|
}
|
|
133
74
|
|
|
@@ -135,8 +76,7 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
|
|
|
135
76
|
if (features && device.isBootloader()) {
|
|
136
77
|
// Use emmcFileWrite + reboot logic for bootloader mode
|
|
137
78
|
this.postTipMessage(FirmwareUpdateTipMessage.UpdateBootloader);
|
|
138
|
-
|
|
139
|
-
return result;
|
|
79
|
+
return this.updateBootloaderWithEmmcFileWrite(device, binary);
|
|
140
80
|
}
|
|
141
81
|
|
|
142
82
|
if (features && !device.isBootloader()) {
|
|
@@ -156,69 +96,13 @@ export default class DeviceUpdateBootloader extends FirmwareUpdateBaseMethod<any
|
|
|
156
96
|
const { features } = device;
|
|
157
97
|
|
|
158
98
|
const payload = this.payload as DeviceUpdateBootloaderParams;
|
|
159
|
-
const hostBinding = payload.artifact
|
|
160
|
-
? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration)
|
|
161
|
-
: undefined;
|
|
162
|
-
const executionParams = {
|
|
163
|
-
...payload,
|
|
164
|
-
artifactReader: hostBinding?.artifactReader ?? payload.artifactReader,
|
|
165
|
-
};
|
|
166
|
-
if (payload.artifact) {
|
|
167
|
-
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
168
|
-
preparedPlan: payload.preparedPlan,
|
|
169
|
-
deviceIdentity: getDeviceUUID(features) || undefined,
|
|
170
|
-
});
|
|
171
|
-
assertFirmwareUpdatePreparedPlanBinding({
|
|
172
|
-
preparedPlan: payload.preparedPlan,
|
|
173
|
-
executor: 'v2',
|
|
174
|
-
scopeTargets: ['bootloader'],
|
|
175
|
-
bindings: [
|
|
176
|
-
{
|
|
177
|
-
target: 'bootloader',
|
|
178
|
-
artifact: payload.artifact,
|
|
179
|
-
},
|
|
180
|
-
],
|
|
181
|
-
});
|
|
182
|
-
const source = await openFirmwareByteSource({
|
|
183
|
-
artifact: payload.artifact,
|
|
184
|
-
reader: executionParams.artifactReader,
|
|
185
|
-
});
|
|
186
|
-
if (!source) {
|
|
187
|
-
throw ERRORS.TypedError(
|
|
188
|
-
HardwareErrorCode.RuntimeError,
|
|
189
|
-
'Bootloader artifact is not prepared'
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
try {
|
|
193
|
-
const deviceType = device.getCurrentDeviceType();
|
|
194
|
-
const deviceFirmwareType = device.getCurrentFirmwareType();
|
|
195
|
-
const firmwareType = payload.firmwareType ?? deviceFirmwareType;
|
|
196
|
-
if (DeviceModelToTypes.model_touch.includes(deviceType)) {
|
|
197
|
-
return await this.updateTouchBootloader({
|
|
198
|
-
device,
|
|
199
|
-
features,
|
|
200
|
-
firmwareType,
|
|
201
|
-
source,
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
return true;
|
|
205
|
-
} finally {
|
|
206
|
-
await source.close();
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
99
|
|
|
210
|
-
const { binary } = payload;
|
|
211
100
|
const deviceType = device.getCurrentDeviceType();
|
|
212
101
|
const deviceFirmwareType = device.getCurrentFirmwareType();
|
|
213
102
|
const firmwareType = payload.firmwareType ?? deviceFirmwareType;
|
|
214
103
|
|
|
215
104
|
if (DeviceModelToTypes.model_touch.includes(deviceType)) {
|
|
216
|
-
return this.updateTouchBootloader({
|
|
217
|
-
device,
|
|
218
|
-
features,
|
|
219
|
-
firmwareType,
|
|
220
|
-
binary,
|
|
221
|
-
});
|
|
105
|
+
return this.updateTouchBootloader({ device, features, firmwareType });
|
|
222
106
|
}
|
|
223
107
|
|
|
224
108
|
return Promise.resolve(true);
|
|
@@ -14,7 +14,6 @@ import { DataManager } from '../../data-manager';
|
|
|
14
14
|
import { BaseMethod } from '../BaseMethod';
|
|
15
15
|
import { DEVICE } from '../../events';
|
|
16
16
|
import { createFirmwareProgressThrottle } from './progressThrottle';
|
|
17
|
-
import { writeFirmwareByteSource } from './FirmwareArtifactSource';
|
|
18
17
|
|
|
19
18
|
import type {
|
|
20
19
|
IFirmwareUpdateProgressType,
|
|
@@ -25,7 +24,6 @@ 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';
|
|
@@ -389,54 +387,6 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
|
|
|
389
387
|
return totalSize !== undefined ? (processedSize ?? 0) + payload.byteLength : 0;
|
|
390
388
|
}
|
|
391
389
|
|
|
392
|
-
async emmcCommonUpdateProcessFromSource({
|
|
393
|
-
source,
|
|
394
|
-
filePath,
|
|
395
|
-
processedSize,
|
|
396
|
-
totalSize,
|
|
397
|
-
}: {
|
|
398
|
-
source: FirmwareByteSource;
|
|
399
|
-
filePath: string;
|
|
400
|
-
processedSize?: number;
|
|
401
|
-
totalSize?: number;
|
|
402
|
-
}) {
|
|
403
|
-
if (!filePath.startsWith('0:')) {
|
|
404
|
-
throw new Error('filePath must start with 0:');
|
|
405
|
-
}
|
|
406
|
-
const env = DataManager.getSettings('env');
|
|
407
|
-
const chunkSize = 1024 * (DataManager.isBleConnect(env) ? 16 : 128);
|
|
408
|
-
|
|
409
|
-
await writeFirmwareByteSource({
|
|
410
|
-
source,
|
|
411
|
-
chunkSize,
|
|
412
|
-
write: async ({ data, sourceOffset, length, first }) => {
|
|
413
|
-
const progress =
|
|
414
|
-
totalSize !== undefined && processedSize !== undefined
|
|
415
|
-
? Math.min(Math.ceil(((processedSize + sourceOffset + length) / totalSize) * 100), 99)
|
|
416
|
-
: Math.min(Math.ceil(((sourceOffset + length) / source.size) * 100), 99);
|
|
417
|
-
const writeRes = await this.emmcFileWriteWithRetry(
|
|
418
|
-
filePath,
|
|
419
|
-
length,
|
|
420
|
-
sourceOffset,
|
|
421
|
-
data,
|
|
422
|
-
first,
|
|
423
|
-
progress
|
|
424
|
-
);
|
|
425
|
-
if (!writeRes) {
|
|
426
|
-
throw ERRORS.TypedError(
|
|
427
|
-
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
428
|
-
'transfer data error'
|
|
429
|
-
);
|
|
430
|
-
}
|
|
431
|
-
const processedBytes = Number(writeRes.message.processed_byte);
|
|
432
|
-
this.postProgressMessage(progress, 'transferData');
|
|
433
|
-
return Number.isFinite(processedBytes) ? processedBytes : length;
|
|
434
|
-
},
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
return totalSize !== undefined ? (processedSize ?? 0) + source.size : 0;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
390
|
async emmcFileWriteWithRetry(
|
|
441
391
|
filePath: string,
|
|
442
392
|
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(
|
|
@@ -530,67 +490,6 @@ export const updateResource = async (
|
|
|
530
490
|
return processResourceRequest(typedCall, res, data);
|
|
531
491
|
};
|
|
532
492
|
|
|
533
|
-
export const updateResourceFromSource = async (
|
|
534
|
-
typedCall: TypedCall,
|
|
535
|
-
fileName: string,
|
|
536
|
-
source: FirmwareByteSource,
|
|
537
|
-
onConfirmAfter?: () => void
|
|
538
|
-
) => {
|
|
539
|
-
const initialLength = Math.min(INIT_DATA_CHUNK_SIZE, source.size);
|
|
540
|
-
const initialChunk = new Uint8Array(await source.readAt(0, initialLength));
|
|
541
|
-
let response = await typedCall('ResourceUpdate', ['ResourceRequest', 'Success'], {
|
|
542
|
-
file_name: fileName,
|
|
543
|
-
data_length: source.size,
|
|
544
|
-
initial_data_chunk: bytesToHex(initialChunk),
|
|
545
|
-
hash: bytesToHex(blake2s(initialChunk)),
|
|
546
|
-
});
|
|
547
|
-
onConfirmAfter?.();
|
|
548
|
-
|
|
549
|
-
while (response.type !== 'Success') {
|
|
550
|
-
const { offset, data_length: dataLength } = response.message;
|
|
551
|
-
if (
|
|
552
|
-
!Number.isSafeInteger(offset) ||
|
|
553
|
-
offset === undefined ||
|
|
554
|
-
offset < 0 ||
|
|
555
|
-
!Number.isSafeInteger(dataLength) ||
|
|
556
|
-
dataLength === undefined ||
|
|
557
|
-
dataLength <= 0 ||
|
|
558
|
-
offset + dataLength > source.size
|
|
559
|
-
) {
|
|
560
|
-
throw ERRORS.TypedError(
|
|
561
|
-
HardwareErrorCode.RuntimeError,
|
|
562
|
-
'Device requested an invalid firmware resource range'
|
|
563
|
-
);
|
|
564
|
-
}
|
|
565
|
-
const chunk = new Uint8Array(await source.readAt(offset, dataLength));
|
|
566
|
-
response = await typedCall('ResourceAck', ['ResourceRequest', 'Success'], {
|
|
567
|
-
data_chunk: bytesToHex(chunk),
|
|
568
|
-
hash: bytesToHex(blake2s(chunk)),
|
|
569
|
-
});
|
|
570
|
-
}
|
|
571
|
-
return response.message;
|
|
572
|
-
};
|
|
573
|
-
|
|
574
|
-
export const updateResourcesFromSources = async (
|
|
575
|
-
typedCall: TypedCall,
|
|
576
|
-
postMessage: (message: CoreMessage) => void,
|
|
577
|
-
device: Device,
|
|
578
|
-
entries: ReadonlyArray<{ entryName: string; source: FirmwareByteSource }>
|
|
579
|
-
) => {
|
|
580
|
-
postProgressTip(device, 'UpdateSysResource', postMessage);
|
|
581
|
-
for (const [index, entry] of entries.entries()) {
|
|
582
|
-
await updateResourceFromSource(typedCall, entry.entryName, entry.source);
|
|
583
|
-
postProgressMessage(
|
|
584
|
-
device,
|
|
585
|
-
Math.floor(((index + 1) / entries.length) * 100),
|
|
586
|
-
'installingFirmware',
|
|
587
|
-
postMessage
|
|
588
|
-
);
|
|
589
|
-
}
|
|
590
|
-
postProgressTip(device, 'UpdateSysResourceSuccess', postMessage);
|
|
591
|
-
return true;
|
|
592
|
-
};
|
|
593
|
-
|
|
594
493
|
export const updateResources = async (
|
|
595
494
|
typedCall: TypedCall,
|
|
596
495
|
postMessage: (message: CoreMessage) => void,
|
|
@@ -625,28 +524,11 @@ export const updateBootloader = async (
|
|
|
625
524
|
typedCall: TypedCall,
|
|
626
525
|
postMessage: (message: CoreMessage) => void,
|
|
627
526
|
device: Device,
|
|
628
|
-
|
|
629
|
-
) => {
|
|
630
|
-
const source = await openFirmwareByteSource({ binary: data });
|
|
631
|
-
if (!source) {
|
|
632
|
-
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'bootloader payload is empty');
|
|
633
|
-
}
|
|
634
|
-
try {
|
|
635
|
-
return await updateBootloaderFromSource(typedCall, postMessage, device, source);
|
|
636
|
-
} finally {
|
|
637
|
-
await source.close();
|
|
638
|
-
}
|
|
639
|
-
};
|
|
640
|
-
|
|
641
|
-
export const updateBootloaderFromSource = async (
|
|
642
|
-
typedCall: TypedCall,
|
|
643
|
-
postMessage: (message: CoreMessage) => void,
|
|
644
|
-
device: Device,
|
|
645
|
-
source: FirmwareByteSource
|
|
527
|
+
source: ArrayBuffer
|
|
646
528
|
) => {
|
|
647
529
|
postProgressTip(device, 'UpdateBootloader', postMessage);
|
|
648
530
|
postProgressMessage(device, Math.floor(0), 'installingFirmware', postMessage);
|
|
649
|
-
await
|
|
531
|
+
await updateResource(typedCall, 'bootloader.bin', source, () => {
|
|
650
532
|
postProcessingMessage('resource', postMessage);
|
|
651
533
|
});
|
|
652
534
|
postProgressMessage(device, Math.floor(100), 'installingFirmware', postMessage);
|
|
@@ -12513,6 +12513,10 @@
|
|
|
12513
12513
|
"passphrase": {
|
|
12514
12514
|
"type": "string",
|
|
12515
12515
|
"id": 1
|
|
12516
|
+
},
|
|
12517
|
+
"on_device": {
|
|
12518
|
+
"type": "bool",
|
|
12519
|
+
"id": 2
|
|
12516
12520
|
}
|
|
12517
12521
|
}
|
|
12518
12522
|
},
|