""" BSD 2-Clause License Copyright (c) 2020, Hefei LCFC Information Technology Co.Ltd. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. """ from Lib.lcfc_lib import * from Lib.action_base import ActionBase import shutil import os import subprocess class ActionBuild(ActionBase): # bios_smt Insyde: for SMT and for sign (Windows); Phoenix: for SMT # crisis Insyde only: for sign (crisis) # bios_cap Phoenix only: for sign (Windows and crisis) BUILD_TYPE_NORMAL = '' BUILD_TYPE_DEBUG = '1' BUILD_TYPE_DDT = '2' BUILD_TYPE_DDT_DEBUG = '3' BUILD_TYPE_POST_TIME_PERFORMANCE = '4' BUILD_TYPE_SPECIFIC_DRIVER = '5' BUILD_TYPE_CLEAN = 'C' cmd_list_insyde = { BUILD_TYPE_NORMAL: 'nmake uefi64', BUILD_TYPE_DEBUG: 'nmake efidebug', BUILD_TYPE_DDT: 'nmake uefi64ddt', BUILD_TYPE_DDT_DEBUG: 'nmake debugddt', BUILD_TYPE_POST_TIME_PERFORMANCE: 'nmake uefi64perf', BUILD_TYPE_SPECIFIC_DRIVER: 'nmake uefi64', BUILD_TYPE_CLEAN: 'nmake clean', } cmd_list_phoenix = { BUILD_TYPE_NORMAL: 'PhMake.bat', BUILD_TYPE_DEBUG: 'PhMake.bat TARGET=DEBUG', BUILD_TYPE_SPECIFIC_DRIVER: 'PhMake.bat', BUILD_TYPE_CLEAN: 'PhMake.bat clean', } __psw_crisis_modify_dict = {} __content_orig = '' def __init__(self, build_type, build_id, psw_crisis=False): super().__init__() self.build_type = build_type self.build_id = build_id self.psw_crisis = psw_crisis def pre_work(self, count, action_str): super().pre_work(count, action_str) if self.build_type == ActionBuild.BUILD_TYPE_CLEAN: return # str_start = '##############################LCFC START##############################\n' # str_end = '##############################LCFC END################################\n' # # insyde_file_dict = { # 'Project.env': [ # '[Defines]\n', # str_start, # """# This code is auto generated by tool, please DO NOT modify # EDK_GLOBAL LCFC_ENABLE = YES # EDK_GLOBAL %s= YES # DEFINE LCFC_CC_FLAGS = # DEFINE LCFC_CC_FLAGS = $(LCFC_CC_FLAGS) /D LCFC_ENABLE # DEFINE LCFC_CC_FLAGS = $(LCFC_CC_FLAGS) /D %s\n""" # % (g.project_config['projectflag'] + # ' ' * (26 - len(g.project_config['projectflag']) + len('LCFC_ENABLE')), # g.project_config['projectflag']), # str_end # ], # 'Project.dsc': [ # '[BuildOptions.common.EDKII]\n', # str_start, # """# This code is auto generated by tool, please DO NOT modify # !if $(LCFC_ENABLE) == YES # MSFT:*_*_*_CC_FLAGS = $(LCFC_CC_FLAGS) # MSFT:*_*_*_VFRPP_FLAGS = $(LCFC_CC_FLAGS) # MSFT:*_*_*_ASLPP_FLAGS = $(LCFC_CC_FLAGS) # MSFT:*_*_*_ASLCC_FLAGS = $(LCFC_CC_FLAGS) # MSFT:*_*_*_VFCFPP_FLAGS = $(LCFC_CC_FLAGS) # !endif\n""", # str_end # ], # 'ProjectSetup.bat': [ # '@echo off\n', # '@REM ' + str_start, # """@REM This code is auto generated by tool, please DO NOT modify # set %s=YES\n""" % g.project_config['projectflag'], # '@REM ' + str_end # ] # } # # phoenix_file_dict = { # 'PhMake.bat': [ # '@ECHO OFF\n', # '@REM ' + str_start, # """@REM This code is auto generated by tool, please DO NOT modify # set %s=YES\n""" % g.project_config['projectflag'], # '@REM ' + str_end # ] # } # # file_dict = {} # if g.insyde: # file_dict = insyde_file_dict.items() # process_bios_ver(2) # shutil.copyfile('Project_%s.uni' % g.build_id, 'Project.uni') # elif g.phoenix: # file_dict = phoenix_file_dict.items() # process_bios_ver(2) # shutil.copyfile('project_%s.def' % g.build_id, 'project.def') # for keys, values in file_dict: # try: # with open(keys) as f: # content = f.readlines() # except FileNotFoundError: # error_handle(1, 'Can not find %s' % keys) # self.status = STATUS_ERROR # return # try: # start = content.index(values[1]) # end = content.index(values[3]) # for _ in range(start, end + 1): # content.pop(start) # except ValueError: # pass # insert = False # for _i, _data in enumerate(content): # if _data == values[0]: # content.insert(_i + 1, values[1]) # content.insert(_i + 2, values[2]) # content.insert(_i + 3, values[3]) # insert = True # break # if insert is False: # error_handle(1, 'Can not modify %s, maybe file format updated, please contact tool owner' % keys) # self.status = STATUS_ERROR # return # with open(keys, 'w') as f: # f.writelines(content) psw_crisis_modify_dict = { 'Insyde': [ 'OemConfig.env', 'DEFINE L05_PASSWORD_RESET_CRISIS_BIOS_ENABLE = NO', r'\n\s*DEFINE\s+L05_PASSWORD_RESET_CRISIS_BIOS_ENABLE\s+=\s+NO', r'\n\s*DEFINE\s+L05_PASSWORD_RESET_CRISIS_BIOS_ENABLE\s+=\s+YES', 'NO', 'YES' ], 'Phoenix': [ 'project_%s.def' % g.build_id, 'Option LENOVOOIL_CRISIS_CLEAR_PASSWORD, 0', r'\n\s*Option\s+LENOVOOIL_CRISIS_CLEAR_PASSWORD,\s+0', r'\n\s*Option\s+LENOVOOIL_CRISIS_CLEAR_PASSWORD,\s+1', '0', '1' ] } if self.psw_crisis: self.__psw_crisis_modify_dict = psw_crisis_modify_dict try: with open(psw_crisis_modify_dict[g.project_config['ibv']][0]) as f: self.__content_orig = content = f.read() except FileNotFoundError: self.status = STATUS_ERROR error_handle(1, 'Cannot find ' + psw_crisis_modify_dict[g.project_config['ibv']][0]) return string1 = psw_crisis_modify_dict[g.project_config['ibv']][2] try: string2 = re.search(string1, content).group(0) except AttributeError: self.status = STATUS_ERROR error_handle(1, 'Cannot modify file for password crisis, please make sure %s contain %s' % (psw_crisis_modify_dict[g.project_config['ibv']][0], psw_crisis_modify_dict[g.project_config['ibv']][1])) return string3 = string2.replace(psw_crisis_modify_dict[g.project_config['ibv']][4], psw_crisis_modify_dict[g.project_config['ibv']][5]) content = content.replace(string2, string3) with open(psw_crisis_modify_dict[g.project_config['ibv']][0], 'w') as f: f.write(content) else: try: with open(psw_crisis_modify_dict[g.project_config['ibv']][0]) as f: self.__content_orig = content = f.read() except FileNotFoundError: self.status = STATUS_ERROR error_handle(1, 'Cannot find ' + psw_crisis_modify_dict[g.project_config['ibv']][0]) return string1 = psw_crisis_modify_dict[g.project_config['ibv']][3] if re.search(string1, content): self.status = STATUS_ERROR error_handle(1, 'Error: this is not psw crisis build, but seems your code set to build psw crisis. ' 'Most likely your previous build is psw crisis build and it failed, so tool ' 'was not able to change the code back. Please check the %s' % psw_crisis_modify_dict[g.project_config['ibv']][0]) return if not process_bios_ver(2): error_handle(1, 'Cannot find BIOS version in project folder, maybe you should set the Project Folder?') if g.gui: g.gui_b_1['state'] = tk.NORMAL self.status = STATUS_ERROR return #set ec full version process_ec_ver(2) for _i in os.listdir(os.getcwd()): if os.path.isfile(_i) and '.' in _i: if _i.split('.')[-2][-3:] == '_' + g.build_id: shutil.copyfile(_i, _i.replace('_' + g.build_id, '')) # self.action_output['crisis'] = shutil.copy(r'Tool\Temp\CrisisPsw_Phoenix.cap', # os.path.join(self.output_folder, 'crisis.bin')) def action(self, count, action_str): super().action(count, action_str) if self.status != STATUS_SUCCESS: return self.status if g.insyde: #try to remove bios_smt.bin try_fun_bypass_error(fun = os.remove, passby_error = (FileNotFoundError),arg = r'bios_smt.bin') # try to remove crisis.bin try_fun_bypass_error(fun = os.remove,passby_error = (FileNotFoundError),arg = r'crisis.bin') # try to remove bios_smtxx.bin for path in search(path=g.working_path_abs, name=r"bios_smt\d{1,}.bin"): try_fun_bypass_error(fun = os.remove,passby_error = (FileNotFoundError),arg = path) if ActionBuild.cmd_list_insyde.get(self.build_type) is None: error_handle(1, 'Did not support %s command' % g.argv['BuildId']) self.status = STATUS_ERROR return if DEBUG_MODE: self.action_output['bios_smt'] = shutil.copy(os.path.join(g.tool_path_abs, r'Tool\Temp\BiosMe_Insyde.bin'), os.path.join(self.output_folder, 'bios_smt.bin')) self.action_output['crisis'] = shutil.copy(os.path.join(g.tool_path_abs, r'Tool\Temp\Crisis_Insyde.fd'), os.path.join(self.output_folder, 'crisis.bin')) shutil.copy(os.path.join(g.tool_path_abs, r'Tool\Temp\bios_smt1.bin'), os.path.join(g.working_path_abs, 'bios_smt1.bin')) shutil.copy(os.path.join(g.tool_path_abs, r'Tool\Temp\bios_smt2.bin'), os.path.join(g.working_path_abs, 'bios_smt2.bin')) match_bios_bin = [] for path in search(path = g.working_path_abs,name=r"bios_smt\d{1,}.bin"): print('weiled path =%s'%path) match_bios_bin.append(path) for bios in match_bios_bin: (path,bios_full_name) = os.path.split(bios) (bios_name, extension) = os.path.splitext(bios_full_name) self.action_output[bios_name] = shutil.copy(bios, os.path.join(self.output_folder,bios_full_name)) else: if self.build_type == ActionBuild.BUILD_TYPE_CLEAN: build_cmd = r'ProjectSetup.bat && %s' % ActionBuild.cmd_list_insyde[self.build_type] else: build_cmd = r'ProjectSetup.bat && BuildFsp.cmd /r && %s' \ % ActionBuild.cmd_list_insyde[self.build_type] print(' Build command:', build_cmd) proc = subprocess.Popen(build_cmd, shell=True) g.build_proc = proc proc.communicate() if proc.stdin: proc.stdin.close() if proc.stdout: proc.stdout.close() if proc.stderr: proc.stderr.close() status = proc.returncode if status: self.status = STATUS_ERROR return if self.build_type == ActionBuild.BUILD_TYPE_CLEAN: return try: self.action_output['bios_smt'] = shutil.copy(r'bios_smt.bin', os.path.join(self.output_folder, 'bios_smt.bin')) self.action_output['crisis'] = shutil.copy(r'crisis.bin', os.path.join(self.output_folder, 'crisis.bin')) except FileNotFoundError: error_handle(1, 'Can not find bios_smt.bin or crisis.bin in project folder, maybe you forgot' ' to modify ProjectPostBuild.bat?') self.status = STATUS_ERROR return match_bios_bin = [] for path in search(path = g.working_path_abs,name=r"bios_smt\d{1,}.bin"): match_bios_bin.append(path) for bios in match_bios_bin: (path,bios_full_name) = os.path.split(bios) (bios_name, extension) = os.path.splitext(bios_full_name) self.action_output[bios_name] = shutil.copy(bios, os.path.join(self.output_folder,bios_full_name)) elif g.phoenix: # try to remove bios_smt.bin try_fun_bypass_error(fun = os.remove, passby_error = (FileNotFoundError),arg = r'bios_smt.bin') # try to remove bios_cap.cap try_fun_bypass_error(fun = os.remove,passby_error = (FileNotFoundError),arg = r'bios_cap.cap') #try to remove bios_smtxx.bin for path in search(path=g.working_path_abs, name=r"bios_smt\d{1,}.bin"): try_fun_bypass_error(fun = os.remove,passby_error = (FileNotFoundError),arg = path) if ActionBuild.cmd_list_phoenix.get(self.build_type) is None: error_handle(1, 'Did not support %s command' % g.argv['BuildId']) self.status = STATUS_ERROR return if DEBUG_MODE: print('g.tool_path_abs ='+g.tool_path_abs) self.action_output['bios_smt'] = shutil.copy(os.path.join(g.tool_path_abs, 'Tool','Temp','BiosMe_Phoenix.bin'), os.path.join(self.output_folder, 'bios_smt.bin')) self.action_output['bios_cap'] = shutil.copy(os.path.join(g.tool_path_abs, 'Tool','Temp','BiosMe_Phoenix.cap'), os.path.join(self.output_folder, 'bios_cap.cap')) shutil.copy(os.path.join(g.tool_path_abs, r'Tool\Temp\bios_smt1.bin'), os.path.join(g.working_path_abs, 'bios_smt1.bin')) shutil.copy(os.path.join(g.tool_path_abs, r'Tool\Temp\bios_smt2.bin'), os.path.join(g.working_path_abs, 'bios_smt2.bin')) match_bios_bin = [] for path in search(path = g.working_path_abs,name=r"bios_smt\d{1,}.bin"): match_bios_bin.append(path) for bios in match_bios_bin: (path,bios_full_name) = os.path.split(bios) (bios_name, extension) = os.path.splitext(bios_full_name) self.action_output[bios_name] = shutil.copy(bios, os.path.join(self.output_folder,bios_full_name)) else: build_tool = '' for _i in range(10): build_tool = g.project_config['buildtool' + str(_i)] if os.path.isfile(build_tool): break if _i == 9: error_handle(1, 'Can not find the Visual Studio bat file path for Phoenix code, ' 'please config the ini correctly') self.status = STATUS_ERROR return build_cmd = r'"%s" && %s'\ % (build_tool, ActionBuild.cmd_list_phoenix[self.build_type]) print(' Build command:', build_cmd) #build_cmd = 'subst w:' + build_cmd proc = subprocess.Popen(build_cmd, shell=True) g.build_proc = proc proc.communicate() if proc.stdin: proc.stdin.close() if proc.stdout: proc.stdout.close() if proc.stderr: proc.stderr.close() status = proc.returncode if status: self.status = STATUS_ERROR return if self.build_type == ActionBuild.BUILD_TYPE_CLEAN: return try: self.action_output['bios_smt'] = shutil.copy(r'bios_smt.bin', os.path.join(self.output_folder, 'bios_smt.bin')) self.action_output['bios_cap'] = shutil.copy(r'bios_cap.cap', os.path.join(self.output_folder, 'bios_cap.bin')) except FileNotFoundError: error_handle(1, 'Can not find bios_smt.bin or crisis.bin in project folder, maybe you forgot ' 'to modify Project.mak?') self.status = STATUS_ERROR return match_bios_bin = [] for path in search(path = g.working_path_abs,name=r"bios_smt\d{1,}.bin"): match_bios_bin.append(path) for bios in match_bios_bin: (path,bios_full_name) = os.path.split(bios) (bios_name, extension) = os.path.splitext(bios_full_name) self.action_output[bios_name] = shutil.copy(bios, os.path.join(self.output_folder,bios_full_name)) return def post_work(self, count, action_str): super().post_work(count, action_str) if self.psw_crisis: with open(self.__psw_crisis_modify_dict[g.project_config['ibv']][0], 'w') as f: f.write(self.__content_orig)