Reverse Engineering the XSA File
- Introduction
- Extracting the XSA
- Hardware Definition
- Hardware Handoff
- Block Design TCL
- Acceleration Resources
- Processing System Initialization
Introduction
The XSA extension stands for Xilinx Shell Archive and these files are generated by Vivado to contain the required hardware information to develop embedded software with Vitis.
The official documentation from Xilinx states that XSA is a Xilinx proprietary file format and only Xilinx software tools understand it. Despite this fact, the XSA files can be easily disassembled and analyzed.
Extracting the XSA
As a first approach to the information content in a XSA file, we will focus in the Vivado hardware design we exported for a design that only makes use of the Processing System, ultra96v2_standalone.xsa.
If we took a look to the generated file for our standalone MPSoC design, we have that this is just a compressed folder. As an example, if we use the file tool in Linux, we can verify the compression type:
file ultra96v2_standalone.xsa
This command generates the following output that confirms that the XSA file is just a Zip compressed folder:
ultra96v2_standalone.xsa: Zip archive data, at least v2.0 to extract
In order to analyze the components that are actually included in the XSA file, we will decompress it into a folder. This can be done with any Zip capable tool, e.g. the unzip command line tool.
If you are using an Ubuntu/Debian distro, you can install it with APT:
sudo apt-get install unzip
If you are using CentOS/RHEL, you can install it with:
yum install unzip
Now, we can decompress the XSA to a new folder with the following command. I you are not following the paths included in the tutorial, change it accordingly:
cd ~/soc-course/vivado/
unzip ultra96v2_standalone/ultra96v2_standalone.xsa -d ultra96v2_standalone_xsa
Now, in the ultra96v2_standalone_xsa folder we have the actual contents of our XSA file:
ultra96v2_standalone_xsa/
├── design_1_bd.tcl
├── design_1.hwh
├── hwdef.xml
├── psu_init.c
├── psu_init_gpl.c
├── psu_init_gpl.h
├── psu_init.h
├── psu_init.html
├── psu_init.tcl
├── ultra96v2.jpg
├── xsa.json
└── xsa.xml
Now that we have uncompressed the XSA contents, we can analyze each of the included files.
Hardware Definition
The hardware definition is the file hwdef.xml, that acts as an index for the components included in the XSA. Inside it, we can find the basic definition of the most important ones:
<?xml version="1.0"?>
<Project Version="1" Minor="4" DIGEST="">
<TOOL_VERSION Version="2019.2"/>
<MODE Name="Pre-Synthesis"/>
<SYSTEMINFO BOARD="em.avnet.com:ultra96v2:1.0" PART="xczu3eg-sbva484-1-e" ARCH="zynquplus" PACKAGE="sbva484" DEVICE="xczu3eg" SPEED="-1"/>
<HIERARCHY Name="design_1_wrapper"/>
<File Type="HW_HANDOFF" Name="design_1.hwh" DESIGN_HIERARCHY="design_1_i" BD_TYPE="DEFAULT_BD">
</File>
<File Type="BD_TCL" Name="design_1_bd.tcl">
</File>
<File Type="PS_FSBL_INIT" Name="psu_init.c">
</File>
<File Type="PS_FSBL_INIT" Name="psu_init.h">
</File>
<File Type="PS_FSBL_INIT_GPL" Name="psu_init_gpl.c">
</File>
<File Type="PS_FSBL_INIT_GPL" Name="psu_init_gpl.h">
</File>
<File Type="PS_INIT_HELP" Name="psu_init.html">
</File>
<File Type="PS_XMD_INIT" Name="psu_init.tcl">
</File>
<BOARD Type="NotIntegrated">
<BASEBOARD Name="em.avnet.com:ultra96v2:1.0">
</BASEBOARD>
</BOARD>
<USEDRESOURCES/>
</Project>
Hardware Handoff
The file called after the name of the block design and with extension .hwh, in our example design_1.hwh, is the Hardware Handoff file. This file is written in XML format and contains the following information:
- Vivado tool version, part, and board tag information
- IP Cores information, including instance, name, and parameters
- Memory Map information of the processors and associated peripherals.
- Internal Connectivity information (including interrupts, clocks, etc.) and external ports information.
Vitis will use the contents of this file to create Board Support Packages (BSP) for our design.
Block Design TCL
The file called after the design, with suffix _bd and extension .tcl, in our example design_1_bd.tcl, is the Block Design TCL. This file can be used from the Vivado TCL console to recreate the original block design included in the exported hardware.
In order to do this, we can execute this command in the Vivado TCL console:
source source design_1_bd.tcl
Acceleration Resources
The xsa.json and xsa.xml files include information about the design that will be used if this is used as a platform for hardware acceleration and high-level synthesis.
In addition to other parameters, these files describes:
- Acceleration Binary Format
- Available Compute Units
- OpenCL regions
- etc.
Processing System Initialization
The Processing System Ultrascale (PSU) initialization files are related with the boot process in the Zynq UltraScale+ MPSoC. These files are critical as they are include the low-level software configuration information that any Zynq MPSoC design to boot.
psu_init.html
The psu_init.html file includes a summary of the configuration of the Zynq UltraScale+ PS in the design for easy user review. It can be opened with any internet browser and includes information about:
- MIO Configurations: Pin multiplexing and I/O types and strength.
- CLK Configurations: Clock source and frequencies for cores and peripherals.
- DDR Configurations: Memory parameters and low level configurations.
- GT Configurations: GT lanes information, reference clocks and used protocols.
psu_init.c/h
The psu_init.c file contains the C language code defining the value for all the registers in the Processing System that should be applied for a proper initialization of the MPSoC.
The psu_init.h is the C header file to properly include the psu_init.c file in other programs.
These files are used by the First Stage Bootloader (FSBL) to initialize the system with the specific values for a design in the post configuration booting stage.
psu_init_gpl.c/h
The contents of the psu_init_gpl.c and psu_init_gpl.h files are exactly the same of those of the psu_init.c and psu_init.h files but released under a GPLv2 license.
As an example, we can generate the diff for the headers by using this command:
diff -u psu_init.h psu_init_gpl.h
And this is the resulting outcomes:
--- psu_init.h 2020-06-04 18:23:24.000000000 +0200
+++ psu_init_gpl.h 2020-06-04 18:23:24.000000000 +0200
@@ -1,30 +1,26 @@
/******************************************************************************
*
-* Copyright (C) 2010-2019 Xilinx, Inc. All rights reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy
-* of this software and associated documentation files (the "Software"), to deal
-* in the Software without restriction, including without limitation the rights
-* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-* copies of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in
-* all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*
+* Copyright (C) 2010-2019 <Xilinx Inc.>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, see <http://www.gnu.org/licenses/>
+*
+*
******************************************************************************/
/****************************************************************************/
/**
*
-* @file psu_init.h
+* @file psu_init_gpl.h
*
* This file is automatically generated
*
The original purpose of these GPL licensed files was to be used with the U-Boot Secondary Program Loader (SPL), a generic implementation included in the GPL licensed U-Boot code that can be used to replace the Xilinx First Stage Boot Loader in the previous generation of Xilinx SoCs, i.e. the Zynq-7000 family.
U-Boot SPL cannot be used on ZynqMP devices, as the PMU Firmware uses the hardware configuration data provided by the FSBL to get knowledge of the platform. As far as the SPL does not handle this configuration data the board bring up cannot be completed successfully.
The PMU Firmware is a mandatory component for a Linux based, so the FSBL based flow is required for Zynq UltraScale+ MPSoC.
psu_init.tcl
Equivalent to psu_init.c is used when booting in JTAG mode to properly configure the system before launching an application for debugging purposes.