25
25
#include "migration/vmstate.h"
26
26
#include "qemu/log.h"
27
27
28
- //#define DEBUG_STM32_FINT
29
- #ifdef DEBUG_STM32_FINT
30
- // NOTE: The usleep() helps the MacOS stdout from freezing when we have a lot of print out
31
- #define DPRINTF (fmt , ...) \
32
- do { printf("STM32F2XX_FINT: " fmt , ## __VA_ARGS__); \
33
- usleep(100); \
34
- } while (0)
35
- #else
36
- #define DPRINTF (fmt , ...)
37
- #endif
28
+ enum RegIndex {
29
+ RI_ACR ,
30
+ RI_KEYR ,
31
+ RI_OPTKEYR ,
32
+ RI_SR ,
33
+ RI_CR ,
34
+ RI_OPTCR ,
35
+ RI_END
36
+ };
38
37
38
+ enum wp_state
39
+ {
40
+ LOCKED ,
41
+ KEY1_OK ,
42
+ UNLOCKED
43
+ };
44
+
45
+ static stm32_reginfo_t stm32f4xx_flashif_reginfo [RI_END ] = {
46
+ [RI_ACR ] = {.mask = 0x1F07 , .unimp_mask = 0x1F07 },
47
+ [RI_KEYR ] = {.mask = UINT32_MAX },
48
+ [RI_OPTKEYR ] = {.unimp_mask = UINT32_MAX },
49
+ [RI_SR ] = {.mask = 0x100F3 , .unimp_mask = 0x100F3 },
50
+ [RI_CR ] = {.mask = 0x8101037F , .unimp_mask = 0x1010304 },
51
+ [RI_OPTCR ] = {.unimp_mask = UINT32_MAX , .reset_val = 0x0FFFAAED },
52
+ };
53
+
54
+ #define KEY1 0x45670123UL
55
+ #define KEY2 0xCDEF89ABUL
56
+
57
+ #define OPTKEY1 0x08192A3BUL
58
+ #define OPTKEY2 0x4C5D6E7FUL
59
+
60
+ static uint32_t sector_boundaries [][2 ] =
61
+ {
62
+ { 0U * KiB , ( 16U * KiB )- 1U },
63
+ { 16U * KiB , ( 32U * KiB )- 1U },
64
+ { 32U * KiB , ( 48U * KiB )- 1U },
65
+ { 48U * KiB , ( 64U * KiB )- 1U },
66
+ { 64U * KiB , (128U * KiB )- 1U },
67
+ {128U * KiB , (256U * KiB )- 1U },
68
+ {256U * KiB , (384U * KiB )- 1U },
69
+ {384U * KiB , (512U * KiB )- 1U },
70
+ {512U * KiB , (640U * KiB )- 1U },
71
+ {640U * KiB , (768U * KiB )- 1U },
72
+ {768U * KiB , (896U * KiB )- 1U },
73
+ {896U * KiB , (1U * MiB )- 1U },
74
+ };
75
+
76
+
77
+ QEMU_BUILD_BUG_MSG (RI_END != STM32_FINT_MAX , "Register index misaligned in " __FILE__ );
39
78
40
79
static uint64_t
41
80
stm32f2xx_fint_read (void * arg , hwaddr offset , unsigned int size )
42
81
{
43
- stm32f2xx_fint * s = arg ;
82
+ STM32F4XX_STRUCT_NAME ( FlashIF ) * s = arg ;
44
83
uint32_t r ;
45
84
46
- offset >>= 2 ;
47
- r = s -> regs [offset ];
85
+ uint32_t index = offset >> 2U ;
86
+ offset &= 0x3 ;
87
+
88
+ switch (index )
89
+ {
90
+ case RI_CR :
91
+ s -> regs .defs .CR .LOCK = (s -> flash_state != UNLOCKED );
92
+ /* FALLTHRU */
93
+ default :
94
+ r = s -> regs .raw [index ];
95
+ break ;
96
+ }
97
+ ADJUST_FOR_OFFSET_AND_SIZE_R (r , size , offset , 0b111 );
48
98
//printf("FINT unit %d reg %x return 0x%x\n", s->periph, (int)offset << 2, r);
49
99
return r ;
50
100
}
51
101
102
+ static void stm32f4xx_flashif_sector_erase (STM32F4XX_STRUCT_NAME (FlashIF ) * s )
103
+ {
104
+ if (s -> regs .defs .CR .LOCK )
105
+ {
106
+ s -> regs .defs .SR .WRPERR = 1 ;
107
+ return ;
108
+ }
109
+ printf ("Erasing flash sector %u\n" , s -> regs .defs .CR .SNB );
110
+ uint32_t (* p )[2 ] = & sector_boundaries [s -> regs .defs .CR .SNB ];
111
+ uint32_t buff = 0xFFFFFFFFU ;
112
+ for (int i = (* p )[0 ]; i <=(* p )[1 ]; i += 4 )
113
+ {
114
+ cpu_physical_memory_write (s -> flash -> addr + i , & buff , 4 );
115
+ }
116
+ }
117
+
52
118
static void
53
119
stm32f2xx_fint_write (void * arg , hwaddr addr , uint64_t data , unsigned int size )
54
120
{
55
- stm32f2xx_fint * s = arg ;
121
+ STM32F4XX_STRUCT_NAME ( FlashIF ) * s = arg ;
56
122
int offset = addr & 0x03 ;
57
123
58
124
addr >>= 2 ;
59
- if (addr > STM32_FINT_MAX ) {
60
- qemu_log_mask (LOG_GUEST_ERROR , "invalid FINT write reg 0x%x\n" ,
61
- (unsigned int )addr << 2 );
62
- return ;
63
- }
125
+ CHECK_BOUNDS_W (addr , data , RI_END , stm32f4xx_flashif_reginfo , "F4xx Flash IF" );
126
+ ADJUST_FOR_OFFSET_AND_SIZE_W (stm32f2xx_fint_read (arg , addr <<2U , 4U ), data , size , offset , 0b111 )
127
+ CHECK_UNIMP_RESVD (data , stm32f4xx_flashif_reginfo , addr );
64
128
65
- switch (size ) {
66
- case 1 :
67
- data = (s -> regs [addr ] & ~(0xff << (offset * 8 ))) | data << (offset * 8 );
68
- break ;
69
- case 2 :
70
- data = (s -> regs [addr ] & ~(0xffff << (offset * 8 ))) | data << (offset * 8 );
71
- break ;
72
- case 4 :
73
- break ;
74
- default :
75
- abort ();
129
+ if (s -> flash_state == KEY1_OK && addr != RI_KEYR )
130
+ {
131
+ s -> flash_state = LOCKED ;
76
132
}
77
133
78
134
switch (addr ) {
135
+ case RI_KEYR :
136
+ {
137
+ if (data == KEY1 )
138
+ s -> flash_state = KEY1_OK ;
139
+ else if (data == KEY2 && s -> flash_state == KEY1_OK )
140
+ {
141
+ s -> flash_state = UNLOCKED ;
142
+ printf ("FLASH unlocked!\n" );
143
+ memory_region_set_readonly (s -> flash , false);
144
+ }
145
+ }
146
+ break ;
147
+ case RI_CR :
148
+ {
149
+ REGDEF_NAME (flashif , cr ) r = {.raw = data };
150
+ if ( s -> flash_state != UNLOCKED && !r .LOCK )
151
+ {
152
+ qemu_log_mask (LOG_GUEST_ERROR , __FILE__ ":Guest tried to clear the set-only flask LOCK bit." );
153
+ r .LOCK = 1 ;
154
+ }
155
+ else if (s -> flash_state == UNLOCKED && r .LOCK )
156
+ {
157
+ printf ("FLASH LOCKED\n" );
158
+ memory_region_set_readonly (s -> flash , true);
159
+ s -> flash_state = LOCKED ;
160
+ }
161
+ s -> regs .defs .CR .raw = r .raw ;
162
+ s -> regs .defs .CR .STRT = false;
163
+ if (r .STRT )
164
+ {
165
+ if (r .SER )
166
+ {
167
+ stm32f4xx_flashif_sector_erase (s );
168
+ } //else if (r.PG)
169
+ }
170
+ }
171
+ break ;
79
172
default :
80
173
qemu_log_mask (LOG_UNIMP , "f2xx FINT reg 0x%x:%d write (0x%x) unimplemented\n" ,
81
174
(int )addr << 2 , offset , (int )data );
82
- s -> regs [addr ] = data ;
175
+ s -> regs . raw [addr ] = data ;
83
176
break ;
84
177
}
85
178
}
@@ -97,27 +190,34 @@ static const MemoryRegionOps stm32f2xx_fint_ops = {
97
190
static void
98
191
stm32f2xx_fint_reset (DeviceState * dev )
99
192
{
100
- stm32f2xx_fint * s = STM32F2XX_FINT (dev );
101
- s -> regs [STM32_FINT_CR ] = 0x80000000 ;
102
- s -> regs [STM32_FINT_OPTCR ] = 0x0FFFAAED ;
193
+ STM32F4XX_STRUCT_NAME (FlashIF ) * s = STM32F4xx_FINT (dev );
194
+ s -> flash_state = LOCKED ;
195
+ if (s -> flash )
196
+ {
197
+ memory_region_set_readonly (s -> flash , true);
198
+ }
199
+ for (int i = 0 ; i < RI_END ; i ++ )
200
+ {
201
+ s -> regs .raw [i ] = stm32f4xx_flashif_reginfo [i ].reset_val ;
202
+ }
103
203
}
104
204
105
205
static void
106
206
stm32f2xx_fint_init (Object * obj )
107
207
{
108
- stm32f2xx_fint * s = STM32F2XX_FINT (obj );
109
-
110
- memory_region_init_io (& s -> iomem , obj , & stm32f2xx_fint_ops , s , "fint" , 0x400 );
208
+ STM32F4XX_STRUCT_NAME (FlashIF ) * s = STM32F4xx_FINT (obj );
209
+ memory_region_init_io (& s -> iomem , obj , & stm32f2xx_fint_ops , s , "flash_if" , 1U * KiB );
111
210
sysbus_init_mmio (SYS_BUS_DEVICE (obj ), & s -> iomem );
112
211
sysbus_init_irq (SYS_BUS_DEVICE (obj ), & s -> irq );
113
212
}
114
213
115
214
static const VMStateDescription vmstate_stm32f2xx_fint = {
116
- .name = TYPE_STM32F2XX_FINT ,
215
+ .name = TYPE_STM32F4xx_FINT ,
117
216
.version_id = 1 ,
118
217
.minimum_version_id = 1 ,
119
218
.fields = (VMStateField []) {
120
- VMSTATE_UINT32_ARRAY (regs , stm32f2xx_fint ,STM32_FINT_MAX ),
219
+ VMSTATE_UINT32_ARRAY (regs .raw , STM32F4XX_STRUCT_NAME (FlashIF ),STM32_FINT_MAX ),
220
+ VMSTATE_UINT8 (flash_state , STM32F4XX_STRUCT_NAME (FlashIF )),
121
221
VMSTATE_END_OF_LIST ()
122
222
}
123
223
};
@@ -132,9 +232,9 @@ stm32f2xx_fint_class_init(ObjectClass *klass, void *data)
132
232
}
133
233
134
234
static const TypeInfo stm32f2xx_fint_info = {
135
- .name = TYPE_STM32F2XX_FINT ,
136
- .parent = TYPE_SYS_BUS_DEVICE ,
137
- .instance_size = sizeof (stm32f2xx_fint ),
235
+ .name = TYPE_STM32F4xx_FINT ,
236
+ .parent = TYPE_STM32_PERIPHERAL ,
237
+ .instance_size = sizeof (STM32F4XX_STRUCT_NAME ( FlashIF ) ),
138
238
.instance_init = stm32f2xx_fint_init ,
139
239
.class_init = stm32f2xx_fint_class_init
140
240
};
0 commit comments