1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using Antmicro.Renode.Core; 8 using Antmicro.Renode.Core.Extensions; 9 using Antmicro.Renode.Core.Structure.Registers; 10 using Antmicro.Renode.Logging; 11 using Antmicro.Renode.Peripherals.Bus; 12 13 namespace Antmicro.Renode.Peripherals.Miscellaneous 14 { 15 [AllowedTranslations(AllowedTranslation.ByteToDoubleWord)] 16 public class MPFS_SystemServices : IDoubleWordPeripheral, IKnownSize, IProvidesRegisterCollection<DoubleWordRegisterCollection> 17 { MPFS_SystemServices(IMachine machine, IMultibyteWritePeripheral flashMemory, IQuadWordPeripheral mailboxMemory)18 public MPFS_SystemServices(IMachine machine, IMultibyteWritePeripheral flashMemory, IQuadWordPeripheral mailboxMemory) 19 { 20 sysbus = machine.GetSystemBus(this); 21 flash = flashMemory; 22 mailbox = mailboxMemory; 23 registers = new DoubleWordRegisterCollection(this); 24 IRQ = new GPIO(); 25 DefineRegisters(); 26 } 27 ReadDoubleWord(long offset)28 public uint ReadDoubleWord(long offset) 29 { 30 return registers.Read(offset); 31 } 32 WriteDoubleWord(long offset, uint value)33 public void WriteDoubleWord(long offset, uint value) 34 { 35 registers.Write(offset, value); 36 } 37 Reset()38 public void Reset() 39 { 40 registers.Reset(); 41 } 42 43 public GPIO IRQ { get; } 44 45 public long Size => 0x100; 46 47 public ulong SerialNumberLower { get; set; } 48 49 public ulong SerialNumberUpper { get; set; } 50 51 public DoubleWordRegisterCollection RegistersCollection => registers; 52 DefineRegisters()53 private void DefineRegisters() 54 { 55 Registers.ServicesCR.Define(this) 56 .WithFlag(0, out controlRequest) 57 .WithTag("CONTROL_BUSY", 1, 1) 58 .WithTag("CONTROL_ABORT", 2, 1) 59 .WithTag("CONTROL_NOTIFY", 3, 1) 60 .WithReservedBits(4, 12) 61 .WithValueField(16, 7, out command) 62 .WithValueField(23, 9, out commandOffset) 63 .WithWriteCallback((_, __) => 64 { 65 if(!controlRequest.Value) 66 { 67 return; 68 } 69 HandleRequest((Commands)command.Value, (uint)commandOffset.Value); 70 IRQ.Blink(); 71 }) 72 ; 73 74 Registers.ServicesSR.Define(this) 75 .WithTag("STATUS_REQUEST", 0, 1) 76 .WithTag("STATUS_BUSY", 1, 1) 77 .WithTag("STATUS_ABORT", 2, 1) 78 .WithTag("STATUS_NOTIFY", 3, 1) 79 .WithReservedBits(4, 12) 80 .WithEnumField<DoubleWordRegister, RequestResult>(16, 16, FieldMode.Read, valueProviderCallback: (_) => status) 81 ; 82 } 83 HandleRequest(Commands opcode, uint offset)84 private void HandleRequest(Commands opcode, uint offset) 85 { 86 controlRequest.Value = false; 87 status = RequestResult.Success; 88 switch(opcode) 89 { 90 case Commands.SerialNumberService: 91 GenerateSerialNumber(offset); 92 break; 93 case Commands.SPICopy: 94 CopyData(offset); 95 break; 96 default: 97 this.Log(LogLevel.Warning, "Unknown request: {0}", opcode); 98 status = RequestResult.Error; 99 break; 100 } 101 } 102 GenerateSerialNumber(uint offset)103 private void GenerateSerialNumber(uint offset) 104 { 105 // the Serial Number is a 128bit value 106 mailbox.WriteQuadWord(offset, SerialNumberLower); 107 mailbox.WriteQuadWord(offset + 8, SerialNumberUpper); 108 } 109 CopyData(uint offset)110 private void CopyData(uint offset) 111 { 112 var destAddr = mailbox.ReadQuadWord(offset); 113 var srcAddr = mailbox.ReadDoubleWordUsingQuadWord(offset + 8); 114 var nBytes = mailbox.ReadDoubleWordUsingQuadWord(offset + 12); 115 var bytes = flash.ReadBytes(srcAddr, (int)nBytes); 116 sysbus.WriteBytes(bytes, destAddr); 117 } 118 119 private RequestResult status; 120 private IFlagRegisterField controlRequest; 121 private IValueRegisterField command; 122 private IValueRegisterField commandOffset; 123 124 private readonly IMultibyteWritePeripheral flash; 125 private readonly IQuadWordPeripheral mailbox; 126 private readonly IBusController sysbus; 127 private readonly DoubleWordRegisterCollection registers; 128 129 private enum Registers 130 { 131 SoftReset = 0x0, 132 VDetector = 0x4, 133 TVSControl = 0x8, 134 TVSTempA = 0xC, 135 TVSTempB = 0x10, 136 TVSTempC = 0x14, 137 TVSVoltA = 0x18, 138 TVSVoltB = 0x1C, 139 TVSVoltC = 0x20, 140 TVSOutput0 = 0x24, 141 TVSOutput1 = 0x28, 142 TVSTrigger = 0x2C, 143 TrimVDET1P05 = 0x30, 144 TrimVDET1P8 = 0x34, 145 TrimVDET2P5 = 0x38, 146 TrimTVS = 0x3C, 147 TrimGDET1P05 = 0x40, 148 // RESERVED0 = 0x44, 149 // RESERVED1 = 0x48, 150 // RESERVED2 = 0x4C, 151 ServicesCR = 0x50, 152 ServicesSR = 0x54, 153 UserDetectorSR = 0x58, 154 UserDetectorCR = 0x5C, 155 MSSSPICR = 0x60, 156 } 157 158 private enum Commands 159 { 160 SerialNumberService = 0x0, 161 UsercodeService = 0x1, 162 DesignInformationService = 0x2, 163 DesignCertificateService = 0x3, 164 ReadDigestsService = 0x4, 165 QuerySecurityService = 0x5, 166 ReadDebugInformationService = 0x6, 167 ReadENVMParametersService = 0x7, 168 // gap intended 169 NonAuthenticatedPlaintextService = 0x10, 170 AuthenticatedPlaintextService = 0x11, 171 AuthenticatedCiphertextService = 0x12, 172 // gap intended 173 SecureNVMReadService = 0x18, 174 DigitalSignatureRawFormatService = 0x19, 175 DigitalSignatureDERFormatService = 0x1A, 176 // gap intended 177 PUFEmulationService = 0x20, 178 NonceService = 0x21, 179 IAPImageAuthenticationService = 0x22, 180 BitstreamAuthenticationService = 0x23, 181 // gap intended 182 IAPProgramRequestByImageIndex = 0x42, 183 IAPProgramRequestByImageAddress = 0x43, 184 IAPVerifyRequestByImageIndex = 0x44, 185 IAPVerifyRequestByImageAddress = 0x45, 186 AutoUpdateService = 0x46, 187 DigestCheckService = 0x47, 188 // gap intended 189 SPICopy = 0x50, 190 // gap intended 191 ProbeReadDebugService = 0x70, 192 ProbeWriteDebugService = 0x71, 193 LiveProbeChannelAService = 0x72, 194 LiveProbeChannelBService = 0x73, 195 MEMSelectDebugService = 0x74, 196 MEMReadDebugService = 0x75, 197 MEMWriteDebugService = 0x76, 198 APBReadDebugService = 0x77, 199 APBWriteDebugService = 0x78, 200 DebugSnapshotService = 0x79, 201 GenerateOTP = 0x7A, 202 MatchOTP = 0x7B, 203 UnlockDebugPasscodeService = 0x7C, 204 OneWayPasscodeService = 0x7D, 205 TerminateDebug = 0x7E 206 } 207 208 private enum RequestResult 209 { 210 Success = 0, 211 Busy = 0xEF, 212 Error = 0xFF 213 } 214 } 215 } 216