1# Copyright (c) 2022 Intel Corporation 2# 3# SPDX-License-Identifier: Apache-2.0 4 5'''Runner for flashing with the Intel ADSP boards.''' 6 7import argparse 8import os 9import sys 10import re 11import hashlib 12import random 13import shutil 14from runners.core import ZephyrBinaryRunner, RunnerCaps 15from zephyr_ext_common import ZEPHYR_BASE 16 17DEFAULT_CAVSTOOL='soc/xtensa/intel_adsp/tools/cavstool_client.py' 18 19class SignParamError(argparse.Action): 20 'User-friendly feedback when trying to sign with west flash' 21 def __call__(self, parser, namespace, values, option_string=None): 22 parser.error(f'Cannot use "west flash {option_string} ..." any more. ' + 23 '"west sign" is now called from CMake, see "west sign -h"') 24 25class IntelAdspBinaryRunner(ZephyrBinaryRunner): 26 '''Runner front-end for the intel ADSP boards.''' 27 28 def __init__(self, 29 cfg, 30 remote_host, 31 pty, 32 tool_opt, 33 ): 34 super().__init__(cfg) 35 36 self.remote_host = remote_host 37 self.bin_fw = os.path.join(cfg.build_dir, 'zephyr', 'zephyr.ri') 38 39 self.cavstool = os.path.join(ZEPHYR_BASE, DEFAULT_CAVSTOOL) 40 self.platform = os.path.basename(cfg.board_dir) 41 self.pty = pty 42 43 self.tool_opt_args = tool_opt 44 45 @classmethod 46 def name(cls): 47 return 'intel_adsp' 48 49 @classmethod 50 def capabilities(cls): 51 return RunnerCaps(commands={'flash'}, tool_opt=True) 52 53 @classmethod 54 def do_add_parser(cls, parser): 55 parser.add_argument('--remote-host', 56 help='hostname of the remote targeting ADSP board') 57 parser.add_argument('--pty', nargs='?', const="remote-host", type=str, 58 help=''''Capture the output of cavstool.py running on --remote-host \ 59 and stream it remotely to west's standard output.''') 60 61 for old_sign_param in [ '--rimage-tool', '--config-dir', '--default-key', '--key']: 62 parser.add_argument(old_sign_param, action=SignParamError, 63 help='do not use, "west sign" is now called from CMake, see "west sign -h"') 64 65 @classmethod 66 def tool_opt_help(cls) -> str: 67 return """Additional options for run/request service tool, 68 e.g. '--lock' """ 69 70 @classmethod 71 def do_create(cls, cfg, args): 72 return IntelAdspBinaryRunner(cfg, 73 remote_host=args.remote_host, 74 pty=args.pty, 75 tool_opt=args.tool_opt, 76 ) 77 78 def do_run(self, command, **kwargs): 79 self.logger.info('Starting Intel ADSP runner') 80 81 if re.search("intel_adsp", self.platform): 82 self.require(self.cavstool) 83 self.flash(**kwargs) 84 else: 85 self.logger.error("No suitable platform for running") 86 sys.exit(1) 87 88 def flash(self, **kwargs): 89 'Generate a hash string for appending to the sending ri file' 90 hash_object = hashlib.md5(self.bin_fw.encode()) 91 random_str = f"{random.getrandbits(64)}".encode() 92 hash_object.update(random_str) 93 send_bin_fw = str(self.bin_fw + "." + hash_object.hexdigest()) 94 shutil.copy(self.bin_fw, send_bin_fw) 95 96 # Copy the zephyr to target remote ADSP host and run 97 self.run_cmd = ([f'{self.cavstool}','-s', f'{self.remote_host}', f'{send_bin_fw}']) 98 99 # Add the extra tool options to run/request service tool 100 if self.tool_opt_args: 101 self.run_cmd = self.run_cmd + self.tool_opt_args 102 103 self.logger.debug(f"rcmd: {self.run_cmd}") 104 105 self.check_call(self.run_cmd) 106 107 # If the self.pty is assigned, the log will output to stdout 108 # directly. That means you don't have to execute the command: 109 # 110 # cavstool_client.py -s {host}:{port} -l 111 # 112 # to get the result later separately. 113 if self.pty is not None: 114 if self.pty == 'remote-host': 115 self.log_cmd = ([f'{self.cavstool}','-s', f'{self.remote_host}', '-l']) 116 else: 117 self.log_cmd = ([f'{self.cavstool}','-s', f'{self.pty}', '-l']) 118 119 self.logger.debug(f"rcmd: {self.log_cmd}") 120 121 self.check_call(self.log_cmd) 122