slimbootloader/BuildLoader.py

1311 lines
58 KiB
Python
Executable File

#!/usr/bin/env python
## @ BuildLoader.py
# Build bootloader main script
#
# Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
# Import Modules
#
import os
import sys
tool_dir = os.path.join(os.path.dirname (os.path.realpath(__file__)), 'BootloaderCorePkg', 'Tools')
sys.dont_write_bytecode = True
sys.path.append (tool_dir)
import re
import imp
import errno
import shutil
import argparse
import subprocess
import multiprocessing
from ctypes import *
from BuildUtility import *
def rebuild_basetools ():
exe_list = 'GenFfs GenFv GenFw GenSec Lz4Compress LzmaCompress'.split()
ret = 0
sblsource = os.environ['SBL_SOURCE']
if os.name == 'posix':
if not check_files_exist (exe_list, os.path.join(sblsource, 'BaseTools', 'Source', 'C', 'bin')):
ret = run_process (['make', '-C', 'BaseTools'])
elif os.name == 'nt':
if not check_files_exist (exe_list, os.path.join(sblsource, 'BaseTools', 'Bin', 'Win32'), '.exe'):
print ("Could not find pre-built BaseTools binaries, try to rebuild BaseTools ...")
ret = run_process (['BaseTools\\toolsetup.bat', 'forcerebuild'])
if ret:
print ("Build BaseTools failed, please check required build environment and utilities !")
sys.exit(1)
def prep_env ():
# check python version first
version = check_for_python ()
os.environ['PYTHON_COMMAND'] = sys.executable
print_tool_version_info(os.environ['PYTHON_COMMAND'], version.strip())
sblsource = os.path.dirname(os.path.realpath(__file__))
os.chdir(sblsource)
if os.name == 'posix':
toolchain = 'GCC49'
gcc_ver = run_process (['gcc', '-dumpversion'], capture_out = True)
gcc_ver = gcc_ver.strip()
if int(gcc_ver.split('.')[0]) > 4:
toolchain = 'GCC5'
os.environ['PATH'] = os.environ['PATH'] + ':' + os.path.join(sblsource, 'BaseTools/BinWrappers/PosixLike')
toolchain_ver = gcc_ver
elif os.name == 'nt':
os.environ['PATH'] = os.environ['PATH'] + ';' + os.path.join(sblsource, 'BaseTools\\Bin\\Win32')
os.environ['PATH'] = os.environ['PATH'] + ';' + os.path.join(sblsource, 'BaseTools\\BinWrappers\\WindowsLike')
os.environ['PYTHONPATH'] = os.path.join(sblsource, 'BaseTools', 'Source', 'Python')
toolchain, toolchain_prefix, toolchain_path, toolchain_ver = get_visual_studio_info ()
if toolchain:
os.environ[toolchain_prefix] = toolchain_path
else:
print("Could not find supported Visual Studio version !")
sys.exit(1)
if 'NASM_PREFIX' not in os.environ:
os.environ['NASM_PREFIX'] = "C:\\Nasm\\"
if 'OPENSSL_PATH' not in os.environ:
os.environ['OPENSSL_PATH'] = "C:\\Openssl\\"
if 'IASL_PREFIX' not in os.environ:
os.environ['IASL_PREFIX'] = "C:\\ASL\\"
else:
print("Unsupported operating system !")
sys.exit(1)
print_tool_version_info(toolchain, toolchain_ver)
check_for_openssl()
check_for_nasm()
check_for_git()
# Update Environment vars
os.environ['SBL_SOURCE'] = sblsource
os.environ['EDK_TOOLS_PATH'] = os.path.join(sblsource, 'BaseTools')
os.environ['BASE_TOOLS_PATH'] = os.path.join(sblsource, 'BaseTools')
if 'WORKSPACE' not in os.environ:
os.environ['WORKSPACE'] = sblsource
os.environ['CONF_PATH'] = os.path.join(os.environ['WORKSPACE'], 'Conf')
os.environ['TOOL_CHAIN'] = toolchain
def get_board_config_file (check_dir, board_cfgs):
platform_dir = os.path.join (check_dir, 'Platform')
if not os.path.isdir (platform_dir):
if os.path.basename(check_dir) == 'Platform':
platform_dir = check_dir
else:
return
board_pkgs = os.listdir(platform_dir)
for pkg in board_pkgs:
cfgfile = os.path.join(platform_dir, pkg, 'BoardConfig.py')
if os.path.exists(cfgfile):
board_cfgs.append(cfgfile)
class BaseBoard(object):
def __init__(self, *args, **kwargs):
# NOTE: Variables starting with '_' will not be exported to Platform.dsc
# Define default private key (PEM format) used to sign configuration data, firmware capsule and IAS image
key_dir = os.path.join('BootloaderCorePkg', 'Tools', 'Keys')
# Allow master key to be able to sign everything by default
self._MASTER_KEY_USAGE = HASH_USAGE['PUBKEY_CFG_DATA'] | HASH_USAGE['PUBKEY_FWU'] | HASH_USAGE['PUBKEY_OS'] | \
HASH_USAGE['PUBKEY_CONT_DEF']
self._MASTER_PRIVATE_KEY = os.path.join(key_dir, 'TestSigningPrivateKey.pem')
self._CFGDATA_PRIVATE_KEY = os.path.join(key_dir, 'TestSigningPrivateKey.pem')
self._CONTAINER_PRIVATE_KEY = os.path.join(key_dir, 'TestSigningPrivateKey.pem')
self.LOGO_FILE = 'Platform/CommonBoardPkg/Logo/Logo.bmp'
self._RSA_SIGN_TYPE = 'RSA2048'
self._SIGN_HASH = 'SHA2_256'
self.SIGN_HASH_TYPE = HASH_TYPE_VALUE[self._SIGN_HASH]
self.VERINFO_IMAGE_ID = 'SB_???? '
self.VERINFO_PROJ_ID = 1
self.VERINFO_CORE_MAJOR_VER = 0
self.VERINFO_CORE_MINOR_VER = 5
self.VERINFO_PROJ_MAJOR_VER = 0
self.VERINFO_PROJ_MINOR_VER = 1
self.VERINFO_SVN = 1
self.VERINFO_BUILD_DATE = '01/01/2018'
self.LOWEST_SUPPORTED_FW_VER = 1
self.FLASH_BLOCK_SIZE = 0x1000
self.FLASH_LAYOUT_START = 0x100000000
self.FLASH_BASE = 0
self.FLASH_SIZE = 0
self.PCI_EXPRESS_BASE = 0xE0000000
self.ACPI_PM_TIMER_BASE = 0x0408
self.USB_KB_POLLING_TIMEOUT = 1
self.VERIFIED_BOOT_HASH_MASK = 0x00000000
self.BOOT_MEDIA_SUPPORT_MASK = 0xFFFFFFFF
self.FILE_SYSTEM_SUPPORT_MASK = 0x00000003
self.DEBUG_OUTPUT_DEVICE_MASK = 0x00000003
self.DEBUG_PORT_NUMBER = 0x00000002
self.CONSOLE_IN_DEVICE_MASK = 0x00000001
self.CONSOLE_OUT_DEVICE_MASK = 0x00000001
self.HAVE_VBT_BIN = 0
self.HAVE_FIT_TABLE = 0
self.HAVE_VERIFIED_BOOT = 0
self.HAVE_MEASURED_BOOT = 0
self.HAVE_FSP_BIN = 1
self.HAVE_ACPI_TABLE = 1
self.HAVE_PSD_TABLE = 0
self.HAVE_SEED_LIST = 0
self.FIT_ENTRY_MAX_NUM = 10
self.ENABLE_PCI_ENUM = 1
self.ENABLE_SMP_INIT = 1
self.ENABLE_FSP_LOAD_IMAGE = 0
self.ENABLE_SPLASH = 0
self.ENABLE_FRAMEBUFFER_INIT = 0
self.ENABLE_PRE_OS_CHECKER = 0
self.ENABLE_CRYPTO_SHA_OPT = IPP_CRYPTO_OPTIMIZATION_MASK['SHA256_V8']
self.ENABLE_FWU = 0
self.ENABLE_SOURCE_DEBUG = 0
self.ENABLE_SMM_REBASE = 0
self.ENABLE_GRUB_CONFIG = 0
self.ENABLE_SMBIOS = 0
self.ENABLE_LINUX_PAYLOAD = 0
self.ENABLE_CONTAINER_BOOT = 1
self.ENABLE_CSME_UPDATE = 0
self.ENABLE_EMMC_HS400 = 1
self.BUILD_CSME_UPDATE_DRIVER = 0
self.CPU_MAX_LOGICAL_PROCESSOR_NUMBER = 16
self.ACM_SIZE = 0
self.ACM3_SIZE = 0
self.UCODE_SIZE = 0
self.CFGDATA_SIZE = 0
self.MRCDATA_SIZE = 0
self.VARIABLE_SIZE = 0
self.UEFI_VARIABLE_SIZE = 0
self.FWUPDATE_SIZE = 0
self.SPI_IAS1_SIZE = 0
self.SPI_IAS2_SIZE = 0
self.KM_SIZE = 0x1000 # valid only if ACM_SIZE > 0
self.BPM_SIZE = 0x1000 # valid only if ACM_SIZE > 0
self.CFG_DATABASE_SIZE = 0
self.STAGE1A_XIP = 1
self.STAGE1B_XIP = 1
self.STAGE1_STACK_BASE_OFFSET = 0x00000000
self.STAGE2_XIP = 0
self.STAGE2_LOAD_HIGH = 1
self.PAYLOAD_LOAD_HIGH = 1
self.PAYLOAD_EXE_BASE = 0x00800000
# 0: Direct access from flash
# other: Load image into memory address
self.PAYLOAD_LOAD_BASE = 0
self.FWUPDATE_LOAD_BASE = 0
# OS Loader FD/FV sizes
self.OS_LOADER_FD_SIZE = 0x00042000
self.OS_LOADER_FD_NUMBLK = self.OS_LOADER_FD_SIZE // self.FLASH_BLOCK_SIZE
self.PLD_HEAP_SIZE = 0x02000000
self.PLD_STACK_SIZE = 0x00010000
self.PLD_RSVD_MEM_SIZE = 0x00004000
# These memory sizes need to be page aligned
self.LOADER_RSVD_MEM_SIZE = 0x0038C000
self.LOADER_ACPI_NVS_MEM_SIZE = 0x00008000
self.LOADER_ACPI_RECLAIM_MEM_SIZE = 0x00068000
self.CFGDATA_REGION_TYPE = FLASH_REGION_TYPE.BIOS
self.RELEASE_MODE = 0
self.NO_OPT_MODE = 0
self.FSPDEBUG_MODE = 0
self.MIN_FSP_REVISION = 0
self.FSP_IMAGE_ID = ''
self.TOP_SWAP_SIZE = 0
self.REDUNDANT_SIZE = 0
self._PAYLOAD_NAME = ''
self._FSP_PATH_NAME = ''
self._PLATFORM_ID = None
self._MULTI_VBT_FILE = {}
self._CFGDATA_INT_FILE = []
self._CFGDATA_EXT_FILE = []
self.IPP_HASH_LIB_SUPPORTED_MASK = IPP_CRYPTO_ALG_MASK[self._SIGN_HASH]
self.HASH_STORE_SIZE = 0x200 #Hash store size to be allocated in bootloader
for key, value in list(kwargs.items()):
setattr(self, '%s' % key, value)
class Build(object):
def __init__(self, board):
self._toolchain = os.environ['TOOL_CHAIN']
self._workspace = os.environ['WORKSPACE']
self._board = board
self._image = "SlimBootloader.bin"
self._target = 'RELEASE' if board.RELEASE_MODE else 'NOOPT' if board.NO_OPT_MODE else 'DEBUG'
self._fsp_basename = 'FspDbg' if board.FSPDEBUG_MODE else 'FspRel'
self._fv_dir = os.path.join(self._workspace, 'Build', 'BootloaderCorePkg', '%s_%s' % (self._target, self._toolchain), 'FV')
self._key_dir = os.path.join('BootloaderCorePkg', 'Tools', 'Keys')
self._img_list = board.GetImageLayout()
self._pld_list = get_payload_list (board._PAYLOAD_NAME.split(';'))
self._comp_list = []
self._region_list = []
def update_fit_table (self):
if not self._board.HAVE_FIT_TABLE:
return
print('Updating FIT')
img_file = os.path.join (self._fv_dir, self._image)
fi = open(img_file,'rb')
rom = bytearray(fi.read())
fi.close()
# Find FIT pointer @ 0xFFFFFFC0
fit_address = c_uint32.from_buffer(rom, len(rom)-0x40)
print(' FIT Address: 0x%08X' % fit_address.value)
if self._board.ACM_SIZE > 0:
# Check FIT address alignment for 64 bytes if ACM is used
# because BIOS IBB segments base/size require 64 bytes alignment.
if fit_address.value & ~0x3F != fit_address.value:
raise Exception (' FIT address (0x%08X) is not 64-byte aligned' % fit_address.value)
# Check FIT address range
base = 0x100000000 - len(rom);
if (fit_address.value < base) or (fit_address.value > (base + len(rom))):
raise Exception(' FIT address (0x%08X) out of range' % fit_address.value)
# Check FIT signature
fit_offset = fit_address.value - base
fit_header = FitEntry.from_buffer(rom, fit_offset)
if fit_header.address != bytes_to_value (bytearray(FitEntry.FIT_SIGNATURE)):
raise Exception(' FIT signature not found')
num_fit_entries = 0
if self._board.UCODE_SIZE > 0:
ucode_base = self._board.UCODE_BASE
ucode_offset = ucode_base - base;
if (ucode_offset < 0):
raise Exception (' UCODE %x\n UCODE address (0x%08X) out of range' % (base, ucode_base))
# Collect all CPU uCode images
u_code_images = []
while ucode_offset < len(rom):
ucode_hdr = UcodeHeader.from_buffer(rom, ucode_offset)
if ucode_hdr.header_version == 1:
if ucode_hdr.total_size:
ucode_size = ucode_hdr.total_size
else:
ucode_size = 0x0800
u_code_images.append((ucode_offset, ucode_size))
ucode_offset += ucode_size
num_fit_entries += 1
else:
break
# Patch FIT with addresses of uCode images
for i in range(0, num_fit_entries):
fit_entry = FitEntry.from_buffer(rom, fit_offset + (i+1)*16)
# uCode Update
if len(u_code_images) > 0:
offset, size = u_code_images.pop(0)
fit_entry.set_values(base + offset, 0, 0x100, 0x1, 0)
print (' Patching entry %d with 0x%08X - uCode' % (i, fit_entry.address))
else:
print (' Nullifying unused uCode patch entry %d' % i)
fit_entry.type = 0x7f
if len(u_code_images) > 0:
raise Exception(' Insufficient uCode entries in FIT. Need %d more.' % len(u_code_images))
# ACM
if self._board.ACM_SIZE > 0:
fit_entry = FitEntry.from_buffer(rom, fit_offset + (num_fit_entries+1)*16)
fit_entry.set_values(self._board.ACM_BASE, 0, 0x100, 0x2, 0)
print (' Patching entry %d with 0x%08X:0x%08X - ACM' % (num_fit_entries, fit_entry.address, fit_entry.size))
num_fit_entries += 1
# ACM3 Fit entry should be in sequential order with/without BTG enabled
# Save the next FIT entry for ACM3 here and set it later below
if self._board.ACM3_SIZE > 0:
acm3_index = num_fit_entries
num_fit_entries += 1
# BIOS Module (IBB segment 0): from FIT table end to 4GB
# Record it now and update later since the FIT size is unknown yet
patch_entry = num_fit_entries
num_fit_entries += 1
# BIOS Module (IBB segment 1): from Stage1A base to FIT table start
addr = self._board.STAGE1A_BASE
module_size = (fit_address.value - addr) >> 4
fit_entry = FitEntry.from_buffer(rom, fit_offset + (num_fit_entries+1)*16)
fit_entry.set_values(addr, module_size, 0x100, 0x7, 0)
print (' Patching entry %d with 0x%08X:0x%08X - BIOS Module(Stage1A base to FIT table start)' % (num_fit_entries, fit_entry.address, fit_entry.size))
num_fit_entries += 1
# BIOS Module (IBB segment 2): full Stage1B
addr = self._board.STAGE1B_BASE
module_size = self._board.STAGE1B_SIZE >> 4
fit_entry = FitEntry.from_buffer(rom, fit_offset + (num_fit_entries+1)*16)
fit_entry.set_values(addr, module_size, 0x100, 0x7, 0)
print (' Patching entry %d with 0x%08X:0x%08X - BIOS Module(Stage1B)' % (num_fit_entries, fit_entry.address, fit_entry.size))
num_fit_entries += 1
# KM
addr = self._board.ACM_BASE + self._board.ACM_SIZE - (self._board.KM_SIZE + self._board.BPM_SIZE)
fit_entry = FitEntry.from_buffer(rom, fit_offset + (num_fit_entries+1)*16)
fit_entry.set_values(addr, self._board.KM_SIZE, 0x100, 0xb, 0)
print (' Patching entry %d with 0x%08X:0x%08X - KM' % (num_fit_entries, fit_entry.address, fit_entry.size))
num_fit_entries += 1
# BPM
addr = self._board.ACM_BASE + self._board.ACM_SIZE - self._board.BPM_SIZE
fit_entry = FitEntry.from_buffer(rom, fit_offset + (num_fit_entries+1)*16)
fit_entry.set_values(addr, self._board.BPM_SIZE, 0x100, 0xc, 0)
print (' Patching entry %d with 0x%08X:0x%08X - BPM' % (num_fit_entries, fit_entry.address, fit_entry.size))
num_fit_entries += 1
# Patch the entry 'FIT table end to 4GB' since FIT table size is known now
# The size of the FIT table end address needs to be adjusted to align with 64
# bytes so that IBB segment start address is 64 byte aligned as per required.
addr = fit_address.value + (num_fit_entries + 1) * 16
addr = (addr + 0x3F) & 0xFFFFFFC0
module_size = (0x100000000 - addr) >> 4
fit_entry = FitEntry.from_buffer(rom, fit_offset + (patch_entry+1)*16)
fit_entry.set_values(addr, module_size, 0x100, 0x7, 0)
print (' Patching entry %d with 0x%08X:0x%08X - BIOS Module(FIT table end to 4GB)' % (patch_entry, fit_entry.address, fit_entry.size))
else :
if self._board.ACM3_SIZE > 0:
acm3_index = num_fit_entries
num_fit_entries += 1
addr = fit_address.value + (num_fit_entries + 1) * 16
# Add ACM3 with the reserved fit entry saved
if self._board.ACM3_SIZE > 0:
fit_entry = FitEntry.from_buffer(rom, fit_offset + (acm3_index+1)*16)
fit_entry.set_values(self._board.ACM3_BASE, self._board.ACM3_SIZE, 0x100, 0x3, 0)
print(' Patching entry %d with 0x%08X:0x%08X - ACM3' % (acm3_index, fit_entry.address, fit_entry.size))
# Check FIT length
spaceleft = addr - (fit_address.value + fit_header.size)
if spaceleft > 0:
raise Exception(' Insufficient FIT entries in FIT table, need %d more entries !' % ((spaceleft + 15) // 16))
print (' FIT %d entries added' % num_fit_entries)
# Update FIT checksum
print(' Updating Checksum')
fit_header.size = num_fit_entries + 1
fit_header.type = 0x80 # Valid checksum
fit_header.version = 0x0100
fit_header.checksum = 0
fit_sum = sum(rom[fit_offset:fit_offset+fit_header.size*16])
fit_header.checksum = (0 - fit_sum) & 0xff
fit_data = rom[fit_offset:fit_offset+fit_header.size*16]
fo = open(img_file,'r+b')
fo.seek(fit_offset)
fo.write(fit_data)
if self._board.REDUNDANT_SIZE != 0:
# Update FIT table in STAGE1A_B
print('Updating FIT in STAGE1A_B')
fit_offset -= self._board.TOP_SWAP_SIZE
rom[fit_offset:fit_offset+fit_header.size*16] = fit_data
# Update components base in Fit table.
fit_data = rom[fit_offset:fit_offset+fit_header.size*16]
for i in range(0, num_fit_entries):
fit_entry = FitEntry.from_buffer(fit_data, (i+1)*16)
if (0x100000000 - fit_entry.address) > self._board.TOP_SWAP_SIZE * 2:
fit_entry.address -= self._board.REDUNDANT_SIZE
print(' Patching entry %d from 0x%08X with 0x%08X size:0x%08X ' %
(i, fit_entry.address + self._board.REDUNDANT_SIZE, fit_entry.address, fit_entry.size))
fit_header = FitEntry.from_buffer(fit_data)
fit_header.checksum = 0
fit_sum = sum(fit_data)
fit_header.checksum = (0 - fit_sum) & 0xff
fo.seek(fit_offset)
fo.write(fit_data)
fo.close()
def update_hash_table (self, img_file):
if not self._board.HAVE_VERIFIED_BOOT:
return
print('Updating HashStore %s' % os.path.basename (img_file))
fi = open(img_file,'rb')
stage1_bins = bytearray(fi.read())
fi.close()
hs_offset = stage1_bins.find (HashStoreTable.HASH_STORE_SIGNATURE)
if hs_offset < 0:
raise Exceptoin ("HashStoreTable not found in '%s'!" % os.path.basename(img_file))
comp_name, part_name = get_redundant_info (img_file)
if part_name:
part_name = '_' + part_name
hash_file_list = [
('STAGE1B%s.hash' % part_name, HASH_USAGE['STAGE_1B']),
('STAGE2.hash', HASH_USAGE['STAGE_2']),
('PAYLOAD.hash', HASH_USAGE['PAYLOAD'])
]
if self._board.ENABLE_FWU:
hash_file_list.append (('FWUPDATE.hash', HASH_USAGE['PAYLOAD_FWU']))
hash_file_list.append (('MSTKEY.hash', HASH_USAGE['PUBKEY_MASTER'] | self._board._MASTER_KEY_USAGE))
if len(hash_file_list) > HashStoreTable.HASH_STORE_MAX_IDX_NUM:
raise Exception ('Insufficant hash entries !')
hash_idx = 0
hash_store = HashStoreTable.from_buffer(stage1_bins, hs_offset)
hash_len = HASH_DIGEST_SIZE[HASH_VAL_STRING[self._board.SIGN_HASH_TYPE]]
hash_store_data_buf = bytearray()
hash_store.UsedLength = sizeof(HashStoreTable())
for hash_file, usage in hash_file_list:
# If the hash verification is not required for certain stage, skip it
if hash_file == 'PLDDYN':
hash_data = bytearray(b'\x00' * hash_len)
else:
src_path = os.path.join(self._fv_dir, hash_file)
if not os.path.exists(src_path):
raise Exception ("Hash data file '%s' not found !" % hash_file )
fh = open(src_path,'rb')
hash_data = bytearray(fh.read())
fh.close()
if hash_len != len (hash_data):
raise Exception ("Hash data file '%s' length is incorrect !" % hash_file )
# update hash data
hashstoredata = HashStoreData()
hashstoredata.Usage = usage
hashstoredata.HashAlg = self._board.SIGN_HASH_TYPE
hashstoredata.DigestLen = hash_len
hash_store.UsedLength += hash_len + sizeof(HashStoreData())
#Append hash store data entries
hash_store_data_buf = hash_store_data_buf + bytearray(hashstoredata) + hash_data
print(' Update HashStore entry %d with file %s' % (hash_idx, hash_file))
hash_idx += 1
#Update Hash store Table
fo = open(img_file,'r+b')
fo.seek(hs_offset)
fo.write(hash_store)
#Update Hash store data
fo.seek(hs_offset + sizeof(hash_store))
fo.write(hash_store_data_buf)
fo.close()
def update_component_list (self):
def process_image_list (idx, offset):
region_name, part_name = get_redundant_info (img_list[idx][0])
redundant = True if part_name == 'B' else False
flags = 0
if redundant:
flags |= FLASH_MAP.FLASH_MAP_DESC_FLAGS['BACKUP']
if region_name in ['TOP_SWAP', 'REDUNDANT', 'NON_REDUNDANT', 'NON_VOLATILE']:
flags |= FLASH_MAP.FLASH_MAP_DESC_FLAGS[region_name]
oldidx = len (comp_list)
parent_size = getattr(self._board, '%s_SIZE' % region_name, 0)
remaining_size = parent_size
for comp in img_list[idx][1]:
if comp[3] & STITCH_OPS.MODE_FILE_IGNOR:
continue
compress = FLASH_MAP.FLASH_MAP_DESC_FLAGS['COMPRESSED'] if comp[1] else 0
if comp[0] in region_name_list:
idx = region_name_list.index (comp[0])
region_size = process_image_list (idx, offset)
region_list.append ({'name':comp[0], 'offset':offset, 'size':region_size})
offset += region_size
else:
comp_list.append ({'name':comp[0], 'size':comp[2], 'flag':flags | compress})
remaining_size -= comp[2]
if remaining_size > 0:
comp_node = find_component_in_image_list (img_list[idx][0], img_list)
pos = STITCH_OPS.MODE_POS_HEAD if comp_node is None else comp_node[4]
comp = {'name':'EMPTY.bin', 'size':remaining_size, 'flag':flags}
if pos == STITCH_OPS.MODE_POS_HEAD:
comp_list.insert (oldidx, comp)
else:
comp_list.append (comp)
elif remaining_size < 0:
if parent_size == 0:
parent_size = -remaining_size
else:
raise Exception ('Insufficant space, please adjust %s_SIZE (0x%X more is requried) !' % (region_name, -remaining_size))
return parent_size
# Create compoent list and update base and offset
img_list = self._img_list
region_name_list = [img[0] for img in img_list]
comp_list = []
region_list = []
try:
master_name = self._image
master_idx = region_name_list.index(master_name)
process_image_list (master_idx, 0)
image_size = sum (comp['size'] for comp in comp_list)
image_base = self._board.FLASH_LAYOUT_START - image_size
image_offs = 0
for comp in comp_list:
comp['bname'] = get_redundant_info (comp['name'])[0]
comp['offset'] = image_offs
comp['base'] = image_base + image_offs
image_offs += comp['size']
for rgn in region_list:
rgn['base'] = image_base + rgn['offset']
except ValueError:
print("Warning: No '%s' component in image list !" % master_name)
#print_component_list (comp_list)
self._comp_list = comp_list
self._region_list = region_list
def patch_stages (self):
print('Patching STAGE1A')
extra_cmd = [
"STAGE1A:STAGE1A",
"0xFFFFFFFC, _BASE_STAGE1A_, @Patch BFV",
"_OFFS_STAGE1A_, Stage1A:__ModuleEntryPoint, @Patch Stage1A Entry",
"_OFFS_STAGE1A_+4, Stage1A:BASE, @Patch Module Base",
"<Stage1A:__gPcd_BinaryPatch_PcdVerInfoBase>, {3473A022-C3C2-4964-B309-22B3DFB0B6CA:0x1C}, @Patch VerInfo",
"<Stage1A:__gPcd_BinaryPatch_PcdFileDataBase>, {EFAC3859-B680-4232-A159-F886F2AE0B83:0x1C}, @Patch PcdBase"
]
extra_cmd.append (
"0xFFFFFFF8, {3CEA8EF3-95FC-476F-ABA5-7EC5DFA1D77B:0x1C}, @Patch FlashMap",
)
if self._board.HAVE_FIT_TABLE:
if self._board.ACM_SIZE > 0:
extra_cmd.append (
"0xFFFFFFC0, ({CD17FF5E-7731-4D16-8441-FC7A113C392F:0x1C} + 0x3F) & ~0x3F, @FIT table"
)
else:
extra_cmd.append (
"0xFFFFFFC0, {CD17FF5E-7731-4D16-8441-FC7A113C392F:0x1C}, @FIT table"
)
extra_cmd.extend ([
"<[0xFFFFFFC0]>+0, 0x5449465F, @FIT Signature Low" ,
"<[0xFFFFFFC0]>+4, 0x2020205F, @FIT Signature High",
"<[0xFFFFFFC0]>+8, [CD17FF5E-7731-4D16-8441-FC7A113C392F:0x18] & 0xFFFFFF , @FIT FFS section length",
"<[0xFFFFFFC0]>+8, {CD17FF5E-7731-4D16-8441-FC7A113C392F:0x1C} + [[0xFFFFFFC0] + 8] - [0xFFFFFFC0], @FIT table max length",
])
if self._board.HAVE_VERIFIED_BOOT:
extra_cmd.append (
"<Stage1A:__gPcd_BinaryPatch_PcdHashStoreBase>, {18EDB1DF-1DBE-4EC5-8E26-C44808B546E1:0x1C}, @Patch HashStore",
)
patch_fv(self._fv_dir, *extra_cmd)
print('Patching STAGE1B')
patch_fv(
self._fv_dir,
"STAGE1B:STAGE1B",
"_OFFS_STAGE1B_, Stage1B:__ModuleEntryPoint, @Patch Stage1B Entry",
"_OFFS_STAGE1B_+4, Stage1B:BASE, @Patch Stage1B Base",
"<Stage1B:__gPcd_BinaryPatch_PcdCfgDataIntBase>, {016E6CD0-4834-4C7E-BCFE-41DFB88A6A6D:0x1C}, @Patch Internal CfgDataBase"
)
print('Patching STAGE2')
extra_cmd = []
if self._board.HAVE_VBT_BIN:
extra_cmd.append (
"<Stage2:__gPcd_BinaryPatch_PcdGraphicsVbtAddress>, {E08CA6D5-8D02-43AE-ABB1-952CC787C933:0x1C}, @Patch VBT"
)
if self._board.HAVE_ACPI_TABLE:
extra_cmd.append (
"<Stage2:__gPcd_BinaryPatch_PcdAcpiTablesAddress>, {7E374E25-8E01-4FEE-87F2-390C23C606CD:0x1C}, @Patch ACPI",
)
if self._board.ENABLE_SPLASH:
extra_cmd.append (
"<Stage2:__gPcd_BinaryPatch_PcdSplashLogoAddress>, {5E2D3BE9-AD72-4D1D-AAD5-6B08AF921590:0x1C}, @Patch Logo",
)
patch_fv(
self._fv_dir,
"STAGE2:STAGE2",
"_OFFS_STAGE2_, Stage2:__ModuleEntryPoint, @Patch Stage2 Entry",
"_OFFS_STAGE2_+4, Stage2:BASE, @Patch Stage2 Base",
*extra_cmd
)
def create_dsc_inc_file (self, file):
lines = []
lines.append('%s\n' % AUTO_GEN_DSC_HDR)
lines.append('# Platform specific macro definitions\n')
lines.append('[Defines]\n')
for attr in sorted(vars(self._board)):
if attr.startswith('_'):
continue
value = getattr(self._board, attr)
if type(value) is not str:
if value == 0 or value == 1:
value = '0x%x' % value
else:
value = '0x%08X' % value
lines.append(' DEFINE %-24s = %s\n' % (attr, value))
if getattr(self._board, "GetDscLibrarys", None):
libsdict = self._board.GetDscLibrarys()
for arch in libsdict:
lines.append('\n# Platform specific libraries\n')
lines.append('[LibraryClasses.%s]\n' % arch)
for lib in libsdict[arch]:
lines.append(' %s\n' % lib)
lines.append('\n')
update = True
text = ''.join(lines)
if os.path.exists(file):
old_text = get_file_data (file, 'r')
if text == old_text:
update = False
if update:
open (file, 'w').write(text)
def create_platform_vars (self):
for comp in self._comp_list:
if comp['flag'] & FLASH_MAP.FLASH_MAP_DESC_FLAGS['BACKUP'] or comp['bname'] == 'EMPTY':
continue
setattr(self._board, '%s_BASE' % comp['bname'], comp['base'])
image_base = self._board.FLASH_LAYOUT_START
for idx, comp_name in enumerate(['STAGE1A', 'STAGE1B', 'STAGE2']):
if not hasattr(self._board, '%s_BASE' % comp_name):
image_base -= getattr(self._board, '%s_SIZE' % comp_name)
if idx > 0:
image_base &= ~0xFFFFF
setattr(self._board, '%s_BASE' % comp_name, image_base)
if getattr(self._board, '%s_XIP' % comp_name) or comp_name == 'STAGE1A':
setattr(self._board, '%s_FD_SIZE' % comp_name, getattr(self._board, '%s_SIZE' % comp_name))
setattr(self._board, '%s_FD_BASE' % comp_name, getattr(self._board, '%s_BASE' % comp_name))
if getattr(self._board, '%s_XIP' % comp_name):
setattr(self._board, '%s_LOAD_BASE' % comp_name, getattr(self._board, '%s_BASE' % comp_name))
else:
var_name = '%s_LOAD_BASE' % comp_name
if not hasattr(self._board, var_name):
setattr(self._board, var_name, getattr(self._board, '%s_BASE' % comp_name))
for var in ['%s_FD_SIZE', '%s_FD_BASE', '%s_LOAD_BASE']:
var_name = var % comp_name
if not hasattr(self._board, var_name):
raise Exception ('%s needs to be defined' % var_name)
fd_size = getattr(self._board, '%s_FD_SIZE' % comp_name)
setattr(self._board, '%s_FD_NUMBLK' % comp_name, fd_size // self._board.FLASH_BLOCK_SIZE)
pld_list = ['PAYLOAD']
if self._board.ENABLE_FWU:
pld_list.append ('FWUPDATE')
for pld in pld_list:
if not hasattr(self._board, '%s_LOAD_BASE' % pld):
if not hasattr(self._board, '%s_BASE' % pld):
raise Exception ('%s_BASE or %s_LOAD_BASE needs to be defined !' % (pld, pld))
setattr(self._board, '%s_LOAD_BASE' % pld, getattr(self._board, '%s_BASE' % pld))
setattr(self._board, 'FSP_T_OFFSET' , 0)
setattr(self._board, 'STAGE1A_FV_OFFSET' , getattr(self._board, 'FSP_T_OFFSET') + getattr(self._board, 'FSP_T_SIZE'))
setattr(self._board, 'STAGE1A_FV_SIZE' , getattr(self._board, 'STAGE1A_FD_SIZE') - getattr(self._board, 'FSP_T_SIZE'))
setattr(self._board, 'STAGE1B_FV_OFFSET' , 0)
setattr(self._board, 'STAGE1B_FV_SIZE' , getattr(self._board, 'STAGE1B_FD_SIZE') - getattr(self._board, 'FSP_M_SIZE'))
setattr(self._board, 'STAGE2_FV_OFFSET' , 0)
setattr(self._board, 'STAGE2_FV_SIZE' , getattr(self._board, 'STAGE2_FD_SIZE') - getattr(self._board, 'FSP_S_SIZE'))
setattr(self._board, 'FSP_S_OFFSET' , getattr(self._board, 'STAGE2_FV_OFFSET') + getattr(self._board, 'STAGE2_FV_SIZE'))
setattr(self._board, 'FSP_M_OFFSET' , getattr(self._board, 'STAGE1B_FV_OFFSET') + getattr(self._board, 'STAGE1B_FV_SIZE'))
setattr(self._board, 'FSP_T_BASE' , getattr(self._board, 'STAGE1A_FD_BASE') + getattr(self._board, 'FSP_T_OFFSET'))
setattr(self._board, 'FSP_M_BASE' , getattr(self._board, 'STAGE1B_FD_BASE') + getattr(self._board, 'FSP_M_OFFSET'))
setattr(self._board, 'FSP_S_BASE' , getattr(self._board, 'STAGE2_FD_BASE') + getattr(self._board, 'FSP_S_OFFSET'))
if getattr(self._board, 'FLASH_SIZE') == 0:
if not hasattr (self._board, 'SLIMBOOTLOADER_SIZE'):
raise Exception ('FLASH_SIZE needs to be defined !')
else:
setattr(self._board, 'FLASH_SIZE' , getattr(self._board, 'SLIMBOOTLOADER_SIZE'))
setattr(self._board, 'FLASH_BASE' , 0x100000000 - getattr(self._board, 'FLASH_SIZE'))
if getattr(self._board, 'ACM_SIZE') > 0:
acm_base = getattr(self._board, 'ACM_BASE')
if acm_base & 0x7FFF:
raise Exception ('ACM base[FSP-T+CAR:0x%x] must be 32KB aligned!' % acm_base)
if getattr(self._board, 'ACM3_SIZE') > 0:
acm3_base = getattr(self._board, 'ACM3_BASE')
if acm3_base & 0x0FFF:
raise Exception ('ACM3 base[FSP-T+CAR:0x%x] must be 4KB aligned!' % acm3_base)
def create_redundant_components (self):
if self._board.REDUNDANT_SIZE == 0:
return
print("Generating redundant components")
shutil.copy(
os.path.join(self._fv_dir, 'STAGE1A.fd'),
os.path.join(self._fv_dir, 'STAGE1A_A.fd'))
shutil.copy(
os.path.join(self._fv_dir, 'STAGE1A.fd'),
os.path.join(self._fv_dir, 'STAGE1A_B.fd'))
# Patch flashmap to indicate boot parititon
fo = open(os.path.join(self._fv_dir, 'STAGE1A_B.fd'), 'r+b')
bins = bytearray(fo.read())
fmapoff = (bytes_to_value(bins[-8:-4]) + len(bins)) & 0xFFFFFFFF
fmaphdr = FLASH_MAP.from_buffer (bins, fmapoff)
if fmaphdr.sig != FLASH_MAP.FLASH_MAP_SIGNATURE:
raise Exception ('Failed to locate flash map in STAGE1A_B.fd !')
fmaphdr.attributes |= fmaphdr.FLASH_MAP_ATTRIBUTES['BACKUP_REGION']
fo.seek(fmapoff)
fo.write(fmaphdr)
fo.close()
# Stage 1B_B will be created during rebasing
shutil.copy(
os.path.join(self._fv_dir, 'STAGE1B.fd'),
os.path.join(self._fv_dir, 'STAGE1B_A.fd'))
stage1b_path = os.path.join(self._fv_dir, 'STAGE1B.fd')
stage1b_b_path = os.path.join(self._fv_dir, 'STAGE1B_B.fd')
if self._board.STAGE1B_XIP:
# Rebase stage1b.fd
print("Rebasing STAGE1B_B")
rebase_stage (stage1b_path, stage1b_b_path, -self._board.REDUNDANT_SIZE)
# rebase FSPM in Stage1B and update stage1B hash in key store
if self._board.HAVE_FSP_BIN:
fsp_path = os.path.join(self._fv_dir, 'Fsp.bin')
rebase_fsp (fsp_path, self._fv_dir, self._board.FSP_T_BASE, self._board.FSP_M_BASE - self._board.REDUNDANT_SIZE, self._board.FSP_S_BASE)
split_fsp (fsp_path, self._fv_dir)
# write rebased fspm to second firmware
di = open(os.path.join(self._fv_dir, 'FSP_M.bin'), 'rb').read()
fo = open(stage1b_b_path,'r+b')
fo.seek(self._board.FSP_M_OFFSET)
fo.write(di)
fo.close()
else:
shutil.copy(stage1b_path, stage1b_b_path)
def create_bootloader_image (self, layout_name):
layout_file = open(os.path.join(self._fv_dir, layout_name), 'w')
layout_file.write("BOARD_INFO = ['%s']\n" % self._board.BOARD_NAME)
rgn_name_list = [rgn['name'] for rgn in self._region_list]
for idx, (comp_name, file_list) in enumerate(self._img_list):
if (self._board.ENABLE_FWU == 0) and (comp_name == 'Stitch_FWU.bin') :
print("No firmware update payload specified, skip firmware update.")
continue
out_file = comp_name
out_path = os.path.join(self._fv_dir, out_file)
bins = bytearray()
new_list = []
for src, algo, val, mode, pos in file_list:
if mode & STITCH_OPS.MODE_FILE_IGNOR:
continue
new_list.append((src, algo, val, mode, pos))
if src == 'EMPTY':
bins.extend (b'\xff' * val)
continue
src_path = os.path.join(self._fv_dir, src)
bas_path = os.path.splitext(src_path)[0]
if not os.path.exists(src_path):
raise Exception ("Component '%s' could not be found !" % src)
if algo:
compress(src_path, algo)
src_path = bas_path + '.lz'
else:
if src == 'STAGE2.fd':
raise Exception ("STAGE2.fd must be compressed, please change BoardConfig.py file !")
if src not in rgn_name_list:
gen_hash_file (src_path, HASH_VAL_STRING[self._board.SIGN_HASH_TYPE], '', False)
if mode != STITCH_OPS.MODE_FILE_NOP:
dst_path = bas_path + '.pad'
align_pad_file(src_path, dst_path, val, mode, pos)
src_path = dst_path
else:
if val and (val != os.path.getsize(src_path)):
raise Exception ("Size of file '%s' does not match expected 0x%X !" % (src_path, val))
if 'STAGE1A' in src :
self.update_hash_table (src_path)
fi = open(src_path, 'rb')
bins.extend(bytearray(fi.read()))
fi.close()
if comp_name == self._image:
bins = b'\xff' * (self._board.SLIMBOOTLOADER_SIZE - len(bins)) + bins
fo = open(out_path,'wb')
fo.write(bins)
fo.close()
comp_file = out_file
comp_node = find_component_in_image_list (comp_name, self._img_list)
if comp_node:
space = comp_node[2] - len(bins)
if space > 0:
empty = ('EMPTY', '', space, STITCH_OPS.MODE_FILE_NOP, STITCH_OPS.MODE_POS_HEAD)
if comp_node[4] == STITCH_OPS.MODE_POS_HEAD:
new_list.insert (0, empty)
else:
new_list.append (empty)
comp_file = os.path.splitext(comp_name)[0] + '.pad'
image_base = self._board.FLASH_LAYOUT_START
comp_name = comp_name.replace ('TOP_SWAP_B.', 'TOP_SWAP_A.')
if comp_name in rgn_name_list:
idx = rgn_name_list.index(comp_name)
image_base = self._region_list[idx]['base'] + self._region_list[idx]['size']
layout_file.write("IMAGE_INFO = ['%s', 0x%X, %d]\n" % (comp_file, image_base, True))
layout_file.write("IMAGE_LIST = %s\n" % new_list)
layout_file.close()
self.update_fit_table ()
# generate flash layout file
layout_file = os.path.splitext(self._image)[0] + '.txt'
report_image_layout (self._fv_dir, layout_name, layout_file)
# copy files to staging directory for stitching
if getattr(self._board, "GetOutputImages", None):
extra_list = self._board.GetOutputImages()
else:
extra_list = []
out_file = os.path.join("Outputs", self._board.BOARD_NAME, 'Stitch_Components.zip')
copy_images_to_output (self._fv_dir, out_file, self._img_list, rgn_name_list, extra_list)
def pre_build(self):
# Check if BaseTools has been compiled
rebuild_basetools ()
# Update search path
sbl_dir = os.environ['SBL_SOURCE']
plt_dir = os.environ['PLT_SOURCE']
os.environ['PACKAGES_PATH'] = plt_dir
if plt_dir != sbl_dir:
os.environ['PACKAGES_PATH'] += os.pathsep + sbl_dir
# create conf and build folder if not exist
if not os.path.exists(os.path.join(self._workspace, 'Conf')):
os.makedirs(os.path.join(self._workspace, 'Conf'))
for name in ['target', 'tools_def', 'build_rule']:
txt_file = os.path.join(self._workspace, 'Conf/%s.txt' % name)
if not os.path.exists(txt_file):
shutil.copy (
os.path.join(sbl_dir, 'BaseTools/Conf/%s.template' % name),
os.path.join(self._workspace, 'Conf/%s.txt' % name))
if not os.path.exists(self._fv_dir):
os.makedirs(self._fv_dir)
# check if FSP binary exists
fsp_dir = os.path.join(plt_dir, 'Silicon', self._board.SILICON_PKG_NAME, "FspBin", self._board._FSP_PATH_NAME)
work_dir = plt_dir
if not os.path.exists(fsp_dir):
fsp_dir = os.path.join(sbl_dir, 'Silicon', self._board.SILICON_PKG_NAME, "FspBin", self._board._FSP_PATH_NAME)
work_dir = sbl_dir
fsp_path = os.path.join(fsp_dir, self._fsp_basename + '.bin')
check_build_component_bin = os.path.join(tool_dir, 'PrepareBuildComponentBin.py')
if os.path.exists(check_build_component_bin):
ret = subprocess.call([sys.executable, check_build_component_bin, work_dir, self._board.SILICON_PKG_NAME, '/d' if self._board.FSPDEBUG_MODE else '/r'])
if ret:
raise Exception ('Failed to prepare build component binaries !')
# create FSP size and UPD size can be known
fsp_list = ['FSP_T', 'FSP_M', 'FSP_S']
if self._board.HAVE_FSP_BIN:
split_fsp (fsp_path, self._fv_dir)
else:
# create dummy FSP files
for each in fsp_list:
open(os.path.join(self._fv_dir, each + '.bin'),'wb').close()
# generate size variables
for each in fsp_list:
fsp_bin = os.path.join(self._fv_dir, "%s.bin" % each)
if self._board.FSP_IMAGE_ID:
imageid = get_fsp_image_id (fsp_bin)
if self._board.FSP_IMAGE_ID != imageid:
raise Exception ('Expecting FSP ImageId: %s, but got %s !' % (self._board.FSP_IMAGE_ID, imageid))
revision = get_fsp_revision (fsp_bin)
if revision < self._board.MIN_FSP_REVISION:
raise Exception ('Required minimum FSP revision is 0x%08X, but current revision is 0x%08X !' %
(self._board.MIN_FSP_REVISION, revision))
setattr(self._board, '%s_SIZE' % each, get_fsp_size(fsp_bin) if self._board.HAVE_FSP_BIN else 0)
setattr(self._board, '%s_UPD_SIZE' % each, get_fsp_upd_size(fsp_bin) if self._board.HAVE_FSP_BIN else 0)
if self._board.BUILD_CSME_UPDATE_DRIVER:
if os.name != 'nt':
raise Exception ('BUILD_CSME_UPDATE_DRIVER is enabled, build only works in WINDOWS !')
# create component base/size variables
self.update_component_list ()
self.create_platform_vars ()
# generate a padding file
gen_file_with_size (os.path.join(self._fv_dir, 'PADDING.bin'), 0)
# create flashmap file
comp_list = self._comp_list
if len(self._comp_list) == 0 and getattr(self._board, "GetFlashMapList", None):
comp_list = self._board.GetFlashMapList()
gen_flash_map_bin (os.path.join(self._fv_dir, 'FlashMap.bin'), comp_list)
if not self._board.HAVE_VERIFIED_BOOT and self._board.HAVE_MEASURED_BOOT:
raise Exception ('Verified Boot must also enabled to enable Measured Boot!')
# create hashstore file
key_hash_list = []
mst_key = None
if self._board.HAVE_VERIFIED_BOOT:
hash_store_size = sizeof(HashStoreTable) + (sizeof(HashStoreData) + HASH_DIGEST_SIZE[HASH_VAL_STRING[self._board.SIGN_HASH_TYPE]]) * HashStoreTable().HASH_STORE_MAX_IDX_NUM
gen_file_with_size (os.path.join(self._fv_dir, 'HashStore.bin'), hash_store_size)
#Intialize with HashStoreTable
fo = open(os.path.join(self._fv_dir, 'HashStore.bin'),'r+b')
hash_store_table = HashStoreTable()
hash_store_table.TotalLength = hash_store_size
fo.write(hash_store_table)
fo.close()
# create key hash file
mst_key = self._board._MASTER_PRIVATE_KEY
if getattr(self._board, "GetKeyHashList", None):
key_hash_list = self._board.GetKeyHashList ()
else:
self._board.VERIFIED_BOOT_HASH_MASK = 0
gen_pub_key_hash_store (mst_key, key_hash_list, HASH_VAL_STRING[self._board.SIGN_HASH_TYPE],
self._key_dir, os.path.join(self._fv_dir, 'KEYHASH.bin'))
# create fit table
if self._board.HAVE_FIT_TABLE:
FitSize = sizeof(FitEntry) * (self._board.FIT_ENTRY_MAX_NUM - 1)
if self._board.ACM_SIZE > 0:
# Make sure FIT table start address and end address are 64 bytes aligned.
FitSize = ((FitSize + 0x3F) & ~0x3F) + 0x3F
gen_file_with_size (os.path.join(self._fv_dir, 'FitTable.bin'), FitSize)
# create bootloader version info file
ver_info_name = 'VerInfo'
ver_bin_file = os.path.join(self._fv_dir, ver_info_name + '.bin')
ver_txt_file = os.path.join(os.environ['PLT_SOURCE'], 'Platform', self._board.BOARD_PKG_NAME, ver_info_name + '.txt')
keys = ['VERINFO_IMAGE_ID', 'VERINFO_BUILD_DATE', 'VERINFO_PROJ_MINOR_VER',
'VERINFO_PROJ_MAJOR_VER', 'VERINFO_CORE_MINOR_VER', 'VERINFO_CORE_MAJOR_VER',
'VERINFO_SVN', 'FSPDEBUG_MODE', 'RELEASE_MODE']
ver_dict = {}
for key in keys:
ver_dict[key] = getattr (self._board, key)
if self._board.USE_VERSION:
ver_info = get_verinfo_via_file (ver_dict, ver_txt_file)
else:
ver_info = get_verinfo_via_git (ver_dict, os.environ['PLT_SOURCE'])
gen_ver_info_txt (ver_txt_file, ver_info)
gen_file_from_object (ver_bin_file, ver_info)
# create VBT file
if self._board.HAVE_VBT_BIN:
gen_vbt_file (self._board.BOARD_PKG_NAME, self._board._MULTI_VBT_FILE, os.path.join(self._fv_dir, 'Vbt.bin'))
# create platform include dsc file
platform_dsc_path = os.path.join(sbl_dir, 'BootloaderCorePkg', 'Platform.dsc')
self.create_dsc_inc_file (platform_dsc_path)
# rebase FSP accordingly
if self._board.HAVE_FSP_BIN:
rebase_fsp(fsp_path, self._fv_dir, self._board.FSP_T_BASE, self._board.FSP_M_BASE, self._board.FSP_S_BASE)
split_fsp(os.path.join(self._fv_dir, 'Fsp.bin'), self._fv_dir)
# create master key hash
if self._board.HAVE_VERIFIED_BOOT:
mst_priv_key = self._board._MASTER_PRIVATE_KEY
mst_pub_key_file = os.path.join(self._fv_dir, "MSTKEY.bin")
gen_pub_key (mst_priv_key, mst_pub_key_file)
gen_hash_file (mst_pub_key_file, HASH_VAL_STRING[self._board.SIGN_HASH_TYPE], '', True)
# create configuration data
if self._board.CFGDATA_SIZE > 0:
# create config data files
gen_config_file (self._fv_dir, self._board.BOARD_PKG_NAME, self._board._PLATFORM_ID,
self._board._CFGDATA_PRIVATE_KEY, self._board.CFG_DATABASE_SIZE, self._board.CFGDATA_SIZE,
self._board._CFGDATA_INT_FILE, self._board._CFGDATA_EXT_FILE, HASH_VAL_STRING[self._board.SIGN_HASH_TYPE])
# rebuild reset vector
vtf_dir = os.path.join('BootloaderCorePkg', 'Stage1A', 'Ia32', 'Vtf0')
x = subprocess.call([sys.executable, 'Build.py'], cwd=vtf_dir)
if x: raise Exception ('Failed to build reset vector !')
def build(self):
print("Build [%s] ..." % self._board.BOARD_NAME)
# Run pre-build
self.pre_build()
# Run build
cmd_args = [
"build" if os.name == 'posix' else "build.bat",
"--platform", os.path.join('BootloaderCorePkg', 'BootloaderCorePkg.dsc'),
"-b", self._target,
"--arch", 'IA32',
"--tagname", self._toolchain,
"-n", str(multiprocessing.cpu_count()),
"-y", "Report.log",
"-Y", "PCD",
"-Y", "FLASH",
"-Y", "LIBRARY"]
run_process (cmd_args)
# Run post-build
self.post_build()
print("Done [%s] !" % self._board.BOARD_NAME)
def post_build(self):
# create bootloader reserved binary of 4K size
gen_file_with_size (os.path.join(self._fv_dir, 'SBLRSVD.bin'), 0x1000)
# create variable region for UEFI payload
if self._board.UEFI_VARIABLE_SIZE > 0:
gen_file_with_size (os.path.join(self._fv_dir, 'UEFIVARIABLE.bin'), self._board.UEFI_VARIABLE_SIZE)
# create ACM binary
if self._board.ACM_SIZE > 0:
gen_file_with_size (os.path.join(self._fv_dir, 'ACM.bin'), self._board.ACM_SIZE)
# create ACM3 binary
if self._board.ACM3_SIZE > 0:
gen_file_with_size (os.path.join(self._fv_dir, 'ACM3.bin'), self._board.ACM3_SIZE)
# create MRC data
if self._board.MRCDATA_SIZE:
gen_file_with_size (os.path.join(self._fv_dir, 'MRCDATA.bin'), self._board.MRCDATA_SIZE)
# create variable binary
if self._board.VARIABLE_SIZE:
varhdr = VariableRegionHeader.from_buffer(bytearray(b'\xFF' * sizeof(VariableRegionHeader)))
varhdr.Signature = b'VARS'
varhdr.Size = self._board.VARIABLE_SIZE >> 1
varhdr.State = 0xFE
varfile = open (os.path.join(self._fv_dir, "VARIABLE.bin"), "wb")
varfile.write(varhdr)
varfile.write(b'\xFF' * (self._board.VARIABLE_SIZE - sizeof(varhdr)));
varfile.close()
# create microcode binary
if self._board.UCODE_SIZE > 0:
shutil.copy (
os.path.join(self._fv_dir, '../IA32/Microcode.bin'),
os.path.join(self._fv_dir, "UCODE.bin"))
# generate payload
gen_payload_bin (self._fv_dir, self._pld_list,
os.path.join(self._fv_dir, "PAYLOAD.bin"),
self._board._CONTAINER_PRIVATE_KEY, HASH_VAL_STRING[self._board.SIGN_HASH_TYPE], self._board.BOARD_PKG_NAME)
# create firmware update key
if self._board.ENABLE_FWU:
srcfile = "../IA32/PayloadPkg/FirmwareUpdate/FirmwareUpdate/OUTPUT/FirmwareUpdate.efi"
shutil.copyfile(
os.path.join(self._fv_dir, srcfile),
os.path.join(self._fv_dir, "FWUPDATE.bin"))
# create SPI IAS image if required
if self._board.SPI_IAS1_SIZE > 0 or self._board.SPI_IAS2_SIZE > 0:
for idx in range (1, 3):
file_path = os.path.join('Platform', self._board.BOARD_PKG_NAME, 'SpiIasBin', 'iasimage%d.bin' % idx)
file_space = getattr(self._board, 'SPI_IAS%d_SIZE' % idx)
gen_ias_file (file_path, file_space, os.path.join(self._fv_dir, "SPI_IAS%d.bin" % idx))
# generate container images
if getattr(self._board, "GetContainerList", None):
container_list = self._board.GetContainerList ()
component_dir = os.path.join(os.environ['PLT_SOURCE'], 'Platform', self._board.BOARD_PKG_NAME, 'Binaries')
gen_container_bin (container_list, self._fv_dir, component_dir, self._key_dir, '')
# patch stages
self.patch_stages ()
# create redundant components
self.create_redundant_components ()
# stitch all components
layout_name = 'ImgStitch.txt'
self.create_bootloader_image (layout_name)
# print flash map
if len(self._comp_list) > 0:
print_addr = False if getattr(self._board, "GetFlashMapList", None) else True
flash_map_text = decode_flash_map (os.path.join(self._fv_dir, 'FlashMap.bin'), print_addr)
print('%s' % flash_map_text)
fd = open (os.path.join(self._fv_dir, 'FlashMap.txt'), 'w')
fd.write (flash_map_text)
fd.close ()
def main():
prep_env ()
board_cfgs = []
board_names = []
# Find all boards
search_dir = os.environ['SBL_SOURCE']
if 'PLT_SOURCE' in os.environ:
search_dir = os.path.abspath(os.path.join(search_dir, os.path.pardir))
board_pkgs = os.listdir (search_dir)
for pkg in board_pkgs:
get_board_config_file (os.path.join (search_dir, pkg), board_cfgs)
for cfgfile in board_cfgs:
brdcfg = imp.load_source('BoardConfig', cfgfile)
board_names.append(brdcfg.Board().BOARD_NAME)
ap = argparse.ArgumentParser()
sp = ap.add_subparsers(help='command')
def cmd_build(args):
for index, name in enumerate(board_names):
if args.board == name:
brdcfg = imp.load_source('BoardConfig', board_cfgs[index])
board = brdcfg.Board(
RELEASE_MODE = args.release, \
NO_OPT_MODE = args.noopt, \
FSPDEBUG_MODE = args.fspdebug, \
USE_VERSION = args.usever, \
_PAYLOAD_NAME = args.payload, \
_FSP_PATH_NAME = args.fsppath
);
os.environ['PLT_SOURCE'] = os.path.abspath (os.path.join (os.path.dirname (board_cfgs[index]), '../..'))
Build(board).build()
break
buildp = sp.add_parser('build', help='build firmware')
buildp.add_argument('-r', '--release', action='store_true', help='Release build')
buildp.add_argument('-v', '--usever', action='store_true', help='Use board version file')
buildp.add_argument('-fp', dest='fsppath', type=str, help='FSP binary path relative to FspBin in Silicon folder', default='')
buildp.add_argument('-fd', '--fspdebug', action='store_true', help='Use debug FSP binary')
buildp.add_argument('-no', '--noopt', action='store_true', help='No compile/link optimization for debugging purpose. Not enabled in Release build.')
buildp.add_argument('-p', '--payload' , dest='payload', type=str, help='Payload file name', default ='OsLoader.efi')
buildp.add_argument('board', metavar='board', choices=board_names, help='Board Name (%s)' % ', '.join(board_names))
buildp.set_defaults(func=cmd_build)
def cmd_clean(args):
workspace = os.environ['WORKSPACE']
sbl_dir = os.environ['SBL_SOURCE']
dirs = ['Build', 'Conf']
files = [
os.path.join (sbl_dir, 'BootloaderCorePkg/Stage1A/Ia32/Vtf0/Bin/ResetVector.ia32.raw'),
os.path.join (sbl_dir, 'BootloaderCorePkg/Platform.dsc'),
os.path.join (workspace, 'Report.log')
]
if args.distclean:
dirs.extend ([
'Outputs',
])
files.extend ([
])
for dir in dirs:
dirpath = os.path.join (workspace, dir)
print('Removing %s' % dirpath)
shutil.rmtree(dirpath, ignore_errors=True)
for file in files:
if os.path.exists(file):
print('Removing %s' % file)
os.remove(file)
if os.path.exists(os.path.join (sbl_dir, '.git')):
cmd = 'git clean -xdf BaseTools'
x = subprocess.call(cmd.split(' '), cwd=sbl_dir)
if x: raise Exception ('Failed to run clean-up commands !')
print('Clean Done !')
cleanp = sp.add_parser('clean', help='clean build dir')
cleanp.add_argument('-d', '--distclean', action='store_true', help='Distribution clean')
cleanp.set_defaults(func=cmd_clean)
args = ap.parse_args()
args.func(args)
if __name__ == '__main__':
main()