2021-09-16 11:12:51 +02:00
## @file
# This file contains the script to build UniversalPayload
#
# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
import argparse
import subprocess
import os
import shutil
import sys
2021-09-24 23:14:28 +02:00
from ctypes import *
2023-04-26 08:32:01 +02:00
from Tools . ElfFv import ReplaceFv
2021-09-24 23:14:28 +02:00
sys . dont_write_bytecode = True
class UPLD_INFO_HEADER ( LittleEndianStructure ) :
_pack_ = 1
_fields_ = [
( ' Identifier ' , ARRAY ( c_char , 4 ) ) ,
( ' HeaderLength ' , c_uint32 ) ,
( ' SpecRevision ' , c_uint16 ) ,
( ' Reserved ' , c_uint16 ) ,
( ' Revision ' , c_uint32 ) ,
( ' Attribute ' , c_uint32 ) ,
( ' Capability ' , c_uint32 ) ,
( ' ProducerId ' , ARRAY ( c_char , 16 ) ) ,
( ' ImageId ' , ARRAY ( c_char , 16 ) ) ,
]
def __init__ ( self ) :
2022-05-26 03:05:39 +02:00
self . Identifier = b ' PLDH '
2021-09-24 23:14:28 +02:00
self . HeaderLength = sizeof ( UPLD_INFO_HEADER )
2023-03-29 04:26:00 +02:00
self . SpecRevision = 0x0070
2021-09-24 23:14:28 +02:00
self . Revision = 0x0000010105
self . ImageId = b ' UEFI '
self . ProducerId = b ' INTEL '
2021-09-16 11:12:51 +02:00
2023-04-26 08:32:01 +02:00
def BuildUniversalPayload ( Args ) :
def RunCommand ( cmd ) :
print ( cmd )
p = subprocess . Popen ( cmd , shell = True , stdout = subprocess . PIPE , stderr = subprocess . STDOUT , cwd = os . environ [ ' WORKSPACE ' ] )
while True :
line = p . stdout . readline ( )
if not line :
break
print ( line . strip ( ) . decode ( errors = ' ignore ' ) )
p . communicate ( )
if p . returncode != 0 :
print ( " - Failed - error happened when run command: %s " % cmd )
raise Exception ( " ERROR: when run command: %s " % cmd )
2023-03-29 04:26:00 +02:00
2021-09-16 11:12:51 +02:00
BuildTarget = Args . Target
ToolChain = Args . ToolChain
2022-04-13 22:42:09 +02:00
Quiet = " --quiet " if Args . Quiet else " "
2021-09-16 11:12:51 +02:00
ElfToolChain = ' CLANGDWARF '
2022-04-19 02:51:10 +02:00
BuildDir = os . path . join ( os . environ [ ' WORKSPACE ' ] , os . path . normpath ( " Build/UefiPayloadPkgX64 " ) )
2023-04-26 08:32:01 +02:00
BuildModule = " "
BuildArch = " "
2023-08-25 06:02:50 +02:00
2022-04-19 02:51:10 +02:00
if Args . Arch == ' X64 ' :
BuildArch = " X64 "
2022-06-24 05:35:43 +02:00
EntryOutputDir = os . path . join ( BuildDir , " {} _ {} " . format ( BuildTarget , ElfToolChain ) , os . path . normpath ( " X64/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll " ) )
2022-04-19 02:51:10 +02:00
else :
BuildArch = " IA32 -a X64 "
2022-06-24 05:35:43 +02:00
EntryOutputDir = os . path . join ( BuildDir , " {} _ {} " . format ( BuildTarget , ElfToolChain ) , os . path . normpath ( " IA32/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll " ) )
2021-09-16 11:12:51 +02:00
DscPath = os . path . normpath ( " UefiPayloadPkg/UefiPayloadPkg.dsc " )
ModuleReportPath = os . path . join ( BuildDir , " UefiUniversalPayloadEntry.txt " )
2021-09-24 23:14:28 +02:00
UpldInfoFile = os . path . join ( BuildDir , " UniversalPayloadInfo.bin " )
2021-09-16 11:12:51 +02:00
2022-06-21 05:52:05 +02:00
Pcds = " "
if ( Args . pcd != None ) :
for PcdItem in Args . pcd :
Pcds + = " --pcd {} " . format ( PcdItem )
2021-09-16 11:12:51 +02:00
Defines = " "
2023-04-26 08:32:01 +02:00
if ( Args . Macro != None ) :
for MacroItem in Args . Macro :
Defines + = " -D {} " . format ( MacroItem )
2021-09-16 11:12:51 +02:00
#
# Building DXE core and DXE drivers as DXEFV.
#
2023-03-16 07:25:52 +01:00
if Args . BuildEntryOnly == False :
2023-04-26 08:32:01 +02:00
PayloadReportPath = os . path . join ( BuildDir , " UefiUniversalPayload.txt " )
2023-03-16 07:25:52 +01:00
BuildPayload = " build -p {} -b {} -a X64 -t {} -y {} {} " . format ( DscPath , BuildTarget , ToolChain , PayloadReportPath , Quiet )
BuildPayload + = Pcds
BuildPayload + = Defines
RunCommand ( BuildPayload )
2021-09-16 11:12:51 +02:00
#
# Building Universal Payload entry.
#
2023-03-16 07:25:52 +01:00
if Args . PreBuildUplBinary is None :
2023-04-26 08:32:01 +02:00
EntryModuleInf = os . path . normpath ( " UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf " )
2023-03-16 07:25:52 +01:00
BuildModule = " build -p {} -b {} -a {} -m {} -t {} -y {} {} " . format ( DscPath , BuildTarget , BuildArch , EntryModuleInf , ElfToolChain , ModuleReportPath , Quiet )
BuildModule + = Pcds
BuildModule + = Defines
RunCommand ( BuildModule )
2023-08-25 06:02:50 +02:00
if Args . PreBuildUplBinary is not None :
EntryOutputDir = os . path . join ( BuildDir , " UniversalPayload.elf " )
shutil . copy ( os . path . abspath ( Args . PreBuildUplBinary ) , EntryOutputDir )
2021-09-24 23:14:28 +02:00
#
# Buid Universal Payload Information Section ".upld_info"
#
2023-04-26 08:32:01 +02:00
upld_info_hdr = UPLD_INFO_HEADER ( )
2023-03-29 04:26:00 +02:00
upld_info_hdr . SpecRevision = Args . SpecRevision
2023-04-26 08:32:01 +02:00
upld_info_hdr . Revision = Args . Revision
upld_info_hdr . ProducerId = Args . ProducerId . encode ( ) [ : 16 ]
upld_info_hdr . ImageId = Args . ImageId . encode ( ) [ : 16 ]
upld_info_hdr . Attribute | = 1 if BuildTarget == " DEBUG " else 0
2021-09-24 23:14:28 +02:00
fp = open ( UpldInfoFile , ' wb ' )
fp . write ( bytearray ( upld_info_hdr ) )
fp . close ( )
2023-04-26 08:32:01 +02:00
MultiFvList = [ ]
2023-03-16 07:25:52 +01:00
if Args . BuildEntryOnly == False :
2023-04-26 08:32:01 +02:00
MultiFvList = [
[ ' uefi_fv ' , os . path . join ( BuildDir , " {} _ {} " . format ( BuildTarget , ToolChain ) , os . path . normpath ( " FV/DXEFV.Fv " ) ) ] ,
[ ' bds_fv ' , os . path . join ( BuildDir , " {} _ {} " . format ( BuildTarget , ToolChain ) , os . path . normpath ( " FV/BDSFV.Fv " ) ) ] ,
[ ' network_fv ' , os . path . join ( BuildDir , " {} _ {} " . format ( BuildTarget , ToolChain ) , os . path . normpath ( " FV/NETWORKFV.Fv " ) ) ] ,
]
AddSectionName = ' .upld_info '
ReplaceFv ( EntryOutputDir , UpldInfoFile , AddSectionName , Alignment = 4 )
2021-09-16 11:12:51 +02:00
2023-08-25 06:02:50 +02:00
if Args . PreBuildUplBinary is None :
shutil . copy ( EntryOutputDir , os . path . join ( BuildDir , ' UniversalPayload.elf ' ) )
2021-09-16 11:12:51 +02:00
2023-04-26 08:32:01 +02:00
return MultiFvList , os . path . join ( BuildDir , ' UniversalPayload.elf ' )
2021-09-16 11:12:51 +02:00
def main ( ) :
2023-04-26 08:32:01 +02:00
def ValidateSpecRevision ( Argument ) :
try :
( MajorStr , MinorStr ) = Argument . split ( ' . ' )
except :
raise argparse . ArgumentTypeError ( ' {} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]). ' . format ( Argument ) )
#
# Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version.
#
if len ( MinorStr ) > 0 and len ( MinorStr ) < 3 :
try :
Minor = int ( MinorStr , 16 ) if len ( MinorStr ) == 2 else ( int ( MinorStr , 16 ) << 4 )
except :
raise argparse . ArgumentTypeError ( ' {} Minor version of SpecRevision is not a valid integer value. ' . format ( Argument ) )
else :
raise argparse . ArgumentTypeError ( ' {} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]). ' . format ( Argument ) )
if len ( MajorStr ) > 0 and len ( MajorStr ) < 3 :
try :
Major = int ( MajorStr , 16 )
except :
raise argparse . ArgumentTypeError ( ' {} Major version of SpecRevision is not a valid integer value. ' . format ( Argument ) )
else :
raise argparse . ArgumentTypeError ( ' {} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]). ' . format ( Argument ) )
return int ( ' 0x {0:02x} {1:02x} ' . format ( Major , Minor ) , 0 )
def Validate32BitInteger ( Argument ) :
try :
Value = int ( Argument , 0 )
except :
raise argparse . ArgumentTypeError ( ' {} is not a valid integer value. ' . format ( Argument ) )
if Value < 0 :
raise argparse . ArgumentTypeError ( ' {} is a negative value. ' . format ( Argument ) )
if Value > 0xffffffff :
raise argparse . ArgumentTypeError ( ' {} is larger than 32-bits. ' . format ( Argument ) )
return Value
def ValidateAddFv ( Argument ) :
Value = Argument . split ( " = " )
if len ( Value ) != 2 :
raise argparse . ArgumentTypeError ( ' {} is incorrect format with " xxx_fv=xxx.fv " ' . format ( Argument ) )
if Value [ 0 ] [ - 3 : ] != " _fv " :
raise argparse . ArgumentTypeError ( ' {} is incorrect format with " xxx_fv=xxx.fv " ' . format ( Argument ) )
if Value [ 1 ] [ - 3 : ] . lower ( ) != " .fv " :
raise argparse . ArgumentTypeError ( ' {} is incorrect format with " xxx_fv=xxx.fv " ' . format ( Argument ) )
if os . path . exists ( Value [ 1 ] ) == False :
raise argparse . ArgumentTypeError ( ' File {} is not found. ' . format ( Value [ 1 ] ) )
return Value
2021-09-16 11:12:51 +02:00
parser = argparse . ArgumentParser ( description = ' For building Universal Payload ' )
parser . add_argument ( ' -t ' , ' --ToolChain ' )
parser . add_argument ( ' -b ' , ' --Target ' , default = ' DEBUG ' )
2022-03-29 19:35:36 +02:00
parser . add_argument ( ' -a ' , ' --Arch ' , choices = [ ' IA32 ' , ' X64 ' ] , help = ' Specify the ARCH for payload entry module. Default build X64 image. ' , default = ' X64 ' )
2021-09-16 11:12:51 +02:00
parser . add_argument ( " -D " , " --Macro " , action = " append " , default = [ " UNIVERSAL_PAYLOAD=TRUE " ] )
2021-09-24 23:14:28 +02:00
parser . add_argument ( ' -i ' , ' --ImageId ' , type = str , help = ' Specify payload ID (16 bytes maximal). ' , default = ' UEFI ' )
2022-04-13 22:42:09 +02:00
parser . add_argument ( ' -q ' , ' --Quiet ' , action = ' store_true ' , help = ' Disable all build messages except FATAL ERRORS. ' )
2022-06-21 05:52:05 +02:00
parser . add_argument ( " -p " , " --pcd " , action = " append " )
2023-04-26 08:32:01 +02:00
parser . add_argument ( " -s " , " --SpecRevision " , type = ValidateSpecRevision , default = ' 0.7 ' , help = ' Indicates compliance with a revision of this specification in the BCD format. ' )
2023-03-29 04:26:00 +02:00
parser . add_argument ( " -r " , " --Revision " , type = Validate32BitInteger , default = ' 0x0000010105 ' , help = ' Revision of the Payload binary. Major.Minor.Revision.Build ' )
parser . add_argument ( " -o " , " --ProducerId " , default = ' INTEL ' , help = ' A null-terminated OEM-supplied string that identifies the payload producer (16 bytes maximal). ' )
2023-04-26 08:32:01 +02:00
parser . add_argument ( " -sk " , " --SkipBuild " , action = ' store_true ' , help = ' Skip UniversalPayload build ' )
parser . add_argument ( " -af " , " --AddFv " , type = ValidateAddFv , action = ' append ' , help = ' Add or replace specific FV into payload, Ex: uefi_fv=XXX.fv ' )
2023-06-07 08:09:34 +02:00
command_group = parser . add_mutually_exclusive_group ( )
command_group . add_argument ( " -e " , " --BuildEntryOnly " , action = ' store_true ' , help = ' Build UniversalPayload Entry file ' )
command_group . add_argument ( " -pb " , " --PreBuildUplBinary " , default = None , help = ' Specify the UniversalPayload file ' )
2021-09-16 11:12:51 +02:00
args = parser . parse_args ( )
2023-04-26 08:32:01 +02:00
MultiFvList = [ ]
UniversalPayloadBinary = args . PreBuildUplBinary
if ( args . SkipBuild == False ) :
MultiFvList , UniversalPayloadBinary = BuildUniversalPayload ( args )
if ( args . AddFv != None ) :
for ( SectionName , SectionFvFile ) in args . AddFv :
MultiFvList . append ( [ SectionName , SectionFvFile ] )
if ( UniversalPayloadBinary != None ) :
for ( SectionName , SectionFvFile ) in MultiFvList :
if os . path . exists ( SectionFvFile ) == False :
continue
print ( " Patch {} = {} into {} " . format ( SectionName , SectionFvFile , UniversalPayloadBinary ) )
ReplaceFv ( UniversalPayloadBinary , SectionFvFile , ' .upld. {} ' . format ( SectionName ) )
print ( " \n Successfully build Universal Payload " )
2021-09-16 11:12:51 +02:00
if __name__ == ' __main__ ' :
main ( )