423 lines
20 KiB
Python
423 lines
20 KiB
Python
"""
|
|
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)
|