1111#include <stdint.h>
1212#include <stdio.h>
1313#include <string.h>
14+ #include <sys/wait.h>
1415#include <unistd.h>
1516#include <syslog.h>
1617
1718#include "cdba-server.h"
19+ #include "cdba.h"
1820#include "circ_buf.h"
1921#include "device.h"
2022#include "device_parser.h"
@@ -26,6 +28,26 @@ static const char *username;
2628
2729struct device * selected_device ;
2830
31+ struct edl_file {
32+ struct list_head node ;
33+
34+ int fd ;
35+
36+ char * filename ;
37+ char * target ;
38+ };
39+
40+ static struct list_head edl_files = LIST_INIT (edl_files );
41+
42+ static void edl_present (bool present )
43+ {
44+ uint8_t value = present ? 1 : 0 ;
45+
46+ warnx ("edl is %spresent" , present ? "" : "not " );
47+
48+ cdba_send_buf (MSG_EDL_PRESENT , 1 , & value );
49+ }
50+
2951static void fastboot_opened (struct fastboot * fb , void * data )
3052{
3153 const uint8_t one = 1 ;
@@ -60,6 +82,7 @@ static void msg_select_board(const void *param)
6082 fprintf (stderr , "failed to open %s\n" , (const char * )param );
6183 watch_quit ();
6284 } else {
85+ device_edl_open (selected_device , edl_present );
6386 device_fastboot_open (selected_device , & fastboot_ops );
6487 }
6588
@@ -93,6 +116,123 @@ static void msg_fastboot_download(const void *data, size_t len)
93116 }
94117}
95118
119+ static struct edl_file * current_edl_file ;
120+
121+ static void msg_edl_download (const void * data , size_t len )
122+ {
123+ char template [] = "/tmp/cdba.XXXXXX" ;
124+ struct edl_file * edl ;
125+
126+ edl = current_edl_file ;
127+
128+ if (!edl ) {
129+ edl = calloc (1 , sizeof (* edl ));
130+
131+ edl -> filename = strdup (template );
132+ edl -> fd = mkstemp (edl -> filename );
133+ if (edl -> fd < 0 )
134+ err (1 , "failed to create temporary file" );
135+
136+ list_append (& edl_files , & edl -> node );
137+
138+ current_edl_file = edl ;
139+ }
140+
141+ write (edl -> fd , data , len );
142+
143+ if (len == 0 )
144+ close (edl -> fd );
145+ }
146+
147+ static void msg_edl_flash (const void * data , size_t len )
148+ {
149+ const char * target = data ;
150+
151+ if (!selected_device || !current_edl_file )
152+ return ;
153+
154+ if (!len || target [len - 1 ]) {
155+ fprintf (stderr , "invalid EDL flash target\n" );
156+ watch_quit ();
157+ return ;
158+ }
159+
160+ fprintf (stderr , "edl flash into '%s'\n" , target );
161+
162+ if (!device_qdl_access_allowed (selected_device , username , target )) {
163+ fprintf (stderr , "user '%s' is not allowed to flash EDL target '%s' on %s\n" ,
164+ username , target , selected_device -> board );
165+ watch_quit ();
166+ return ;
167+ }
168+
169+ current_edl_file -> target = strdup (target );
170+ current_edl_file = NULL ;
171+ }
172+
173+ static void msg_edl_reset (void )
174+ {
175+ struct edl_file * edl ;
176+ const char * * argv ;
177+ size_t args ;
178+ size_t arg = 0 ;
179+
180+ fprintf (stderr , "edl reset\n" );
181+
182+ if (!selected_device ) {
183+ fprintf (stderr , "no device selected\n" );
184+ watch_quit ();
185+ return ;
186+ }
187+
188+ if (!selected_device -> qdl_programmer ) {
189+ fprintf (stderr , "no EDL support configured for %s\n" , selected_device -> name );
190+ watch_quit ();
191+ return ;
192+ }
193+
194+ list_for_each_entry (edl , & edl_files , node ) {
195+ if (!edl -> target ) {
196+ fprintf (stderr , "EDL image without flash target\n" );
197+ watch_quit ();
198+ return ;
199+ }
200+ }
201+
202+ args = 7 + list_len (& edl_files ) * 3 + 1 ;
203+ argv = calloc (args , sizeof (char * ));
204+
205+ argv [arg ++ ] = "qdl" ;
206+ argv [arg ++ ] = selected_device -> qdl_programmer ;
207+
208+ if (selected_device -> qdl_storage ) {
209+ argv [arg ++ ] = "--storage" ;
210+ argv [arg ++ ] = selected_device -> qdl_storage ;
211+ }
212+
213+ if (selected_device -> qdl_serial ) {
214+ argv [arg ++ ] = "--serial" ;
215+ argv [arg ++ ] = selected_device -> qdl_serial ;
216+ }
217+
218+ list_for_each_entry (edl , & edl_files , node ) {
219+ argv [arg ++ ] = "write" ;
220+ argv [arg ++ ] = edl -> target ;
221+ argv [arg ++ ] = edl -> filename ;
222+ }
223+ argv [arg ] = NULL ;
224+
225+ if (fork () == 0 ) {
226+ dup2 (STDERR_FILENO , STDOUT_FILENO );
227+ execvp ("qdl" , (char * * )argv );
228+ err (127 , "failed to spawn qdl" );
229+ }
230+ wait (NULL );
231+
232+ list_for_each_entry (edl , & edl_files , node )
233+ unlink (edl -> filename );
234+ }
235+
96236static void msg_fastboot_continue (void )
97237{
98238 device_fastboot_continue (selected_device );
@@ -138,6 +278,7 @@ static int handle_stdin(int fd, void *buf)
138278 static struct circ_buf recv_buf = { };
139279 struct msg * msg ;
140280 struct msg hdr ;
281+ uint8_t mode ;
141282 size_t n ;
142283 int ret ;
143284
@@ -171,12 +312,22 @@ static int handle_stdin(int fd, void *buf)
171312 // fprintf(stderr, "hard reset\n");
172313 break ;
173314 case MSG_POWER_ON :
174- device_power (selected_device , true);
315+ if (msg -> len == 1 )
316+ mode = * (uint8_t * )msg -> data ;
317+ else
318+ mode = MSG_POWER_ON_FASTBOOT ;
319+
320+ if (mode >= MSG_POWER_ON_COUNT ) {
321+ fprintf (stderr , "invalid power on mode requested\n" );
322+ exit (1 );
323+ }
324+
325+ device_power_on (selected_device , mode );
175326
176327 cdba_send (MSG_POWER_ON );
177328 break ;
178329 case MSG_POWER_OFF :
179- device_power (selected_device , false );
330+ device_power_off (selected_device );
180331
181332 cdba_send (MSG_POWER_OFF );
182333 break ;
@@ -210,6 +361,15 @@ static int handle_stdin(int fd, void *buf)
210361 case MSG_KEY_PRESS :
211362 msg_key_press (msg -> data , msg -> len );
212363 break ;
364+ case MSG_EDL_DOWNLOAD :
365+ msg_edl_download (msg -> data , msg -> len );
366+ break ;
367+ case MSG_EDL_WRITE :
368+ msg_edl_flash (msg -> data , msg -> len );
369+ break ;
370+ case MSG_EDL_RESET :
371+ msg_edl_reset ();
372+ break ;
213373 default :
214374 fprintf (stderr , "unk %d len %d\n" , msg -> type , msg -> len );
215375 exit (1 );
0 commit comments