Files
slimbootloader/BuildLoader.py
T
Maurice Ma 697c02302f Enable USB keyboard console support for QEMU
Previous USB keyboard console support commit worked fine on APL real
platform, but it has issue on QEMU. This patch further enables USB
keyboard console support for QEMU. A new PcdUsbKeyboardPollingTimeout
is added. It will be used to control the USB keyboard interrupt
transfer polling timeout. For QEMU, it needs a larger number due to
timing issue. As part of it, booting from USB device is also enabled
by this patch. This patch fixes #30.

To test USB keyboard console in QEMU, please first change
CONSOLE_IN _DEVICE_MASK in BoardConfig.py to 3, and then add the
following in the QEMU command line to add XHCI controller and USB KB:
-device qemu-xhci,id=xhci,bus=pcie.0,addr=4 -device usb-kbd,bus=xhci.0

Signed-off-by: Maurice Ma <maurice.ma@intel.com>
2018-10-29 09:39:27 -07:00

1244 lines
45 KiB
Python
Executable File

#!/usr/bin/env python
## @ BuildLoader.py
# Build bootloader main script
#
# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials are licensed and made available under
# the terms and conditions of the BSD License that accompanies this distribution.
# The full text of the license may be 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 IMPLIED.
#
##
##
# 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 ():
ret = 0
sblsource = os.environ['SBL_SOURCE']
if os.name == 'posix':
genffs_exe_path = os.path.join(sblsource, 'BaseTools', 'Source', 'C', 'bin', 'GenFfs')
genffs_exist = os.path.exists(genffs_exe_path)
if not genffs_exist:
ret = subprocess.call(['make', '-C', 'BaseTools'])
elif os.name == 'nt':
build_exe_path = os.path.join(sblsource, 'BaseTools', 'Bin', 'Win32', 'build.exe')
genffs_exe_path = os.path.join(sblsource, 'BaseTools', 'Bin', 'Win32', 'GenFfs.exe')
build_exist = os.path.exists(build_exe_path)
if not build_exist:
print "Could not find pre-built BaseTools binaries, try to rebuild BaseTools ..."
if 'PYTHON_HOME' not in os.environ:
os.environ['PYTHON_HOME'] = 'C:\\Python27'
if 'PYTHON_FREEZER_PATH' not in os.environ:
os.environ['PYTHON_FREEZER_PATH'] = os.path.join(os.environ['PYTHON_HOME'], 'Scripts')
ret = subprocess.call(['BaseTools\\toolsetup.bat', 'forcerebuild'])
if ret:
print "Build BaseTools failed, please check required build environment and utilities !"
sys.exit(1)
genffs_exist = os.path.exists(genffs_exe_path)
if not genffs_exist:
print "Build python executables failed !\n" \
"Please set environment variable PYTHON_FREEZER_PATH properly and then try again!"
sys.exit(1)
def prep_env ():
sblsource = os.path.dirname(os.path.realpath(__file__))
os.chdir(sblsource)
if os.name == 'posix':
toolchain = 'GCC49'
gcc_ver = subprocess.Popen(['gcc', '-dumpversion'], stdout=subprocess.PIPE)
(gcc_ver, err) = subprocess.Popen(['sed', 's/\\..*//'], stdin=gcc_ver.stdout, stdout=subprocess.PIPE).communicate()
if int(gcc_ver) > 4:
toolchain = 'GCC5'
os.environ['PATH'] = os.environ['PATH'] + ':' + os.path.join(sblsource, 'BaseTools/BinWrappers/PosixLike')
elif os.name == 'nt':
toolchain = ''
os.environ['PATH'] = os.environ['PATH'] + ';' + os.path.join(sblsource, 'BaseTools/Bin/Win32')
vs_ver_list = [
('2015', 'VS140COMNTOOLS'),
('2013', 'VS120COMNTOOLS'),
('2012', 'VS110COMNTOOLS'),
('2010', 'VS100COMNTOOLS'),
('2008', 'VS90COMNTOOLS'),
('2005', 'VS80COMNTOOLS')
]
for vs_ver, vs_tool in vs_ver_list:
if vs_tool in os.environ:
toolchain='VS%s%s' % (vs_ver, 'x86')
toolchainprefix = 'VS%s_PREFIX' % (vs_ver)
os.environ[toolchainprefix] = os.path.join(os.environ[vs_tool], '..//..//')
break
if not toolchain:
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)
# Update Environment vars
os.environ['SBL_SOURCE'] = sblsource
os.environ['EDK_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
# Check if BaseTools has been compiled
rebuild_basetools ()
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')
self._CFG_PRIVATE_KEY = os.path.join(key_dir, 'TestSigningPrivateKey.pem')
self._FWU_PRIVATE_KEY = os.path.join(key_dir, 'TestSigningPrivateKey.pem')
self._IAS_PRIVATE_KEY = os.path.join(key_dir, 'TestSigningPrivateKey.pem')
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.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.DEBUG_OUTPUT_DEVICE_MASK = 0x00000003
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_FLASH_MAP = 1
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_CRYPTO_SHA_NI = 0
self.ENABLE_FWU = 0
self.ENABLE_SOURCE_DEBUG = 0
self.ACM_SIZE = 0
self.UCODE_SIZE = 0
self.CFGDATA_SIZE = 0
self.MRCDATA_SIZE = 0
self.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.STAGE2_XIP = 0
self.STAGE2_LOAD_HIGH = 1
self.PAYLOAD_LOAD_HIGH = 0
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
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.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._CFGDATA_INT_FILE = []
self._CFGDATA_EXT_FILE = []
for key, value in 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 '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._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 != Bytes2Val (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))
if self._board.ACM_SIZE > 0:
# ACM
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
# 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
# Keep this temporary to compare BTG with BTG+VerifiedBoot
if not self._board.HAVE_VERIFIED_BOOT:
# Stage2
addr = self._board.STAGE2_BASE
src = 'STAGE2.lz'
src_path = os.path.join(self._fv_dir, src)
if not os.path.exists(src_path):
module_size = (self._board.STAGE2_SIZE >> 4)
else:
module_size = os.path.getsize(src_path)
module_size = ((module_size + 0x3F) & 0xFFFFFFC0) # 0x40 align
module_size = module_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(Stage2)' % (num_fit_entries, fit_entry.address, fit_entry.size))
num_fit_entries += 1
# Payload
addr = self._board.PAYLOAD_BASE
src = 'PAYLOAD.lz'
src_path = os.path.join(self._fv_dir, src)
if not os.path.exists(src_path):
module_size = (self._board.PAYLOAD_SIZE >> 4)
else:
module_size = os.path.getsize(src_path)
module_size = ((module_size + 0x3F) & 0xFFFFFFC0) # 0x40 align
module_size = module_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(Payload)' % (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 :
addr = fit_address.value + (num_fit_entries + 1) * 16
# 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 (HashStore.HASH_STORE_SIGNATURE)
if hs_offset < 0:
raise Exceptoin ("HashStore 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, 0), ('STAGE2.hash', 1), ('PAYLOAD.hash', 2), ('FWUPDATE.hash', 3), ('CFGKEY.hash', 4), ('FWUKEY.hash', 5), ('OSKEY.hash', 6), ('PLDDYN', 7)]
if len(hash_file_list) > HashStore.HASH_STORE_MAX_IDX_NUM:
raise Exception ('Insufficant hash entries !')
hash_store = HashStore.from_buffer(stage1_bins, hs_offset)
hash_len = HashStore.HASH_STORE_ENTRY_LEN
for hash_file, hash_idx in hash_file_list:
# If the hash verification is not required for certain stage, skip it
if ((1 << hash_idx) & self._board.VERIFIED_BOOT_HASH_MASK) == 0:
continue
if hash_file == 'PLDDYN':
hash_data = bytearray('\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
start = hash_len * hash_idx
hash_store.Data[start:start+hash_len] = hash_data
# update valid bit
hash_store.Valid |= 1 << hash_idx
print ' Update HashStore entry %d at offset 0x%08X:0x%X with file %s' % (hash_idx, start, hash_len, hash_file)
fo = open(img_file,'r+b')
fo.seek(hs_offset)
fo.write(hash_store)
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 |= FlashMap.FLASH_MAP_DESC_FLAGS['BACKUP']
if region_name in ['TOP_SWAP', 'REDUNDANT', 'NON_REDUNDANT', 'NON_VOLATILE']:
flags |= FlashMap.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 = FlashMap.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"
]
if self._board.HAVE_FLASH_MAP:
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_PcdKeyStoreBase>, {18EDB1DF-1DBE-4EC5-8E26-C44808B546E1:0x1C}, @Patch KeyStore",
)
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",
)
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):
with open(file, 'w') as fh:
fh.write('%s\n' % AUTO_GEN_DSC_HDR)
fh.write('# Platform specific macro definitions\n')
fh.write('[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
fh.write(' DEFINE %-24s = %s\n' % (attr, value))
if getattr(self._board, "GetDscLibrarys", None):
libsdict = self._board.GetDscLibrarys()
for arch in libsdict:
fh.write('\n# Platform specific libraries\n')
fh.write('[LibraryClasses.%s]\n' % arch)
for lib in libsdict[arch]:
fh.write(' %s\n' % lib)
fh.write('\n')
def create_platform_vars (self):
for comp in self._comp_list:
if comp['flag'] & FlashMap.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)
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'))
# put a marker (@ 0xFFFFFFF4) for STAGE1A_B so that
# boot partition can be detected easily
fo = open(os.path.join(self._fv_dir, 'STAGE1A_B.fd'), 'r+b')
fo.seek(-12, 2)
nop = fo.read(1)
if nop != '\x90':
raise Exception ('Unexpected instructions at reset vector!')
fo.seek(-12, 2)
fo.write('\x80')
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))
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)
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 = '\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):
# 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)
fsp_path = os.path.join(fsp_dir, self._fsp_basename + '.bin')
check_fsp = os.path.join(tool_dir, 'PrepareFspBin.py')
if os.path.exists(check_fsp):
ret = subprocess.call(['python', check_fsp, plt_dir, self._board.BOARD_NAME, '/d' if self._board.FSPDEBUG_MODE else '/r'])
if ret:
raise Exception ('Failed to checkout FSP 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)
# 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
if self._board.HAVE_FLASH_MAP:
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
if self._board.HAVE_VERIFIED_BOOT:
gen_file_from_object (os.path.join(self._fv_dir, 'HashStore.bin'), HashStore())
else:
self._board.VERIFIED_BOOT_HASH_MASK = 0
# 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')
if self._board.USE_VERSION:
ver_info = get_verinfo_via_file (ver_txt_file)
else:
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)
ver_info = get_verinfo_via_git (ver_dict)
gen_ver_info_txt (ver_txt_file, ver_info)
gen_file_from_object (ver_bin_file, ver_info)
# 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 configuration data
if self._board.CFGDATA_SIZE > 0:
# create config key hash
if self._board.HAVE_VERIFIED_BOOT:
cfg_priv_key = self._board._CFG_PRIVATE_KEY
cfg_pub_key_file = os.path.join(self._fv_dir, "CFGKEY.bin")
gen_pub_key (cfg_priv_key, cfg_pub_key_file)
gen_hash_file (cfg_pub_key_file, '', True)
else:
cfg_priv_key = None
# create config data files
gen_config_file (self._fv_dir, self._board.BOARD_PKG_NAME, self._board._PLATFORM_ID,
cfg_priv_key, self._board.CFG_DATABASE_SIZE, self._board.CFGDATA_SIZE,
self._board._CFGDATA_INT_FILE, self._board._CFGDATA_EXT_FILE)
# rebuild reset vector
vtf_dir = os.path.join('BootloaderCorePkg', 'Stage1A', 'Ia32', 'Vtf0')
x = subprocess.call(['python', '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
x = subprocess.call([
"build",
"--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"])
if x: sys.exit(1)
# 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 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 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('\xFF' * sizeof(VariableRegionHeader)))
varhdr.Signature = '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('\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"))
# create OS public key hash
if self._board.HAVE_VERIFIED_BOOT:
ias_pub_key_file = os.path.join(self._fv_dir, "OSKEY.bin")
gen_pub_key (self._board._IAS_PRIVATE_KEY, ias_pub_key_file)
gen_hash_file (ias_pub_key_file, '', True)
# generate payload
gen_payload_bin (self._fv_dir, self._pld_list,
os.path.join(self._fv_dir, "PAYLOAD.bin"),
self._board._CFG_PRIVATE_KEY)
# 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"))
fwup_key_file = os.path.join(self._fv_dir, "FWUKEY.bin")
gen_pub_key (self._board._FWU_PRIVATE_KEY, fwup_key_file)
gen_hash_file (fwup_key_file, '', True)
# create SPI IAS image if required
if self._board.SPI_IAS1_SIZE > 0 or self._board.SPI_IAS2_SIZE > 0:
for idx in xrange (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))
# 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 self._board.HAVE_FLASH_MAP and 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, \
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('-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:
shutil.rmtree(os.path.join (workspace, dir), ignore_errors=True)
for file in files:
if os.path.exists(file):
os.remove(file)
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()