From 82ed40d3860eb42faca1e2a895ceb1815406fe33 Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Mallo Date: Tue, 25 Feb 2025 17:08:13 +0100 Subject: [PATCH] Add FPGA u280 firmware (working ok) --- m/raccoon/configuration.nix | 1 + m/raccoon/xilinx-create-xsabin.sh | 335 ++++++++++++++++++++++++++++++ m/raccoon/xilinx-fw.nix | 75 +++++++ m/raccoon/xilinx-xrt.nix | 5 + 4 files changed, 416 insertions(+) create mode 100755 m/raccoon/xilinx-create-xsabin.sh create mode 100644 m/raccoon/xilinx-fw.nix diff --git a/m/raccoon/configuration.nix b/m/raccoon/configuration.nix index e971515d..390645a4 100644 --- a/m/raccoon/configuration.nix +++ b/m/raccoon/configuration.nix @@ -37,6 +37,7 @@ nixpkgs.overlays = [ (final: prev: { xilinx-xrt = prev.callPackage ./xilinx-xrt.nix { }; + xilinx-fw = prev.callPackage ./xilinx-fw.nix { }; xilinx-xocl = prev.callPackage ./xilinx-xocl.nix { kernel = config.boot.kernelPackages.kernel; }; diff --git a/m/raccoon/xilinx-create-xsabin.sh b/m/raccoon/xilinx-create-xsabin.sh new file mode 100755 index 00000000..893eb5cc --- /dev/null +++ b/m/raccoon/xilinx-create-xsabin.sh @@ -0,0 +1,335 @@ +#!/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//// +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" diff --git a/m/raccoon/xilinx-fw.nix b/m/raccoon/xilinx-fw.nix new file mode 100644 index 00000000..16186aca --- /dev/null +++ b/m/raccoon/xilinx-fw.nix @@ -0,0 +1,75 @@ +{ + stdenv +, lib +, dpkg +, fetchurl +, xilinx-xrt +}: + +with lib; + +# Must read: https://xilinx.github.io/XRT/master/html/platforms_partitions.html#shell +# Taken from: +# - https://aur.archlinux.org/packages/xilinx-sc-fw-u280 +# - https://aur.archlinux.org/packages/xilinx-u280-gen3x16-xdma-base + +stdenv.mkDerivation rec { + pname = "xilinx-fw"; + version = "1.3.5-3592445"; + srcs = [ + # List packages with: curl https://packages.xilinx.com/artifactory/debian-packages-cache/pool/ + (fetchurl { + url = "https://packages.xilinx.com/artifactory/debian-packages-cache/pool/xilinx-cmc-u280_1.3.5-3592445_all.deb"; + hash = "sha256-H48bdeuBc9dK6LExMnw1RCfY85PKntBk/X8CMcAI+zI="; + }) + (fetchurl { + url = "https://packages.xilinx.com/artifactory/debian-packages-cache/pool/xilinx-sc-fw-u280_4.3.28-1.ea1b92f_all.deb"; + hash = "sha256-JxQal2IqYAgebAgfjs2noFG5ghxC9sJQFppJFUCx6jA="; + }) + (fetchurl { + url = "https://packages.xilinx.com/artifactory/debian-packages-cache/pool/xilinx-u280-gen3x16-xdma-base_1-3585717_all.deb"; + hash = "sha256-oe84YgmmRFZjNa63j0pIneuFUG0Bb4aA7wulyU4bCrY="; + }) + (fetchurl { + url = "https://packages.xilinx.com/artifactory/debian-packages-cache/pool/xilinx-u280-gen3x16-xdma-validate_1-3585755_all.deb"; + hash = "sha256-F+IAzR8NVc9FDsgQstpBcKeq3ogH1PI8nuq94sEExCg="; + }) + # Needed for the ERT firmware + (fetchurl { + url = "https://packages.xilinx.com/artifactory/debian-packages-cache/pool/xrt_202320.2.16.204_22.04-amd64-xrt.deb"; + hash = "sha256-FEhzx2KlIYpunXmTSBjtyAtblbuz5tkvnt2qp21gUho="; + }) + ]; + + dontStrip = true; + hardeningDisable = [ "all" ]; + nativeBuildInputs = [ dpkg ]; + unpackPhase = '' + for f in $srcs; do + dpkg-deb -x "$f" deb + done + sourceRoot=deb + ''; + # Generate the xsabin firmware file by fixing the original script + buildPhase = '' + set -x + + ln -rs lib/firmware/xilinx/283bab8f654d8674968f4da57f7fa5d7 lib/firmware/xilinx/fb2b2c5a19ed63593fea95f51fbc8eb9 + ln -rs lib/firmware/xilinx/283bab8f654d8674968f4da57f7fa5d7/partition_metadata.json opt/xilinx/firmware/u280/gen3x16-xdma/base/partition_metadata.json + ln -rs lib/firmware/xilinx/283bab8f654d8674968f4da57f7fa5d7/partition.xsabin opt/xilinx/firmware/u280/gen3x16-xdma/base/partition.xsabin + ln -rs opt/xilinx/xrt/share/fw opt/xilinx/firmware/u280/gen3x16-xdma/base/firmware/ert-v30 + ln -rs opt/xilinx/firmware/cmc/u280 opt/xilinx/firmware/u280/gen3x16-xdma/base/firmware/cmc-u280 + ln -rs opt/xilinx/firmware/sc-fw/u280 opt/xilinx/firmware/u280/gen3x16-xdma/base/firmware/sc-fw-u280 + + find + + export xclbinutil=${xilinx-xrt}/xrt/bin/xclbinutil + cp -a ${./xilinx-create-xsabin.sh} opt/xilinx/firmware/u280/gen3x16-xdma/base/scripts/create_xsabin.sh + bash -x opt/xilinx/firmware/u280/gen3x16-xdma/base/scripts/create_xsabin.sh xilinx-u280-gen3x16-xdma-base 1 3585717 + set +x + ''; + installPhase = '' + mkdir -p $out + cp -a * $out + ''; +} diff --git a/m/raccoon/xilinx-xrt.nix b/m/raccoon/xilinx-xrt.nix index 199bc4e3..ec9f50b5 100644 --- a/m/raccoon/xilinx-xrt.nix +++ b/m/raccoon/xilinx-xrt.nix @@ -46,6 +46,11 @@ stdenv.mkDerivation rec { "-DXRT_INSTALL_DIR=${placeholder "out"}" "-DXRT_NATIVE_BUILD=yes" "-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON" + # Enable debug + "-DCMAKE_BUILD_TYPE=RelWithDebInfo" + #"-DCMAKE_BUILD_TYPE=Debug" + #"-DXOCL_VERBOSE=1" + #"-DXRT_VERBOSE=1" ]; # A directory named "build" already exists cmakeBuildDir = "the-build";