@onekeyfe/hd-core 1.2.0-alpha.164 → 1.2.0-alpha.166
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/device-state-events.test.ts +2 -2
- package/__tests__/device-state-mapper.test.ts +11 -2
- package/__tests__/device-utils.test.ts +6 -0
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +13 -3
- package/__tests__/protocol-v2-resources.test.ts +35 -2
- package/__tests__/protocol-v2.test.ts +89 -42
- package/__tests__/search-devices.test.ts +4 -3
- package/dist/api/FirmwareUpdateV4.d.ts +3 -1
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -15
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
- package/dist/index.d.ts +2 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +98 -245
- package/dist/protocols/protocol-v2/resources.d.ts +1 -0
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV4.ts +75 -179
- package/src/api/SearchDevices.ts +2 -2
- package/src/api/firmware/FirmwareUpdatePlan.ts +0 -41
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +10 -6
- package/src/core/index.ts +16 -6
- package/src/device/Device.ts +3 -1
- package/src/device/DeviceStateMapper.ts +2 -2
- package/src/deviceProfile/buildDeviceFeatures.ts +7 -2
- package/src/index.ts +0 -6
- package/src/protocols/protocol-v2/resources.ts +16 -12
- package/src/types/api/firmwareUpdate.ts +1 -1
- package/src/utils/deviceFeaturesCompat.ts +9 -4
- package/src/utils/deviceInfoUtils.ts +3 -1
- package/__tests__/firmware-memory-host.test.ts +0 -126
- package/dist/api/firmware/FirmwareMemoryHost.d.ts +0 -22
- package/dist/api/firmware/FirmwareMemoryHost.d.ts.map +0 -1
- package/src/api/firmware/FirmwareMemoryHost.ts +0 -143
|
@@ -49,10 +49,22 @@ export function parseProtocolV2Resources(value: unknown): IProtocolV2Resources |
|
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
export function isProtocolV2ResourceArchiveEntryName(entryName: string): boolean {
|
|
53
|
+
const normalized = entryName.replace(/\\/g, '/');
|
|
54
|
+
if (!normalized.toLowerCase().endsWith('.okpkg')) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
const parts = normalized.split('/');
|
|
58
|
+
const fileName = parts[parts.length - 1] ?? '';
|
|
59
|
+
return (
|
|
60
|
+
fileName.length > 0 &&
|
|
61
|
+
!fileName.startsWith('.') &&
|
|
62
|
+
!parts.some(part => part === '__MACOSX' || part === '.' || part === '..' || part === '')
|
|
63
|
+
);
|
|
64
|
+
}
|
|
53
65
|
|
|
54
|
-
function
|
|
55
|
-
|
|
66
|
+
function isSafeResourceDevicePath(path: string): boolean {
|
|
67
|
+
return !(
|
|
56
68
|
path.includes('\\') ||
|
|
57
69
|
path.includes('//') ||
|
|
58
70
|
[...path].some(char => {
|
|
@@ -60,14 +72,6 @@ function isAllowedResourceDevicePath(path: string): boolean {
|
|
|
60
72
|
return code <= 0x1f || code === 0x7f;
|
|
61
73
|
}) ||
|
|
62
74
|
path.split('/').some(part => part === '.' || part === '..')
|
|
63
|
-
) {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
if (path === PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH) {
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
return (
|
|
70
|
-
path.endsWith('.okpkg') && PROTOCOL_V2_RESOURCE_DEVICE_ROOTS.some(root => path.startsWith(root))
|
|
71
75
|
);
|
|
72
76
|
}
|
|
73
77
|
|
|
@@ -93,7 +97,7 @@ function readResourceDevicePath(bytes: Uint8Array): string {
|
|
|
93
97
|
throw new Error('Invalid Pro2 RESOURCE package device path metadata');
|
|
94
98
|
}
|
|
95
99
|
const path = readAscii(pathBytes, 0, pathBytes.byteLength);
|
|
96
|
-
if (!
|
|
100
|
+
if (!isSafeResourceDevicePath(path)) {
|
|
97
101
|
throw new Error(`Invalid Pro2 RESOURCE package device path: ${path}`);
|
|
98
102
|
}
|
|
99
103
|
return path;
|
|
@@ -158,7 +158,7 @@ export interface FirmwareUpdateV4Params {
|
|
|
158
158
|
se02Binary?: ArrayBuffer;
|
|
159
159
|
se03Binary?: ArrayBuffer;
|
|
160
160
|
se04Binary?: ArrayBuffer;
|
|
161
|
-
/** Complete Protocol V2 resource ZIP
|
|
161
|
+
/** Complete Protocol V2 resource ZIP. Core parses RESC packages and writes only changed files. */
|
|
162
162
|
resourceArchiveBinary?: ArrayBuffer;
|
|
163
163
|
forcedUpdateRes?: boolean;
|
|
164
164
|
artifactReader?: FirmwareArtifactReader;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
EDeviceType,
|
|
3
|
+
EFirmwareType,
|
|
4
|
+
canonicalizePro2BleAdvertisementName,
|
|
5
|
+
} from '@onekeyfe/hd-shared';
|
|
2
6
|
import { Enum_Capability } from '@onekeyfe/hd-transport';
|
|
3
7
|
|
|
4
8
|
import type { PROTO } from '../constants';
|
|
@@ -125,9 +129,10 @@ export const resolveDeviceFirmwareType = (features?: DeviceFeaturesInput): EFirm
|
|
|
125
129
|
export const resolveDeviceBleName = (features?: DeviceFeaturesInput): string | null => {
|
|
126
130
|
if (!features) return null;
|
|
127
131
|
const compatible = asCompatibleFeatures(features);
|
|
128
|
-
|
|
129
|
-
firstNonEmptyString(compatible.bleName, compatible.onekey_ble_name, compatible.ble_name) ??
|
|
130
|
-
|
|
132
|
+
const bleName =
|
|
133
|
+
firstNonEmptyString(compatible.bleName, compatible.onekey_ble_name, compatible.ble_name) ??
|
|
134
|
+
null;
|
|
135
|
+
return bleName ? canonicalizePro2BleAdvertisementName(bleName) : null;
|
|
131
136
|
};
|
|
132
137
|
|
|
133
138
|
export const resolveDeviceFirmwareVersion = (features?: DeviceFeaturesInput): string | null => {
|
|
@@ -31,7 +31,9 @@ export const getDeviceTypeByBleName = (name?: string): IDeviceType => {
|
|
|
31
31
|
if (/^Touch/i.test(name)) return EDeviceType.Touch;
|
|
32
32
|
|
|
33
33
|
const compactName = name.replace(/[\s-]/g, '');
|
|
34
|
-
|
|
34
|
+
// Require a 4-hex Pro2 suffix in the compact form. A bare `^Pro2` prefix
|
|
35
|
+
// would also match OneKey Pro names such as "Pro 22D8" / "Pro 2D8F".
|
|
36
|
+
if (/\bPro\s*2\b/i.test(name) || /^(?:OneKey)?Pro2[a-f0-9]{4}$/i.test(compactName)) {
|
|
35
37
|
return EDeviceType.Pro2;
|
|
36
38
|
}
|
|
37
39
|
if (/\bNeo\b/i.test(name) || /^Neo/i.test(name) || /^(?:OneKey)?Neo/i.test(compactName)) {
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import { prepareFirmwareUpdateV4MemoryHost } from '../src/api/firmware/FirmwareMemoryHost';
|
|
2
|
-
|
|
3
|
-
import type { CoreApi } from '../src/types/api';
|
|
4
|
-
import type { FirmwareUpdatePlan } from '../src/types/api/firmwareUpdatePlan';
|
|
5
|
-
|
|
6
|
-
describe('prepareFirmwareUpdateV4MemoryHost', () => {
|
|
7
|
-
test('registers artifact-backed component and resource readers', async () => {
|
|
8
|
-
const componentBinary = new Uint8Array([1, 2, 3, 4]).buffer;
|
|
9
|
-
const archiveBinary = new Uint8Array([5, 6]).buffer;
|
|
10
|
-
const manifestBinary = new TextEncoder().encode('{"schema":1}').buffer;
|
|
11
|
-
let artifactReader: Parameters<
|
|
12
|
-
CoreApi['registerFirmwareUpdateHostBinding']
|
|
13
|
-
>[0]['artifactReader'];
|
|
14
|
-
const unregisterFirmwareUpdateHostBinding = jest.fn();
|
|
15
|
-
const sdk = {
|
|
16
|
-
prepareFirmwareUpdatePlan: jest.fn(({ plan, artifacts }) => ({
|
|
17
|
-
schemaVersion: 2,
|
|
18
|
-
preparedPlanDigest: 'b'.repeat(64),
|
|
19
|
-
planDigest: plan.planDigest,
|
|
20
|
-
networkPolicy: 'forbid',
|
|
21
|
-
executor: plan.executor,
|
|
22
|
-
deviceIdentity: plan.deviceIdentity,
|
|
23
|
-
deviceModel: plan.deviceModel,
|
|
24
|
-
firmwareType: plan.firmwareType,
|
|
25
|
-
platform: plan.platform,
|
|
26
|
-
leaseRef: 'test-lease',
|
|
27
|
-
targetsToUpdate: plan.targetsToUpdate,
|
|
28
|
-
artifacts: plan.artifacts.map(planArtifact => {
|
|
29
|
-
const input = artifacts.find(item => item.artifactId === planArtifact.artifactId);
|
|
30
|
-
return {
|
|
31
|
-
...planArtifact,
|
|
32
|
-
artifact: input?.artifact,
|
|
33
|
-
materializedEntries: input?.materializedEntries,
|
|
34
|
-
};
|
|
35
|
-
}),
|
|
36
|
-
})),
|
|
37
|
-
registerFirmwareUpdateHostBinding: jest.fn(binding => {
|
|
38
|
-
artifactReader = binding.artifactReader;
|
|
39
|
-
return 7;
|
|
40
|
-
}),
|
|
41
|
-
unregisterFirmwareUpdateHostBinding,
|
|
42
|
-
} as unknown as Pick<
|
|
43
|
-
CoreApi,
|
|
44
|
-
| 'prepareFirmwareUpdatePlan'
|
|
45
|
-
| 'registerFirmwareUpdateHostBinding'
|
|
46
|
-
| 'unregisterFirmwareUpdateHostBinding'
|
|
47
|
-
>;
|
|
48
|
-
const plan = {
|
|
49
|
-
schemaVersion: 2,
|
|
50
|
-
planDigest: 'a'.repeat(64),
|
|
51
|
-
executor: 'v4',
|
|
52
|
-
deviceIdentity: 'device-id',
|
|
53
|
-
deviceModel: 'pro2',
|
|
54
|
-
firmwareType: 0,
|
|
55
|
-
platform: 'web',
|
|
56
|
-
targetsToUpdate: ['boot', 'resource'],
|
|
57
|
-
artifacts: [
|
|
58
|
-
{
|
|
59
|
-
artifactId: 'component:boot',
|
|
60
|
-
role: 'component',
|
|
61
|
-
target: 'boot',
|
|
62
|
-
url: 'https://example.com/boot.okpkg',
|
|
63
|
-
container: 'raw',
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
artifactId: 'resource:archive',
|
|
67
|
-
role: 'resourceBundle',
|
|
68
|
-
target: 'resource',
|
|
69
|
-
url: 'https://example.com/resource.zip',
|
|
70
|
-
container: 'zip',
|
|
71
|
-
logicalName: 'resource-archive',
|
|
72
|
-
},
|
|
73
|
-
],
|
|
74
|
-
} as FirmwareUpdatePlan;
|
|
75
|
-
|
|
76
|
-
const host = prepareFirmwareUpdateV4MemoryHost({
|
|
77
|
-
sdk,
|
|
78
|
-
plan,
|
|
79
|
-
artifacts: [
|
|
80
|
-
{ artifactId: 'component:boot', binary: componentBinary },
|
|
81
|
-
{
|
|
82
|
-
artifactId: 'resource:archive',
|
|
83
|
-
binary: archiveBinary,
|
|
84
|
-
materializedEntries: [{ entryName: 'manifest.json', binary: manifestBinary }],
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
expect(host.hostBindingGeneration).toBe(7);
|
|
90
|
-
expect(sdk.registerFirmwareUpdateHostBinding).toHaveBeenCalledWith(
|
|
91
|
-
expect.objectContaining({ preparedPlanDigest: host.preparedPlan.preparedPlanDigest })
|
|
92
|
-
);
|
|
93
|
-
const componentArtifact = host.preparedPlan.artifacts.find(
|
|
94
|
-
artifact => artifact.target === 'boot'
|
|
95
|
-
)?.artifact;
|
|
96
|
-
const resourceEntryArtifact = host.preparedPlan.artifacts.find(
|
|
97
|
-
artifact => artifact.target === 'resource'
|
|
98
|
-
)?.materializedEntries?.[0]?.artifact;
|
|
99
|
-
expect(componentArtifact?.size).toBe(componentBinary.byteLength);
|
|
100
|
-
expect(resourceEntryArtifact?.size).toBe(manifestBinary.byteLength);
|
|
101
|
-
if (!artifactReader || !componentArtifact || !resourceEntryArtifact) {
|
|
102
|
-
throw new Error('Firmware memory host test setup is incomplete');
|
|
103
|
-
}
|
|
104
|
-
new Uint8Array(componentBinary).fill(9);
|
|
105
|
-
const opened = await artifactReader.open({
|
|
106
|
-
artifactRef: componentArtifact.artifactRef,
|
|
107
|
-
});
|
|
108
|
-
const chunk = await artifactReader.read({
|
|
109
|
-
readerId: opened.readerId,
|
|
110
|
-
offset: 1,
|
|
111
|
-
length: 2,
|
|
112
|
-
});
|
|
113
|
-
expect(Array.from(new Uint8Array(chunk.data))).toEqual([2, 3]);
|
|
114
|
-
await artifactReader.close({ readerId: opened.readerId });
|
|
115
|
-
|
|
116
|
-
// Materialized ZIP entries are receipts only. Execution opens the approved
|
|
117
|
-
// archive and re-derives these bytes, so the memory host must not retain a
|
|
118
|
-
// second readable copy of every expanded resource file.
|
|
119
|
-
expect(() => artifactReader.open({ artifactRef: resourceEntryArtifact.artifactRef })).toThrow(
|
|
120
|
-
'Firmware memory artifact is unavailable'
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
host.release();
|
|
124
|
-
expect(unregisterFirmwareUpdateHostBinding).toHaveBeenCalledWith(7);
|
|
125
|
-
});
|
|
126
|
-
});
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { CoreApi } from '../../types/api';
|
|
2
|
-
import type { FirmwareUpdatePlan } from '../../types/api/firmwareUpdatePlan';
|
|
3
|
-
export type FirmwareMemoryArtifactEntry = {
|
|
4
|
-
entryName: string;
|
|
5
|
-
binary: ArrayBuffer;
|
|
6
|
-
};
|
|
7
|
-
export type FirmwareMemoryArtifact = {
|
|
8
|
-
artifactId: string;
|
|
9
|
-
binary: ArrayBuffer;
|
|
10
|
-
materializedEntries?: FirmwareMemoryArtifactEntry[];
|
|
11
|
-
};
|
|
12
|
-
export type FirmwareUpdateV4MemoryHost = {
|
|
13
|
-
preparedPlan: ReturnType<CoreApi['prepareFirmwareUpdatePlan']>;
|
|
14
|
-
hostBindingGeneration: number;
|
|
15
|
-
release: () => void;
|
|
16
|
-
};
|
|
17
|
-
export declare function prepareFirmwareUpdateV4MemoryHost({ sdk, plan, artifacts, }: {
|
|
18
|
-
sdk: Pick<CoreApi, 'prepareFirmwareUpdatePlan' | 'registerFirmwareUpdateHostBinding' | 'unregisterFirmwareUpdateHostBinding'>;
|
|
19
|
-
plan: FirmwareUpdatePlan;
|
|
20
|
-
artifacts: FirmwareMemoryArtifact[];
|
|
21
|
-
}): FirmwareUpdateV4MemoryHost;
|
|
22
|
-
//# sourceMappingURL=FirmwareMemoryHost.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FirmwareMemoryHost.d.ts","sourceRoot":"","sources":["../../../src/api/firmware/FirmwareMemoryHost.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAK/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAE7E,MAAM,MAAM,2BAA2B,GAAG;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,mBAAmB,CAAC,EAAE,2BAA2B,EAAE,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,YAAY,EAAE,UAAU,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC,CAAC;IAC/D,qBAAqB,EAAE,MAAM,CAAC;IAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAaF,wBAAgB,iCAAiC,CAAC,EAChD,GAAG,EACH,IAAI,EACJ,SAAS,GACV,EAAE;IACD,GAAG,EAAE,IAAI,CACP,OAAO,EACL,2BAA2B,GAC3B,mCAAmC,GACnC,qCAAqC,CACxC,CAAC;IACF,IAAI,EAAE,kBAAkB,CAAC;IACzB,SAAS,EAAE,sBAAsB,EAAE,CAAC;CACrC,GAAG,0BAA0B,CA0F7B"}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { sha256 } from '@noble/hashes/sha256';
|
|
2
|
-
import { bytesToHex } from '@noble/hashes/utils';
|
|
3
|
-
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
4
|
-
|
|
5
|
-
import type { CoreApi } from '../../types/api';
|
|
6
|
-
import type {
|
|
7
|
-
FirmwareArtifactReader,
|
|
8
|
-
FirmwareArtifactReference,
|
|
9
|
-
} from '../../types/api/firmwareUpdate';
|
|
10
|
-
import type { FirmwareUpdatePlan } from '../../types/api/firmwareUpdatePlan';
|
|
11
|
-
|
|
12
|
-
export type FirmwareMemoryArtifactEntry = {
|
|
13
|
-
entryName: string;
|
|
14
|
-
binary: ArrayBuffer;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type FirmwareMemoryArtifact = {
|
|
18
|
-
artifactId: string;
|
|
19
|
-
binary: ArrayBuffer;
|
|
20
|
-
materializedEntries?: FirmwareMemoryArtifactEntry[];
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export type FirmwareUpdateV4MemoryHost = {
|
|
24
|
-
preparedPlan: ReturnType<CoreApi['prepareFirmwareUpdatePlan']>;
|
|
25
|
-
hostBindingGeneration: number;
|
|
26
|
-
release: () => void;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
let memoryHostSequence = 0;
|
|
30
|
-
|
|
31
|
-
const createReference = (binary: ArrayBuffer, prefix: string): FirmwareArtifactReference => {
|
|
32
|
-
const digest = bytesToHex(sha256(new Uint8Array(binary)));
|
|
33
|
-
return {
|
|
34
|
-
artifactRef: `fwmem:${prefix}:${digest.slice(0, 32)}`,
|
|
35
|
-
size: binary.byteLength,
|
|
36
|
-
sha256: digest,
|
|
37
|
-
};
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export function prepareFirmwareUpdateV4MemoryHost({
|
|
41
|
-
sdk,
|
|
42
|
-
plan,
|
|
43
|
-
artifacts,
|
|
44
|
-
}: {
|
|
45
|
-
sdk: Pick<
|
|
46
|
-
CoreApi,
|
|
47
|
-
| 'prepareFirmwareUpdatePlan'
|
|
48
|
-
| 'registerFirmwareUpdateHostBinding'
|
|
49
|
-
| 'unregisterFirmwareUpdateHostBinding'
|
|
50
|
-
>;
|
|
51
|
-
plan: FirmwareUpdatePlan;
|
|
52
|
-
artifacts: FirmwareMemoryArtifact[];
|
|
53
|
-
}): FirmwareUpdateV4MemoryHost {
|
|
54
|
-
if (plan.executor !== 'v4') {
|
|
55
|
-
throw ERRORS.TypedError(
|
|
56
|
-
HardwareErrorCode.RuntimeError,
|
|
57
|
-
'Firmware memory host only supports V4 plans'
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
memoryHostSequence += 1;
|
|
61
|
-
const hostId = `${Date.now()}:${memoryHostSequence}`;
|
|
62
|
-
const binaries = new Map<string, Uint8Array>();
|
|
63
|
-
const inputs = artifacts.map((input, artifactIndex) => {
|
|
64
|
-
const artifactBinary = new Uint8Array(input.binary).slice();
|
|
65
|
-
const artifact = createReference(
|
|
66
|
-
artifactBinary.buffer as ArrayBuffer,
|
|
67
|
-
`${hostId}:artifact:${artifactIndex}`
|
|
68
|
-
);
|
|
69
|
-
binaries.set(artifact.artifactRef, artifactBinary);
|
|
70
|
-
const materializedEntries = input.materializedEntries?.map((entry, entryIndex) => {
|
|
71
|
-
const entryArtifact = createReference(
|
|
72
|
-
entry.binary,
|
|
73
|
-
`${hostId}:entry:${artifactIndex}:${entryIndex}`
|
|
74
|
-
);
|
|
75
|
-
// Entry references are compact receipts for bytes that will be re-derived
|
|
76
|
-
// from the verified archive. Retaining another readable copy here doubles
|
|
77
|
-
// resource memory without adding an execution trust boundary.
|
|
78
|
-
return {
|
|
79
|
-
entryName: entry.entryName,
|
|
80
|
-
artifact: entryArtifact,
|
|
81
|
-
};
|
|
82
|
-
});
|
|
83
|
-
return {
|
|
84
|
-
artifactId: input.artifactId,
|
|
85
|
-
artifact,
|
|
86
|
-
...(materializedEntries?.length ? { materializedEntries } : {}),
|
|
87
|
-
};
|
|
88
|
-
});
|
|
89
|
-
const preparedPlan = sdk.prepareFirmwareUpdatePlan({
|
|
90
|
-
plan,
|
|
91
|
-
leaseRef: `fwmemlease:${hostId}`,
|
|
92
|
-
artifacts: inputs,
|
|
93
|
-
});
|
|
94
|
-
const readers = new Map<string, Uint8Array>();
|
|
95
|
-
let readerSequence = 0;
|
|
96
|
-
const artifactReader: FirmwareArtifactReader = {
|
|
97
|
-
open({ artifactRef }) {
|
|
98
|
-
const binary = binaries.get(artifactRef);
|
|
99
|
-
if (!binary) {
|
|
100
|
-
throw ERRORS.TypedError(
|
|
101
|
-
HardwareErrorCode.RuntimeError,
|
|
102
|
-
'Firmware memory artifact is unavailable'
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
readerSequence += 1;
|
|
106
|
-
const readerId = `fwmemreader:${hostId}:${readerSequence}`;
|
|
107
|
-
readers.set(readerId, binary);
|
|
108
|
-
return Promise.resolve({ readerId, size: binary.byteLength });
|
|
109
|
-
},
|
|
110
|
-
read({ readerId, offset, length }) {
|
|
111
|
-
const binary = readers.get(readerId);
|
|
112
|
-
if (!binary || offset < 0 || length <= 0 || offset + length > binary.byteLength) {
|
|
113
|
-
throw ERRORS.TypedError(
|
|
114
|
-
HardwareErrorCode.RuntimeError,
|
|
115
|
-
'Firmware memory artifact read is invalid'
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
const data = binary.slice(offset, offset + length).buffer;
|
|
119
|
-
return Promise.resolve({
|
|
120
|
-
data,
|
|
121
|
-
bytesRead: data.byteLength,
|
|
122
|
-
eof: offset + length === binary.byteLength,
|
|
123
|
-
});
|
|
124
|
-
},
|
|
125
|
-
close({ readerId }) {
|
|
126
|
-
readers.delete(readerId);
|
|
127
|
-
return Promise.resolve();
|
|
128
|
-
},
|
|
129
|
-
};
|
|
130
|
-
const hostBindingGeneration = sdk.registerFirmwareUpdateHostBinding({
|
|
131
|
-
artifactReader,
|
|
132
|
-
preparedPlanDigest: preparedPlan.preparedPlanDigest,
|
|
133
|
-
});
|
|
134
|
-
return {
|
|
135
|
-
preparedPlan,
|
|
136
|
-
hostBindingGeneration,
|
|
137
|
-
release: () => {
|
|
138
|
-
sdk.unregisterFirmwareUpdateHostBinding(hostBindingGeneration);
|
|
139
|
-
readers.clear();
|
|
140
|
-
binaries.clear();
|
|
141
|
-
},
|
|
142
|
-
};
|
|
143
|
-
}
|