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