1*91f16700Schasinglulu#!/usr/bin/python3 2*91f16700Schasinglulu# Copyright (c) 2022, Arm Limited. All rights reserved. 3*91f16700Schasinglulu# 4*91f16700Schasinglulu# SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu''' 6*91f16700SchasingluluThis is a python module for defining and executing SP setup actions, targeting 7*91f16700Schasinglulua system deploying an SPM implementation. 8*91f16700SchasingluluEach action consists of a function, that processes the SP layout json file and 9*91f16700Schasingluluother provided arguments. 10*91f16700SchasingluluAt the core of this is the SpSetupActions which provides a means to register 11*91f16700Schasingluluthe functions into a table of actions, and execute them all when invoking 12*91f16700SchasingluluSpSetupActions.run_actions. 13*91f16700SchasingluluRegistering the function is done by using the decorator '@SpSetupActions.sp_action' 14*91f16700Schasingluluat function definition. 15*91f16700Schasinglulu 16*91f16700SchasingluluFunctions can be called: 17*91f16700Schasinglulu- once only, or per SP defined in the SP layout file; 18*91f16700Schasinglulu- following an order, from lowest to highest of their execution order. 19*91f16700SchasingluluMore information in the doc comments below. 20*91f16700Schasinglulu''' 21*91f16700Schasingluluimport bisect 22*91f16700Schasinglulu 23*91f16700SchasingluluDEFAULT_ACTION_ORDER = 100 24*91f16700Schasinglulu 25*91f16700Schasingluluclass _ConfiguredAction: 26*91f16700Schasinglulu """ 27*91f16700Schasinglulu Wraps action function with its configuration. 28*91f16700Schasinglulu """ 29*91f16700Schasinglulu def __init__(self, action, exec_order=DEFAULT_ACTION_ORDER, global_action=True, log_calls = False): 30*91f16700Schasinglulu self.exec_order = exec_order 31*91f16700Schasinglulu self.__name__ = action.__name__ 32*91f16700Schasinglulu def logged_action(action): 33*91f16700Schasinglulu def inner_logged_action(sp_layout, sp, args :dict): 34*91f16700Schasinglulu print(f"Calling {action.__name__} -> {sp}") 35*91f16700Schasinglulu return action(sp_layout, sp, args) 36*91f16700Schasinglulu return inner_logged_action 37*91f16700Schasinglulu self.action = logged_action(action) if log_calls is True else action 38*91f16700Schasinglulu self.global_action = global_action 39*91f16700Schasinglulu 40*91f16700Schasinglulu def __lt__(self, other): 41*91f16700Schasinglulu """ 42*91f16700Schasinglulu To allow for ordered inserts in a list of actions. 43*91f16700Schasinglulu """ 44*91f16700Schasinglulu return self.exec_order < other.exec_order 45*91f16700Schasinglulu 46*91f16700Schasinglulu def __call__(self, sp_layout, sp, args :dict): 47*91f16700Schasinglulu """ 48*91f16700Schasinglulu Calls action function. 49*91f16700Schasinglulu """ 50*91f16700Schasinglulu return self.action(sp_layout, sp, args) 51*91f16700Schasinglulu 52*91f16700Schasinglulu def __repr__(self) -> str: 53*91f16700Schasinglulu """ 54*91f16700Schasinglulu Pretty format to show debug information about the action. 55*91f16700Schasinglulu """ 56*91f16700Schasinglulu return f"func: {self.__name__}; global:{self.global_action}; exec_order: {self.exec_order}" 57*91f16700Schasinglulu 58*91f16700Schasingluluclass SpSetupActions: 59*91f16700Schasinglulu actions = [] 60*91f16700Schasinglulu 61*91f16700Schasinglulu def sp_action(in_action = None, global_action = False, log_calls=False, exec_order=DEFAULT_ACTION_ORDER): 62*91f16700Schasinglulu """ 63*91f16700Schasinglulu Function decorator that registers and configures action. 64*91f16700Schasinglulu 65*91f16700Schasinglulu :param in_action - function to register 66*91f16700Schasinglulu :param global_action - make the function global, i.e. make it be 67*91f16700Schasinglulu only called once. 68*91f16700Schasinglulu :param log_calls - at every call to action, a useful log will be printed. 69*91f16700Schasinglulu :param exec_order - action's calling order. 70*91f16700Schasinglulu """ 71*91f16700Schasinglulu def append_action(action): 72*91f16700Schasinglulu action = _ConfiguredAction(action, exec_order, global_action, log_calls) 73*91f16700Schasinglulu bisect.insort(SpSetupActions.actions, action) 74*91f16700Schasinglulu return action 75*91f16700Schasinglulu if in_action is not None: 76*91f16700Schasinglulu return append_action(in_action) 77*91f16700Schasinglulu return append_action 78*91f16700Schasinglulu 79*91f16700Schasinglulu def run_actions(sp_layout: dict, args: dict, verbose=False): 80*91f16700Schasinglulu """ 81*91f16700Schasinglulu Executes all actions in accordance to their registering configuration: 82*91f16700Schasinglulu - If set as "global" it will be called once. 83*91f16700Schasinglulu - Actions are called respecting the order established by their "exec_order" field. 84*91f16700Schasinglulu 85*91f16700Schasinglulu :param sp_layout - dictionary containing the SP layout information. 86*91f16700Schasinglulu :param args - arguments to be propagated through the call of actions. 87*91f16700Schasinglulu :param verbose - prints actions information in order of execution. 88*91f16700Schasinglulu """ 89*91f16700Schasinglulu args["called"] = [] # for debug purposes 90*91f16700Schasinglulu def append_called(action, sp, args :dict): 91*91f16700Schasinglulu args["called"].append(f"{action.__name__} -> {sp}") 92*91f16700Schasinglulu return args 93*91f16700Schasinglulu 94*91f16700Schasinglulu for action in SpSetupActions.actions: 95*91f16700Schasinglulu if verbose: 96*91f16700Schasinglulu print(f"Calling {action}") 97*91f16700Schasinglulu if action.global_action: 98*91f16700Schasinglulu scope = "global" 99*91f16700Schasinglulu args = action(sp_layout, scope, args) 100*91f16700Schasinglulu args = append_called(action, scope, args) 101*91f16700Schasinglulu else: 102*91f16700Schasinglulu # Functions that are not global called for each SP defined in 103*91f16700Schasinglulu # the SP layout. 104*91f16700Schasinglulu for sp in sp_layout.keys(): 105*91f16700Schasinglulu args = action(sp_layout, sp, args) 106*91f16700Schasinglulu args = append_called(action, sp, args) 107*91f16700Schasinglulu 108*91f16700Schasingluluif __name__ == "__main__": 109*91f16700Schasinglulu # Executing this module will have the following test code/playground executed 110*91f16700Schasinglulu sp_layout = { 111*91f16700Schasinglulu "partition1" : { 112*91f16700Schasinglulu "boot-info": True, 113*91f16700Schasinglulu "image": { 114*91f16700Schasinglulu "file": "partition.bin", 115*91f16700Schasinglulu "offset":"0x2000" 116*91f16700Schasinglulu }, 117*91f16700Schasinglulu "pm": { 118*91f16700Schasinglulu "file": "cactus.dts", 119*91f16700Schasinglulu "offset":"0x1000" 120*91f16700Schasinglulu }, 121*91f16700Schasinglulu "owner": "SiP" 122*91f16700Schasinglulu }, 123*91f16700Schasinglulu "partition2" : { 124*91f16700Schasinglulu "image": "partition.bin", 125*91f16700Schasinglulu "pm": "cactus-secondary.dts", 126*91f16700Schasinglulu "owner": "Plat" 127*91f16700Schasinglulu }, 128*91f16700Schasinglulu "partition3" : { 129*91f16700Schasinglulu "image": "partition.bin", 130*91f16700Schasinglulu "pm": "cactus-tertiary.dts", 131*91f16700Schasinglulu "owner": "Plat" 132*91f16700Schasinglulu }, 133*91f16700Schasinglulu "partition4" : { 134*91f16700Schasinglulu "image": "ivy.bin", 135*91f16700Schasinglulu "pm": "ivy.dts", 136*91f16700Schasinglulu "owner": "Plat" 137*91f16700Schasinglulu } 138*91f16700Schasinglulu } 139*91f16700Schasinglulu 140*91f16700Schasinglulu #Example of how to use this module 141*91f16700Schasinglulu @SpSetupActions.sp_action(global_action=True) 142*91f16700Schasinglulu def my_action1(sp_layout, _, args :dict): 143*91f16700Schasinglulu print(f"inside function my_action1{sp_layout}\n\n args:{args})") 144*91f16700Schasinglulu return args # Always return args in action function. 145*91f16700Schasinglulu @SpSetupActions.sp_action(exec_order=1) 146*91f16700Schasinglulu def my_action2(sp_layout, sp_name, args :dict): 147*91f16700Schasinglulu print(f"inside function my_action2; SP: {sp_name} {sp_layout} args:{args}") 148*91f16700Schasinglulu return args 149*91f16700Schasinglulu 150*91f16700Schasinglulu # Example arguments to be propagated through the functions. 151*91f16700Schasinglulu # 'args' can be extended in the action functions. 152*91f16700Schasinglulu args = dict() 153*91f16700Schasinglulu args["arg1"] = 0xEEE 154*91f16700Schasinglulu args["arg2"] = 0xFF 155*91f16700Schasinglulu SpSetupActions.run_actions(sp_layout, args) 156