336 lines
12 KiB
Bash
Executable File
336 lines
12 KiB
Bash
Executable File
#!/bin/bash
|
|
## (c) Copyright 2020 Xilinx, Inc. All rights reserved.
|
|
##
|
|
## This file contains confidential and proprietary information
|
|
## of Xilinx, Inc. and is protected under U.S. and
|
|
## international copyright and other intellectual property
|
|
## laws.
|
|
##
|
|
## DISCLAIMER
|
|
## This disclaimer is not a license and does not grant any
|
|
## rights to the materials distributed herewith. Except as
|
|
## otherwise provided in a valid license issued to you by
|
|
## Xilinx, and to the maximum extent permitted by applicable
|
|
## law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
|
|
## WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
|
|
## AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
|
|
## BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
|
|
## INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
|
|
## (2) Xilinx shall not be liable (whether in contract or tort,
|
|
## including negligence, or under any other theory of
|
|
## liability) for any loss or damage of any kind or nature
|
|
## related to, arising under or in connection with these
|
|
## materials, including for any direct, or any indirect,
|
|
## special, incidental, or consequential loss or damage
|
|
## (including loss of data, profits, goodwill, or any type of
|
|
## loss or damage suffered as a result of any action brought
|
|
## by a third party) even if such damage or loss was
|
|
## reasonably foreseeable or Xilinx had been advised of the
|
|
## possibility of the same.
|
|
##
|
|
## CRITICAL APPLICATIONS
|
|
## Xilinx products are not designed or intended to be fail-
|
|
## safe, or for use in any application requiring fail-safe
|
|
## performance, such as life-support or safety devices or
|
|
## systems, Class III medical devices, nuclear facilities,
|
|
## applications related to the deployment of airbags, or any
|
|
## other applications that could lead to death, personal
|
|
## injury, or severe property or environmental damage
|
|
## (individually and collectively, "Critical
|
|
## Applications"). Customer assumes the sole risk and
|
|
## liability of any use of Xilinx products in Critical
|
|
## Applications, subject only to applicable laws and
|
|
## regulations governing limitations on product liability.
|
|
##
|
|
## THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
|
|
## PART OF THIS FILE AT ALL TIMES.
|
|
|
|
# This script must be run with root permissions
|
|
# if [[ "$EUID" -ne 0 ]]; then
|
|
# echo "This script must be run as root."
|
|
# exit
|
|
# fi
|
|
|
|
# Get absolute path to this script with any symlinks resolved
|
|
realme=$(realpath $0)
|
|
scriptpath="${realme%/*}"
|
|
echo "This is create_xsabin.sh running from $scriptpath on $(date)"
|
|
|
|
# The directory above that is the human-readable installation path - probably /opt/xilinx/firmware/<card>/<family>/<partition>/
|
|
humanpath=${scriptpath%/*}
|
|
pushd $humanpath > /dev/null
|
|
|
|
# This script may be called during firmware upgrade, in which case the firmware product, branch, version and release
|
|
# are provided as script arguments, to help this script to select the new firmware file
|
|
if [[ "$#" -ge 4 ]]; then
|
|
firmware_upgrade_product=$1
|
|
firmware_upgrade_branch=$2
|
|
firmware_upgrade_version=$3
|
|
firmware_upgrade_release=$4
|
|
echo "Run for install of firmware $firmware_upgrade_product-$firmware_upgrade_branch version $firmware_upgrade_version release $firmware_upgrade_release"
|
|
elif [[ "$#" -eq 3 ]]; then
|
|
# If 3 script arguments, these are the partition name, version and release, so that this script can report them for debug
|
|
echo "Run for install of partition $1 version $2 release $3"
|
|
fi
|
|
|
|
# Find the partition_metadata.json link in the install directory
|
|
jsonlink="partition_metadata.json"
|
|
if [[ ! -e "$jsonlink" ]]; then
|
|
echo "Cannot find $jsonlink file in $humanpath - install failed"
|
|
exit 1
|
|
fi
|
|
|
|
# Find the machine-readable directory for this partition:
|
|
# this is the target of the partition_metadata.json link
|
|
if [[ ! -h "$jsonlink" ]]; then
|
|
echo "$jsonlink in $humanpath should be a symlink, but it is not - install failed"
|
|
exit 1
|
|
fi
|
|
jsonpath=$(readlink $jsonlink)
|
|
if [[ $? -ne 0 ]]; then
|
|
echo "Failed to read target of symlink $jsonlink in $humanpath - install failed"
|
|
exit 1
|
|
fi
|
|
if [[ ! -e "$jsonpath" ]]; then
|
|
echo "Target of symlink $jsonlink in $humanpath is $jsonpath, which does not exist - install failed"
|
|
exit 1
|
|
fi
|
|
echo "Metadata file is $jsonpath"
|
|
machinepath=${jsonpath%/*}
|
|
json=${jsonpath##*/}
|
|
echo "User install path is $humanpath"
|
|
echo "Machine-readable path is $machinepath"
|
|
pushd $machinepath > /dev/null
|
|
|
|
# Parse the partition_metadata.json file to find the required firmware
|
|
declare -A firmware
|
|
firmware_products=()
|
|
product=""
|
|
branch="mainline"
|
|
major="*"
|
|
minor="*"
|
|
revision="*"
|
|
while IFS= read -r line; do
|
|
key=${line#*\"}
|
|
key=${key%%\"*}
|
|
value=${line%\"*}
|
|
value=${value##*\"}
|
|
numvalue=$value
|
|
if [[ "$numvalue" =~ ^0x ]]; then
|
|
numvalue=$(($numvalue))
|
|
fi
|
|
case "$key" in
|
|
"firmware")
|
|
# Starts a new section: record current one (except if before the first section)
|
|
if [[ -n "$product" ]]; then
|
|
firmware_products+=($product)
|
|
firmware["$product.branch"]=$branch
|
|
firmware["$product.version"]="$major.$minor.$revision"
|
|
product=""
|
|
branch="mainline"
|
|
major="*"
|
|
minor="*"
|
|
revision="*"
|
|
fi
|
|
;;
|
|
"firmware_product_name")
|
|
product=${value,,}
|
|
;;
|
|
"firmware_branch_name")
|
|
branch=${value,,}
|
|
;;
|
|
"firmware_version_major")
|
|
major=$numvalue
|
|
;;
|
|
"firmware_version_minor")
|
|
minor=$numvalue
|
|
;;
|
|
"firmware_version_revision")
|
|
revision=$numvalue
|
|
;;
|
|
esac
|
|
done <<< "$(grep '\"firmware' $json)"
|
|
# Record last section
|
|
firmware_products+=($product)
|
|
firmware["$product.branch"]=$branch
|
|
firmware["$product.version"]="$major.$minor.$revision"
|
|
|
|
# Locate the required firmware in existing installed directories, and build xclbinutil options to add firmware
|
|
# For each firmware, there is already a symlink in the human-readable directory's firmware directory
|
|
# which points to the existing firmware install directory
|
|
firmware_opts=""
|
|
for product in "${firmware_products[@]}"; do
|
|
uc_product=${product^^}
|
|
branch=${firmware[$product.branch]}
|
|
version=${firmware[$product.version]}
|
|
link="$humanpath/firmware/$product-$branch"
|
|
if [[ ! -L "$link" ]]; then
|
|
echo "Expected symlink $link for required $product firmware, but this either does not exist or is not a symlink - install failed"
|
|
exit 1
|
|
fi
|
|
firmware_path=$(readlink -f $humanpath/firmware/$product-$branch)
|
|
if [[ ! -e "$firmware_path" ]]; then
|
|
echo "Required $product firmware install directory not found at $firmware_path. Unable to build xsabin files"
|
|
exit 1
|
|
fi
|
|
# Locate the required firmware binary file
|
|
case "$product" in
|
|
"ert")
|
|
# ERT firmware is deployed within XRT and has its own file naming rule
|
|
if [[ "$branch" == "mainline" ]] || [[ "$branch" == "legacy" ]] || [[ "$branch" == "" ]]; then
|
|
ert_name="sched.bin"
|
|
else
|
|
ert_name="sched_$branch.bin"
|
|
fi
|
|
firmware_file="$firmware_path/$ert_name"
|
|
if [[ ! -e "$firmware_file" ]]; then
|
|
echo "Cannot locate required $product firmware: not found at $firmware_file. Unable to build xsabin files"
|
|
exit 1
|
|
fi
|
|
firmware_opts+=" --add-section SCHED_FIRMWARE:RAW:${firmware_file}"
|
|
;;
|
|
*)
|
|
# All other firmware is deployed in its own package
|
|
# Accommodate possible variations in firmware file name, as long as the file name contains the product name
|
|
# During firmware upgrade, it is possible that both the old and the new firmware files are both present
|
|
# (the old one may not be removed until after this script has run).
|
|
# In this situation, the new firmware product, branch and version are provided as script arguments:
|
|
# select the appropriate file here (if multiple files are found).
|
|
firmware_files=()
|
|
for globfile in $firmware_path/*; do
|
|
if [[ -e "$globfile" ]] && [[ ! -d "$globfile" ]]; then
|
|
globfilename=${globfile##*/}
|
|
if [[ "$globfilename" == *"$product"* ]] || [[ "$globfilename" == *"$uc_product"* ]]; then
|
|
firmware_files+=($globfile)
|
|
fi
|
|
fi
|
|
done
|
|
if [[ "${#firmware_files[@]}" -eq 0 ]]; then
|
|
echo "Cannot locate required $product firmware: not found at $firmware_path. Unable to build xsabin files"
|
|
exit 1
|
|
fi
|
|
firmware_file=""
|
|
if [[ "${#firmware_files[@]}" -gt 1 ]]; then
|
|
IFS=$'\n'
|
|
firmware_files=( $(sort -V <<<"${firmware_files[*]}") )
|
|
unset IFS
|
|
if [[ "$firmware_upgrade_product" == "$product" ]]; then
|
|
firmware_file=""
|
|
for fw_file in "${firmware_files[@]}"; do
|
|
fw_filename=${fw_file##*/}
|
|
if [[ "$fw_filename" == *"$firmware_upgrade_version"* ]]; then
|
|
firmware_file=$fw_file
|
|
fi
|
|
done
|
|
fi
|
|
fi
|
|
if [[ -z "$firmware_file" ]]; then
|
|
firmware_file="${firmware_files[-1]}"
|
|
fi
|
|
# Select the correct xsabin section name, depending on the firmware product
|
|
section=""
|
|
case "$product" in
|
|
"cmc")
|
|
section="FIRMWARE"
|
|
;;
|
|
"sc-fw" | "sc")
|
|
section="BMC-FW"
|
|
;;
|
|
*)
|
|
echo "Unrecognised firmware product name '$product', unable to select the correct xsabin section name"
|
|
exit 1
|
|
;;
|
|
esac
|
|
firmware_opts+=" --add-section ${section}:RAW:${firmware_file}"
|
|
# The SC firmware (BMC-FW section) may have a metadata JSON file also to be added
|
|
if [[ "$section" == "BMC-FW" && -e "$firmware_path/metadata.json" ]]; then
|
|
firmware_opts+=" --add-section BMC-METADATA:JSON:${firmware_path}/metadata.json"
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Extract vendor, board, name and version from partition_metadata.json, to build PlatformVBNV
|
|
declare -A vbnv
|
|
for element in {partition_vendor,partition_card,partition_family,partition_name,installed_package_version}; do
|
|
line="$(grep $element $json)"
|
|
if [[ -n "$line" ]]; then
|
|
value=${line%\"*}
|
|
value=${value##*\"}
|
|
if [[ "$element" != "partition_vendor" ]] && [[ "$element" != "partition_card" ]]; then
|
|
value=${value//-/_}
|
|
fi
|
|
else
|
|
value="UNKNOWN"
|
|
fi
|
|
vbnv[$element]=$value
|
|
done
|
|
platform_vbnv="${vbnv[partition_vendor]}:${vbnv[partition_card]}:${vbnv[partition_family]}_${vbnv[partition_name]}:${vbnv[installed_package_version]}"
|
|
|
|
# Check for VBNV override in partition_metadata.json
|
|
line="$(grep vbnv_override $json)"
|
|
if [[ -n "$line" ]]; then
|
|
value=${line%\"*}
|
|
value=${value##*\"}
|
|
# Check VBNV override value is correctly formatted (4 fields separated by colons)
|
|
fields="$(echo "$value" | tr ':' ' ' | wc -w)"
|
|
if [[ "$fields" == "4" ]]; then
|
|
platform_vbnv=$value
|
|
fi
|
|
fi
|
|
|
|
# Use the XRT standard install path to find xclbinutil
|
|
xclbinutil="${xclbinutil:-/opt/xilinx/xrt/bin/xclbinutil}"
|
|
if [[ ! -e "$xclbinutil" ]]; then
|
|
echo "xclbinutil tool not found at $xclbinutil, unable to build xsabin files"
|
|
exit 1
|
|
fi
|
|
|
|
## Must source XRT's setup.sh to set up environment correctly
|
|
#if [[ ! -e /opt/xilinx/xrt/setup.sh ]]; then
|
|
# echo "XRT setup.sh not found at /opt/xilinx/xrt/setup.sh, XRT installation is bad. Cannot build xsabin files"
|
|
# exit 1
|
|
#fi
|
|
#source /opt/xilinx/xrt/setup.sh
|
|
|
|
# Build xclbinutil options for creating xsabin files
|
|
xclbinopts=" --force"
|
|
if [[ -e "partition.mcs" ]]; then
|
|
xclbinopts+=" --add-section MCS-PRIMARY:RAW:partition.mcs"
|
|
fi
|
|
if [[ -e "partition_secondary.mcs" ]]; then
|
|
xclbinopts+=" --add-section MCS-SECONDARY:RAW:partition_secondary.mcs"
|
|
fi
|
|
if [[ -e "partition.bin" ]]; then
|
|
xclbinopts+=" --add-section FLASH[BIN]-DATA:RAW:partition.bin"
|
|
fi
|
|
if [[ -e "bin_metadata.json" ]]; then
|
|
xclbinopts+=" --add-section FLASH[BIN]-METADATA:JSON:bin_metadata.json"
|
|
fi
|
|
if [[ -e "partition.bit" ]]; then
|
|
xclbinopts+=" --add-section BITSTREAM:RAW:partition.bit"
|
|
fi
|
|
if [[ -e "partition.pdi" ]]; then
|
|
xclbinopts+=" --add-section PDI:RAW:partition.pdi"
|
|
fi
|
|
xclbinopts+=" --add-section PARTITION_METADATA:JSON:${json}"
|
|
xclbinopts+=$firmware_opts
|
|
xclbinopts+=" --key-value SYS:PlatformVBNV:${platform_vbnv}"
|
|
|
|
# Create partition.xsabin
|
|
xsabin="partition.xsabin"
|
|
xclbincmd="${xclbinutil} ${xclbinopts} --output $xsabin"
|
|
echo $xclbincmd
|
|
$xclbincmd
|
|
if [[ $? -ne 0 ]]; then
|
|
echo "An error occurred while running xclbinutil"
|
|
exit 1
|
|
fi
|
|
if [[ ! -e "$xsabin" ]]; then
|
|
echo "xclbinutil did not create output file $xsabin"
|
|
exit 1
|
|
fi
|
|
|
|
# And we're done
|
|
echo "create_xsabin.sh completed successfully"
|