1 //
2 // Copyright (c) 2010-2023 Antmicro
3 //
4 //  This file is licensed under the MIT License.
5 //  Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System;
8 using System.Linq;
9 using System.Collections.Generic;
10 using Antmicro.Renode.Core;
11 using Antmicro.Renode.Core.Structure.Registers;
12 using Antmicro.Renode.Logging;
13 using Antmicro.Renode.Logging.Profiling;
14 using Antmicro.Renode.Peripherals.Bus;
15 using Antmicro.Renode.Peripherals.CPU;
16 using Antmicro.Renode.Peripherals.Memory;
17 
18 namespace Antmicro.Renode.Peripherals.MTD
19 {
20     public abstract class STM32_FlashController : BasicDoubleWordPeripheral
21     {
STM32_FlashController(IMachine machine)22         public STM32_FlashController(IMachine machine) : base(machine)
23         {
24         }
25 
26         protected class LockRegister
27         {
LockRegister(STM32_FlashController owner, string name, uint[] keys, bool unlockedAfterReset = false)28             public LockRegister(STM32_FlashController owner, string name, uint[] keys, bool unlockedAfterReset = false)
29             {
30                 this.owner = owner;
31                 this.name = name;
32                 this.keys = keys;
33                 this.unlockedAfterReset = unlockedAfterReset;
34                 IsLocked = this.unlockedAfterReset ? false : true;
35             }
36 
ConsumeValue(uint value)37             public void ConsumeValue(uint value)
38             {
39                 owner.Log(LogLevel.Debug, "Lock {0} received 0x{1:x8}", name, value);
40                 if(DisabledUntilReset)
41                 {
42                     owner.Log(LogLevel.Debug, "Lock {0} is disabled until reset, ignoring", name);
43                     return;
44                 }
45 
46                 if(keyIndex >= keys.Length || keys[keyIndex] != value)
47                 {
48                     owner.Log(LogLevel.Debug, "Lock {0} now disabled until reset after bad write", name);
49                     Lock();
50                     DisabledUntilReset = true;
51                     return;
52                 }
53 
54                 if(++keyIndex == keys.Length)
55                 {
56                     IsLocked = false;
57                     owner.Log(LogLevel.Debug, "Lock {0} unlocked", name);
58                 }
59             }
60 
Lock()61             public void Lock()
62             {
63                 if(IsLocked)
64                 {
65                     return;
66                 }
67 
68                 owner.Log(LogLevel.Debug, "Lock {0} locked", name);
69                 IsLocked = true;
70                 keyIndex = 0;
71                 Locked?.Invoke();
72             }
73 
Reset()74             public void Reset()
75             {
76                 if(unlockedAfterReset)
77                 {
78                     IsLocked = false;
79                 }
80                 else
81                 {
82                     Lock();
83                 }
84                 DisabledUntilReset = false;
85             }
86 
87             public bool IsLocked { get; private set; }
88             public bool DisabledUntilReset { get; private set; }
89             public event Action Locked;
90 
91             private readonly STM32_FlashController owner;
92             private readonly string name;
93             private readonly uint[] keys;
94             private readonly bool unlockedAfterReset;
95             private int keyIndex;
96         }
97     }
98 }
99