11import asyncio
2+ import binascii
3+ import logging
24import os
35import shlex
46import socket
1214if t .TYPE_CHECKING :
1315 from .app import QemuApp
1416
17+ QEMU_DEFAULT_EFUSE = {
18+ 'esp32' : binascii .unhexlify (
19+ '00000000000000000000000000800000000000000000100000000000000000000000000000000000'
20+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
21+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
22+ '00000000'
23+ ),
24+ 'esp32c3' : binascii .unhexlify (
25+ '00000000000000000000000000000000000000000000000000000000000000000000000000000c00'
26+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
27+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
28+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
29+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
30+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
31+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
32+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
33+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
34+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
35+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
36+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
37+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
38+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
39+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
40+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
41+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
42+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
43+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
44+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
45+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
46+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
47+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
48+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
49+ '00000000000000000000000000000000000000000000000000000000000000000000000000000000'
50+ '000000000000000000000000000000000000000000000000'
51+ ),
52+ }
53+
1554
1655class Qemu (DuplicateStdoutPopen ):
1756 """
@@ -37,6 +76,7 @@ def __init__(
3776 qemu_prog_path : t .Optional [str ] = None ,
3877 qemu_cli_args : t .Optional [str ] = None ,
3978 qemu_extra_args : t .Optional [str ] = None ,
79+ qemu_efuse_path : t .Optional [str ] = None ,
4080 app : t .Optional ['QemuApp' ] = None ,
4181 ** kwargs ,
4282 ):
@@ -55,11 +95,28 @@ def __init__(
5595
5696 qemu_prog_path = qemu_prog_path or self .qemu_prog_name
5797
98+ self .current_qemu_executable_path = qemu_prog_path
99+ self .image_path = image_path
100+ self .efuse_path = qemu_efuse_path
101+
58102 if qemu_cli_args :
59103 qemu_cli_args = qemu_cli_args .strip ('"' ).strip ("'" )
60104 qemu_cli_args = shlex .split (qemu_cli_args or self .qemu_default_args )
61105 qemu_extra_args = shlex .split (qemu_extra_args or '' )
62106
107+ if self .efuse_path :
108+ logging .debug ('The eFuse file will be saved to: %s' , self .efuse_path )
109+ with open (self .efuse_path , 'wb' ) as f :
110+ f .write (QEMU_DEFAULT_EFUSE [self .app .target ])
111+ qemu_extra_args += [
112+ '-global' ,
113+ f'driver={ self .app .target } .gpio,property=strap_mode,value=0x08' ,
114+ '-drive' ,
115+ f'file={ self .efuse_path } ,if=none,format=raw,id=efuse' ,
116+ '-global' ,
117+ f'driver=nvram.{ self .app .target } .efuse,property=drive,value=efuse' ,
118+ ]
119+
63120 self .qmp_addr = None
64121 self .qmp_port = None
65122
@@ -87,6 +144,47 @@ def __init__(
87144 ** kwargs ,
88145 )
89146
147+ def execute_efuse_command (self , command : str ):
148+ import espefuse
149+ import pexpect
150+
151+ with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as s :
152+ s .bind (('127.0.0.1' , 0 ))
153+ _ , available_port = s .getsockname ()
154+
155+ run_qemu_command = [
156+ '-nographic' ,
157+ '-machine' ,
158+ self .app .target ,
159+ '-drive' ,
160+ f'file={ self .image_path } ,if=mtd,format=raw' ,
161+ '-global' ,
162+ f'driver={ self .app .target } .gpio,property=strap_mode,value=0x0f' ,
163+ '-drive' ,
164+ f'file={ self .efuse_path } ,if=none,format=raw,id=efuse' ,
165+ '-global' ,
166+ f'driver=nvram.{ self .app .target } .efuse,property=drive,value=efuse' ,
167+ '-serial' ,
168+ f'tcp::{ available_port } ,server,nowait' ,
169+ ]
170+ try :
171+ child = pexpect .spawn (self .current_qemu_executable_path , run_qemu_command )
172+ res = shlex .split (command )
173+ child .expect ('qemu' )
174+
175+ res = [r for r in res if r != '--do-not-confirm' ]
176+ espefuse .main ([
177+ '--port' ,
178+ f'socket://localhost:{ available_port } ' ,
179+ '--before' ,
180+ 'no_reset' ,
181+ '--do-not-confirm' ,
182+ * res ,
183+ ])
184+ self ._hard_reset ()
185+ finally :
186+ child .terminate ()
187+
90188 @property
91189 def qemu_prog_name (self ):
92190 if self .app :
0 commit comments