1 // 2 // Copyright (c) 2010-2025 Antmicro 3 // Copyright (c) 2022-2025 Silicon Labs 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 9 using System; 10 using System.Collections.Generic; 11 using Antmicro.Renode.Utilities; 12 using Antmicro.Renode.Exceptions; 13 using Antmicro.Renode.Core.Structure.Registers; 14 using Antmicro.Renode.Peripherals.Bus; 15 using Antmicro.Renode.Peripherals.Memory; 16 using Antmicro.Renode.Peripherals.Miscellaneous; 17 using Antmicro.Renode.Peripherals.Miscellaneous.SiLabs; 18 using Antmicro.Renode.Logging; 19 20 namespace Antmicro.Renode.Peripherals.Miscellaneous.SiLabs 21 { 22 [AllowedTranslations(AllowedTranslation.ByteToDoubleWord | AllowedTranslation.WordToDoubleWord)] 23 public class EFR32xG2_LockbitsData : IDoubleWordPeripheral, IKnownSize 24 { EFR32xG2_LockbitsData(uint size, String cbkeDataCertificate = null, String cbkeDataCaPublicKey = null, String cbkeDataPrivateKey = null, String cbkeDataFlags = null, String securityConfig = null, String installationCodeFlags = null, String installationCodeValue = null, String installationCodeCrc = null, String secureBootloaderKey = null, String cbke283k1DataCertificate = null, String cbke283k1DataCaPublicKey = null, String cbke283k1DataPrivateKey = null, String ccbke283k1DataFlags = null, String bootloadAesKey = null, String signedBootloaderKeyX = null, String signedBootloaderKeyY = null, String threadJoinKey = null, byte threadJoinKeyLength = 0, String nvm3CryptoKey = null, String zWavePrivateKey = null, String zWavePublicKey = null, String zWaveQrCode = null, String zWaveInitialized = null, String zWaveQrCodeExtended = null)25 public EFR32xG2_LockbitsData(uint size, 26 String cbkeDataCertificate = null, 27 String cbkeDataCaPublicKey = null, 28 String cbkeDataPrivateKey = null, 29 String cbkeDataFlags = null, 30 String securityConfig = null, 31 String installationCodeFlags = null, 32 String installationCodeValue = null, 33 String installationCodeCrc = null, 34 String secureBootloaderKey = null, 35 String cbke283k1DataCertificate = null, 36 String cbke283k1DataCaPublicKey = null, 37 String cbke283k1DataPrivateKey = null, 38 String ccbke283k1DataFlags = null, 39 String bootloadAesKey = null, 40 String signedBootloaderKeyX = null, 41 String signedBootloaderKeyY = null, 42 String threadJoinKey = null, 43 byte threadJoinKeyLength = 0, 44 String nvm3CryptoKey = null, 45 String zWavePrivateKey = null, 46 String zWavePublicKey = null, 47 String zWaveQrCode = null, 48 String zWaveInitialized = null, 49 String zWaveQrCodeExtended = null) 50 { 51 if ((size & 0x3) > 0) 52 { 53 throw new ConstructionException("Size must be a multiple of 4"); 54 } 55 this.size = size; 56 57 memory = new byte[size]; 58 for(uint i = 0; i < size; i++) 59 { 60 memory[i] = 0xFF; 61 } 62 63 if (cbkeDataCertificate != null) 64 { 65 ParseHexStringArgument("cbke data certificate", cbkeDataCertificate, 48, (uint)DataOffset.CbkeData); 66 } 67 if (cbkeDataCaPublicKey != null) 68 { 69 ParseHexStringArgument("cbke data public key", cbkeDataCaPublicKey, 22, (uint)DataOffset.CbkeData + 48); 70 } 71 if (cbkeDataPrivateKey != null) 72 { 73 ParseHexStringArgument("cbke data private key", cbkeDataPrivateKey, 21, (uint)DataOffset.CbkeData + 48 + 22); 74 } 75 if (cbkeDataFlags != null) 76 { 77 ParseHexStringArgument("cbke data flags", cbkeDataFlags, 1, (uint)DataOffset.CbkeData + 48 + 22 + 21); 78 } 79 if (securityConfig != null) 80 { 81 ParseHexStringArgument("security config", securityConfig, 2, (uint)DataOffset.SecurityConfig); 82 } 83 if (installationCodeFlags != null) 84 { 85 ParseHexStringArgument("installation code flags", installationCodeFlags, 2, (uint)DataOffset.InstallationCode); 86 } 87 if (installationCodeValue != null) 88 { 89 ParseHexStringArgument("installation code value", installationCodeValue, 16, (uint)DataOffset.InstallationCode + 2); 90 } 91 if (installationCodeCrc != null) 92 { 93 ParseHexStringArgument("installation code CRC", installationCodeCrc, 2, (uint)DataOffset.InstallationCode + 2 + 16); 94 } 95 if (secureBootloaderKey != null) 96 { 97 ParseHexStringArgument("secure bootloader key", secureBootloaderKey, 16, (uint)DataOffset.SecureBootloaderKey); 98 } 99 if (cbke283k1DataCertificate != null) 100 { 101 ParseHexStringArgument("cbke 283k certificate", cbke283k1DataCertificate, 74, (uint)DataOffset.Cbke283k1Data); 102 } 103 if (cbke283k1DataCaPublicKey != null) 104 { 105 ParseHexStringArgument("cbke 283k public key", cbke283k1DataCaPublicKey, 37, (uint)DataOffset.Cbke283k1Data + 74); 106 } 107 if (cbke283k1DataPrivateKey != null) 108 { 109 ParseHexStringArgument("cbke 283k private key", cbke283k1DataPrivateKey, 36, (uint)DataOffset.Cbke283k1Data + 74 + 37); 110 } 111 if (ccbke283k1DataFlags != null) 112 { 113 ParseHexStringArgument("cbke 283k flags", ccbke283k1DataFlags, 1, (uint)DataOffset.Cbke283k1Data + 74 + 37 + 36); 114 } 115 if (bootloadAesKey != null) 116 { 117 ParseHexStringArgument("bootloader AES key", bootloadAesKey, 16, (uint)DataOffset.BootloadAesKey); 118 } 119 if (signedBootloaderKeyX != null) 120 { 121 ParseHexStringArgument("signed bootloader key X", signedBootloaderKeyX, 32, (uint)DataOffset.SignedBootloaderKeyX); 122 } 123 if (signedBootloaderKeyY != null) 124 { 125 ParseHexStringArgument("signed bootloader key Y", signedBootloaderKeyY, 32, (uint)DataOffset.SignedBootloaderKeyY); 126 } 127 if (threadJoinKey != null) 128 { 129 if (threadJoinKeyLength > 32) 130 { 131 throw new ConstructionException("threadJoinKeyLength > 32"); 132 } 133 ParseHexStringArgument("thread join key", threadJoinKey, threadJoinKeyLength, (uint)DataOffset.ThreadJoinKey); 134 } 135 memory[(uint)DataOffset.ThreadJoinKey + 32] = threadJoinKeyLength; 136 if (nvm3CryptoKey != null) 137 { 138 ParseHexStringArgument("NVM3 crypto key", nvm3CryptoKey, 16, (uint)DataOffset.Nvm3CryptoKey); 139 } 140 if (zWavePrivateKey != null) 141 { 142 ParseHexStringArgument("Z-Wave private key", zWavePrivateKey, 32, (uint)DataOffset.ZWavePrivateKey); 143 } 144 if (zWavePublicKey != null) 145 { 146 ParseHexStringArgument("Z-Wave public key", zWavePublicKey, 32, (uint)DataOffset.ZWavePublicKey); 147 } 148 if (zWaveQrCode != null) 149 { 150 ParseHexStringArgument("Z-Wave QR code", zWaveQrCode, 90, (uint)DataOffset.ZWaveQrCode); 151 } 152 if (zWaveInitialized != null) 153 { 154 ParseHexStringArgument("Z-Wave initialized", zWaveInitialized, 1, (uint)DataOffset.ZWaveInitialized); 155 } 156 if (zWaveQrCodeExtended != null) 157 { 158 ParseHexStringArgument("Z-Wave QR code extended", zWaveQrCodeExtended, 90, (uint)DataOffset.ZWaveQrCodeExtended); 159 } 160 } 161 Reset()162 public void Reset() 163 { 164 } 165 ReadDoubleWord(long offset)166 public uint ReadDoubleWord(long offset) 167 { 168 if ((offset & 0x3) > 0) 169 { 170 this.Log(LogLevel.Error, "ReadDoubleWord: Offset must be a multiple of 4"); 171 return 0; 172 } 173 174 uint ret = (memory[offset] 175 | ((uint)memory[offset + 1] << 8) 176 | ((uint)memory[offset + 2] << 16) 177 | ((uint)memory[offset + 3] << 24)); 178 return ret; 179 } 180 WriteDoubleWord(long offset, uint value)181 public void WriteDoubleWord(long offset, uint value) 182 { 183 if ((offset & 0x3) > 0) 184 { 185 this.Log(LogLevel.Error, "WriteDoubleWord: Offset must be a multiple of 4"); 186 return; 187 } 188 189 memory[offset] = (byte)(value & 0xFF); 190 memory[offset + 1] = (byte)((value >> 8) & 0xFF); 191 memory[offset + 2] = (byte)((value >> 16) & 0xFF); 192 memory[offset + 3] = (byte)((value >> 24) & 0xFF); 193 } 194 ParseHexStringArgument(string fieldName, string value, uint expectedLength, uint destinationOffset)195 private void ParseHexStringArgument(string fieldName, string value, uint expectedLength, uint destinationOffset) 196 { 197 byte[] temp; 198 var lengthInBytes = value.Length / 2; 199 200 if(lengthInBytes != expectedLength) 201 { 202 throw new ConstructionException($"Expected `{fieldName}`'s size is {expectedLength} bytes, got {lengthInBytes}"); 203 } 204 try 205 { 206 temp = Misc.HexStringToByteArray(value); 207 } 208 catch 209 { 210 throw new ConstructionException($"Could not parse `{fieldName}`: Expected hexstring, got: \"{value}\""); 211 } 212 213 temp.CopyTo(memory, destinationOffset); 214 } 215 216 217 private uint size; 218 private byte[] memory; 219 public long Size => (long)size; 220 221 private enum DataOffset 222 { 223 CbkeData = 0x204, 224 SecurityConfig = 0x260, 225 InstallationCode = 0x270, 226 SecureBootloaderKey = 0x286, 227 Cbke283k1Data = 0x298, 228 BootloadAesKey = 0x32C, 229 SignedBootloaderKeyX = 0x34C, 230 SignedBootloaderKeyY = 0x36C, 231 ThreadJoinKey = 0x38C, 232 Nvm3CryptoKey = 0x3B0, 233 ZWavePrivateKey = 0x3C0, 234 ZWavePublicKey = 0x3E0, 235 ZWaveQrCode = 0x400, 236 ZWaveInitialized = 0x45C, 237 ZWaveQrCodeExtended = 0x460, 238 } 239 } 240 } 241