1 //
2 // Copyright (c) 2010-2022 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.Logging;
8 using System.Collections.Generic;
9 using System.Linq;
10 
11 namespace Antmicro.Renode.Peripherals.Miscellaneous.Crypto
12 {
13     public class InternalMemoryManager
14     {
InternalMemoryManager()15         public InternalMemoryManager()
16         {
17             coreMemories = new Dictionary<long, InternalMemoryAccessor>
18             {
19                 { 0x0, new InternalMemoryAccessor(BERLength, "BER_BE", Endianness.BigEndian) },
20                 { 0x1, new InternalMemoryAccessor(MMRLength, "MMR_BE", Endianness.BigEndian) },
21                 { 0x2, new InternalMemoryAccessor(TSRLength, "TSR_BE", Endianness.BigEndian) },
22                 { 0x3, new InternalMemoryAccessor(FPRLength, "FPR_BE", Endianness.BigEndian) },
23                 { 0x8, new InternalMemoryAccessor(BERLength, "BER_LE", Endianness.LittleEndian) },
24                 { 0x9, new InternalMemoryAccessor(MMRLength, "MMR_LE", Endianness.LittleEndian) },
25                 { 0xA, new InternalMemoryAccessor(TSRLength, "TSR_LE", Endianness.LittleEndian) },
26                 { 0xB, new InternalMemoryAccessor(FPRLength, "FPR_LE", Endianness.LittleEndian) }
27             };
28         }
29 
ResetMemories()30         public void ResetMemories()
31         {
32             foreach(var memory in coreMemories)
33             {
34                 memory.Value.Reset();
35             }
36         }
37 
TryReadDoubleWord(long offset, out uint result)38         public bool TryReadDoubleWord(long offset, out uint result)
39         {
40             if(!TryAddressInternalMemory(offset, out var mem, out var internalOffset))
41             {
42                 result = 0;
43                 return false;
44             }
45             result = mem.ReadDoubleWord(internalOffset);
46             return true;
47         }
48 
TryReadBytes(long offset, int count, out byte[] result)49         public bool TryReadBytes(long offset, int count, out byte[] result)
50         {
51             if(!TryAddressInternalMemory(offset, out var mem, out var internalOffset))
52             {
53                 result = new byte[0];
54                 return false;
55             }
56 
57             result = mem.ReadBytes(internalOffset, count).ToArray();
58             return true;
59         }
60 
TryWriteDoubleWord(long offset, uint value)61         public bool TryWriteDoubleWord(long offset, uint value)
62         {
63             if(!TryAddressInternalMemory(offset, out var mem, out var internalOffset))
64             {
65                 return false;
66             }
67             mem.WriteDoubleWord(internalOffset, value);
68             return true;
69         }
70 
TryWriteBytes(long offset, byte[] bytes)71         public bool TryWriteBytes(long offset, byte[] bytes)
72         {
73             if(!TryAddressInternalMemory(offset, out var mem, out var internalOffset))
74             {
75                 return false;
76             }
77             mem.WriteBytes(internalOffset, bytes);
78             return true;
79         }
80 
TryAddressInternalMemory(long offset, out InternalMemoryAccessor mem, out long internalMemoryOffset)81         private bool TryAddressInternalMemory(long offset, out InternalMemoryAccessor mem, out long internalMemoryOffset)
82         {
83             var offsetMask = offset >> OffsetShift;
84             if(!coreMemories.TryGetValue(offsetMask, out mem))
85             {
86                 internalMemoryOffset = 0;
87                 Logger.Log(LogLevel.Noisy, "Could not write to internal memory at address 0x{0:X}", offset);
88                 return false;
89             }
90             internalMemoryOffset = offset - (offsetMask << OffsetShift);
91             return true;
92         }
93 
94         private readonly Dictionary<long, InternalMemoryAccessor> coreMemories;
95 
96         private const int BERLength = 0x1000;
97         private const int MMRLength = 0x1000;
98         private const int TSRLength = 0x1000;
99         private const int FPRLength = 0x1000;
100         private const int OffsetShift = 12;
101     }
102 }
103