1
1
import asyncio
2
+ import binascii
2
3
import logging
3
4
import os
4
5
import shlex
5
6
import socket
6
7
import typing as t
8
+ from dataclasses import dataclass
7
9
8
10
from pytest_embedded .log import DuplicateStdoutPopen
9
11
from qemu .qmp import QMPClient
14
16
from .app import QemuApp
15
17
16
18
19
+ @dataclass
20
+ class QemuTarget :
21
+ strap_mode : str
22
+ default_efuse : bytes
23
+
24
+
25
+ QEMU_TARGETS : dict [str , QemuTarget ] = {
26
+ 'esp32' : QemuTarget (
27
+ strap_mode = '0x0F' ,
28
+ default_efuse = binascii .unhexlify (
29
+ '00000000000000000000000000800000000000000000100000000000000000000000000000000000'
30
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
31
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
32
+ '00000000'
33
+ ),
34
+ ),
35
+ 'esp32c3' : QemuTarget (
36
+ strap_mode = '0x02' ,
37
+ default_efuse = binascii .unhexlify (
38
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000c00'
39
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
40
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
41
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
42
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
43
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
44
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
45
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
46
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
47
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
48
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
49
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
50
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
51
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
52
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
53
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
54
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
55
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
56
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
57
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
58
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
59
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
60
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
61
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
62
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
63
+ '000000000000000000000000000000000000000000000000'
64
+ ),
65
+ ),
66
+ 'esp32s3' : QemuTarget (
67
+ strap_mode = '0x07' ,
68
+ default_efuse = binascii .unhexlify (
69
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000c00'
70
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
71
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
72
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
73
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
74
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
75
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
76
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
77
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
78
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
79
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
80
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
81
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
82
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
83
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
84
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
85
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
86
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
87
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
88
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
89
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
90
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
91
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
92
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
93
+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
94
+ '000000000000000000000000000000000000000000000000'
95
+ ),
96
+ ),
97
+ }
98
+
99
+
17
100
class Qemu (DuplicateStdoutPopen ):
18
101
"""
19
102
QEMU class
@@ -26,9 +109,7 @@ class Qemu(DuplicateStdoutPopen):
26
109
QEMU_DEFAULT_ARGS = '-nographic -machine esp32'
27
110
QEMU_DEFAULT_FMT = '-nographic -machine {}'
28
111
29
- QEMU_STRAP_MODE_FMT = '-global driver=esp32.gpio,property=strap_mode,value={}'
30
- QEMU_SERIAL_TCP_FMT = '-serial tcp::{},server,nowait'
31
-
112
+ QEMU_STRAP_MODE_FMT = 'driver={}.gpio,property=strap_mode,value={}'
32
113
QEMU_DEFAULT_QMP_FMT = '-qmp tcp:127.0.0.1:{},server,wait=off'
33
114
34
115
def __init__ (
@@ -37,6 +118,7 @@ def __init__(
37
118
qemu_prog_path : str | None = None ,
38
119
qemu_cli_args : str | None = None ,
39
120
qemu_extra_args : str | None = None ,
121
+ qemu_efuse_path : str | None = None ,
40
122
app : t .Optional ['QemuApp' ] = None ,
41
123
** kwargs ,
42
124
):
@@ -55,11 +137,28 @@ def __init__(
55
137
56
138
qemu_prog_path = qemu_prog_path or self .qemu_prog_name
57
139
140
+ self .current_qemu_executable_path = qemu_prog_path
141
+ self .image_path = image_path
142
+ self .efuse_path = qemu_efuse_path
143
+
58
144
if qemu_cli_args :
59
145
qemu_cli_args = qemu_cli_args .strip ('"' ).strip ("'" )
60
146
qemu_cli_args = shlex .split (qemu_cli_args or self .qemu_default_args )
61
147
qemu_extra_args = shlex .split (qemu_extra_args or '' )
62
148
149
+ if self .efuse_path :
150
+ logging .debug ('The eFuse file will be saved to: %s' , self .efuse_path )
151
+ with open (self .efuse_path , 'wb' ) as f :
152
+ f .write (QEMU_TARGETS [self .app .target ].default_efuse )
153
+ qemu_extra_args += [
154
+ '-global' ,
155
+ self .QEMU_STRAP_MODE_FMT .format (self .app .target , QEMU_TARGETS [self .app .target ].strap_mode ),
156
+ '-drive' ,
157
+ f'file={ self .efuse_path } ,if=none,format=raw,id=efuse' ,
158
+ '-global' ,
159
+ f'driver=nvram.{ self .app .target } .efuse,property=drive,value=efuse' ,
160
+ ]
161
+
63
162
self .qmp_addr = None
64
163
self .qmp_port = None
65
164
@@ -87,6 +186,49 @@ def __init__(
87
186
** kwargs ,
88
187
)
89
188
189
+ def execute_efuse_command (self , command : str ):
190
+ import espefuse
191
+ import pexpect
192
+
193
+ with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as s :
194
+ s .bind (('127.0.0.1' , 0 ))
195
+ _ , available_port = s .getsockname ()
196
+
197
+ run_qemu_command = [
198
+ '-nographic' ,
199
+ '-machine' ,
200
+ self .app .target ,
201
+ '-drive' ,
202
+ f'file={ self .image_path } ,if=mtd,format=raw' ,
203
+ '-global' ,
204
+ self .QEMU_STRAP_MODE_FMT .format (self .app .target , QEMU_TARGETS [self .app .target ].strap_mode ),
205
+ '-drive' ,
206
+ f'file={ self .efuse_path } ,if=none,format=raw,id=efuse' ,
207
+ '-global' ,
208
+ f'driver=nvram.{ self .app .target } .efuse,property=drive,value=efuse' ,
209
+ '-serial' ,
210
+ f'tcp::{ available_port } ,server,nowait' ,
211
+ ]
212
+ try :
213
+ child = pexpect .spawn (self .current_qemu_executable_path , run_qemu_command )
214
+ res = shlex .split (command )
215
+ child .expect ('qemu' )
216
+
217
+ res = [r for r in res if r != '--do-not-confirm' ]
218
+ espefuse .main (
219
+ [
220
+ '--port' ,
221
+ f'socket://localhost:{ available_port } ' ,
222
+ '--before' ,
223
+ 'no_reset' ,
224
+ '--do-not-confirm' ,
225
+ * res ,
226
+ ]
227
+ )
228
+ self ._hard_reset ()
229
+ finally :
230
+ child .terminate ()
231
+
90
232
@property
91
233
def qemu_prog_name (self ):
92
234
if self .app :
0 commit comments