@onekeyfe/hd-core 1.2.0-alpha.24 → 1.2.0-alpha.26
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__/AllNetworkGetAddressBase.tracing.test.ts +2 -0
- package/__tests__/chain-params-onekey-compatibility.test.ts +229 -0
- package/__tests__/connectSettings.test.ts +47 -5
- package/__tests__/device-state-events.test.ts +124 -0
- package/__tests__/evmLedgerLegacySafety.test.ts +3 -1
- package/__tests__/firmware-update/check-all-firmware-release.test.ts +127 -0
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +119 -0
- package/__tests__/firmware-update/firmware-host-binding.test.ts +70 -0
- package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
- package/__tests__/firmware-update/firmware-update-plan.test.ts +354 -0
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +213 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +39 -30
- package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
- package/__tests__/kaspa-public-types.type-test.ts +16 -0
- package/__tests__/kaspaSignTransaction.test.ts +4 -3
- package/__tests__/method-protocol-support.test.ts +113 -0
- package/__tests__/protocol-v2.test.ts +400 -123
- package/__tests__/public-device-state-api.test.ts +10 -8
- package/__tests__/tron-sign-message-init.test.ts +74 -0
- package/dist/api/BaseMethod.d.ts +6 -2
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/CipherKeyValue.d.ts +1 -0
- package/dist/api/CipherKeyValue.d.ts.map +1 -1
- package/dist/api/DirList.d.ts +1 -0
- package/dist/api/DirList.d.ts.map +1 -1
- package/dist/api/DirMake.d.ts +1 -0
- package/dist/api/DirMake.d.ts.map +1 -1
- package/dist/api/DirRemove.d.ts +1 -0
- package/dist/api/DirRemove.d.ts.map +1 -1
- package/dist/api/FileDelete.d.ts +1 -0
- package/dist/api/FileDelete.d.ts.map +1 -1
- package/dist/api/FileRead.d.ts +1 -0
- package/dist/api/FileRead.d.ts.map +1 -1
- package/dist/api/FileWrite.d.ts +1 -0
- package/dist/api/FileWrite.d.ts.map +1 -1
- package/dist/api/FirmwareUpdate.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +11 -0
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts +7 -3
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +23 -5
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetDeviceState.d.ts +1 -0
- package/dist/api/GetDeviceState.d.ts.map +1 -1
- package/dist/api/GetFeatures.d.ts.map +1 -1
- package/dist/api/GetOnekeyFeatures.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts +1 -0
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts +1 -0
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/PathInfo.d.ts +1 -0
- package/dist/api/PathInfo.d.ts.map +1 -1
- package/dist/api/alephium/AlephiumGetAddress.d.ts.map +1 -1
- package/dist/api/alephium/AlephiumSignMessage.d.ts.map +1 -1
- package/dist/api/alephium/AlephiumSignTransaction.d.ts.map +1 -1
- package/dist/api/algo/AlgoGetAddress.d.ts +1 -0
- package/dist/api/algo/AlgoGetAddress.d.ts.map +1 -1
- package/dist/api/algo/AlgoSignTransaction.d.ts +1 -0
- package/dist/api/algo/AlgoSignTransaction.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts +1 -0
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/aptos/AptosGetAddress.d.ts +1 -0
- package/dist/api/aptos/AptosGetAddress.d.ts.map +1 -1
- package/dist/api/aptos/AptosGetPublicKey.d.ts +1 -0
- package/dist/api/aptos/AptosGetPublicKey.d.ts.map +1 -1
- package/dist/api/aptos/AptosSignInMessage.d.ts +1 -0
- package/dist/api/aptos/AptosSignInMessage.d.ts.map +1 -1
- package/dist/api/aptos/AptosSignMessage.d.ts +1 -0
- package/dist/api/aptos/AptosSignMessage.d.ts.map +1 -1
- package/dist/api/aptos/AptosSignTransaction.d.ts +1 -0
- package/dist/api/aptos/AptosSignTransaction.d.ts.map +1 -1
- package/dist/api/benfen/BenfenGetAddress.d.ts.map +1 -1
- package/dist/api/benfen/BenfenGetPublicKey.d.ts.map +1 -1
- package/dist/api/benfen/BenfenSignMessage.d.ts.map +1 -1
- package/dist/api/benfen/BenfenSignTransaction.d.ts.map +1 -1
- package/dist/api/btc/BTCGetAddress.d.ts +1 -0
- package/dist/api/btc/BTCGetAddress.d.ts.map +1 -1
- package/dist/api/btc/BTCGetPublicKey.d.ts +1 -0
- package/dist/api/btc/BTCGetPublicKey.d.ts.map +1 -1
- package/dist/api/btc/BTCSignMessage.d.ts +1 -0
- package/dist/api/btc/BTCSignMessage.d.ts.map +1 -1
- package/dist/api/btc/BTCSignPsbt.d.ts +1 -0
- package/dist/api/btc/BTCSignPsbt.d.ts.map +1 -1
- package/dist/api/btc/BTCSignTransaction.d.ts +1 -0
- package/dist/api/btc/BTCSignTransaction.d.ts.map +1 -1
- package/dist/api/btc/BTCVerifyMessage.d.ts +1 -0
- package/dist/api/btc/BTCVerifyMessage.d.ts.map +1 -1
- package/dist/api/btc/helpers/versionLimit.d.ts +2 -0
- package/dist/api/btc/helpers/versionLimit.d.ts.map +1 -1
- package/dist/api/cardano/CardanoGetAddress.d.ts +1 -0
- package/dist/api/cardano/CardanoGetAddress.d.ts.map +1 -1
- package/dist/api/cardano/CardanoGetPublicKey.d.ts +1 -0
- package/dist/api/cardano/CardanoGetPublicKey.d.ts.map +1 -1
- package/dist/api/cardano/CardanoSignMessage.d.ts +1 -0
- package/dist/api/cardano/CardanoSignMessage.d.ts.map +1 -1
- package/dist/api/cardano/CardanoSignTransaction.d.ts +1 -0
- package/dist/api/cardano/CardanoSignTransaction.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxGetAddress.d.ts +1 -0
- package/dist/api/conflux/ConfluxGetAddress.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignMessage.d.ts +1 -0
- package/dist/api/conflux/ConfluxSignMessage.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts +1 -0
- package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts.map +1 -1
- package/dist/api/conflux/ConfluxSignTransaction.d.ts +1 -0
- package/dist/api/conflux/ConfluxSignTransaction.d.ts.map +1 -1
- package/dist/api/cosmos/CosmosGetAddress.d.ts +1 -0
- package/dist/api/cosmos/CosmosGetAddress.d.ts.map +1 -1
- package/dist/api/cosmos/CosmosGetPublicKey.d.ts +1 -0
- package/dist/api/cosmos/CosmosGetPublicKey.d.ts.map +1 -1
- package/dist/api/cosmos/CosmosSignTransaction.d.ts +1 -0
- package/dist/api/cosmos/CosmosSignTransaction.d.ts.map +1 -1
- package/dist/api/device/DeviceCancel.d.ts +1 -0
- package/dist/api/device/DeviceCancel.d.ts.map +1 -1
- package/dist/api/device/DeviceChangePin.d.ts +1 -0
- package/dist/api/device/DeviceChangePin.d.ts.map +1 -1
- package/dist/api/device/DeviceLock.d.ts +1 -0
- package/dist/api/device/DeviceLock.d.ts.map +1 -1
- package/dist/api/device/DeviceRebootToBoardloader.d.ts +1 -0
- package/dist/api/device/DeviceRebootToBoardloader.d.ts.map +1 -1
- package/dist/api/device/DeviceRebootToBootloader.d.ts +1 -0
- package/dist/api/device/DeviceRebootToBootloader.d.ts.map +1 -1
- package/dist/api/device/DeviceSettings.d.ts +1 -0
- package/dist/api/device/DeviceSettings.d.ts.map +1 -1
- package/dist/api/device/DeviceSupportFeatures.d.ts +1 -0
- package/dist/api/device/DeviceSupportFeatures.d.ts.map +1 -1
- package/dist/api/device/DeviceUnlock.d.ts +1 -0
- package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/device/DeviceWipe.d.ts +1 -0
- package/dist/api/device/DeviceWipe.d.ts.map +1 -1
- package/dist/api/device/PreInitialize.d.ts +1 -0
- package/dist/api/device/PreInitialize.d.ts.map +1 -1
- package/dist/api/dynex/DnxGetAddress.d.ts.map +1 -1
- package/dist/api/dynex/DnxSignTransaction.d.ts.map +1 -1
- package/dist/api/evm/EVMGetAddress.d.ts +1 -0
- package/dist/api/evm/EVMGetAddress.d.ts.map +1 -1
- package/dist/api/evm/EVMGetPublicKey.d.ts +1 -0
- package/dist/api/evm/EVMGetPublicKey.d.ts.map +1 -1
- package/dist/api/evm/EVMSignMessage.d.ts +1 -0
- package/dist/api/evm/EVMSignMessage.d.ts.map +1 -1
- package/dist/api/evm/EVMSignMessageEIP712.d.ts.map +1 -1
- package/dist/api/evm/EVMSignTransaction.d.ts +1 -0
- package/dist/api/evm/EVMSignTransaction.d.ts.map +1 -1
- package/dist/api/evm/EVMSignTypedData.d.ts +1 -0
- package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
- package/dist/api/evm/EVMVerifyMessage.d.ts +1 -0
- package/dist/api/evm/EVMVerifyMessage.d.ts.map +1 -1
- package/dist/api/filecoin/FilecoinGetAddress.d.ts +1 -0
- package/dist/api/filecoin/FilecoinGetAddress.d.ts.map +1 -1
- package/dist/api/filecoin/FilecoinSignTransaction.d.ts +1 -0
- package/dist/api/filecoin/FilecoinSignTransaction.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareArtifactSource.d.ts +25 -0
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
- package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +7 -0
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +23 -0
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +30 -0
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
- package/dist/api/firmware/getBinary.d.ts +7 -0
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/updateBootloader.d.ts +2 -0
- package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/uploadFirmware.d.ts +9 -1
- package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
- package/dist/api/kaspa/KaspaGetAddress.d.ts +1 -0
- package/dist/api/kaspa/KaspaGetAddress.d.ts.map +1 -1
- package/dist/api/kaspa/KaspaSignTransaction.d.ts +1 -0
- package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
- package/dist/api/kaspa/helpers/TransferSerialize.d.ts.map +1 -1
- package/dist/api/lightning/LnurlAuth.d.ts +0 -4
- package/dist/api/lightning/LnurlAuth.d.ts.map +1 -1
- package/dist/api/near/NearGetAddress.d.ts +1 -0
- package/dist/api/near/NearGetAddress.d.ts.map +1 -1
- package/dist/api/near/NearSignTransaction.d.ts +1 -0
- package/dist/api/near/NearSignTransaction.d.ts.map +1 -1
- package/dist/api/nem/NEMGetAddress.d.ts +1 -0
- package/dist/api/nem/NEMGetAddress.d.ts.map +1 -1
- package/dist/api/nem/NEMSignTransaction.d.ts +1 -0
- package/dist/api/nem/NEMSignTransaction.d.ts.map +1 -1
- package/dist/api/neo/NeoGetAddress.d.ts.map +1 -1
- package/dist/api/neo/NeoSignTransaction.d.ts.map +1 -1
- package/dist/api/nervos/NervosGetAddress.d.ts.map +1 -1
- package/dist/api/nervos/NervosSignTransaction.d.ts.map +1 -1
- package/dist/api/nexa/NexaGetAddress.d.ts.map +1 -1
- package/dist/api/nexa/NexaSignTransaction.d.ts.map +1 -1
- package/dist/api/nostr/NostrDecryptMessage.d.ts +1 -0
- package/dist/api/nostr/NostrDecryptMessage.d.ts.map +1 -1
- package/dist/api/nostr/NostrEncryptMessage.d.ts +1 -0
- package/dist/api/nostr/NostrEncryptMessage.d.ts.map +1 -1
- package/dist/api/nostr/NostrGetPublicKey.d.ts +1 -0
- package/dist/api/nostr/NostrGetPublicKey.d.ts.map +1 -1
- package/dist/api/nostr/NostrSignEvent.d.ts +1 -0
- package/dist/api/nostr/NostrSignEvent.d.ts.map +1 -1
- package/dist/api/nostr/NostrSignSchnorr.d.ts +1 -0
- package/dist/api/nostr/NostrSignSchnorr.d.ts.map +1 -1
- package/dist/api/polkadot/PolkadotGetAddress.d.ts +1 -0
- package/dist/api/polkadot/PolkadotGetAddress.d.ts.map +1 -1
- package/dist/api/polkadot/PolkadotSignTransaction.d.ts +1 -0
- package/dist/api/polkadot/PolkadotSignTransaction.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceReboot.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceReboot.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceStatusGet.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceStatusGet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts +1 -0
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/api/protocol-v2/FilesystemFormat.d.ts +1 -0
- package/dist/api/protocol-v2/FilesystemFormat.d.ts.map +1 -1
- package/dist/api/protocol-v2/FilesystemPermissionFix.d.ts +1 -0
- package/dist/api/protocol-v2/FilesystemPermissionFix.d.ts.map +1 -1
- package/dist/api/protocol-v2/Ping.d.ts +1 -0
- package/dist/api/protocol-v2/Ping.d.ts.map +1 -1
- package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts +1 -0
- package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
- package/dist/api/scdo/ScdoGetAddress.d.ts.map +1 -1
- package/dist/api/scdo/ScdoSignMessage.d.ts.map +1 -1
- package/dist/api/scdo/ScdoSignTransaction.d.ts.map +1 -1
- package/dist/api/solana/SolGetAddress.d.ts +1 -0
- package/dist/api/solana/SolGetAddress.d.ts.map +1 -1
- package/dist/api/solana/SolSignMessage.d.ts +1 -0
- package/dist/api/solana/SolSignMessage.d.ts.map +1 -1
- package/dist/api/solana/SolSignOffchainMessage.d.ts +1 -0
- package/dist/api/solana/SolSignOffchainMessage.d.ts.map +1 -1
- package/dist/api/solana/SolSignTransaction.d.ts +1 -0
- package/dist/api/solana/SolSignTransaction.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinGetAddress.d.ts +1 -0
- package/dist/api/starcoin/StarcoinGetAddress.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinGetPublicKey.d.ts +1 -0
- package/dist/api/starcoin/StarcoinGetPublicKey.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinSignMessage.d.ts +1 -0
- package/dist/api/starcoin/StarcoinSignMessage.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinSignTransaction.d.ts +1 -0
- package/dist/api/starcoin/StarcoinSignTransaction.d.ts.map +1 -1
- package/dist/api/starcoin/StarcoinVerifyMessage.d.ts +1 -0
- package/dist/api/starcoin/StarcoinVerifyMessage.d.ts.map +1 -1
- package/dist/api/stellar/StellarGetAddress.d.ts +1 -2
- package/dist/api/stellar/StellarGetAddress.d.ts.map +1 -1
- package/dist/api/stellar/StellarSignTransaction.d.ts +2 -3
- package/dist/api/stellar/StellarSignTransaction.d.ts.map +1 -1
- package/dist/api/sui/SuiGetAddress.d.ts +1 -0
- package/dist/api/sui/SuiGetAddress.d.ts.map +1 -1
- package/dist/api/sui/SuiGetPublicKey.d.ts +1 -0
- package/dist/api/sui/SuiGetPublicKey.d.ts.map +1 -1
- package/dist/api/sui/SuiSignMessage.d.ts +1 -0
- package/dist/api/sui/SuiSignMessage.d.ts.map +1 -1
- package/dist/api/sui/SuiSignTransaction.d.ts +1 -0
- package/dist/api/sui/SuiSignTransaction.d.ts.map +1 -1
- package/dist/api/ton/TonGetAddress.d.ts +1 -0
- package/dist/api/ton/TonGetAddress.d.ts.map +1 -1
- package/dist/api/ton/TonSignData.d.ts +1 -0
- package/dist/api/ton/TonSignData.d.ts.map +1 -1
- package/dist/api/ton/TonSignMessage.d.ts +1 -0
- package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
- package/dist/api/ton/TonSignProof.d.ts +1 -0
- package/dist/api/ton/TonSignProof.d.ts.map +1 -1
- package/dist/api/tron/TronGetAddress.d.ts +1 -0
- package/dist/api/tron/TronGetAddress.d.ts.map +1 -1
- package/dist/api/tron/TronSignMessage.d.ts +5 -0
- package/dist/api/tron/TronSignMessage.d.ts.map +1 -1
- package/dist/api/tron/TronSignTransaction.d.ts +1 -0
- package/dist/api/tron/TronSignTransaction.d.ts.map +1 -1
- package/dist/api/xrp/XrpGetAddress.d.ts +1 -0
- package/dist/api/xrp/XrpGetAddress.d.ts.map +1 -1
- package/dist/api/xrp/XrpSignTransaction.d.ts +1 -0
- package/dist/api/xrp/XrpSignTransaction.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/data-manager/DataManager.d.ts +1 -0
- 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 +3 -1
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/index.d.ts +271 -87
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2864 -893
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -1
- package/dist/topLevelInject.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +3 -0
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
- package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +5 -2
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +69 -0
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
- package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
- package/dist/types/api/firmwareUpdatePlan.d.ts +27 -0
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
- package/dist/types/api/index.d.ts +9 -1
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/kaspaSignTransaction.d.ts +15 -2
- package/dist/types/api/kaspaSignTransaction.d.ts.map +1 -1
- package/dist/types/device.d.ts +0 -1
- package/dist/types/device.d.ts.map +1 -1
- package/dist/types/settings.d.ts +13 -0
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts +0 -1
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/dist/utils/deviceVersionUtils.d.ts +1 -0
- package/dist/utils/deviceVersionUtils.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +21 -18
- package/src/api/CheckAllFirmwareRelease.ts +44 -4
- package/src/api/CipherKeyValue.ts +4 -0
- package/src/api/DirList.ts +4 -1
- package/src/api/DirMake.ts +4 -1
- package/src/api/DirRemove.ts +4 -1
- package/src/api/FileDelete.ts +4 -1
- package/src/api/FileRead.ts +4 -1
- package/src/api/FileWrite.ts +4 -1
- package/src/api/FirmwareUpdate.ts +0 -8
- package/src/api/FirmwareUpdateV2.ts +292 -120
- package/src/api/FirmwareUpdateV3.ts +256 -61
- package/src/api/FirmwareUpdateV4.ts +767 -289
- package/src/api/GetDeviceState.ts +4 -0
- package/src/api/GetFeatures.ts +1 -4
- package/src/api/GetOnekeyFeatures.ts +0 -5
- package/src/api/GetPassphraseState.ts +4 -0
- package/src/api/OpenWalletSession.ts +4 -0
- package/src/api/PathInfo.ts +4 -1
- package/src/api/UploadPortfolio.ts +1 -1
- package/src/api/alephium/AlephiumGetAddress.ts +0 -4
- package/src/api/alephium/AlephiumSignMessage.ts +0 -4
- package/src/api/alephium/AlephiumSignTransaction.ts +0 -4
- package/src/api/algo/AlgoGetAddress.ts +4 -0
- package/src/api/algo/AlgoSignTransaction.ts +4 -0
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +5 -13
- package/src/api/aptos/AptosGetAddress.ts +4 -0
- package/src/api/aptos/AptosGetPublicKey.ts +4 -0
- package/src/api/aptos/AptosSignInMessage.ts +4 -0
- package/src/api/aptos/AptosSignMessage.ts +4 -0
- package/src/api/aptos/AptosSignTransaction.ts +4 -0
- package/src/api/benfen/BenfenGetAddress.ts +11 -7
- package/src/api/benfen/BenfenGetPublicKey.ts +0 -4
- package/src/api/benfen/BenfenSignMessage.ts +0 -4
- package/src/api/benfen/BenfenSignTransaction.ts +0 -4
- package/src/api/btc/BTCGetAddress.ts +8 -1
- package/src/api/btc/BTCGetPublicKey.ts +8 -1
- package/src/api/btc/BTCSignMessage.ts +8 -1
- package/src/api/btc/BTCSignPsbt.ts +4 -0
- package/src/api/btc/BTCSignTransaction.ts +8 -1
- package/src/api/btc/BTCVerifyMessage.ts +8 -1
- package/src/api/btc/helpers/versionLimit.ts +7 -4
- package/src/api/cardano/CardanoGetAddress.ts +4 -0
- package/src/api/cardano/CardanoGetPublicKey.ts +4 -0
- package/src/api/cardano/CardanoSignMessage.ts +4 -0
- package/src/api/cardano/CardanoSignTransaction.ts +4 -0
- package/src/api/conflux/ConfluxGetAddress.ts +4 -0
- package/src/api/conflux/ConfluxSignMessage.ts +4 -0
- package/src/api/conflux/ConfluxSignMessageCIP23.ts +4 -0
- package/src/api/conflux/ConfluxSignTransaction.ts +6 -5
- package/src/api/cosmos/CosmosGetAddress.ts +4 -0
- package/src/api/cosmos/CosmosGetPublicKey.ts +4 -0
- package/src/api/cosmos/CosmosSignTransaction.ts +4 -0
- package/src/api/device/DeviceCancel.ts +4 -0
- package/src/api/device/DeviceChangePin.ts +4 -0
- package/src/api/device/DeviceLock.ts +4 -0
- package/src/api/device/DeviceRebootToBoardloader.ts +4 -0
- package/src/api/device/DeviceRebootToBootloader.ts +4 -0
- package/src/api/device/DeviceSettings.ts +4 -0
- package/src/api/device/DeviceSupportFeatures.ts +4 -0
- package/src/api/device/DeviceUnlock.ts +4 -0
- package/src/api/device/DeviceUpdateBootloader.ts +122 -6
- package/src/api/device/DeviceWipe.ts +4 -0
- package/src/api/device/PreInitialize.ts +4 -0
- package/src/api/dynex/DnxGetAddress.ts +0 -6
- package/src/api/dynex/DnxSignTransaction.ts +0 -6
- package/src/api/evm/EVMGetAddress.ts +4 -0
- package/src/api/evm/EVMGetPublicKey.ts +4 -0
- package/src/api/evm/EVMSignMessage.ts +4 -0
- package/src/api/evm/EVMSignMessageEIP712.ts +1 -11
- package/src/api/evm/EVMSignTransaction.ts +4 -0
- package/src/api/evm/EVMSignTypedData.ts +4 -0
- package/src/api/evm/EVMVerifyMessage.ts +4 -0
- package/src/api/filecoin/FilecoinGetAddress.ts +4 -0
- package/src/api/filecoin/FilecoinSignTransaction.ts +4 -0
- package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
- package/src/api/firmware/FirmwareHostBinding.ts +100 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +50 -0
- package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
- package/src/api/firmware/FirmwareUpdatePlan.ts +628 -0
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +392 -0
- package/src/api/firmware/updateBootloader.ts +19 -4
- package/src/api/firmware/uploadFirmware.ts +140 -22
- package/src/api/kaspa/KaspaGetAddress.ts +4 -0
- package/src/api/kaspa/KaspaSignTransaction.ts +37 -15
- package/src/api/kaspa/helpers/TransferSerialize.ts +3 -7
- package/src/api/lightning/LnurlAuth.ts +0 -4
- package/src/api/near/NearGetAddress.ts +4 -0
- package/src/api/near/NearSignTransaction.ts +4 -0
- package/src/api/nem/NEMGetAddress.ts +4 -0
- package/src/api/nem/NEMSignTransaction.ts +4 -0
- package/src/api/neo/NeoGetAddress.ts +0 -4
- package/src/api/neo/NeoSignTransaction.ts +0 -4
- package/src/api/nervos/NervosGetAddress.ts +0 -4
- package/src/api/nervos/NervosSignTransaction.ts +0 -4
- package/src/api/nexa/NexaGetAddress.ts +0 -4
- package/src/api/nexa/NexaSignTransaction.ts +0 -4
- package/src/api/nostr/NostrDecryptMessage.ts +4 -0
- package/src/api/nostr/NostrEncryptMessage.ts +4 -0
- package/src/api/nostr/NostrGetPublicKey.ts +4 -0
- package/src/api/nostr/NostrSignEvent.ts +4 -0
- package/src/api/nostr/NostrSignSchnorr.ts +4 -0
- package/src/api/polkadot/PolkadotGetAddress.ts +4 -0
- package/src/api/polkadot/PolkadotSignTransaction.ts +4 -0
- package/src/api/protocol-v2/DeviceFactoryInfoGet.ts +4 -1
- package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +4 -1
- package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +4 -1
- package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +4 -1
- package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +4 -1
- package/src/api/protocol-v2/DeviceInfoGet.ts +4 -8
- package/src/api/protocol-v2/DeviceReboot.ts +4 -2
- package/src/api/protocol-v2/DeviceStatusGet.ts +4 -1
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +4 -1
- package/src/api/protocol-v2/FilesystemFormat.ts +4 -1
- package/src/api/protocol-v2/FilesystemPermissionFix.ts +4 -1
- package/src/api/protocol-v2/Ping.ts +4 -1
- package/src/api/protocol-v2/ProtocolInfoRequest.ts +4 -1
- package/src/api/scdo/ScdoGetAddress.ts +0 -4
- package/src/api/scdo/ScdoSignMessage.ts +0 -4
- package/src/api/scdo/ScdoSignTransaction.ts +0 -4
- package/src/api/solana/SolGetAddress.ts +4 -0
- package/src/api/solana/SolSignMessage.ts +4 -0
- package/src/api/solana/SolSignOffchainMessage.ts +4 -0
- package/src/api/solana/SolSignTransaction.ts +4 -0
- package/src/api/starcoin/StarcoinGetAddress.ts +4 -0
- package/src/api/starcoin/StarcoinGetPublicKey.ts +4 -0
- package/src/api/starcoin/StarcoinSignMessage.ts +4 -0
- package/src/api/starcoin/StarcoinSignTransaction.ts +4 -0
- package/src/api/starcoin/StarcoinVerifyMessage.ts +4 -0
- package/src/api/stellar/StellarGetAddress.ts +1 -10
- package/src/api/stellar/StellarSignTransaction.ts +1 -14
- package/src/api/sui/SuiGetAddress.ts +4 -0
- package/src/api/sui/SuiGetPublicKey.ts +4 -0
- package/src/api/sui/SuiSignMessage.ts +4 -0
- package/src/api/sui/SuiSignTransaction.ts +4 -0
- package/src/api/ton/TonGetAddress.ts +4 -0
- package/src/api/ton/TonSignData.ts +5 -1
- package/src/api/ton/TonSignMessage.ts +4 -0
- package/src/api/ton/TonSignProof.ts +4 -0
- package/src/api/tron/TronGetAddress.ts +4 -0
- package/src/api/tron/TronSignMessage.ts +18 -7
- package/src/api/tron/TronSignTransaction.ts +4 -0
- package/src/api/xrp/XrpGetAddress.ts +4 -0
- package/src/api/xrp/XrpSignTransaction.ts +5 -1
- package/src/core/index.ts +4 -17
- package/src/data-manager/DataManager.ts +33 -33
- package/src/data-manager/connectSettings.ts +11 -0
- package/src/device/Device.ts +53 -53
- package/src/index.ts +5 -0
- package/src/inject.ts +22 -2
- package/src/lowLevelInject.ts +5 -1
- package/src/protocols/protocol-v2/unlockRetry.ts +18 -11
- package/src/topLevelInject.ts +5 -1
- package/src/types/api/checkAllFirmwareRelease.ts +3 -0
- package/src/types/api/deviceUpdateBootloader.ts +6 -0
- package/src/types/api/export.ts +20 -0
- package/src/types/api/firmwareUpdate.ts +76 -0
- package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
- package/src/types/api/firmwareUpdatePlan.ts +36 -0
- package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
- package/src/types/api/index.ts +14 -0
- package/src/types/api/kaspaSignTransaction.ts +20 -2
- package/src/types/device.ts +0 -1
- package/src/types/settings.ts +13 -0
- package/src/utils/deviceInfoUtils.ts +0 -3
- package/src/utils/deviceVersionUtils.ts +1 -1
- package/src/utils/index.ts +0 -1
- package/tsconfig.type-tests.json +8 -0
|
@@ -30,11 +30,20 @@ import {
|
|
|
30
30
|
getProtocolV2UnknownErrorText,
|
|
31
31
|
isProtocolV2DeviceDisconnectedError,
|
|
32
32
|
} from './protocol-v2/helpers';
|
|
33
|
+
import { openFirmwareByteSource, writeFirmwareByteSource } from './firmware/FirmwareArtifactSource';
|
|
34
|
+
import { resolveFirmwareUpdateHostBinding } from './firmware/FirmwareHostBinding';
|
|
35
|
+
import {
|
|
36
|
+
assertFirmwareUpdatePreparedPlanBinding,
|
|
37
|
+
assertFirmwareUpdatePreparedPlanDeviceIdentity,
|
|
38
|
+
} from './firmware/FirmwareUpdatePreparedPlan';
|
|
33
39
|
|
|
34
|
-
import type {
|
|
40
|
+
import type {
|
|
41
|
+
FirmwareArtifactReference,
|
|
42
|
+
FirmwareUpdateV4Params,
|
|
43
|
+
FirmwareUpdateV4Target,
|
|
44
|
+
} from '../types/api/firmwareUpdate';
|
|
35
45
|
import type { EFirmwareType } from '@onekeyfe/hd-shared';
|
|
36
46
|
import type { ProtocolV2DeviceInfo } from '@onekeyfe/hd-transport';
|
|
37
|
-
import type { PROTO } from '../constants';
|
|
38
47
|
import type { TypedResponseMessage } from '../device/DeviceCommands';
|
|
39
48
|
import type {
|
|
40
49
|
Features,
|
|
@@ -42,6 +51,7 @@ import type {
|
|
|
42
51
|
IProtocolV2FirmwareComponent,
|
|
43
52
|
IVersionArray,
|
|
44
53
|
} from '../types';
|
|
54
|
+
import type { FirmwareByteSource } from './firmware/FirmwareArtifactSource';
|
|
45
55
|
|
|
46
56
|
const Log = getLogger(LoggerNames.Method);
|
|
47
57
|
|
|
@@ -85,11 +95,6 @@ const getProtocolV2DeviceTransferProgress = (
|
|
|
85
95
|
return Math.min(Math.max(Math.ceil((bytesAfterChunk / totalBytes) * 100), 1), 99);
|
|
86
96
|
};
|
|
87
97
|
|
|
88
|
-
const formatProtocolV2TransferSpeed = (bytes: number, elapsedMs: number) => {
|
|
89
|
-
const safeElapsedMs = Math.max(elapsedMs, 1);
|
|
90
|
-
return (bytes / 1024 / (safeElapsedMs / 1000)).toFixed(2);
|
|
91
|
-
};
|
|
92
|
-
|
|
93
98
|
type ProtocolV2FirmwareUpdateStatusTarget = {
|
|
94
99
|
target_id: number | string;
|
|
95
100
|
status?: number | string;
|
|
@@ -103,17 +108,6 @@ type ProtocolV2TargetBinary = { fileName: string; binary: ArrayBuffer; targetId:
|
|
|
103
108
|
type ProtocolV2InstallItem = ProtocolV2TargetBinary & {
|
|
104
109
|
kind: ProtocolV2RemoteComponentTarget['kind'];
|
|
105
110
|
};
|
|
106
|
-
type ProtocolV2InstallTarget = ProtocolV2InstallItem & {
|
|
107
|
-
path: string;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
type ProtocolV2FileTransferParams = PROTO.FirmwareUpload & {
|
|
111
|
-
filePath: string;
|
|
112
|
-
processedSize?: number;
|
|
113
|
-
totalSize?: number;
|
|
114
|
-
onTransferredBytes?: (transferredBytes: number) => void;
|
|
115
|
-
};
|
|
116
|
-
|
|
117
111
|
/** RESC bundle okpkg written independently to devicePath through FileWrite. */
|
|
118
112
|
type ProtocolV2ResourceBundleBinary = {
|
|
119
113
|
name: string;
|
|
@@ -136,6 +130,35 @@ type ProtocolV2RemoteComponentTarget = {
|
|
|
136
130
|
kind: 'bootloader' | 'firmware';
|
|
137
131
|
};
|
|
138
132
|
|
|
133
|
+
type ProtocolV2InstallSource = {
|
|
134
|
+
fileName: string;
|
|
135
|
+
source: FirmwareByteSource;
|
|
136
|
+
targetId: number;
|
|
137
|
+
kind: ProtocolV2RemoteComponentTarget['kind'];
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
type ProtocolV2ResourceBundleSource = {
|
|
141
|
+
name: string;
|
|
142
|
+
source: FirmwareByteSource;
|
|
143
|
+
devicePath: string;
|
|
144
|
+
version?: IVersionArray;
|
|
145
|
+
payloadHash?: string;
|
|
146
|
+
headerHash?: string;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
type ProtocolV2ExecutionPhaseKind =
|
|
150
|
+
| 'resource-sync'
|
|
151
|
+
| 'bootloader-install'
|
|
152
|
+
| 'bootloader-verify'
|
|
153
|
+
| 'component-install'
|
|
154
|
+
| 'final-verify';
|
|
155
|
+
|
|
156
|
+
type ProtocolV2ExecutionPhase = {
|
|
157
|
+
kind: ProtocolV2ExecutionPhaseKind;
|
|
158
|
+
installSources: ProtocolV2InstallSource[];
|
|
159
|
+
resourceSources: ProtocolV2ResourceBundleSource[];
|
|
160
|
+
};
|
|
161
|
+
|
|
139
162
|
type ProtocolV2OkppHeader = {
|
|
140
163
|
type: string;
|
|
141
164
|
version: IVersionArray;
|
|
@@ -395,6 +418,20 @@ export const assertProtocolV2ReconnectIdentity = (
|
|
|
395
418
|
export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareUpdateV4Params> {
|
|
396
419
|
private protocolV2ExpectedSerialNumber?: string;
|
|
397
420
|
|
|
421
|
+
getSupportedProtocols() {
|
|
422
|
+
return ['V2'] as const;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
private protocolV2PreparedSources: FirmwareByteSource[] = [];
|
|
426
|
+
|
|
427
|
+
private protocolV2ExecutionInLoader = false;
|
|
428
|
+
|
|
429
|
+
private protocolV2CompletedTargetVersions = new Map<number, number>();
|
|
430
|
+
|
|
431
|
+
private protocolV2LatestFinalFeatures?: Features;
|
|
432
|
+
|
|
433
|
+
private protocolV2FinalStatusVerified = false;
|
|
434
|
+
|
|
398
435
|
init() {
|
|
399
436
|
this.allowDeviceMode = [UI_REQUEST.BOOTLOADER, UI_REQUEST.NOT_INITIALIZE];
|
|
400
437
|
this.requireDeviceMode = [];
|
|
@@ -432,10 +469,62 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
432
469
|
{ name: 'firmwareType', type: 'string' },
|
|
433
470
|
{ name: 'targetsToUpdate', type: 'array', allowEmpty: true },
|
|
434
471
|
{ name: 'platform', type: 'string' },
|
|
472
|
+
{ name: 'expectedDeviceId', type: 'string' },
|
|
435
473
|
{ name: 'resourceBundleFiles', type: 'array', allowEmpty: true },
|
|
436
474
|
]);
|
|
475
|
+
if (
|
|
476
|
+
payload.expectedDeviceId !== undefined &&
|
|
477
|
+
(payload.expectedDeviceId.length === 0 || payload.expectedDeviceId.length > 160)
|
|
478
|
+
) {
|
|
479
|
+
throw ERRORS.TypedError(
|
|
480
|
+
HardwareErrorCode.CallMethodInvalidParameter,
|
|
481
|
+
'Protocol V2 expected device identity is invalid'
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
const hostBinding =
|
|
485
|
+
payload.preparedPlan || payload.componentArtifacts || payload.resourceBundleArtifacts
|
|
486
|
+
? resolveFirmwareUpdateHostBinding(payload.hostBindingGeneration)
|
|
487
|
+
: undefined;
|
|
488
|
+
if (hostBinding) {
|
|
489
|
+
assertFirmwareUpdatePreparedPlanBinding({
|
|
490
|
+
preparedPlan: payload.preparedPlan,
|
|
491
|
+
executor: 'v4',
|
|
492
|
+
platform: payload.platform,
|
|
493
|
+
scopeTargets: [
|
|
494
|
+
'boot',
|
|
495
|
+
'app_v1',
|
|
496
|
+
'app_v2',
|
|
497
|
+
'coprocessor',
|
|
498
|
+
'resource',
|
|
499
|
+
'se01',
|
|
500
|
+
'se02',
|
|
501
|
+
'se03',
|
|
502
|
+
'se04',
|
|
503
|
+
],
|
|
504
|
+
bindings: [
|
|
505
|
+
...Object.entries(payload.componentArtifacts ?? {}).flatMap(([target, artifact]) =>
|
|
506
|
+
artifact
|
|
507
|
+
? [
|
|
508
|
+
{
|
|
509
|
+
target: target as Exclude<FirmwareUpdateV4Target, 'resource'>,
|
|
510
|
+
artifact,
|
|
511
|
+
},
|
|
512
|
+
]
|
|
513
|
+
: []
|
|
514
|
+
),
|
|
515
|
+
...(payload.resourceBundleArtifacts ?? []).map(
|
|
516
|
+
(entry: { name: string; artifact: FirmwareArtifactReference }) => ({
|
|
517
|
+
target: 'resource' as const,
|
|
518
|
+
logicalName: entry.name,
|
|
519
|
+
artifact: entry.artifact,
|
|
520
|
+
})
|
|
521
|
+
),
|
|
522
|
+
],
|
|
523
|
+
});
|
|
524
|
+
}
|
|
437
525
|
|
|
438
526
|
this.params = {
|
|
527
|
+
preparedPlan: payload.preparedPlan,
|
|
439
528
|
chunkSize: payload.chunkSize,
|
|
440
529
|
forcedUpdateRes: payload.forcedUpdateRes,
|
|
441
530
|
bootloaderBinary: payload.bootloaderBinary,
|
|
@@ -450,7 +539,12 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
450
539
|
resourceBundleFiles: payload.resourceBundleFiles,
|
|
451
540
|
firmwareType: payload.firmwareType,
|
|
452
541
|
targetsToUpdate: payload.targetsToUpdate,
|
|
542
|
+
expectedTargetVersions: payload.expectedTargetVersions,
|
|
453
543
|
platform: payload.platform,
|
|
544
|
+
expectedDeviceId: payload.expectedDeviceId,
|
|
545
|
+
artifactReader: hostBinding?.artifactReader ?? payload.artifactReader,
|
|
546
|
+
componentArtifacts: payload.componentArtifacts,
|
|
547
|
+
resourceBundleArtifacts: payload.resourceBundleArtifacts,
|
|
454
548
|
};
|
|
455
549
|
}
|
|
456
550
|
|
|
@@ -475,13 +569,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
475
569
|
}
|
|
476
570
|
|
|
477
571
|
async run() {
|
|
478
|
-
if (!this.device.isProtocolV2()) {
|
|
479
|
-
throw ERRORS.TypedError(
|
|
480
|
-
HardwareErrorCode.RuntimeError,
|
|
481
|
-
'firmwareUpdateV4 requires a Protocol V2 device'
|
|
482
|
-
);
|
|
483
|
-
}
|
|
484
|
-
|
|
485
572
|
Log.debug('FirmwareUpdateV4 strategy: Protocol V2');
|
|
486
573
|
return this.runProtocolV2();
|
|
487
574
|
}
|
|
@@ -491,6 +578,14 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
491
578
|
const deviceFeatures = await this.getProtocolV2DeviceFeatures();
|
|
492
579
|
const deviceFirmwareType = getFirmwareType(deviceFeatures);
|
|
493
580
|
const firmwareType = this.params.firmwareType ?? deviceFirmwareType;
|
|
581
|
+
this.validateExpectedTargetVersions();
|
|
582
|
+
|
|
583
|
+
if (
|
|
584
|
+
(this.params.componentArtifacts && Object.keys(this.params.componentArtifacts).length > 0) ||
|
|
585
|
+
this.params.resourceBundleArtifacts?.length
|
|
586
|
+
) {
|
|
587
|
+
return this.runProtocolV2PreparedArtifacts(deviceFeatures, firmwareType);
|
|
588
|
+
}
|
|
494
589
|
|
|
495
590
|
let fwBinaryMap: ProtocolV2TargetBinary[] = [];
|
|
496
591
|
let bootloaderBinary: ArrayBuffer | null = null;
|
|
@@ -501,6 +596,18 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
501
596
|
fwBinaryMap = this.collectExplicitTargetBinaries();
|
|
502
597
|
bootloaderBinary = this.prepareBootloaderBinary();
|
|
503
598
|
if (!this.hasExplicitProtocolV2Payload(fwBinaryMap)) {
|
|
599
|
+
if (
|
|
600
|
+
this.params.artifactReader ||
|
|
601
|
+
DataManager.getSettings('firmwareManifestMode') === 'external-only'
|
|
602
|
+
) {
|
|
603
|
+
throw ERRORS.TypedError(
|
|
604
|
+
HardwareErrorCode.RuntimeError,
|
|
605
|
+
'Protocol V2 firmware artifacts must be prepared by the external firmware host',
|
|
606
|
+
{
|
|
607
|
+
firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
|
|
608
|
+
}
|
|
609
|
+
);
|
|
610
|
+
}
|
|
504
611
|
const remoteBinaries = await this.prepareRemoteProtocolV2Binaries(
|
|
505
612
|
firmwareType,
|
|
506
613
|
deviceFeatures
|
|
@@ -509,10 +616,13 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
509
616
|
fwBinaryMap = remoteBinaries.fwBinaryMap;
|
|
510
617
|
installItems = remoteBinaries.installItems;
|
|
511
618
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
619
|
+
const resourceDescriptors = this.prepareProtocolV2ResourceBundles(
|
|
620
|
+
firmwareType,
|
|
621
|
+
deviceFeatures
|
|
622
|
+
);
|
|
623
|
+
resourceBundles = resourceDescriptors?.length
|
|
624
|
+
? await this.materializeProtocolV2ResourceBundles(resourceDescriptors)
|
|
625
|
+
: undefined;
|
|
516
626
|
this.postTipMessage(FirmwareUpdateTipMessage.FinishDownloadFirmware);
|
|
517
627
|
} catch (err) {
|
|
518
628
|
throw ERRORS.TypedError(HardwareErrorCode.FirmwareUpdateDownloadFailed, err.message ?? err);
|
|
@@ -525,22 +635,289 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
525
635
|
);
|
|
526
636
|
}
|
|
527
637
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
await this.executeProtocolV2Update({
|
|
638
|
+
return this.executeProtocolV2Update({
|
|
531
639
|
fwBinaryMap,
|
|
532
640
|
bootloaderBinary,
|
|
533
641
|
...(installItems ? { installItems } : undefined),
|
|
534
642
|
...(resourceBundles?.length ? { resourceBundles } : undefined),
|
|
535
643
|
});
|
|
644
|
+
}
|
|
536
645
|
|
|
537
|
-
|
|
646
|
+
private async openProtocolV2PreparedSource(artifact: FirmwareArtifactReference) {
|
|
647
|
+
const source = await openFirmwareByteSource({
|
|
648
|
+
artifact,
|
|
649
|
+
reader: this.params.artifactReader,
|
|
650
|
+
});
|
|
651
|
+
if (!source) {
|
|
652
|
+
throw ERRORS.TypedError(
|
|
653
|
+
HardwareErrorCode.RuntimeError,
|
|
654
|
+
`Firmware artifact ${artifact.artifactRef} is not prepared`,
|
|
655
|
+
{
|
|
656
|
+
firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
|
|
657
|
+
}
|
|
658
|
+
);
|
|
659
|
+
}
|
|
660
|
+
this.protocolV2PreparedSources.push(source);
|
|
661
|
+
return source;
|
|
662
|
+
}
|
|
538
663
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
664
|
+
private async openProtocolV2MemorySource(binary: ArrayBuffer) {
|
|
665
|
+
const source = await openFirmwareByteSource({ binary });
|
|
666
|
+
if (!source) {
|
|
667
|
+
throw ERRORS.TypedError(
|
|
668
|
+
HardwareErrorCode.RuntimeError,
|
|
669
|
+
'Protocol V2 firmware binary is empty'
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
this.protocolV2PreparedSources.push(source);
|
|
673
|
+
return source;
|
|
674
|
+
}
|
|
542
675
|
|
|
543
|
-
|
|
676
|
+
private async closeProtocolV2PreparedSources() {
|
|
677
|
+
const sources = this.protocolV2PreparedSources.splice(0);
|
|
678
|
+
await Promise.all(sources.map(source => source.close().catch(() => undefined)));
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
private async prepareProtocolV2InstallSources(
|
|
682
|
+
firmwareType: EFirmwareType,
|
|
683
|
+
features: Features
|
|
684
|
+
): Promise<ProtocolV2InstallSource[]> {
|
|
685
|
+
const release = DataManager.getFirmwareLatestRelease(features, firmwareType);
|
|
686
|
+
if (!release) {
|
|
687
|
+
throw ERRORS.TypedError(
|
|
688
|
+
HardwareErrorCode.RuntimeError,
|
|
689
|
+
'Protocol V2 firmware release is unavailable'
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
const componentArtifacts = this.params.componentArtifacts ?? {};
|
|
693
|
+
const requestedTargets = new Set(
|
|
694
|
+
this.params.targetsToUpdate ?? (Object.keys(componentArtifacts) as FirmwareUpdateV4Target[])
|
|
695
|
+
);
|
|
696
|
+
const installSources: ProtocolV2InstallSource[] = [];
|
|
697
|
+
const preparedTargets = new Set<FirmwareUpdateV4Target>();
|
|
698
|
+
|
|
699
|
+
for (const [key, component] of this.getRemoteComponentEntries(release)) {
|
|
700
|
+
const target = this.getRemoteComponentTarget(key, component);
|
|
701
|
+
const updateTarget = PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(target.targetId);
|
|
702
|
+
if (updateTarget && updateTarget !== 'resource' && requestedTargets.has(updateTarget)) {
|
|
703
|
+
const artifact = componentArtifacts[updateTarget];
|
|
704
|
+
if (!artifact) {
|
|
705
|
+
throw ERRORS.TypedError(
|
|
706
|
+
HardwareErrorCode.RuntimeError,
|
|
707
|
+
`Protocol V2 ${updateTarget} artifact is not prepared`,
|
|
708
|
+
{
|
|
709
|
+
firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
|
|
710
|
+
artifactName: updateTarget,
|
|
711
|
+
}
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
installSources.push({
|
|
715
|
+
...target,
|
|
716
|
+
source: await this.openProtocolV2PreparedSource(artifact),
|
|
717
|
+
});
|
|
718
|
+
preparedTargets.add(updateTarget);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
const unknownTarget = Array.from(requestedTargets).find(
|
|
723
|
+
target => target !== 'resource' && !preparedTargets.has(target)
|
|
724
|
+
);
|
|
725
|
+
if (unknownTarget) {
|
|
726
|
+
throw ERRORS.TypedError(
|
|
727
|
+
HardwareErrorCode.RuntimeError,
|
|
728
|
+
`Protocol V2 release does not contain requested target ${unknownTarget}`
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
return installSources;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
private async prepareProtocolV2ResourceSources(
|
|
735
|
+
firmwareType: EFirmwareType,
|
|
736
|
+
features: Features
|
|
737
|
+
): Promise<ProtocolV2ResourceBundleSource[]> {
|
|
738
|
+
const preparedArtifacts = this.params.resourceBundleArtifacts ?? [];
|
|
739
|
+
const resourceRequested =
|
|
740
|
+
this.params.targetsToUpdate?.includes('resource') || preparedArtifacts.length > 0;
|
|
741
|
+
if (!resourceRequested) {
|
|
742
|
+
return [];
|
|
743
|
+
}
|
|
744
|
+
const release = DataManager.getFirmwareLatestRelease(features, firmwareType);
|
|
745
|
+
const descriptors = release?.resourceBundles ?? [];
|
|
746
|
+
const artifactByName = new Map(
|
|
747
|
+
preparedArtifacts.map(item => [item.name, item.artifact] as const)
|
|
748
|
+
);
|
|
749
|
+
const sources: ProtocolV2ResourceBundleSource[] = [];
|
|
750
|
+
for (const descriptor of descriptors) {
|
|
751
|
+
const artifact = artifactByName.get(descriptor.name);
|
|
752
|
+
if (!artifact) {
|
|
753
|
+
throw ERRORS.TypedError(
|
|
754
|
+
HardwareErrorCode.RuntimeError,
|
|
755
|
+
`Protocol V2 resource bundle ${descriptor.name} is not prepared`,
|
|
756
|
+
{
|
|
757
|
+
firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
|
|
758
|
+
artifactName: descriptor.name,
|
|
759
|
+
}
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
const devicePath = validateProtocolV2FilesystemPath(
|
|
763
|
+
descriptor.devicePath,
|
|
764
|
+
'resourceBundles[].devicePath'
|
|
765
|
+
);
|
|
766
|
+
sources.push({
|
|
767
|
+
name: descriptor.name,
|
|
768
|
+
source: await this.openProtocolV2PreparedSource(artifact),
|
|
769
|
+
devicePath,
|
|
770
|
+
version: descriptor.version,
|
|
771
|
+
payloadHash: descriptor.payloadHash,
|
|
772
|
+
headerHash: descriptor.headerHash,
|
|
773
|
+
});
|
|
774
|
+
artifactByName.delete(descriptor.name);
|
|
775
|
+
}
|
|
776
|
+
if (artifactByName.size > 0) {
|
|
777
|
+
throw ERRORS.TypedError(
|
|
778
|
+
HardwareErrorCode.RuntimeError,
|
|
779
|
+
`Protocol V2 release does not contain resource bundle ${artifactByName.keys().next().value}`
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
return sources;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
private async runProtocolV2PreparedArtifacts(features: Features, firmwareType: EFirmwareType) {
|
|
786
|
+
try {
|
|
787
|
+
this.postTipMessage(FirmwareUpdateTipMessage.StartDownloadFirmware);
|
|
788
|
+
const installSources = await this.prepareProtocolV2InstallSources(firmwareType, features);
|
|
789
|
+
const resourceSources = await this.prepareProtocolV2ResourceSources(firmwareType, features);
|
|
790
|
+
if (installSources.length === 0 && resourceSources.length === 0) {
|
|
791
|
+
throw ERRORS.TypedError(
|
|
792
|
+
HardwareErrorCode.FirmwareUpdateDownloadFailed,
|
|
793
|
+
'No firmware to update'
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
this.postTipMessage(FirmwareUpdateTipMessage.FinishDownloadFirmware);
|
|
797
|
+
|
|
798
|
+
return await this.executeProtocolV2SourceUpdate({
|
|
799
|
+
installSources,
|
|
800
|
+
resourceSources,
|
|
801
|
+
});
|
|
802
|
+
} finally {
|
|
803
|
+
await this.closeProtocolV2PreparedSources();
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
private validateExpectedTargetVersions() {
|
|
808
|
+
const expected = this.params.expectedTargetVersions;
|
|
809
|
+
if (expected === undefined) return;
|
|
810
|
+
if (typeof expected !== 'object' || expected === null || Array.isArray(expected)) {
|
|
811
|
+
throw ERRORS.TypedError(
|
|
812
|
+
HardwareErrorCode.RuntimeError,
|
|
813
|
+
'Protocol V2 expected target versions are invalid'
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
for (const [target, version] of Object.entries(expected)) {
|
|
817
|
+
if (
|
|
818
|
+
!Array.from(PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.values()).includes(
|
|
819
|
+
target as FirmwareUpdateV4Target
|
|
820
|
+
) ||
|
|
821
|
+
typeof version !== 'string' ||
|
|
822
|
+
!/^\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?$/u.test(version) ||
|
|
823
|
+
version.length > 64
|
|
824
|
+
) {
|
|
825
|
+
throw ERRORS.TypedError(
|
|
826
|
+
HardwareErrorCode.RuntimeError,
|
|
827
|
+
'Protocol V2 expected target version is invalid'
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
private getExpectedProtocolV2TargetVersion(targetId: number) {
|
|
834
|
+
const target = PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(targetId);
|
|
835
|
+
const version = target ? this.params?.expectedTargetVersions?.[target] : undefined;
|
|
836
|
+
if (!version) return undefined;
|
|
837
|
+
const parts = version.split(/[+-]/u, 1)[0].split('.').map(Number);
|
|
838
|
+
if (
|
|
839
|
+
parts.length !== 3 ||
|
|
840
|
+
parts.some(part => !Number.isSafeInteger(part) || part < 0 || part > 0xff)
|
|
841
|
+
) {
|
|
842
|
+
return undefined;
|
|
843
|
+
}
|
|
844
|
+
return parts[0] * 0x10000 + parts[1] * 0x100 + parts[2];
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
private assertExpectedProtocolV2Versions(targets?: readonly FirmwareUpdateV4Target[]) {
|
|
848
|
+
const expected = this.params?.expectedTargetVersions;
|
|
849
|
+
if (!expected) return;
|
|
850
|
+
const features = this.protocolV2LatestFinalFeatures;
|
|
851
|
+
const requestedTargets = this.getProtocolV2RequestedTargets();
|
|
852
|
+
const applicationTargets = requestedTargets.filter(
|
|
853
|
+
target => target === 'app_v1' || target === 'app_v2'
|
|
854
|
+
);
|
|
855
|
+
const visibleVersions: Partial<Record<FirmwareUpdateV4Target, string>> = {
|
|
856
|
+
boot: features ? getDeviceBootloaderVersion(features).join('.') : undefined,
|
|
857
|
+
coprocessor: features ? getDeviceBLEFirmwareVersion(features).join('.') : undefined,
|
|
858
|
+
se01: features?.se01Version ?? undefined,
|
|
859
|
+
se02: features?.se02Version ?? undefined,
|
|
860
|
+
se03: features?.se03Version ?? undefined,
|
|
861
|
+
se04: features?.se04Version ?? undefined,
|
|
862
|
+
};
|
|
863
|
+
if (features && applicationTargets.length === 1) {
|
|
864
|
+
visibleVersions[applicationTargets[0]] = getDeviceFirmwareVersion(features).join('.');
|
|
865
|
+
}
|
|
866
|
+
const expectedEntries = (
|
|
867
|
+
Object.entries(expected) as Array<[FirmwareUpdateV4Target, string]>
|
|
868
|
+
).filter(([target]) => !targets || targets.includes(target));
|
|
869
|
+
for (const [target, expectedVersion] of expectedEntries) {
|
|
870
|
+
const targetId = Array.from(PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.entries()).find(
|
|
871
|
+
([, mappedTarget]) => mappedTarget === target
|
|
872
|
+
)?.[0];
|
|
873
|
+
const statusVersion =
|
|
874
|
+
targetId === undefined ? undefined : this.protocolV2CompletedTargetVersions.get(targetId);
|
|
875
|
+
const observedVersion =
|
|
876
|
+
statusVersion === undefined
|
|
877
|
+
? visibleVersions[target]
|
|
878
|
+
: `${Math.floor(statusVersion / 0x10000) % 0x100}.${
|
|
879
|
+
Math.floor(statusVersion / 0x100) % 0x100
|
|
880
|
+
}.${statusVersion % 0x100}`;
|
|
881
|
+
if (!observedVersion) {
|
|
882
|
+
if (this.protocolV2FinalStatusVerified) {
|
|
883
|
+
Log.warn(
|
|
884
|
+
`Protocol V2 target ${target} has no observable final version; completed target status is authoritative`
|
|
885
|
+
);
|
|
886
|
+
} else {
|
|
887
|
+
throw ERRORS.TypedError(
|
|
888
|
+
HardwareErrorCode.FirmwareVerificationFailed,
|
|
889
|
+
`Protocol V2 target ${target} has no observable final version after status fallback`
|
|
890
|
+
);
|
|
891
|
+
}
|
|
892
|
+
} else if (observedVersion !== expectedVersion) {
|
|
893
|
+
throw ERRORS.TypedError(
|
|
894
|
+
HardwareErrorCode.FirmwareVerificationFailed,
|
|
895
|
+
`Protocol V2 target ${target} reached ${observedVersion}, expected ${expectedVersion}`
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
private getProtocolV2RequestedTargets(): FirmwareUpdateV4Target[] {
|
|
902
|
+
if (this.params.targetsToUpdate?.length) {
|
|
903
|
+
return [...new Set(this.params.targetsToUpdate)];
|
|
904
|
+
}
|
|
905
|
+
const targets = new Set<FirmwareUpdateV4Target>();
|
|
906
|
+
Object.keys(this.params.componentArtifacts ?? {}).forEach(target =>
|
|
907
|
+
targets.add(target as FirmwareUpdateV4Target)
|
|
908
|
+
);
|
|
909
|
+
if (this.params.resourceBundleArtifacts?.length || this.params.resourceBundleFiles?.length) {
|
|
910
|
+
targets.add('resource');
|
|
911
|
+
}
|
|
912
|
+
if (this.params.bootloaderBinary) targets.add('boot');
|
|
913
|
+
if (this.params.applicationP1Binary) targets.add('app_v1');
|
|
914
|
+
if (this.params.applicationP2Binary) targets.add('app_v2');
|
|
915
|
+
if (this.params.coprocessorBinary) targets.add('coprocessor');
|
|
916
|
+
if (this.params.se01Binary) targets.add('se01');
|
|
917
|
+
if (this.params.se02Binary) targets.add('se02');
|
|
918
|
+
if (this.params.se03Binary) targets.add('se03');
|
|
919
|
+
if (this.params.se04Binary) targets.add('se04');
|
|
920
|
+
return Array.from(targets);
|
|
544
921
|
}
|
|
545
922
|
|
|
546
923
|
private async getProtocolV2DeviceFeatures(): Promise<Features> {
|
|
@@ -576,7 +953,16 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
576
953
|
private async captureProtocolV2PhysicalIdentity() {
|
|
577
954
|
const deviceInfo = await this.requestProtocolV2PhysicalIdentity();
|
|
578
955
|
const serialNumber = this.getProtocolV2SerialNumber(deviceInfo);
|
|
579
|
-
|
|
956
|
+
if (this.params?.preparedPlan) {
|
|
957
|
+
assertFirmwareUpdatePreparedPlanDeviceIdentity({
|
|
958
|
+
preparedPlan: this.params.preparedPlan,
|
|
959
|
+
deviceIdentity: serialNumber,
|
|
960
|
+
});
|
|
961
|
+
} else if (this.params?.expectedDeviceId) {
|
|
962
|
+
assertProtocolV2ReconnectIdentity(this.params?.expectedDeviceId, serialNumber);
|
|
963
|
+
} else {
|
|
964
|
+
assertProtocolV2ReconnectIdentity(serialNumber, serialNumber);
|
|
965
|
+
}
|
|
580
966
|
this.protocolV2ExpectedSerialNumber = serialNumber;
|
|
581
967
|
}
|
|
582
968
|
|
|
@@ -829,98 +1215,47 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
829
1215
|
})) as ProtocolV2ResourceBundleBinary[];
|
|
830
1216
|
}
|
|
831
1217
|
|
|
832
|
-
private async
|
|
1218
|
+
private async materializeProtocolV2ResourceBundles(
|
|
833
1219
|
bundles: ProtocolV2ResourceBundleBinary[]
|
|
834
1220
|
): Promise<ProtocolV2ResourceBundleBinary[]> {
|
|
835
|
-
const prefetched: ProtocolV2ResourceBundleBinary[] = [];
|
|
836
1221
|
for (const bundle of bundles) {
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
1222
|
+
if (bundle.binary.byteLength === 0 && bundle.url) {
|
|
1223
|
+
if (
|
|
1224
|
+
this.params.artifactReader ||
|
|
1225
|
+
DataManager.getSettings('firmwareManifestMode') === 'external-only'
|
|
1226
|
+
) {
|
|
1227
|
+
throw ERRORS.TypedError(
|
|
1228
|
+
HardwareErrorCode.RuntimeError,
|
|
1229
|
+
`Firmware resource bundle ${bundle.name} is not prepared`,
|
|
1230
|
+
{
|
|
1231
|
+
firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
|
|
1232
|
+
artifactName: bundle.name,
|
|
1233
|
+
}
|
|
1234
|
+
);
|
|
841
1235
|
}
|
|
842
|
-
Log.log(`[FirmwareUpdateV4]
|
|
843
|
-
|
|
844
|
-
}
|
|
845
|
-
if (binary.byteLength === 0) {
|
|
846
|
-
throw new Error(`Protocol V2 RESC bundle is empty: ${bundle.name}`);
|
|
1236
|
+
Log.log(`[FirmwareUpdateV4] preloading RESC bundle ${bundle.name}`);
|
|
1237
|
+
bundle.binary = (await getSysResourceBinary(bundle.url)).binary;
|
|
847
1238
|
}
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
/**
|
|
854
|
-
* Synchronize RESC bundles to the device.
|
|
855
|
-
*
|
|
856
|
-
* Manual mode writes supplied binaries directly.
|
|
857
|
-
* Remote-config mode uses prefetched binaries and skips matching bundles after FileRead.
|
|
858
|
-
*/
|
|
859
|
-
private async syncProtocolV2ResourceBundles(
|
|
860
|
-
bundles: ProtocolV2ResourceBundleBinary[],
|
|
861
|
-
firmwareSize: number
|
|
862
|
-
): Promise<{ processedSize: number; totalSize: number }> {
|
|
863
|
-
const transferStartTime = Date.now();
|
|
864
|
-
const transferTransport = this.getProtocolV2FirmwareTransferTransport();
|
|
865
|
-
|
|
866
|
-
const isRemoteMode = bundles.some(bundle => !!bundle.url);
|
|
867
|
-
let bundlesToSync = bundles;
|
|
868
|
-
|
|
869
|
-
// Remote binaries were prefetched before bootloader entry. Only device-local
|
|
870
|
-
// header comparison and transfer are allowed in this phase.
|
|
871
|
-
if (isRemoteMode) {
|
|
872
|
-
const filtered: ProtocolV2ResourceBundleBinary[] = [];
|
|
873
|
-
for (const bundle of bundles) {
|
|
874
|
-
// Compare the existing device header.
|
|
875
|
-
const upToDate = await this.isProtocolV2ResourceBundleUpToDate(bundle);
|
|
876
|
-
if (upToDate) {
|
|
877
|
-
Log.log(`[FirmwareUpdateV4] skip RESC bundle ${bundle.name}; already up to date`);
|
|
878
|
-
} else {
|
|
879
|
-
filtered.push(bundle);
|
|
880
|
-
}
|
|
1239
|
+
if (bundle.binary.byteLength === 0) {
|
|
1240
|
+
throw ERRORS.TypedError(
|
|
1241
|
+
HardwareErrorCode.FirmwareUpdateDownloadFailed,
|
|
1242
|
+
`Protocol V2 RESC bundle is empty: ${bundle.name}`
|
|
1243
|
+
);
|
|
881
1244
|
}
|
|
882
|
-
bundlesToSync = filtered;
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
if (bundlesToSync.length === 0) {
|
|
886
|
-
Log.log('[FirmwareUpdateV4] all RESC bundles up to date, nothing to sync');
|
|
887
|
-
return { processedSize: 0, totalSize: firmwareSize };
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
// Write directly to the device through FileWrite.
|
|
891
|
-
let totalSize = 0;
|
|
892
|
-
for (const b of bundlesToSync) totalSize += b.binary.byteLength;
|
|
893
|
-
|
|
894
|
-
const transferTotalSize = totalSize + firmwareSize;
|
|
895
|
-
let processedSize = 0;
|
|
896
|
-
for (const bundle of bundlesToSync) {
|
|
897
|
-
Log.log(
|
|
898
|
-
`[FirmwareUpdateV4] syncing RESC bundle ${bundle.name} -> ${bundle.devicePath} bytes=${bundle.binary.byteLength}`
|
|
899
|
-
);
|
|
900
|
-
processedSize = await this.protocolV2CommonUpdateProcess({
|
|
901
|
-
payload: bundle.binary,
|
|
902
|
-
filePath: bundle.devicePath,
|
|
903
|
-
processedSize,
|
|
904
|
-
totalSize: transferTotalSize,
|
|
905
|
-
});
|
|
906
1245
|
}
|
|
907
|
-
|
|
908
|
-
const elapsedMs = Date.now() - transferStartTime;
|
|
909
|
-
Log.log(
|
|
910
|
-
`[FirmwareUpdateV4] RESC bundle sync finished transport=${transferTransport} bytes=${totalSize} elapsed=${(
|
|
911
|
-
elapsedMs / 1000
|
|
912
|
-
).toFixed(2)}s speed=${formatProtocolV2TransferSpeed(totalSize, elapsedMs)} KB/s`
|
|
913
|
-
);
|
|
914
|
-
return { processedSize, totalSize: transferTotalSize };
|
|
1246
|
+
return bundles;
|
|
915
1247
|
}
|
|
916
1248
|
|
|
917
1249
|
/**
|
|
918
1250
|
* Compare the existing okpkg OKPP header in remote-config mode.
|
|
919
1251
|
*/
|
|
920
1252
|
private async isProtocolV2ResourceBundleUpToDate(
|
|
921
|
-
bundle:
|
|
1253
|
+
bundle: Pick<
|
|
1254
|
+
ProtocolV2ResourceBundleBinary,
|
|
1255
|
+
'name' | 'devicePath' | 'version' | 'payloadHash' | 'headerHash'
|
|
1256
|
+
>
|
|
922
1257
|
): Promise<boolean> {
|
|
923
|
-
if (this.params
|
|
1258
|
+
if (this.params?.forcedUpdateRes) return false;
|
|
924
1259
|
if (!bundle.version && !bundle.payloadHash) return false;
|
|
925
1260
|
|
|
926
1261
|
try {
|
|
@@ -958,6 +1293,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
958
1293
|
// It rejects DeviceRebootType.Bootloader, so reuse the current connection.
|
|
959
1294
|
if (this.isProtocolV2BootloaderMode() || this.device.features?.mode === 'romloader') {
|
|
960
1295
|
Log.debug('Protocol V2 device is already in loader mode, skip reboot to bootloader');
|
|
1296
|
+
this.protocolV2ExecutionInLoader = true;
|
|
961
1297
|
return false;
|
|
962
1298
|
}
|
|
963
1299
|
|
|
@@ -967,6 +1303,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
967
1303
|
this.postTipMessage(FirmwareUpdateTipMessage.GoToBootloaderSuccess);
|
|
968
1304
|
await wait(1000);
|
|
969
1305
|
await this.waitForProtocolV2BootloaderMode();
|
|
1306
|
+
this.protocolV2ExecutionInLoader = true;
|
|
970
1307
|
return true;
|
|
971
1308
|
} catch (error) {
|
|
972
1309
|
if (error instanceof HardwareError) {
|
|
@@ -1055,6 +1392,98 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1055
1392
|
return entries;
|
|
1056
1393
|
}
|
|
1057
1394
|
|
|
1395
|
+
private buildProtocolV2ExecutionPhases({
|
|
1396
|
+
installSources,
|
|
1397
|
+
resourceSources,
|
|
1398
|
+
}: {
|
|
1399
|
+
installSources: ProtocolV2InstallSource[];
|
|
1400
|
+
resourceSources: ProtocolV2ResourceBundleSource[];
|
|
1401
|
+
}): ProtocolV2ExecutionPhase[] {
|
|
1402
|
+
const phases: ProtocolV2ExecutionPhase[] = [];
|
|
1403
|
+
if (resourceSources.length > 0) {
|
|
1404
|
+
phases.push({
|
|
1405
|
+
kind: 'resource-sync',
|
|
1406
|
+
installSources: [],
|
|
1407
|
+
resourceSources,
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
const bootloaderSources = installSources.filter(source => source.kind === 'bootloader');
|
|
1411
|
+
if (bootloaderSources.length > 0) {
|
|
1412
|
+
phases.push(
|
|
1413
|
+
{
|
|
1414
|
+
kind: 'bootloader-install',
|
|
1415
|
+
installSources: bootloaderSources,
|
|
1416
|
+
resourceSources: [],
|
|
1417
|
+
},
|
|
1418
|
+
{
|
|
1419
|
+
kind: 'bootloader-verify',
|
|
1420
|
+
installSources: [],
|
|
1421
|
+
resourceSources: [],
|
|
1422
|
+
}
|
|
1423
|
+
);
|
|
1424
|
+
}
|
|
1425
|
+
const componentSources = installSources.filter(source => source.kind !== 'bootloader');
|
|
1426
|
+
if (componentSources.length > 0) {
|
|
1427
|
+
phases.push({
|
|
1428
|
+
kind: 'component-install',
|
|
1429
|
+
installSources: componentSources,
|
|
1430
|
+
resourceSources: [],
|
|
1431
|
+
});
|
|
1432
|
+
}
|
|
1433
|
+
phases.push({
|
|
1434
|
+
kind: 'final-verify',
|
|
1435
|
+
installSources: [],
|
|
1436
|
+
resourceSources: [],
|
|
1437
|
+
});
|
|
1438
|
+
return phases;
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
private async executeProtocolV2Phases({
|
|
1442
|
+
installSources,
|
|
1443
|
+
resourceSources,
|
|
1444
|
+
}: {
|
|
1445
|
+
installSources: ProtocolV2InstallSource[];
|
|
1446
|
+
resourceSources: ProtocolV2ResourceBundleSource[];
|
|
1447
|
+
}) {
|
|
1448
|
+
const phases = this.buildProtocolV2ExecutionPhases({
|
|
1449
|
+
installSources,
|
|
1450
|
+
resourceSources,
|
|
1451
|
+
});
|
|
1452
|
+
for (const phase of phases) {
|
|
1453
|
+
if (phase.kind === 'final-verify') {
|
|
1454
|
+
return this.completeProtocolV2FinalVerification();
|
|
1455
|
+
}
|
|
1456
|
+
if (phase.kind === 'resource-sync') {
|
|
1457
|
+
await this.enterProtocolV2BootloaderMode();
|
|
1458
|
+
await this.executeProtocolV2TransferPhase(phase);
|
|
1459
|
+
} else if (phase.kind === 'bootloader-install' || phase.kind === 'component-install') {
|
|
1460
|
+
await this.enterProtocolV2BootloaderMode();
|
|
1461
|
+
await this.executeProtocolV2TransferPhase(phase);
|
|
1462
|
+
await this.exitProtocolV2BootloaderToNormal();
|
|
1463
|
+
} else if (phase.kind === 'bootloader-verify') {
|
|
1464
|
+
await this.waitForProtocolV2FinalFeatures();
|
|
1465
|
+
this.assertExpectedProtocolV2Versions(['boot']);
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
throw ERRORS.TypedError(
|
|
1469
|
+
HardwareErrorCode.RuntimeError,
|
|
1470
|
+
'Protocol V2 execution has no final verification phase'
|
|
1471
|
+
);
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
private async executeProtocolV2SourceUpdate({
|
|
1475
|
+
installSources,
|
|
1476
|
+
resourceSources,
|
|
1477
|
+
}: {
|
|
1478
|
+
installSources: ProtocolV2InstallSource[];
|
|
1479
|
+
resourceSources: ProtocolV2ResourceBundleSource[];
|
|
1480
|
+
}) {
|
|
1481
|
+
return this.executeProtocolV2Phases({
|
|
1482
|
+
installSources,
|
|
1483
|
+
resourceSources,
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1058
1487
|
private async executeProtocolV2Update({
|
|
1059
1488
|
fwBinaryMap,
|
|
1060
1489
|
bootloaderBinary,
|
|
@@ -1066,104 +1495,158 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1066
1495
|
installItems?: ProtocolV2InstallItem[];
|
|
1067
1496
|
resourceBundles?: ProtocolV2ResourceBundleBinary[];
|
|
1068
1497
|
}) {
|
|
1069
|
-
const
|
|
1498
|
+
const memoryInstallItems =
|
|
1070
1499
|
installItems ??
|
|
1071
1500
|
this.buildProtocolV2InstallItems({
|
|
1072
|
-
bootloaderBinary: bootloaderBinary ?? null,
|
|
1073
1501
|
fwBinaryMap: fwBinaryMap ?? [],
|
|
1502
|
+
bootloaderBinary: bootloaderBinary ?? null,
|
|
1074
1503
|
});
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
if (resourceBundles?.length) {
|
|
1084
|
-
const resourceTransfer = await this.syncProtocolV2ResourceBundles(
|
|
1085
|
-
resourceBundles,
|
|
1086
|
-
firmwareSize
|
|
1504
|
+
try {
|
|
1505
|
+
const installSources = await Promise.all(
|
|
1506
|
+
memoryInstallItems.map(async item => ({
|
|
1507
|
+
fileName: item.fileName,
|
|
1508
|
+
source: await this.openProtocolV2MemorySource(item.binary),
|
|
1509
|
+
targetId: item.targetId,
|
|
1510
|
+
kind: item.kind,
|
|
1511
|
+
}))
|
|
1087
1512
|
);
|
|
1088
|
-
|
|
1089
|
-
|
|
1513
|
+
const resourceSources = await Promise.all(
|
|
1514
|
+
(resourceBundles ?? []).map(async bundle => ({
|
|
1515
|
+
name: bundle.name,
|
|
1516
|
+
source: await this.openProtocolV2MemorySource(bundle.binary),
|
|
1517
|
+
devicePath: bundle.devicePath,
|
|
1518
|
+
version: bundle.version,
|
|
1519
|
+
payloadHash: bundle.payloadHash,
|
|
1520
|
+
headerHash: bundle.headerHash,
|
|
1521
|
+
}))
|
|
1522
|
+
);
|
|
1523
|
+
return await this.executeProtocolV2Phases({
|
|
1524
|
+
installSources,
|
|
1525
|
+
resourceSources,
|
|
1526
|
+
});
|
|
1527
|
+
} finally {
|
|
1528
|
+
await this.closeProtocolV2PreparedSources();
|
|
1090
1529
|
}
|
|
1530
|
+
}
|
|
1091
1531
|
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1532
|
+
private async executeProtocolV2TransferPhase({
|
|
1533
|
+
installSources,
|
|
1534
|
+
resourceSources,
|
|
1535
|
+
}: ProtocolV2ExecutionPhase) {
|
|
1536
|
+
let totalSize = installSources.reduce((total, item) => total + item.source.size, 0);
|
|
1537
|
+
const resourcesToSync: ProtocolV2ResourceBundleSource[] = [];
|
|
1538
|
+
for (const resource of resourceSources) {
|
|
1539
|
+
if (await this.isProtocolV2ResourceBundleUpToDate(resource)) {
|
|
1540
|
+
Log.log(`[FirmwareUpdateV4] skip RESC bundle ${resource.name}; already up to date`);
|
|
1541
|
+
} else {
|
|
1542
|
+
resourcesToSync.push(resource);
|
|
1543
|
+
totalSize += resource.source.size;
|
|
1097
1544
|
}
|
|
1098
|
-
return;
|
|
1099
1545
|
}
|
|
1100
|
-
let transferredSize = processedSize;
|
|
1101
|
-
const transferStartTime = Date.now();
|
|
1102
|
-
const transferTransport = this.getProtocolV2FirmwareTransferTransport();
|
|
1103
|
-
const chunkSize = this.getProtocolV2FirmwareChunkSize();
|
|
1104
|
-
const onTransferredBytes = (bytes: number) => {
|
|
1105
|
-
transferredSize = bytes;
|
|
1106
|
-
};
|
|
1107
|
-
Log.log(
|
|
1108
|
-
`[FirmwareUpdateV4] transfer started transport=${transferTransport} total=${totalSize} bytes chunk=${chunkSize} bytes`
|
|
1109
|
-
);
|
|
1110
|
-
|
|
1111
|
-
const stagedInstallTargets: ProtocolV2InstallTarget[] = [];
|
|
1112
1546
|
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
processedSize
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
onTransferredBytes,
|
|
1125
|
-
});
|
|
1126
|
-
transferredSize = processedSize;
|
|
1127
|
-
await this.verifyProtocolV2StagedFile(filePath, item.binary.byteLength);
|
|
1128
|
-
|
|
1129
|
-
stagedInstallTargets.push({
|
|
1130
|
-
...item,
|
|
1131
|
-
path: filePath,
|
|
1132
|
-
});
|
|
1133
|
-
}
|
|
1547
|
+
this.postTipMessage(FirmwareUpdateTipMessage.StartTransferData);
|
|
1548
|
+
let processedSize = 0;
|
|
1549
|
+
for (const resource of resourcesToSync) {
|
|
1550
|
+
processedSize = await this.protocolV2SourceUpdateProcess({
|
|
1551
|
+
source: resource.source,
|
|
1552
|
+
filePath: resource.devicePath,
|
|
1553
|
+
processedSize,
|
|
1554
|
+
totalSize,
|
|
1555
|
+
});
|
|
1556
|
+
await this.verifyProtocolV2StagedFile(resource.devicePath, resource.source.size);
|
|
1557
|
+
}
|
|
1134
1558
|
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1559
|
+
const stagedInstallTargets: Array<{ targetId: number; path: string }> = [];
|
|
1560
|
+
for (const item of installSources) {
|
|
1561
|
+
const filePath = this.getProtocolV2InstallItemStagingPath(item);
|
|
1562
|
+
processedSize = await this.protocolV2SourceUpdateProcess({
|
|
1563
|
+
source: item.source,
|
|
1564
|
+
filePath,
|
|
1565
|
+
processedSize,
|
|
1566
|
+
totalSize,
|
|
1567
|
+
});
|
|
1568
|
+
await this.verifyProtocolV2StagedFile(filePath, item.source.size);
|
|
1569
|
+
stagedInstallTargets.push({
|
|
1570
|
+
targetId: item.targetId,
|
|
1571
|
+
path: filePath,
|
|
1572
|
+
});
|
|
1573
|
+
}
|
|
1138
1574
|
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
);
|
|
1145
|
-
} catch (error) {
|
|
1146
|
-
const elapsedMs = Date.now() - transferStartTime;
|
|
1147
|
-
Log.warn(
|
|
1148
|
-
`[FirmwareUpdateV4] transfer failed transport=${transferTransport} bytes=${transferredSize}/${totalSize} elapsed=${(
|
|
1149
|
-
elapsedMs / 1000
|
|
1150
|
-
).toFixed(2)}s speed=${formatProtocolV2TransferSpeed(transferredSize, elapsedMs)} KB/s`
|
|
1151
|
-
);
|
|
1152
|
-
throw error;
|
|
1575
|
+
if (totalSize > 0) {
|
|
1576
|
+
this.postProgressMessage(100, 'transferData');
|
|
1577
|
+
}
|
|
1578
|
+
if (stagedInstallTargets.length === 0) {
|
|
1579
|
+
return;
|
|
1153
1580
|
}
|
|
1154
1581
|
|
|
1155
1582
|
this.postTipMessage(FirmwareUpdateTipMessage.ConfirmOnDevice);
|
|
1156
|
-
|
|
1157
|
-
const allTargets = stagedInstallTargets.map(item => ({
|
|
1583
|
+
const targets = stagedInstallTargets.map(item => ({
|
|
1158
1584
|
target_id: item.targetId,
|
|
1159
1585
|
path: item.path,
|
|
1160
1586
|
}));
|
|
1161
|
-
|
|
1162
|
-
await this.
|
|
1163
|
-
|
|
1587
|
+
await this.protocolV2StartFirmwareUpdate({ targets });
|
|
1588
|
+
await this.waitForProtocolV2FirmwareUpdateComplete(targets);
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
private async protocolV2SourceUpdateProcess({
|
|
1592
|
+
source,
|
|
1593
|
+
filePath,
|
|
1594
|
+
processedSize,
|
|
1595
|
+
totalSize,
|
|
1596
|
+
}: {
|
|
1597
|
+
source: FirmwareByteSource;
|
|
1598
|
+
filePath: string;
|
|
1599
|
+
processedSize: number;
|
|
1600
|
+
totalSize: number;
|
|
1601
|
+
}) {
|
|
1602
|
+
let lastError: unknown;
|
|
1603
|
+
for (let attempt = 1; attempt <= PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT; attempt += 1) {
|
|
1604
|
+
try {
|
|
1605
|
+
await writeFirmwareByteSource({
|
|
1606
|
+
source,
|
|
1607
|
+
chunkSize: this.getProtocolV2FirmwareChunkSize(),
|
|
1608
|
+
write: async ({ data, sourceOffset, length, first }) => {
|
|
1609
|
+
const chunkEnd = sourceOffset + length;
|
|
1610
|
+
const progress = getProtocolV2DeviceTransferProgress(
|
|
1611
|
+
processedSize + sourceOffset,
|
|
1612
|
+
processedSize + chunkEnd,
|
|
1613
|
+
totalSize
|
|
1614
|
+
);
|
|
1615
|
+
const response = await this.fileWriteChunk(
|
|
1616
|
+
filePath,
|
|
1617
|
+
source.size,
|
|
1618
|
+
sourceOffset,
|
|
1619
|
+
data,
|
|
1620
|
+
first,
|
|
1621
|
+
progress
|
|
1622
|
+
);
|
|
1623
|
+
const rawProcessedByte = response.message.processed_byte;
|
|
1624
|
+
const nextOffset = rawProcessedByte === undefined ? chunkEnd : Number(rawProcessedByte);
|
|
1625
|
+
if (!Number.isFinite(nextOffset) || nextOffset !== chunkEnd) {
|
|
1626
|
+
throw ERRORS.TypedError(
|
|
1627
|
+
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
1628
|
+
`invalid processed_byte ${rawProcessedByte} for offset ${sourceOffset}`
|
|
1629
|
+
);
|
|
1630
|
+
}
|
|
1631
|
+
this.postProgressMessage(progress, 'transferData');
|
|
1632
|
+
return length;
|
|
1633
|
+
},
|
|
1634
|
+
});
|
|
1635
|
+
return processedSize + source.size;
|
|
1636
|
+
} catch (error) {
|
|
1637
|
+
lastError = error;
|
|
1638
|
+
if (attempt < PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT) {
|
|
1639
|
+
await this.recoverProtocolV2FileTransfer();
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
throw ERRORS.TypedError(
|
|
1644
|
+
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
1645
|
+
`transfer data error: ${getProtocolV2UnknownErrorText(lastError)}`
|
|
1646
|
+
);
|
|
1164
1647
|
}
|
|
1165
1648
|
|
|
1166
|
-
private getProtocolV2InstallItemStagingPath(item: ProtocolV2InstallItem) {
|
|
1649
|
+
private getProtocolV2InstallItemStagingPath(item: Pick<ProtocolV2InstallItem, 'fileName'>) {
|
|
1167
1650
|
return `${PROTOCOL_V2_FIRMWARE_STAGING_VOLUME}${item.fileName}`;
|
|
1168
1651
|
}
|
|
1169
1652
|
|
|
@@ -1182,7 +1665,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1182
1665
|
|
|
1183
1666
|
private assertProtocolV2TargetStatus(
|
|
1184
1667
|
statusTargets: ProtocolV2FirmwareUpdateStatusTarget[],
|
|
1185
|
-
expectedTargetIds: Set<number
|
|
1668
|
+
expectedTargetIds: Set<number>,
|
|
1669
|
+
expectedPaths = new Map<number, string>()
|
|
1186
1670
|
) {
|
|
1187
1671
|
Log.log(
|
|
1188
1672
|
`[FirmwareUpdateV4] DeviceFirmwareUpdateStatus records=${JSON.stringify(statusTargets)}`
|
|
@@ -1213,10 +1697,47 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1213
1697
|
const matchingTargets = statusTargets.filter(target =>
|
|
1214
1698
|
expectedTargetIds.has(normalizeProtocolV2TargetId(target.target_id) ?? -1)
|
|
1215
1699
|
);
|
|
1700
|
+
const seenTargetIds = new Set<number>();
|
|
1701
|
+
for (const target of matchingTargets) {
|
|
1702
|
+
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
1703
|
+
if (
|
|
1704
|
+
targetId === undefined ||
|
|
1705
|
+
seenTargetIds.has(targetId) ||
|
|
1706
|
+
(target.path && expectedPaths.get(targetId) && target.path !== expectedPaths.get(targetId))
|
|
1707
|
+
) {
|
|
1708
|
+
throw ERRORS.TypedError(
|
|
1709
|
+
HardwareErrorCode.RuntimeError,
|
|
1710
|
+
`Protocol V2 install status conflicts with target ${target.target_id}`
|
|
1711
|
+
);
|
|
1712
|
+
}
|
|
1713
|
+
seenTargetIds.add(targetId);
|
|
1714
|
+
}
|
|
1216
1715
|
const completedTargets = matchingTargets.filter(target =>
|
|
1217
1716
|
isProtocolV2TargetStatusFinished(target.status)
|
|
1218
1717
|
);
|
|
1219
1718
|
if (completedTargets.length === expectedTargetIds.size && expectedTargetIds.size > 0) {
|
|
1719
|
+
for (const target of completedTargets) {
|
|
1720
|
+
const targetId = normalizeProtocolV2TargetId(target.target_id);
|
|
1721
|
+
const payloadVersion = toProtocolV2FiniteNumber(target.payload_version);
|
|
1722
|
+
if (targetId === undefined) {
|
|
1723
|
+
throw ERRORS.TypedError(
|
|
1724
|
+
HardwareErrorCode.RuntimeError,
|
|
1725
|
+
'Protocol V2 completed target identity is invalid'
|
|
1726
|
+
);
|
|
1727
|
+
}
|
|
1728
|
+
const expectedVersion = this.getExpectedProtocolV2TargetVersion(targetId);
|
|
1729
|
+
if (expectedVersion !== undefined && payloadVersion !== undefined) {
|
|
1730
|
+
if (payloadVersion !== expectedVersion) {
|
|
1731
|
+
throw ERRORS.TypedError(
|
|
1732
|
+
HardwareErrorCode.FirmwareVerificationFailed,
|
|
1733
|
+
`Protocol V2 target ${targetId} reached payload version ${payloadVersion}, expected ${expectedVersion}`
|
|
1734
|
+
);
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
if (payloadVersion !== undefined) {
|
|
1738
|
+
this.protocolV2CompletedTargetVersions.set(targetId, payloadVersion);
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1220
1741
|
this.postProgressMessage(100, 'installingFirmware');
|
|
1221
1742
|
return true;
|
|
1222
1743
|
}
|
|
@@ -1240,7 +1761,9 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1240
1761
|
private async waitForProtocolV2FirmwareUpdateComplete(
|
|
1241
1762
|
targets: Array<{ target_id: number; path: string }>
|
|
1242
1763
|
) {
|
|
1764
|
+
this.protocolV2FinalStatusVerified = false;
|
|
1243
1765
|
const expectedTargetIds = new Set(targets.map(target => target.target_id));
|
|
1766
|
+
const expectedPaths = new Map(targets.map(target => [target.target_id, target.path]));
|
|
1244
1767
|
const startTime = Date.now();
|
|
1245
1768
|
let lastError: unknown;
|
|
1246
1769
|
|
|
@@ -1264,9 +1787,11 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1264
1787
|
if (
|
|
1265
1788
|
this.assertProtocolV2TargetStatus(
|
|
1266
1789
|
(statusResponse.message.records ?? []) as ProtocolV2FirmwareUpdateStatusTarget[],
|
|
1267
|
-
expectedTargetIds
|
|
1790
|
+
expectedTargetIds,
|
|
1791
|
+
expectedPaths
|
|
1268
1792
|
)
|
|
1269
1793
|
) {
|
|
1794
|
+
this.protocolV2FinalStatusVerified = true;
|
|
1270
1795
|
return;
|
|
1271
1796
|
}
|
|
1272
1797
|
lastError = new Error('Protocol V2 firmware targets are still installing');
|
|
@@ -1281,10 +1806,34 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1281
1806
|
// device already rebooted into App, this endpoint error signals that the
|
|
1282
1807
|
// install phase ended; the later phase performs the final readiness check.
|
|
1283
1808
|
if (isProtocolV2FirmwareStatusEndpointUnavailable(error)) {
|
|
1284
|
-
|
|
1285
|
-
|
|
1809
|
+
try {
|
|
1810
|
+
const deviceInfo = await requestProtocolV2DeviceInfo({
|
|
1811
|
+
commands: this.device.getCommands(),
|
|
1812
|
+
timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT,
|
|
1813
|
+
});
|
|
1814
|
+
this.assertProtocolV2DeviceInfoIdentity(deviceInfo);
|
|
1815
|
+
const observed = await this.device.probeProtocolV2RuntimeState(
|
|
1816
|
+
deviceInfo,
|
|
1817
|
+
PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT
|
|
1818
|
+
);
|
|
1819
|
+
if (observed.mode === 'normal' && !observed.bootloaderMode) {
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1822
|
+
lastError = new Error(
|
|
1823
|
+
'Protocol V2 status endpoint is unavailable outside normal mode'
|
|
1824
|
+
);
|
|
1825
|
+
} catch (probeError) {
|
|
1826
|
+
lastError = probeError;
|
|
1827
|
+
}
|
|
1828
|
+
throw ERRORS.TypedError(
|
|
1829
|
+
HardwareErrorCode.RuntimeError,
|
|
1830
|
+
`Protocol V2 firmware install status is unavailable: ${this.normalizeErrorMessage(
|
|
1831
|
+
lastError
|
|
1832
|
+
)}`,
|
|
1833
|
+
{
|
|
1834
|
+
firmwareUpdateCode: 'FirmwareInstallStatusUnavailable',
|
|
1835
|
+
}
|
|
1286
1836
|
);
|
|
1287
|
-
return;
|
|
1288
1837
|
}
|
|
1289
1838
|
lastError = error;
|
|
1290
1839
|
Log.log(
|
|
@@ -1300,6 +1849,12 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1300
1849
|
if (error instanceof HardwareError && error.errorCode === HardwareErrorCode.FirmwareError) {
|
|
1301
1850
|
throw error;
|
|
1302
1851
|
}
|
|
1852
|
+
if (
|
|
1853
|
+
error instanceof HardwareError &&
|
|
1854
|
+
error.params?.firmwareUpdateCode === 'FirmwareInstallStatusUnavailable'
|
|
1855
|
+
) {
|
|
1856
|
+
throw error;
|
|
1857
|
+
}
|
|
1303
1858
|
Log.log('Protocol V2 firmware install device readiness probe failed: ', error);
|
|
1304
1859
|
}
|
|
1305
1860
|
await wait(1000);
|
|
@@ -1317,6 +1872,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1317
1872
|
// The connection may still be in bootloader. Request a Normal reboot directly;
|
|
1318
1873
|
// repeating it after an automatic App reboot is idempotent.
|
|
1319
1874
|
await this.protocolV2Reboot(DeviceRebootType.Normal);
|
|
1875
|
+
this.protocolV2ExecutionInLoader = false;
|
|
1320
1876
|
}
|
|
1321
1877
|
|
|
1322
1878
|
private async waitForProtocolV2FinalFeatures() {
|
|
@@ -1327,6 +1883,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1327
1883
|
const bootloaderVersion = getDeviceBootloaderVersion(features).join('.');
|
|
1328
1884
|
const bleVersion = getDeviceBLEFirmwareVersion(features).join('.');
|
|
1329
1885
|
const firmwareVersion = getDeviceFirmwareVersion(features).join('.');
|
|
1886
|
+
this.protocolV2LatestFinalFeatures = features;
|
|
1330
1887
|
if (firmwareVersion === '0.0.0') {
|
|
1331
1888
|
Log.warn(
|
|
1332
1889
|
'Protocol V2 firmware update finished but app firmware version is still 0.0.0. This is allowed for Pro2 debug BLE-only update flows.'
|
|
@@ -1340,6 +1897,17 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1340
1897
|
};
|
|
1341
1898
|
}
|
|
1342
1899
|
|
|
1900
|
+
private async completeProtocolV2FinalVerification() {
|
|
1901
|
+
if (this.protocolV2ExecutionInLoader || this.isProtocolV2BootloaderMode()) {
|
|
1902
|
+
await this.exitProtocolV2BootloaderToNormal();
|
|
1903
|
+
}
|
|
1904
|
+
const versions = await this.waitForProtocolV2FinalFeatures();
|
|
1905
|
+
this.assertExpectedProtocolV2Versions();
|
|
1906
|
+
this.postTipMessage(FirmwareUpdateTipMessage.FirmwareUpdateCompleted);
|
|
1907
|
+
DevicePool.resetState();
|
|
1908
|
+
return versions;
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1343
1911
|
private async waitForProtocolV2ReconnectAndFeatures(timeout: number) {
|
|
1344
1912
|
const startTime = Date.now();
|
|
1345
1913
|
let lastError: unknown;
|
|
@@ -1446,96 +2014,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
|
|
|
1446
2014
|
return this.normalizeErrorMessage(error).includes('Protocol V2 reconnect physical identity');
|
|
1447
2015
|
}
|
|
1448
2016
|
|
|
1449
|
-
private async protocolV2CommonUpdateProcess(params: ProtocolV2FileTransferParams) {
|
|
1450
|
-
let lastError: unknown;
|
|
1451
|
-
for (let attempt = 1; attempt <= PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT; attempt += 1) {
|
|
1452
|
-
try {
|
|
1453
|
-
return await this.protocolV2WriteWholeFile(params);
|
|
1454
|
-
} catch (error) {
|
|
1455
|
-
lastError = error;
|
|
1456
|
-
Log.error(
|
|
1457
|
-
`Protocol V2 file transfer failed path=${params.filePath} attempt=${attempt}/${PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT}; restarting from offset 0`,
|
|
1458
|
-
error
|
|
1459
|
-
);
|
|
1460
|
-
if (attempt === PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT) {
|
|
1461
|
-
break;
|
|
1462
|
-
}
|
|
1463
|
-
await this.recoverProtocolV2FileTransfer();
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
|
|
1467
|
-
throw ERRORS.TypedError(
|
|
1468
|
-
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
1469
|
-
`transfer data error: ${getProtocolV2UnknownErrorText(lastError)}`
|
|
1470
|
-
);
|
|
1471
|
-
}
|
|
1472
|
-
|
|
1473
|
-
private async protocolV2WriteWholeFile({
|
|
1474
|
-
payload,
|
|
1475
|
-
filePath,
|
|
1476
|
-
processedSize,
|
|
1477
|
-
totalSize,
|
|
1478
|
-
onTransferredBytes,
|
|
1479
|
-
}: ProtocolV2FileTransferParams) {
|
|
1480
|
-
const chunkSize = this.getProtocolV2FirmwareChunkSize();
|
|
1481
|
-
let offset = 0;
|
|
1482
|
-
const getUploadProgress = (fileOffset: number) => {
|
|
1483
|
-
if (totalSize !== undefined && processedSize !== undefined) {
|
|
1484
|
-
return Math.min(Math.ceil(((processedSize + fileOffset) / totalSize) * 100), 99);
|
|
1485
|
-
}
|
|
1486
|
-
return Math.min(Math.ceil((fileOffset / payload.byteLength) * 100), 99);
|
|
1487
|
-
};
|
|
1488
|
-
|
|
1489
|
-
while (offset < payload.byteLength) {
|
|
1490
|
-
const chunkEnd = Math.min(offset + chunkSize, payload.byteLength);
|
|
1491
|
-
const chunkLength = chunkEnd - offset;
|
|
1492
|
-
const chunk = payload.slice(offset, chunkEnd);
|
|
1493
|
-
const overwrite = offset === 0;
|
|
1494
|
-
const progress = getProtocolV2DeviceTransferProgress(
|
|
1495
|
-
(processedSize ?? 0) + offset,
|
|
1496
|
-
(processedSize ?? 0) + chunkEnd,
|
|
1497
|
-
totalSize ?? payload.byteLength
|
|
1498
|
-
);
|
|
1499
|
-
|
|
1500
|
-
const writeRes = await this.fileWriteChunk(
|
|
1501
|
-
filePath,
|
|
1502
|
-
payload.byteLength,
|
|
1503
|
-
offset,
|
|
1504
|
-
chunk,
|
|
1505
|
-
overwrite,
|
|
1506
|
-
progress
|
|
1507
|
-
);
|
|
1508
|
-
const rawProcessedByte = writeRes.message.processed_byte;
|
|
1509
|
-
const processedByte = Number(rawProcessedByte);
|
|
1510
|
-
const nextOffset = rawProcessedByte === undefined ? offset + chunkLength : processedByte;
|
|
1511
|
-
if (!Number.isFinite(nextOffset) || nextOffset <= offset || nextOffset > chunkEnd) {
|
|
1512
|
-
throw ERRORS.TypedError(
|
|
1513
|
-
HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
1514
|
-
`invalid processed_byte ${writeRes.message.processed_byte} for offset ${offset}`
|
|
1515
|
-
);
|
|
1516
|
-
}
|
|
1517
|
-
offset = nextOffset;
|
|
1518
|
-
onTransferredBytes?.((processedSize ?? 0) + offset);
|
|
1519
|
-
this.postProgressMessage(getUploadProgress(offset), 'transferData');
|
|
1520
|
-
}
|
|
1521
|
-
|
|
1522
|
-
return totalSize !== undefined ? (processedSize ?? 0) + payload.byteLength : 0;
|
|
1523
|
-
}
|
|
1524
|
-
|
|
1525
|
-
private getProtocolV2FirmwareTransferTransport() {
|
|
1526
|
-
const env = DataManager.getSettings('env');
|
|
1527
|
-
if (env && DataManager.isBleConnect(env)) {
|
|
1528
|
-
return 'BLE';
|
|
1529
|
-
}
|
|
1530
|
-
if (
|
|
1531
|
-
env &&
|
|
1532
|
-
(DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env) || env === 'web')
|
|
1533
|
-
) {
|
|
1534
|
-
return 'WebUSB';
|
|
1535
|
-
}
|
|
1536
|
-
return env ?? 'unknown';
|
|
1537
|
-
}
|
|
1538
|
-
|
|
1539
2017
|
private async fileWriteChunk(
|
|
1540
2018
|
filePath: string,
|
|
1541
2019
|
totalFileSize: number,
|