1111import ctypes
1212import mmap
1313import argparse
14- import socketserver
15- import threading
16- import hashlib
17- from urllib .parse import urlparse
18-
19- # Global variable use to sync between log and request services.
20- # When it is true, the adsp is able to start running.
21- start_output = False
22- lock = threading .Lock ()
23-
24- # INADDR_ANY as default
25- HOST = ''
26- PORT_LOG = 9999
27- PORT_REQ = PORT_LOG + 1
28- BUF_SIZE = 4096
29-
30- # Define the command and the max size
31- CMD_LOG_START = "start_log"
32- CMD_DOWNLOAD = "download"
33- MAX_CMD_SZ = 16
34-
35- # Define the header format and size for
36- # transmiting the firmware
37- PACKET_HEADER_FORMAT_FW = 'I 42s 32s'
38- HEADER_SZ = 78
3914
15+ start_output = True
4016
4117logging .basicConfig (level = logging .INFO )
4218log = logging .getLogger ("cavs-fw" )
@@ -666,10 +642,10 @@ def ipc_command(data, ext_data):
666642 dsp .HIPCIDD = ext_data
667643 dsp .HIPCIDR = (1 << 31 ) | ext_data
668644
669- async def _main ( server ):
645+ async def main ( ):
670646 #TODO this bit me, remove the globals, write a little FirmwareLoader class or something to contain.
671647 global hda , sd , dsp , hda_ostream_id , hda_streams
672- global start_output
648+
673649 try :
674650 (hda , sd , dsp , hda_ostream_id ) = map_regs ()
675651 except Exception as e :
@@ -682,14 +658,14 @@ async def _main(server):
682658 if args .log_only :
683659 wait_fw_entered (timeout_s = None )
684660 else :
685- if not fw_file :
661+ if not args . fw_file :
686662 log .error ("Firmware file argument missing" )
687663 sys .exit (1 )
688664
689- load_firmware (fw_file )
665+ load_firmware (args . fw_file )
690666 time .sleep (0.1 )
691667 if not args .quiet :
692- adsp_log ("--\n " , server )
668+ sys . stdout . write ("--\n " )
693669
694670 hda_streams = dict ()
695671
@@ -698,152 +674,14 @@ async def _main(server):
698674 await asyncio .sleep (0.03 )
699675 (last_seq , output ) = winstream_read (last_seq )
700676 if output :
701- adsp_log (output , server )
677+ sys .stdout .write (output )
678+ sys .stdout .flush ()
702679 if not args .log_only :
703680 if dsp .HIPCIDA & 0x80000000 :
704681 dsp .HIPCIDA = 1 << 31 # must ACK any DONE interrupts that arrive!
705682 if dsp .HIPCTDR & 0x80000000 :
706683 ipc_command (dsp .HIPCTDR & ~ 0x80000000 , dsp .HIPCTDD )
707684
708- if server :
709- # Check if the client connection is alive.
710- if not is_connection_alive (server ):
711- lock .acquire ()
712- start_output = False
713- lock .release ()
714-
715- class adsp_request_handler (socketserver .BaseRequestHandler ):
716- """
717- The request handler class for control the actions of server.
718- """
719-
720- def receive_fw (self ):
721- log .info ("Receiving..." )
722- # Receive the header first
723- d = self .request .recv (HEADER_SZ )
724-
725- # Unpacked the header data
726- # Include size(4), filename(42) and MD5(32)
727- header = d [:HEADER_SZ ]
728- total = d [HEADER_SZ :]
729- s = struct .Struct (PACKET_HEADER_FORMAT_FW )
730- fsize , fname , md5_tx_b = s .unpack (header )
731- log .info (f'size:{ fsize } , filename:{ fname } , MD5:{ md5_tx_b } ' )
732-
733- # Receive the firmware. We only receive the specified amount of bytes.
734- while len (total ) < fsize :
735- data = self .request .recv (min (BUF_SIZE , fsize - len (total )))
736- if not data :
737- raise EOFError ("truncated firmware file" )
738- total += data
739-
740- log .info (f"Done Receiving { len (total )} ." )
741-
742- try :
743- with open (fname ,'wb' ) as f :
744- f .write (total )
745- except Exception as e :
746- log .error (f"Get exception { e } during FW transfer." )
747- return None
748-
749- # Check the MD5 of the firmware
750- md5_rx = hashlib .md5 (total ).hexdigest ()
751- md5_tx = md5_tx_b .decode ('utf-8' )
752-
753- if md5_tx != md5_rx :
754- log .error (f'MD5 mismatch: { md5_tx } vs. { md5_rx } ' )
755- return None
756-
757- return fname
758-
759- def handle (self ):
760- global start_output , fw_file
761-
762- cmd = self .request .recv (MAX_CMD_SZ )
763- log .info (f"{ self .client_address [0 ]} wrote: { cmd } " )
764- action = cmd .decode ("utf-8" )
765- log .debug (f'load { action } ' )
766-
767- if action == CMD_DOWNLOAD :
768- self .request .sendall (cmd )
769- recv_file = self .receive_fw ()
770-
771- if recv_file :
772- self .request .sendall ("success" .encode ('utf-8' ))
773- log .info ("Firmware well received. Ready to download." )
774- else :
775- self .request .sendall ("failed" .encode ('utf-8' ))
776- log .error ("Receive firmware failed." )
777-
778- lock .acquire ()
779- fw_file = recv_file
780- start_output = True
781- lock .release ()
782-
783- else :
784- log .error ("incorrect load communitcation!" )
785-
786- class adsp_log_handler (socketserver .BaseRequestHandler ):
787- """
788- The log handler class for grabbing output messages of server.
789- """
790- def run_adsp (self ):
791- self .loop = asyncio .get_event_loop ()
792- self .loop .run_until_complete (_main (self ))
793-
794- def handle (self ):
795- cmd = self .request .recv (MAX_CMD_SZ )
796- log .info (f"{ self .client_address [0 ]} wrote: { cmd } " )
797- action = cmd .decode ("utf-8" )
798- log .debug (f'monitor { action } ' )
799-
800- if action == CMD_LOG_START :
801- global start_output , fw_file
802-
803- self .request .sendall (cmd )
804-
805- log .info (f"Waiting for instruction..." )
806- while start_output is False :
807- time .sleep (1 )
808- if not is_connection_alive (self ):
809- break
810-
811- if fw_file :
812- log .info (f"Loaded FW { fw_file } and running..." )
813- if os .path .exists (fw_file ):
814- self .run_adsp ()
815- log .info ("service complete." )
816- else :
817- log .error ("Cannot find the FW file." )
818-
819- lock .acquire ()
820- start_output = False
821- if fw_file :
822- os .remove (fw_file )
823- fw_file = None
824- lock .release ()
825-
826- else :
827- log .error ("incorrect monitor communitcation!" )
828-
829- log .info ("Wait for next service..." )
830-
831- def is_connection_alive (server ):
832- try :
833- server .request .sendall (b' ' )
834- except (BrokenPipeError , ConnectionResetError ):
835- log .info ("Client is disconnect." )
836- return False
837-
838- return True
839-
840- def adsp_log (output , server ):
841- if server :
842- server .request .sendall (output .encode ("utf-8" ))
843- else :
844- sys .stdout .write (output )
845- sys .stdout .flush ()
846-
847685
848686ap = argparse .ArgumentParser (description = "DSP loader/logger tool" )
849687ap .add_argument ("-q" , "--quiet" , action = "store_true" ,
@@ -854,12 +692,6 @@ def adsp_log(output, server):
854692 help = "Don't load firmware, just show log output" )
855693ap .add_argument ("-n" , "--no-history" , action = "store_true" ,
856694 help = "No current log buffer at start, just new output" )
857- ap .add_argument ("-s" , "--server-addr" ,
858- help = "Specify the only IP address the log server will LISTEN on" )
859- ap .add_argument ("-p" , "--log-port" ,
860- help = "Specify the PORT that the log server to active" )
861- ap .add_argument ("-r" , "--req-port" ,
862- help = "Specify the PORT that the request server to active" )
863695ap .add_argument ("fw_file" , nargs = "?" , help = "Firmware file" )
864696
865697args = ap .parse_args ()
@@ -869,58 +701,8 @@ def adsp_log(output, server):
869701elif args .verbose :
870702 log .setLevel (logging .DEBUG )
871703
872- if args .fw_file :
873- fw_file = args .fw_file
874- else :
875- fw_file = None
876-
877- if args .server_addr :
878- url = urlparse ("//" + args .server_addr )
879-
880- if url .hostname :
881- HOST = url .hostname
882-
883- if url .port :
884- PORT_LOG = int (url .port )
885-
886- if args .log_port :
887- PORT_LOG = int (args .log_port )
888-
889- if args .req_port :
890- PORT_REQ = int (args .req_port )
891-
892- log .info (f"Serve on LOG PORT: { PORT_LOG } REQ PORT: { PORT_REQ } " )
893-
894704if __name__ == "__main__" :
895- # When fw_file is assigned or in log_only mode, it will
896- # not serve as a daemon. That mean it just run load
897- # firmware or read the log directly.
898- if args .fw_file or args .log_only :
899- start_output = True
900- try :
901- asyncio .get_event_loop ().run_until_complete (_main (None ))
902- except KeyboardInterrupt :
903- start_output = False
904- except Exception as e :
905- log .error (e )
906- finally :
907- sys .exit (0 )
908-
909- # Launch the command request service
910- socketserver .TCPServer .allow_reuse_address = True
911- req_server = socketserver .TCPServer ((HOST , PORT_REQ ), adsp_request_handler )
912- req_t = threading .Thread (target = req_server .serve_forever , daemon = True )
913-
914- # Activate the log service which output adsp execution
915- with socketserver .TCPServer ((HOST , PORT_LOG ), adsp_log_handler ) as log_server :
916- try :
917- log .info ("Req server start..." )
918- req_t .start ()
919- log .info ("Log server start..." )
920- log_server .serve_forever ()
921- except KeyboardInterrupt :
922- lock .acquire ()
923- start_output = False
924- lock .release ()
925- log_server .shutdown ()
926- req_server .shutdown ()
705+ try :
706+ asyncio .get_event_loop ().run_until_complete (main ())
707+ except KeyboardInterrupt :
708+ start_output = False
0 commit comments