@onekeyfe/hd-core 1.2.0-alpha.78 → 1.2.0-alpha.79
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 +12 -71
- package/__tests__/protocol-v2-resources.test.ts +102 -222
- package/__tests__/protocol-v2.test.ts +110 -380
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +0 -6
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/UploadPortfolio.d.ts.map +1 -1
- package/dist/data-manager/DataManager.d.ts +1 -2
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/index.d.ts +74 -32
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +255 -499
- package/dist/inject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/resources.d.ts +31 -28
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -0
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +1 -0
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +2 -0
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2ResourceManifest.d.ts +17 -0
- package/dist/types/api/protocolV2ResourceManifest.d.ts.map +1 -0
- package/dist/types/settings.d.ts +30 -21
- package/dist/types/settings.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/CheckAllFirmwareRelease.ts +5 -34
- package/src/api/FirmwareUpdateV4.ts +48 -220
- package/src/api/UploadPortfolio.ts +18 -0
- package/src/data-manager/DataManager.ts +2 -6
- package/src/index.ts +6 -0
- package/src/inject.ts +2 -0
- package/src/protocols/protocol-v2/resources.ts +193 -324
- package/src/types/api/checkAllFirmwareRelease.ts +1 -0
- package/src/types/api/export.ts +4 -0
- package/src/types/api/index.ts +2 -0
- package/src/types/api/protocolV2ResourceManifest.ts +19 -0
- package/src/types/settings.ts +30 -36
|
@@ -30,12 +30,7 @@ import {
|
|
|
30
30
|
ProtocolV2FirmwareTargetType,
|
|
31
31
|
} from '../protocols/protocol-v2';
|
|
32
32
|
import { requestProtocolV2DeviceInfo } from '../protocols/protocol-v2/features';
|
|
33
|
-
import {
|
|
34
|
-
PROTOCOL_V2_RESOURCE_DEVICE_PATHS,
|
|
35
|
-
buildProtocolV2ResourceUpdatePlan,
|
|
36
|
-
isProtocolV2ResourceFileValid,
|
|
37
|
-
readProtocolV2ResourceInventory,
|
|
38
|
-
} from '../protocols/protocol-v2/resources';
|
|
33
|
+
import { isProtocolV2ResourceFileValid } from '../protocols/protocol-v2/resources';
|
|
39
34
|
import {
|
|
40
35
|
getProtocolV2UnknownErrorText,
|
|
41
36
|
isProtocolV2DeviceDisconnectedError,
|
|
@@ -59,8 +54,6 @@ import type {
|
|
|
59
54
|
Features,
|
|
60
55
|
IFirmwareReleaseInfo,
|
|
61
56
|
IProtocolV2FirmwareComponent,
|
|
62
|
-
IProtocolV2Resource,
|
|
63
|
-
IProtocolV2ResourceFile,
|
|
64
57
|
IVersionArray,
|
|
65
58
|
} from '../types';
|
|
66
59
|
import type { FirmwareByteSource } from './firmware/FirmwareArtifactSource';
|
|
@@ -252,6 +245,16 @@ const PROTOCOL_V2_FIRMWARE_STAGING_PATHS = new Set(
|
|
|
252
245
|
)
|
|
253
246
|
);
|
|
254
247
|
|
|
248
|
+
const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH = 'vol0:/loaders/bootloader/boot_resource.okpkg';
|
|
249
|
+
const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH = `${PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH}.staging`;
|
|
250
|
+
|
|
251
|
+
const resolveProtocolV2ResourceWritePath = (devicePath: string) => {
|
|
252
|
+
const normalizedPath = devicePath.replace(/^vol0:(?!\/)/i, 'vol0:/').toLowerCase();
|
|
253
|
+
return normalizedPath === PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH
|
|
254
|
+
? PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH
|
|
255
|
+
: devicePath;
|
|
256
|
+
};
|
|
257
|
+
|
|
255
258
|
const PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID = new Map<number, FirmwareUpdateV4Target>([
|
|
256
259
|
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_BOOTLOADER, 'boot'],
|
|
257
260
|
[ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P1, 'app_v1'],
|
|
@@ -667,9 +670,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
667
670
|
const hasExplicitResourceFiles = !!this.params.resourceFiles?.length;
|
|
668
671
|
const wantsStableResources = !!this.params.targetsToUpdate?.includes('resource');
|
|
669
672
|
const wantsBootResources = !!this.params.targetsToUpdate?.includes('boot_resources');
|
|
670
|
-
const
|
|
671
|
-
|
|
672
|
-
!hasExplicitResourceFiles && (wantsBootResources || wantsStableResources);
|
|
673
|
+
const needsPreparedResources =
|
|
674
|
+
!hasExplicitResourceFiles && (wantsStableResources || wantsBootResources);
|
|
673
675
|
|
|
674
676
|
let fwBinaryMap: ProtocolV2TargetBinary[] = [];
|
|
675
677
|
let bootloaderBinary: ArrayBuffer | null = null;
|
|
@@ -681,8 +683,17 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
681
683
|
fwBinaryMap = this.collectExplicitTargetBinaries();
|
|
682
684
|
bootloaderBinary = this.prepareBootloaderBinary();
|
|
683
685
|
const needsRemoteFirmware = !this.hasExplicitProtocolV2Payload(fwBinaryMap);
|
|
686
|
+
if (needsPreparedResources) {
|
|
687
|
+
throw ERRORS.TypedError(
|
|
688
|
+
HardwareErrorCode.RuntimeError,
|
|
689
|
+
'Protocol V2 resource manifest must be prepared by the external firmware host',
|
|
690
|
+
{
|
|
691
|
+
firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
|
|
692
|
+
}
|
|
693
|
+
);
|
|
694
|
+
}
|
|
684
695
|
if (
|
|
685
|
-
|
|
696
|
+
needsRemoteFirmware &&
|
|
686
697
|
(this.params.artifactReader ||
|
|
687
698
|
DataManager.getSettings('firmwareManifestMode') === 'external-only')
|
|
688
699
|
) {
|
|
@@ -694,11 +705,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
694
705
|
}
|
|
695
706
|
);
|
|
696
707
|
}
|
|
697
|
-
if (needsRemoteFirmware
|
|
708
|
+
if (needsRemoteFirmware) {
|
|
698
709
|
// Remote updates must use a freshly fetched config before any reboot or file write.
|
|
699
|
-
await DataManager.forceReloadData(
|
|
700
|
-
requireResources: needsRemoteResources || needsRemoteBootResources,
|
|
701
|
-
});
|
|
710
|
+
await DataManager.forceReloadData();
|
|
702
711
|
}
|
|
703
712
|
if (needsRemoteFirmware) {
|
|
704
713
|
const remoteBinaries = await this.prepareRemoteProtocolV2Binaries(
|
|
@@ -709,14 +718,16 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
709
718
|
fwBinaryMap = remoteBinaries.fwBinaryMap;
|
|
710
719
|
installItems = remoteBinaries.installItems;
|
|
711
720
|
}
|
|
712
|
-
|
|
713
|
-
if (bootResourceFiles?.length) {
|
|
714
|
-
resourceBundles = this.mergeProtocolV2ResourceBundles(resourceBundles, bootResourceFiles);
|
|
715
|
-
}
|
|
716
|
-
if (!needsRemoteResources) {
|
|
717
|
-
this.postTipMessage(FirmwareUpdateTipMessage.FinishDownloadFirmware);
|
|
718
|
-
}
|
|
721
|
+
this.postTipMessage(FirmwareUpdateTipMessage.FinishDownloadFirmware);
|
|
719
722
|
} catch (err) {
|
|
723
|
+
if (
|
|
724
|
+
typeof err === 'object' &&
|
|
725
|
+
err !== null &&
|
|
726
|
+
'params' in err &&
|
|
727
|
+
(err as HardwareError).params?.firmwareUpdateCode === 'FirmwareArtifactsNotPrepared'
|
|
728
|
+
) {
|
|
729
|
+
throw err;
|
|
730
|
+
}
|
|
720
731
|
if (err instanceof HardwareError && err.errorCode === HardwareErrorCode.NetworkError) {
|
|
721
732
|
throw err;
|
|
722
733
|
}
|
|
@@ -727,8 +738,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
727
738
|
!bootloaderBinary &&
|
|
728
739
|
fwBinaryMap.length === 0 &&
|
|
729
740
|
!installItems?.length &&
|
|
730
|
-
!resourceBundles?.length
|
|
731
|
-
!needsRemoteResources
|
|
741
|
+
!resourceBundles?.length
|
|
732
742
|
) {
|
|
733
743
|
throw ERRORS.TypedError(
|
|
734
744
|
HardwareErrorCode.FirmwareUpdateDownloadFailed,
|
|
@@ -736,27 +746,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
736
746
|
);
|
|
737
747
|
}
|
|
738
748
|
|
|
739
|
-
if (needsRemoteResources) {
|
|
740
|
-
const enteredBootloader = await this.enterProtocolV2BootloaderMode();
|
|
741
|
-
try {
|
|
742
|
-
const stableResources = await this.prepareProtocolV2ResourceBundles();
|
|
743
|
-
resourceBundles = this.mergeProtocolV2ResourceBundles(resourceBundles, stableResources);
|
|
744
|
-
this.postTipMessage(FirmwareUpdateTipMessage.FinishDownloadFirmware);
|
|
745
|
-
} catch (err) {
|
|
746
|
-
if (enteredBootloader) {
|
|
747
|
-
try {
|
|
748
|
-
await this.exitProtocolV2BootloaderToNormal();
|
|
749
|
-
} catch (restoreError) {
|
|
750
|
-
Log.warn(
|
|
751
|
-
'[FirmwareUpdateV4] failed to restore App mode after resource preparation error:',
|
|
752
|
-
restoreError
|
|
753
|
-
);
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
throw normalizeFirmwarePreparationError(err);
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
|
|
760
749
|
return this.executeProtocolV2Update({
|
|
761
750
|
fwBinaryMap,
|
|
762
751
|
bootloaderBinary,
|
|
@@ -1261,117 +1250,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1261
1250
|
};
|
|
1262
1251
|
}
|
|
1263
1252
|
|
|
1264
|
-
private getProtocolV2DeviceType(): EDeviceType.Pro2 | EDeviceType.Neo {
|
|
1265
|
-
const deviceType = this.device.getCurrentDeviceType();
|
|
1266
|
-
if (deviceType === EDeviceType.Pro2 || deviceType === EDeviceType.Neo) return deviceType;
|
|
1267
|
-
throw new Error(`Unsupported Protocol V2 device type: ${deviceType}`);
|
|
1268
|
-
}
|
|
1269
|
-
|
|
1270
|
-
private async prepareProtocolV2BootResources(): Promise<
|
|
1271
|
-
ProtocolV2ResourceBundleBinary[] | undefined
|
|
1272
|
-
> {
|
|
1273
|
-
const wantsStableResources = !!this.params.targetsToUpdate?.includes('resource');
|
|
1274
|
-
const wantsBootResources = !!this.params.targetsToUpdate?.includes('boot_resources');
|
|
1275
|
-
if (!wantsStableResources && !wantsBootResources) {
|
|
1276
|
-
return undefined;
|
|
1277
|
-
}
|
|
1278
|
-
if (this.params.resourceFiles?.length) {
|
|
1279
|
-
return undefined;
|
|
1280
|
-
}
|
|
1281
|
-
const resource = DataManager.getProtocolV2BootResources(this.getProtocolV2DeviceType());
|
|
1282
|
-
if (!resource) {
|
|
1283
|
-
if (wantsBootResources) {
|
|
1284
|
-
throw new Error('Missing Protocol V2 boot resources configuration');
|
|
1285
|
-
}
|
|
1286
|
-
Log.debug('[FirmwareUpdateV4] no boot resources configured; continue with stable resources');
|
|
1287
|
-
return undefined;
|
|
1288
|
-
}
|
|
1289
|
-
|
|
1290
|
-
const files: ProtocolV2ResourceBundleBinary[] = [];
|
|
1291
|
-
for (const file of resource.files) {
|
|
1292
|
-
const isCurrent =
|
|
1293
|
-
!this.params.forcedUpdateRes && (await this.isProtocolV2BootResourceCurrent(file));
|
|
1294
|
-
if (isCurrent) {
|
|
1295
|
-
Log.log(`[FirmwareUpdateV4] boot resource unchanged, skipping ${file.devicePath}`);
|
|
1296
|
-
} else {
|
|
1297
|
-
Log.log(`[FirmwareUpdateV4] downloading boot resource ${file.devicePath}`);
|
|
1298
|
-
const { binary } = await getSysResourceBinary(file.url);
|
|
1299
|
-
if (!isProtocolV2ResourceFileValid(binary, file)) {
|
|
1300
|
-
throw new Error(`Boot resource file verification failed: ${file.devicePath}`);
|
|
1301
|
-
}
|
|
1302
|
-
files.push({
|
|
1303
|
-
name: file.name ?? file.devicePath.split('/').pop() ?? file.devicePath,
|
|
1304
|
-
binary,
|
|
1305
|
-
devicePath: file.devicePath,
|
|
1306
|
-
});
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
return files;
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
private async isProtocolV2BootResourceCurrent(file: IProtocolV2ResourceFile) {
|
|
1313
|
-
try {
|
|
1314
|
-
const commands = this.device.getCommands();
|
|
1315
|
-
const pathInfo = await commands.typedCall(
|
|
1316
|
-
'FilesystemPathInfoQuery',
|
|
1317
|
-
'FilesystemPathInfo',
|
|
1318
|
-
{ path: file.devicePath },
|
|
1319
|
-
{ timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT }
|
|
1320
|
-
);
|
|
1321
|
-
const size = toProtocolV2FiniteNumber(pathInfo.message?.size);
|
|
1322
|
-
if (
|
|
1323
|
-
!pathInfo.message?.exist ||
|
|
1324
|
-
pathInfo.message?.directory ||
|
|
1325
|
-
!Number.isSafeInteger(size) ||
|
|
1326
|
-
size !== file.size
|
|
1327
|
-
) {
|
|
1328
|
-
return false;
|
|
1329
|
-
}
|
|
1330
|
-
|
|
1331
|
-
const digest = sha256.create();
|
|
1332
|
-
const chunkSize = this.getProtocolV2FirmwareChunkSize('write');
|
|
1333
|
-
let offset = 0;
|
|
1334
|
-
while (offset < file.size) {
|
|
1335
|
-
const response = await commands.typedCall(
|
|
1336
|
-
'FilesystemFileRead',
|
|
1337
|
-
'FilesystemFile',
|
|
1338
|
-
{
|
|
1339
|
-
file: { path: file.devicePath, offset, total_size: 0 },
|
|
1340
|
-
chunk_len: Math.min(chunkSize, file.size - offset),
|
|
1341
|
-
},
|
|
1342
|
-
{ timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT }
|
|
1343
|
-
);
|
|
1344
|
-
const data = toProtocolV2Bytes(response.message?.data);
|
|
1345
|
-
if (data.byteLength === 0) return false;
|
|
1346
|
-
const consumed = data.subarray(0, Math.min(data.byteLength, file.size - offset));
|
|
1347
|
-
digest.update(consumed);
|
|
1348
|
-
offset += consumed.byteLength;
|
|
1349
|
-
}
|
|
1350
|
-
return bytesToHex(digest.digest()) === normalizeProtocolV2Hex(file.fileHash);
|
|
1351
|
-
} catch (error) {
|
|
1352
|
-
Log.debug(
|
|
1353
|
-
`[FirmwareUpdateV4] unable to compare boot resource ${file.devicePath}; scheduling rewrite`,
|
|
1354
|
-
error
|
|
1355
|
-
);
|
|
1356
|
-
return false;
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
private mergeProtocolV2ResourceBundles(
|
|
1361
|
-
...groups: Array<ProtocolV2ResourceBundleBinary[] | undefined>
|
|
1362
|
-
): ProtocolV2ResourceBundleBinary[] | undefined {
|
|
1363
|
-
const merged = groups.flatMap(group => group ?? []);
|
|
1364
|
-
if (!merged.length) return undefined;
|
|
1365
|
-
const seenPaths = new Set<string>();
|
|
1366
|
-
for (const bundle of merged) {
|
|
1367
|
-
if (seenPaths.has(bundle.devicePath)) {
|
|
1368
|
-
throw new Error(`Duplicate Protocol V2 resource devicePath: ${bundle.devicePath}`);
|
|
1369
|
-
}
|
|
1370
|
-
seenPaths.add(bundle.devicePath);
|
|
1371
|
-
}
|
|
1372
|
-
return merged;
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
1253
|
private prepareExplicitProtocolV2ResourceFiles(): ProtocolV2ResourceBundleBinary[] | undefined {
|
|
1376
1254
|
const files = this.params.resourceFiles ?? [];
|
|
1377
1255
|
if (!files?.length) return undefined;
|
|
@@ -1381,8 +1259,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1381
1259
|
file.devicePath,
|
|
1382
1260
|
`resourceFiles[${index}].devicePath`
|
|
1383
1261
|
);
|
|
1384
|
-
const descriptor = file as typeof file &
|
|
1385
|
-
Pick<Partial<IProtocolV2ResourceFile>, 'size' | 'fileHash'>;
|
|
1262
|
+
const descriptor = file as typeof file & Partial<{ size: number; fileHash: string }>;
|
|
1386
1263
|
if (descriptor.size !== undefined && descriptor.size !== file.binary.byteLength) {
|
|
1387
1264
|
throw new Error(`resourceFiles[${index}] size mismatch`);
|
|
1388
1265
|
}
|
|
@@ -1407,58 +1284,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1407
1284
|
return prepared;
|
|
1408
1285
|
}
|
|
1409
1286
|
|
|
1410
|
-
private async prepareProtocolV2ResourceBundles(): Promise<
|
|
1411
|
-
ProtocolV2ResourceBundleBinary[] | undefined
|
|
1412
|
-
> {
|
|
1413
|
-
if (!this.params.targetsToUpdate?.includes('resource')) {
|
|
1414
|
-
return undefined;
|
|
1415
|
-
}
|
|
1416
|
-
|
|
1417
|
-
const resources = DataManager.getProtocolV2Resources(this.getProtocolV2DeviceType());
|
|
1418
|
-
if (!resources?.length) {
|
|
1419
|
-
throw new Error('Missing Pro2 stable resource configuration');
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
const inventory = this.params.forcedUpdateRes
|
|
1423
|
-
? undefined
|
|
1424
|
-
: await readProtocolV2ResourceInventory({
|
|
1425
|
-
commands: this.device.getCommands(),
|
|
1426
|
-
resources,
|
|
1427
|
-
chunkSize: this.getProtocolV2FirmwareChunkSize('write'),
|
|
1428
|
-
timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT,
|
|
1429
|
-
});
|
|
1430
|
-
const plan = buildProtocolV2ResourceUpdatePlan({
|
|
1431
|
-
resources,
|
|
1432
|
-
inventory,
|
|
1433
|
-
mode: 'bootloader-recovery',
|
|
1434
|
-
forced: this.params.forcedUpdateRes,
|
|
1435
|
-
});
|
|
1436
|
-
Log.log(
|
|
1437
|
-
`[FirmwareUpdateV4] Protocol V2 resource plan mode=bootloader-recovery status=${plan.status} count=${plan.resources.length}`
|
|
1438
|
-
);
|
|
1439
|
-
|
|
1440
|
-
const bundles: ProtocolV2ResourceBundleBinary[] = [];
|
|
1441
|
-
for (const resource of plan.resources) {
|
|
1442
|
-
bundles.push(await this.downloadProtocolV2Resource(resource));
|
|
1443
|
-
}
|
|
1444
|
-
return bundles;
|
|
1445
|
-
}
|
|
1446
|
-
|
|
1447
|
-
private async downloadProtocolV2Resource(
|
|
1448
|
-
resource: IProtocolV2Resource
|
|
1449
|
-
): Promise<ProtocolV2ResourceBundleBinary> {
|
|
1450
|
-
Log.log(`[FirmwareUpdateV4] downloading Pro2 resource ${resource.type}`);
|
|
1451
|
-
const { binary } = await getSysResourceBinary(resource.url);
|
|
1452
|
-
if (!isProtocolV2ResourceFileValid(binary, resource)) {
|
|
1453
|
-
throw new Error(`Pro2 resource file verification failed: ${resource.type}`);
|
|
1454
|
-
}
|
|
1455
|
-
return {
|
|
1456
|
-
name: `${resource.type}.okpkg`,
|
|
1457
|
-
binary,
|
|
1458
|
-
devicePath: PROTOCOL_V2_RESOURCE_DEVICE_PATHS[resource.type],
|
|
1459
|
-
};
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
1287
|
private getProtocolV2ResourceFilePath(path: string) {
|
|
1463
1288
|
if (path.startsWith('vol')) return path;
|
|
1464
1289
|
if (path.startsWith('/')) return `vol0:${path}`;
|
|
@@ -1691,13 +1516,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1691
1516
|
resourceSources: ProtocolV2ResourceBundleSource[];
|
|
1692
1517
|
}): ProtocolV2ExecutionPhase[] {
|
|
1693
1518
|
const phases: ProtocolV2ExecutionPhase[] = [];
|
|
1694
|
-
if (resourceSources.length > 0) {
|
|
1695
|
-
phases.push({
|
|
1696
|
-
kind: 'resource-sync',
|
|
1697
|
-
installSources: [],
|
|
1698
|
-
resourceSources,
|
|
1699
|
-
});
|
|
1700
|
-
}
|
|
1701
1519
|
const bootloaderSources = installSources.filter(source => source.kind === 'bootloader');
|
|
1702
1520
|
if (bootloaderSources.length > 0) {
|
|
1703
1521
|
phases.push(
|
|
@@ -1713,6 +1531,13 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1713
1531
|
}
|
|
1714
1532
|
);
|
|
1715
1533
|
}
|
|
1534
|
+
if (resourceSources.length > 0) {
|
|
1535
|
+
phases.push({
|
|
1536
|
+
kind: 'resource-sync',
|
|
1537
|
+
installSources: [],
|
|
1538
|
+
resourceSources,
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1716
1541
|
const componentSources = installSources.filter(source => source.kind !== 'bootloader');
|
|
1717
1542
|
if (componentSources.length > 0) {
|
|
1718
1543
|
phases.push({
|
|
@@ -1835,13 +1660,16 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1835
1660
|
this.postTipMessage(FirmwareUpdateTipMessage.StartTransferData);
|
|
1836
1661
|
let processedSize = 0;
|
|
1837
1662
|
for (const resource of resourcesToSync) {
|
|
1663
|
+
// The bootloader keeps its live resource package mounted. FatFs rejects
|
|
1664
|
+
// replacing an open file, so early boot promotes this staging file before mounting it.
|
|
1665
|
+
const writePath = resolveProtocolV2ResourceWritePath(resource.devicePath);
|
|
1838
1666
|
processedSize = await this.protocolV2SourceUpdateProcess({
|
|
1839
1667
|
source: resource.source,
|
|
1840
|
-
filePath:
|
|
1668
|
+
filePath: writePath,
|
|
1841
1669
|
processedSize,
|
|
1842
1670
|
totalSize,
|
|
1843
1671
|
});
|
|
1844
|
-
await this.verifyProtocolV2StagedFile(
|
|
1672
|
+
await this.verifyProtocolV2StagedFile(writePath, resource.source.size);
|
|
1845
1673
|
}
|
|
1846
1674
|
|
|
1847
1675
|
const stagedInstallTargets: Array<{ targetId: number; path: string }> = [];
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { createDeviceNotSupportMethodError } from '@onekeyfe/hd-shared';
|
|
2
|
+
|
|
3
|
+
import { supportsProtocolV2Message } from '../protocols/protocol-v2/features';
|
|
1
4
|
import FileWrite from './FileWrite';
|
|
2
5
|
|
|
3
6
|
export type UploadPortfolioParams = {
|
|
@@ -7,6 +10,8 @@ export type UploadPortfolioParams = {
|
|
|
7
10
|
|
|
8
11
|
const PORTFOLIO_PENDING_PATH = 'vol1:/portfolio/portfolio.okpkg.pending';
|
|
9
12
|
const PORTFOLIO_CHUNK_SIZE = 2048;
|
|
13
|
+
const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
|
|
14
|
+
const PORTFOLIO_UPDATE_MESSAGE_TYPE = 61400;
|
|
10
15
|
|
|
11
16
|
export default class UploadPortfolio extends FileWrite {
|
|
12
17
|
init() {
|
|
@@ -29,6 +34,19 @@ export default class UploadPortfolio extends FileWrite {
|
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
async run() {
|
|
37
|
+
const protocolInfo = await this.device.ensureProtocolV2RuntimeContext();
|
|
38
|
+
const hasFileWrite = supportsProtocolV2Message(
|
|
39
|
+
protocolInfo,
|
|
40
|
+
FILESYSTEM_FILE_WRITE_MESSAGE_TYPE
|
|
41
|
+
);
|
|
42
|
+
const hasPortfolioUpdate = supportsProtocolV2Message(
|
|
43
|
+
protocolInfo,
|
|
44
|
+
PORTFOLIO_UPDATE_MESSAGE_TYPE
|
|
45
|
+
);
|
|
46
|
+
if (!hasFileWrite || !hasPortfolioUpdate) {
|
|
47
|
+
throw createDeviceNotSupportMethodError(this.name, this.device.getCurrentFirmwareType());
|
|
48
|
+
}
|
|
49
|
+
|
|
32
50
|
const stagedFile = await super.run();
|
|
33
51
|
this.throwIfAborted();
|
|
34
52
|
await this.device.commands.typedCall('PortfolioUpdate', 'Success', {});
|
|
@@ -569,14 +569,10 @@ export default class DataManager {
|
|
|
569
569
|
this.lastCheckTimestamp = getTimeStamp();
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
-
static
|
|
573
|
-
return this.deviceMap[deviceType]?.resources?.stable;
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
static getProtocolV2BootResources(
|
|
572
|
+
static getProtocolV2ResourceSource(
|
|
577
573
|
deviceType: EDeviceType.Pro2 | EDeviceType.Neo = EDeviceType.Pro2
|
|
578
574
|
) {
|
|
579
|
-
return this.deviceMap[deviceType]?.resources?.
|
|
575
|
+
return this.deviceMap[deviceType]?.resources?.source;
|
|
580
576
|
}
|
|
581
577
|
|
|
582
578
|
static getProtobufMessages(schema: ProtobufMessageSchema = 'v1CurrentSchema'): JSON {
|
package/src/index.ts
CHANGED
|
@@ -21,6 +21,12 @@ export { executeCallback, cleanupCallback };
|
|
|
21
21
|
export { preloadSessionCache } from './device/Device';
|
|
22
22
|
export { projectFeatures as projectDeviceStateFeatures } from './device/DeviceStateProjector';
|
|
23
23
|
export { getMethodSupportedProtocols } from './api/utils';
|
|
24
|
+
export {
|
|
25
|
+
parseProtocolV2ResourceManifest,
|
|
26
|
+
prepareProtocolV2ResourceFiles,
|
|
27
|
+
resolveProtocolV2ResourceManifestFileUrl,
|
|
28
|
+
selectProtocolV2ResourceManifestFiles,
|
|
29
|
+
} from './protocols/protocol-v2/resources';
|
|
24
30
|
export {
|
|
25
31
|
getFirmwareUpdateHostBindingGeneration,
|
|
26
32
|
registerFirmwareUpdateHostBinding,
|
package/src/inject.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
prepareFirmwareUpdatePlan,
|
|
4
4
|
validateFirmwareUpdatePreparedPlan,
|
|
5
5
|
} from './api/firmware/FirmwareUpdatePreparedPlan';
|
|
6
|
+
import { prepareProtocolV2ResourceFiles } from './protocols/protocol-v2/resources';
|
|
6
7
|
import {
|
|
7
8
|
getFirmwareUpdateHostBindingGeneration,
|
|
8
9
|
registerFirmwareUpdateHostBinding,
|
|
@@ -168,6 +169,7 @@ export const createCoreApi = (
|
|
|
168
169
|
getFirmwareUpdateHostBindingGeneration,
|
|
169
170
|
prepareFirmwareUpdatePlan,
|
|
170
171
|
validateFirmwareUpdatePreparedPlan,
|
|
172
|
+
prepareProtocolV2ResourceFiles,
|
|
171
173
|
getLogs: () => call({ method: 'getLogs' }),
|
|
172
174
|
clearSessionCache: params => call({ ...params, method: 'clearSessionCache' }),
|
|
173
175
|
/**
|