From nobody Sun May 5 09:25:34 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1531798960515731.2978356734772; Mon, 16 Jul 2018 20:42:40 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 041DF2098877F; Mon, 16 Jul 2018 20:42:40 -0700 (PDT) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 2EAE320988750 for ; Mon, 16 Jul 2018 20:42:37 -0700 (PDT) Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Jul 2018 20:42:37 -0700 Received: from shwde7172.ccr.corp.intel.com ([10.239.158.25]) by fmsmga006.fm.intel.com with ESMTP; 16 Jul 2018 20:42:36 -0700 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.115; helo=mga14.intel.com; envelope-from=liming.gao@intel.com; receiver=edk2-devel@lists.01.org X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,364,1526367600"; d="scan'208";a="246276095" From: Liming Gao To: edk2-devel@lists.01.org Date: Tue, 17 Jul 2018 11:42:21 +0800 Message-Id: <1531798941-8220-1-git-send-email-liming.gao@intel.com> X-Mailer: git-send-email 2.8.0.windows.1 Subject: [edk2] [Patch] BaseTools Script: Add the script to generate Structure PCD setting X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Here is this script usage. 1. Build one platform. 2. Use FCE tool to read HII config from the generated FD image. FCE read -i Platform.fd > Config.txt 3. Call the script to generate StructurePcd setting. ConvertFceToStructurePcd.py -p Build\PlatformPkg\DEBUG_VS2015x86 -c Config.= txt -o OutputDir OutputDir directory have StructurePcd.dec, StructurePcd.dsc, StructurePcd.i= nf. 4. Refer to wiki https://github.com/lgao4/edk2/wiki/StructurePcd-Enable-Ste= ps to enable structure pcd in this platform. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Liming Gao Reviewed-by: Yonghong Zhu =20 --- BaseTools/Scripts/ConvertFceToStructurePcd.py | 675 ++++++++++++++++++++++= ++++ 1 file changed, 675 insertions(+) create mode 100644 BaseTools/Scripts/ConvertFceToStructurePcd.py diff --git a/BaseTools/Scripts/ConvertFceToStructurePcd.py b/BaseTools/Scri= pts/ConvertFceToStructurePcd.py new file mode 100644 index 0000000..6ca51c4 --- /dev/null +++ b/BaseTools/Scripts/ConvertFceToStructurePcd.py @@ -0,0 +1,675 @@ +#!/usr/bin/python +## @file +# Firmware Configuration Editor (FCE) from https://firmware.intel.com/deve= lop +# can parse BIOS image and generate Firmware Configuration file. +# This script bases on Firmware Configuration file, and generate the struc= ture +# PCD setting in DEC/DSC/INF files. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BS= D License +# which accompanies this distribution. The full text of the license may b= e found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. +# + +''' +ConvertFceToStructurePcd +''' + +import re +import os +import datetime +import argparse + +# +# Globals for help information +# +__prog__ =3D 'ConvertFceToStructurePcd' +__version__ =3D '%s Version %s' % (__prog__, '0.1 ') +__copyright__ =3D 'Copyright (c) 2018, Intel Corporation. All rights res= erved.' +__description__ =3D 'Generate Structure PCD in DEC/DSC/INF based on Firmwa= re Configuration.\n' + + +dscstatement=3D'''[Defines] + VPD_TOOL_GUID =3D 8C3D856A-9BE6-468E-850A-24F7A8D38E08 + +[SkuIds] + 0|DEFAULT # The entry: 0|DEFAULT is reserved and always req= uired. + +[DefaultStores] + 0|STANDARD # UEFI Standard default 0|STANDARD is reserved. + 1|MANUFACTURING # UEFI Manufacturing default 1|MANUFACTURING is r= eserved. + +[PcdsDynamicExVpd.common.DEFAULT] + gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer|* +''' + +decstatement =3D '''[Guids] + gStructPcdTokenSpaceGuid =3D {0x3f1406f4, 0x2b, 0x487a, {0x8b, 0x69, 0x7= 4, 0x29, 0x1b, 0x36, 0x16, 0xf4}} + +[PcdsFixedAtBuild,PcdsPatchableInModule,PcdsDynamic,PcdsDynamicEx] +''' + +infstatement =3D '''[Pcd] +''' + +SECTION=3D'PcdsDynamicHii' +PCD_NAME=3D'gStructPcdTokenSpaceGuid.Pcd' + +WARNING=3D[] +ERRORMSG=3D[] + +class parser_lst(object): + + def __init__(self,filelist): + self._ignore=3D['BOOLEAN', 'UINT8', 'UINT16', 'UINT32', 'UINT64'] + self.file=3Dfilelist + self.text=3Dself.megre_lst()[0] + self.content=3Dself.megre_lst()[1] + + def megre_lst(self): + alltext=3D'' + content=3D{} + for file in self.file: + with open(file,'r') as f: + read =3Df.read() + alltext +=3D read + content[file]=3Dread + return alltext,content + + def struct_lst(self):#{struct:lst file} + structs_file=3D{} + name_format =3D re.compile(r'(?') + name_format =3D re.compile(r'(?> m * 8 & 0xff)) + else: + tmp.append('0x%s' % i) + for i in tmp: + line +=3D '%s,' % i + value =3D '{%s}' % line[:-1] + else: + value =3D "0x%01x" % int(list1[-1], 16) + return value + + +#parser Guid file, get guid name form guid value +class GUID(object): + + def __init__(self,path): + self.path =3D path + self.guidfile =3D self.gfile() + self.guiddict =3D self.guid_dict() + + def gfile(self): + for root, dir, file in os.walk(self.path, topdown=3DTrue, followlinks= =3DFalse): + if 'FV' in dir: + gfile =3D os.path.join(root,'Fv','Guid.xref') + if os.path.isfile(gfile): + return gfile + else: + print("ERROR: Guid.xref file not found") + ERRORMSG.append("ERROR: Guid.xref file not found") + exit() + + def guid_dict(self): + guiddict=3D{} + with open(self.guidfile,'r') as file: + lines =3D file.readlines() + guidinfo=3Dlines + for line in guidinfo: + list=3Dline.strip().split(' ') + if list: + if len(list)>1: + guiddict[list[0].upper()]=3Dlist[1] + elif list[0] !=3D ''and len(list)=3D=3D1: + print("Error: line %s can't be parser in %s"%(line.strip(),self.= guidfile)) + ERRORMSG.append("Error: line %s can't be parser in %s"%(line.str= ip(),self.guidfile)) + else: + print("ERROR: No data in %s" %self.guidfile) + ERRORMSG.append("ERROR: No data in %s" %self.guidfile) + return guiddict + + def guid_parser(self,guid): + if guid.upper() in self.guiddict: + return self.guiddict[guid.upper()] + else: + print("ERROR: GUID %s not found in file %s"%(guid, self.guidfile)) + ERRORMSG.append("ERROR: GUID %s not found in file %s"%(guid, self.gu= idfile)) + return guid + +class PATH(object): + + def __init__(self,path): + self.path=3Dpath + self.rootdir=3Dself.get_root_dir() + self.usefuldir=3D[] + self.lstinf =3D {} + for path in self.rootdir: + for o_root, o_dir, o_file in os.walk(os.path.join(path, "OUTPUT"), t= opdown=3DTrue, followlinks=3DFalse): + for INF in o_file: + if os.path.splitext(INF)[1] =3D=3D '.inf': + for l_root, l_dir, l_file in os.walk(os.path.join(path, "DEBUG= "), topdown=3DTrue, + followlinks=3DFalse): + for LST in l_file: + if os.path.splitext(LST)[1] =3D=3D '.lst': + self.lstinf[os.path.join(l_root, LST)] =3D os.path.join(= o_root, INF) + self.usefuldir.append(path) + + def get_root_dir(self): + rootdir=3D[] + for root,dir,file in os.walk(self.path,topdown=3DTrue,followlinks=3DFa= lse): + if "OUTPUT" in root: + updir=3Droot.split("OUTPUT",1)[0] + rootdir.append(updir) + rootdir=3Dlist(set(rootdir)) + return rootdir + + def lst_inf(self): + return self.lstinf + + def package(self): + package=3D{} + package_re=3Dre.compile(r'Packages\.\w+]\n(.*)',re.S) + for i in list(self.lstinf.values()): + with open(i,'r') as inf: + read=3Dinf.read() + section=3Dread.split('[') + for j in section: + p=3Dpackage_re.findall(j) + if p: + package[i]=3Dp[0].rstrip() + return package + + def header(self,struct): + header=3D{} + head_re =3D re.compile(r'} %s;[\s\S\n]+h{1}"'%struct,re.M|re.S) + head_re2 =3D re.compile(r'#line[\s\d]+"(\S+h)"') + for i in list(self.lstinf.keys()): + with open(i,'r') as lst: + read =3D lst.read() + h =3D head_re.findall(read) + if h: + head=3Dhead_re2.findall(h[0]) + if head: + format =3D head[0].replace('\\\\','/').replace('\\','/') + name =3Dformat.split('/')[-1] + head =3D self.makefile(name).replace('\\','/') + header[struct] =3D head + return header + + def makefile(self,filename): + re_format =3D re.compile(r'DEBUG_DIR.*(?:\S+Pkg)\\(.*\\%s)'%filename) + for i in self.usefuldir: + with open(os.path.join(i,'Makefile'),'r') as make: + read =3D make.read() + dir =3D re_format.findall(read) + if dir: + return dir[0] + +class mainprocess(object): + + def __init__(self,InputPath,Config,OutputPath): + self.init =3D 0xFCD00000 + self.inputpath =3D os.path.abspath(InputPath) + self.outputpath =3D os.path.abspath(OutputPath) + self.LST =3D PATH(self.inputpath) + self.lst_dict =3D self.LST.lst_inf() + self.Config =3D Config + self.attribute_dict =3D {'0x3': 'NV, BS', '0x7': 'NV, BS, RT'} + self.guid =3D GUID(self.inputpath) + self.header=3D{} + + def main(self): + conf=3DConfig(self.Config) + config_dict=3Dconf.config_parser() #get {'0_0':[offset,name,guid,value= ,attribute]...,'1_0':....} + lst=3Dparser_lst(list(self.lst_dict.keys())) + efi_dict=3Dlst.efivarstore_parser() #get {name:struct} form lst file + keys=3Dsorted(config_dict.keys()) + all_struct=3Dlst.struct() + stru_lst=3Dlst.struct_lst() + title_list=3D[] + info_list=3D[] + header_list=3D[] + inf_list =3D[] + for i in stru_lst: + tmp =3D self.LST.header(i) + self.header.update(tmp) + for id_key in keys: + tmp_id=3D[id_key] #['0_0',[(struct,[name...]),(struct,[name...])]] + tmp_info=3D{} #{name:struct} + for section in config_dict[id_key]: + c_offset,c_name,c_guid,c_value,c_attribute =3D section + if c_name in efi_dict: + struct =3D efi_dict[c_name] + title=3D'%s%s|L"%s"|%s|0x00||%s\n'%(PCD_NAME,c_name,c_name,self.= guid.guid_parser(c_guid),self.attribute_dict[c_attribute]) + if struct in all_struct: + lstfile =3D stru_lst[struct] + struct_dict=3Dall_struct[struct] + try: + title2 =3D '%s%s|{0}|%s|0xFCD00000{\n \n %s\n = \n%s\n}\n' % (PCD_NAME, c_name, struct, self.header[struct], self= .LST.package()[self.lst_dict[lstfile]]) + except KeyError: + WARNING.append("Warning: No for struct %s"%str= uct) + title2 =3D '%s%s|{0}|%s|0xFCD00000{\n \n %s\n = \n%s\n}\n' % (PCD_NAME, c_name, struct, '', self.LST.package()[se= lf.lst_dict[lstfile]]) + header_list.append(title2) + else: + struct_dict =3D{} + print("ERROR: Struct %s can't found in lst file" %struct) + ERRORMSG.append("ERROR: Struct %s can't found in lst file" %st= ruct) + if c_offset in struct_dict: + offset_name=3Dstruct_dict[c_offset] + info =3D "%s%s.%s|%s\n"%(PCD_NAME,c_name,offset_name,c_value) + inf =3D "%s%s\n"%(PCD_NAME,c_name) + inf_list.append(inf) + tmp_info[info]=3Dtitle + else: + print("ERROR: Can't find offset %s with struct name %s"%(c_off= set,struct)) + ERRORMSG.append("ERROR: Can't find offset %s with name %s"%(c_= offset,struct)) + else: + print("ERROR: Can't find name %s in lst file"%(c_name)) + ERRORMSG.append("ERROR: Can't find name %s in lst file"%(c_name)) + tmp_id.append(list(self.reverse_dict(tmp_info).items())) + id,tmp_title_list,tmp_info_list =3D self.read_list(tmp_id) + title_list +=3Dtmp_title_list + info_list.append(tmp_info_list) + inf_list =3D self.del_repeat(inf_list) + header_list =3D self.plus(self.del_repeat(header_list)) + title_all=3Dlist(set(title_list)) + info_list =3D self.del_repeat(info_list) + for i in range(len(info_list)-1,-1,-1): + if len(info_list[i]) =3D=3D 0: + info_list.remove(info_list[i]) + return keys,title_all,info_list,header_list,inf_list + + + def write_all(self): + title_flag=3D1 + info_flag=3D1 + if not os.path.isdir(self.outputpath): + os.makedirs(self.outputpath) + decwrite =3D write2file(os.path.join(self.outputpath,'StructurePcd.dec= ')) + dscwrite =3D write2file(os.path.join(self.outputpath,'StructurePcd.dsc= ')) + infwrite =3D write2file(os.path.join(self.outputpath, 'StructurePcd.in= f')) + conf =3D Config(self.Config) + ids,title,info,header,inf=3Dself.main() + decwrite.add2file(decstatement) + decwrite.add2file(header) + infwrite.add2file(infstatement) + infwrite.add2file(inf) + dscwrite.add2file(dscstatement) + for id in ids: + dscwrite.add2file(conf.eval_id(id)) + if title_flag: + dscwrite.add2file(title) + title_flag=3D0 + if len(info) =3D=3D 1: + dscwrite.add2file(info) + elif len(info) =3D=3D 2: + if info_flag: + dscwrite.add2file(info[0]) + info_flag =3D0 + else: + dscwrite.add2file(info[1]) + + def del_repeat(self,List): + if len(List) =3D=3D 1 or len(List) =3D=3D 0: + return List + else: + if type(List[0]) !=3D type('xxx'): + alist=3D[] + for i in range(len(List)): + if i =3D=3D 0: + alist.append(List[0]) + else: + plist =3D [] + for j in range(i): + plist +=3D List[j] + alist.append(self.__del(list(set(plist)), List[i])) + return alist + else: + return list(set(List)) + + + def __del(self,list1,list2): + return list(set(list2).difference(set(list1))) + + def reverse_dict(self,dict): + data=3D{} + for i in list(dict.items()): + if i[1] not in list(data.keys()): + data[i[1]]=3D[i[0]] + else: + data[i[1]].append(i[0]) + return data + + def read_list(self,list): + title_list=3D[] + info_list=3D[] + for i in list[1]: + title_list.append(i[0]) + for j in i[1]: + info_list.append(j) + return list[0],title_list,info_list + + def plus(self,list): + nums=3D[] + for i in list: + if type(i) !=3D type([0]): + self.init +=3D 1 + num =3D "0x%01x" % self.init + j=3Di.replace('0xFCD00000',num.upper()) + nums.append(j) + return nums + +class write2file(object): + + def __init__(self,Output): + self.output=3DOutput + self.text=3D'' + if os.path.exists(self.output): + os.remove(self.output) + + def add2file(self,content): + self.text =3D '' + with open(self.output,'a+') as file: + file.write(self.__gen(content)) + + def __gen(self,content): + if type(content) =3D=3D type(''): + return content + elif type(content) =3D=3D type([0,0])or type(content) =3D=3D type((0,0= )): + return self.__readlist(content) + elif type(content) =3D=3D type({0:0}): + return self.__readdict(content) + + def __readlist(self,list): + for i in list: + if type(i) =3D=3D type([0,0])or type(i) =3D=3D type((0,0)): + self.__readlist(i) + elif type(i) =3D=3D type('') : + self.text +=3Di + return self.text + + def __readdict(self,dict): + content=3Dlist(dict.items()) + return self.__readlist(content) + +def stamp(): + return datetime.datetime.now() + +def dtime(start,end,id=3DNone): + if id: + pass + print("%s time:%s" % (id,str(end - start))) + else: + print("Total time:%s" %str(end-start)[:-7]) + + +def main(): + start =3D stamp() + parser =3D argparse.ArgumentParser(prog =3D __prog__, + description =3D __description__ + __cop= yright__, + conflict_handler =3D 'resolve') + parser.add_argument('-v', '--version', action =3D 'version',version =3D = __version__, help=3D"show program's version number and exit") + parser.add_argument('-p', '--path', metavar=3D'PATH', dest=3D'path', hel= p=3D"platform build output directory") + parser.add_argument('-c', '--config',metavar=3D'FILENAME', dest=3D'confi= g', help=3D"firmware configuration file") + parser.add_argument('-o', '--outputdir', metavar=3D'PATH', dest=3D'outpu= t', help=3D"output directoy") + options =3D parser.parse_args() + if options.config: + if options.path: + if options.output: + run =3D mainprocess(options.path, options.config, options.output) + print("Running...") + run.write_all() + if WARNING: + warning =3D list(set(WARNING)) + for j in warning: + print(j) + if ERRORMSG: + ERROR =3D list(set(ERRORMSG)) + with open("ERROR.log", 'w+') as error: + for i in ERROR: + error.write(i + '\n') + print("Some error find, error log in ERROR.log") + print('Finished, Output files in directory %s'%os.path.abspath(opt= ions.output)) + else: + print('Error command, no output path, use -h for help') + else: + print('Error command, no build path input, use -h for help') + else: + print('Error command, no output file, use -h for help') + end =3D stamp() + dtime(start, end) + +if __name__ =3D=3D '__main__': + main() --=20 2.8.0.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel