diff --git a/lib/sw_services/xilskey/data/xilskey.mld b/lib/sw_services/xilskey/data/xilskey.mld new file mode 100755 index 00000000..41436f50 --- /dev/null +++ b/lib/sw_services/xilskey/data/xilskey.mld @@ -0,0 +1,51 @@ +############################################################################### +# +# Copyright (C) 2013 - 2014 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. +# +# Use of the Software is limited solely to applications: +# (a) running on a Xilinx device, or +# (b) that interact with a Xilinx device through a bus or interconnect. +# +# 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 +# XILINX CONSORTIUM 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. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### +# +# Modification History +# +# Ver Who Date Changes +# ----- ---- -------- ----------------------------------------------- +# 1.00a rpo 04/24/13 Initial Release +# +############################################################################## + +OPTION psf_version = 2.1; + +BEGIN LIBRARY xilskey + OPTION copyfiles = all; + OPTION REQUIRES_OS = (standalone); + OPTION SUPPORTED_PERIPHERALS = (cortexa9); + OPTION APP_LINKER_FLAGS = "-Wl,--start-group,-lxilskey,-lxil,-lgcc,-lc,--end-group"; + OPTION desc = "Xilinx Secure Key Library "; + OPTION VERSION = 2.1; + OPTION NAME = xilskey; +END LIBRARY diff --git a/lib/sw_services/xilskey/data/xilskey.tcl b/lib/sw_services/xilskey/data/xilskey.tcl new file mode 100755 index 00000000..ffe47050 --- /dev/null +++ b/lib/sw_services/xilskey/data/xilskey.tcl @@ -0,0 +1,86 @@ +############################################################################### +# +# Copyright (C) 2013 - 2014 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. +# +# Use of the Software is limited solely to applications: +# (a) running on a Xilinx device, or +# (b) that interact with a Xilinx device through a bus or interconnect. +# +# 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 +# XILINX CONSORTIUM 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. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### +# +# Modification History +# +# Ver Who Date Changes +# ----- ---- -------- ----------------------------------------------- +# 1.00a rpo 04/25/13 Initial Release +############################################################################## + +#--------------------------------------------- +# skey_drc +#--------------------------------------------- +proc skey_drc {libhandle} { + +} + +proc generate {libhandle} { + +} + +#------- +# post_generate: called after generate called on all libraries +#------- +proc post_generate {libhandle} { + + xgen_opts_file $libhandle +} + +#------- +# execs_generate: called after BSP's, libraries and drivers have been compiled +# This procedure builds the libxilskey.a library +#------- +proc execs_generate {libhandle} { + +} + +proc xgen_opts_file {libhandle} { + + + # Copy the include files to the include directory + set srcdir [file join src include] + set dstdir [file join .. .. include] + + # Create dstdir if it does not exist + if { ! [file exists $dstdir] } { + file mkdir $dstdir + } + + # Get list of files in the srcdir + set sources [glob -join $srcdir *.h] + + # Copy each of the files in the list to dstdir + foreach source $sources { + file copy -force $source $dstdir + } +} diff --git a/lib/sw_services/xilskey/examples/xilskey_bbram_example.c b/lib/sw_services/xilskey/examples/xilskey_bbram_example.c new file mode 100644 index 00000000..9f0dec0f --- /dev/null +++ b/lib/sw_services/xilskey/examples/xilskey_bbram_example.c @@ -0,0 +1,154 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file +* xilskey_bbram_example.c +* @note +* Example illustrates the method of programming the AES key to BBRAM. +* The user key should be mentioned in xilskey_input.h. +* BBRAM is a battery backed RAM and there is no restriction on the +* number of times key can programmed. +* This algorithm only wokrs when program and verify key are done +* together and in that order. +. +* Procedure: +* 1. Create a hardware project using the appropriate design. +* 2. Create a BSP. +* 3. Create fsbl +* 4. Create an application project using bbram example and xilskey_input.h +* 5. The 256 bit key to be programmed has to be mentioned +* 6. A hardware setup which dedicates four MIO pins for JTAG signals +* should be used and the MIO pins should be mentioned in xilskey_input.h +* There should be a method to download this example and have the +* MIO pins connected to JTAG before running this application. +* 7. Run the application which will program and verify the BBRAM key +* 8. After programming and veifying the key, power off. +* 9. Place a BBRAM key encrypted boot image in one of the boot devices, +* set the appropriate boot pins and power on. +* 10. The bbram example will be run from DDR with the default linker. +* 11. To run from OCM, modify the linker to map all sections to +* ps7_ram_0_S_AXI_BASEADDR instead of ps7_ddr_0_S_AXI_BASEADDR. +* +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- -------------------------------------------------------- +* 1.01a hk 09/18/13 First release +* +* +****************************************************************************/ +/***************************** Include Files *********************************/ +#include "stdio.h" +#include "xil_io.h" +#include "xstatus.h" +#include "xilskey_utils.h" +#include "xilskey_bbram.h" +#include "xilskey_input.h" +/************************** Constant Definitions *****************************/ +/**************************** Type Definitions ******************************/ +/***************** Macros (Inline Functions) Definitions ********************/ +/************************** Variable Definitions ****************************/ +XilSKey_Bbram InstancePtr; +/************************** Function Prototypes *****************************/ +int XilSKey_Bbram_InitData(XilSKey_Bbram *BbramInstancePtr); +/***************************************************************************/ + +int main() +{ + int Status; + u8 StartProg; + + xil_printf(" BBRAM Example start \r\n"); + + Status = XilSKey_Bbram_InitData(&InstancePtr); + if(Status != XST_SUCCESS) { + xil_printf(" BBRAM Example failed \r\n"); + return XST_FAILURE; + } + + Status = XilSKey_Bbram_Program(&InstancePtr); + if(Status != XST_SUCCESS) { + xil_printf(" BBRAM Example failed \r\n"); + return XST_FAILURE; + } + + xil_printf(" Successfully programmed and verified BBRAM key \r\n"); + return XST_SUCCESS; + +} + +/****************************************************************************/ +/** +* +* +* Function to initialize BBRAM instance +* +* +* @param BBRAM instance pointer +* +* @return +* +* - XST_SUCCESS - In case of Success +* - XST_FAILURE - If initialization fails +* +* @note +* +*****************************************************************************/ +int XilSKey_Bbram_InitData(XilSKey_Bbram *BbramInstancePtr) +{ + + u32 Status; + + BbramInstancePtr->ForcePowerCycle = XSK_BBRAM_FORCE_PCYCLE_RECONFIG; + BbramInstancePtr->JtagDisable = XSK_BBRAM_DISABLE_JTAG_CHAIN; + BbramInstancePtr->JtagMioTDI = XSK_BBRAM_MIO_JTAG_TDI; + BbramInstancePtr->JtagMioTDO = XSK_BBRAM_MIO_JTAG_TDO; + BbramInstancePtr->JtagMioTCK = XSK_BBRAM_MIO_JTAG_TCK; + BbramInstancePtr->JtagMioTMS = XSK_BBRAM_MIO_JTAG_TMS; + BbramInstancePtr->JtagMioMuxSel = XSK_BBRAM_MIO_JTAG_MUX_SELECT; + BbramInstancePtr->JtagMuxSelLineDefVal = XSK_BBRAM_MIO_MUX_SEL_DEFAULT_VAL; + + /* + * Convert key given in xilskey_input.h and + * assign it to the variable in instance. + */ + XilSKey_Efuse_ConvertStringToHexBE(XSK_BBRAM_AES_KEY, + &(BbramInstancePtr->AESKey[0]), + XSK_BBRAM_AES_KEY_SIZE_IN_BITS); + + Status = XST_SUCCESS; + return Status; + +} diff --git a/lib/sw_services/xilskey/examples/xilskey_efuse_example.c b/lib/sw_services/xilskey/examples/xilskey_efuse_example.c new file mode 100644 index 00000000..1a50d5b3 --- /dev/null +++ b/lib/sw_services/xilskey/examples/xilskey_efuse_example.c @@ -0,0 +1,626 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file +* xilskey_efuse_example.c +* @note +* +* Contains the api functions for the PS & PL eFUSE functionality. +* eFUSE Application project is capable of programming the PS and PL eFUSE +* bits given by the user. PS eFUSE holds the RSA primary key hash bits and +* user feature bits, which will enable/disable some features in ZYNQ. +* PL eFUSE holds the AES key, user key and some feature bits. +* User has the provision to write PS eFUSE & PL eFUSE independently or +* can combine together. This can be selected by using the compilation +* switch provided in xilskey_input.h. XSK_EFUSEPS_DRIVER should be +* defined to enable PS functionality & XSK_EFUSEPL_DRIVER for PL +* functionality. +* +* eFUSE bits are one-time programmable. Once they are burnt, they +* cannot be changed. Make sure you enter the correct information before +* you program eFUSE bits. +* +* POR reset is required for the eFUSE values to become into effect. +* Please do a POR reset after eFUSE writing. +* +* All the user configurable parameters for PS & PL eFUSE writing should be +* defined in xilskey_input.h. By default, all the macros will be defined +* with FALSE values. +* +* For PL eFUSE writing enabling the caches are necessary if the image is +* executing from DDR. This will be done in BSP by default. User has to +* take care not to disable caches. +* +* eFUSE writing procedure running out of DDR as an application: +* (This sequence is same as the existing flow described below) +* +* 1) After providing the required inputs in xilskey_input.h, compile the +* project. +* 2) Take the latest FSBL (.elf) and stitch the .elf generated +* to it using the bootgen utility and generate a bootable image. +* 3) Write the generated binary image into the flash device. +* (Ex: QSPI,NAND etc) +* 4) Execute image from flash which will write the mentioned eFUSE key +* bits. +* +* eFUSE driver compilation procedure for OCM: +* +* 1) Open the linker script (lscript.ld) in the SDK project. +* 2) Now map all the sections points to “ps7_ram_0_S_AXI_BASEADDR” +* instead of “ps7_ddr_0_S_AXI_BASEADDR”. +* +* Example: Click on the “Memory Region” tab for .text section & select +* “ps7_ram_0_S_AXI_BASEADDR” from the drop down list. +* +* 3) Copy the ps7_init.c & ps7_init.h files from the hw_platform folder +* into the example folder. +* 4) Uncomment calling of “ps7_init()” routine in +* “xilskey_efuse_example.c” +* 5) Compile the project. +* 6) .elf will be generated. This will be executed +* out of OCM. +* +* SVF File Generation using .elf : +* +* 1) Use the below xmd to create the svf file from the above generated +* elf file. Please note that path to the elf file should be given in opt file. +* +* “xmd –tcl efuse.tcl –opt efuse.opt” +* +* 2) Output of the above command will be .svf. +* +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- -------------------------------------------------------- +* 1.00a rpoolla 04/26/13 First release +* 1.02a hk 10/28/13 Added use of API's read status and key. PR# 735957. +* +* +****************************************************************************/ +/***************************** Include Files *********************************/ +#include "stdio.h" +#include "xil_io.h" +#include "xstatus.h" +#include "xilskey_utils.h" +#include "xilskey_eps.h" +#include "xilskey_epl.h" +#include "xilskey_input.h" +/************************** Constant Definitions *****************************/ +/**************************** Type Definitions ******************************/ +/***************** Macros (Inline Functions) Definitions ********************/ +/** + * Address for the Reboot Status Register + */ +#define REBOOT_STATUS_REG_ADDR (0xF8000258) +/** + * PL eFUSE aes key size in characters + */ +#define XSK_EFUSEPL_AES_KEY_STRING_SIZE (64) +/** + * PL eFUSE user low key size in characters + */ +#define XSK_EFUSEPL_USER_LOW_KEY_STRING_SIZE (2) +/** + * PL eFUSE user high key size in characters + */ +#define XSK_EFUSEPL_USER_HIGH_KEY_STRING_SIZE (6) +/** + * User AES Key size in Bytes + */ +#define XSK_EFUSEPL_AES_KEY_SIZE_IN_BITS (256) +/** + * User Low Key size in Bytes + */ +#define XSK_EFUSEPL_USER_LOW_KEY_SIZE_IN_BITS (8) +/** + * User High Key size in Bytes + */ +#define XSK_EFUSEPL_USER_HIGH_KEY_SIZE_IN_BITS (24) +/** + * Key length definition for RSA KEY Hash + */ +/** + * PS eFUSE RSA key Hash size in characters + */ +#define XSK_EFUSEPL_RSA_KEY_HASH_STRING_SIZE (64) + +/* + * PS efuse status bit definitions + */ +#define XSK_EFUSEPS_STATUS_WP_BIT_LOW 0x1000 +#define XSK_EFUSEPS_STATUS_WP_BIT_HIGH 0x2000 +#define XSK_EFUSEPS_STATUS_RSA_EN 0x400 +#define XSK_EFUSEPS_STATUS_ROM_128_CRC 0x800 + +/* + * PL efuse status bit definitions + */ +#define XSK_EFUSEPL_STATUS_FORCE_PCYCLE_RECONFIG 0x002 +#define XSK_EFUSEPL_STATUS_DISABLE_KEY_WRITE 0x004 +#define XSK_EFUSEPL_STATUS_DISABLE_AES_KEY_READ 0x008 +#define XSK_EFUSEPL_STATUS_DISABLE_USER_KEY_READ 0x010 +#define XSK_EFUSEPL_STATUS_DISABLE_FUSE_CNTRL_WRITE 0x020 +#define XSK_EFUSEPL_STATUS_EFUSE_SEC_ENABLE 0x100 +#define XSK_EFUSEPL_STATUS_JTAG_DISABLE 0x200 +#define XSK_EFUSEPL_STATUS_BBRAM_KEY_DISABLE 0x400 + +/************************** Variable Definitions ****************************/ +/************************** Function Prototypes *****************************/ +/** + * Function used to convert the string to Hex in Little Endian format + */ +u32 XilSKey_Efuse_ConvertStringToHexLE(const char * Str, u8 * Buf, u32 Len); +/** + * Function used to convert the string to Hex in Little Endian format + */ +u32 XilSKey_Efuse_ConvertStringToHexBE(const char * Str, u8 * Buf, u32 Len); +/** + * Function used to validate the AES & RSA key provided as input + */ +u32 XilSKey_Efuse_ValidateKey(const char *Key, u32 Len); +u32 XilSKey_EfusePs_InitData(XilSKey_EPs *PsInstancePtr); +u32 XilSKey_EfusePl_InitData(XilSKey_EPl *PlInstancePtr); +/*extern void ps7_init();*/ +/***************************************************************************/ +int main() +{ + u32 PlStatus = 0xFFFF; + u32 PsStatus = 0xFFFF; + u32 Status = 0; + + /*ps7_init();*/ +#ifdef XSK_EFUSEPS_DRIVER + XilSKey_EPs PsInstancePtr; + u32 PsStatusBits = 0; + + /** + * Initialize the PS instance pointer with the data + * populated in xilskey_input.h + */ + PsStatus = XilSKey_EfusePs_InitData(&PsInstancePtr); + if(PsStatus != XST_SUCCESS) { + printf("PS Data Initialization failed\r\n"); + goto EFUSE_ERROR; + } + + /* + * Read the PS efuse status + * Change in these status bits will only be reflected after POR + */ + PsStatus = XilSKey_EfusePs_ReadStatus(&PsInstancePtr, &PsStatusBits); + if(PsStatus != XST_SUCCESS) { + printf("PS status read failed\r\n"); + goto EFUSE_ERROR; + } + + /* + * Print Efuse PS status bits + */ + xil_printf("EfusePS status bits : 0x%x \n\r", PsStatusBits); + + if((PsStatusBits & XSK_EFUSEPS_STATUS_WP_BIT_LOW) || + (PsStatusBits & XSK_EFUSEPS_STATUS_WP_BIT_HIGH)) { + xil_printf("EfusePS status bits : Write protect enabled\n\r"); + }else { + xil_printf("EfusePS status bits : Write protect disabled\n\r"); + } + + if(PsStatusBits & XSK_EFUSEPS_STATUS_RSA_EN) { + xil_printf("EfusePS status bits : RSA authentication of " + "fsbl enabled\n\r"); + }else { + xil_printf("EfusePS status bits : RSA authentication of " + "fsbl disabled\n\r"); + } + + if(PsStatusBits & XSK_EFUSEPS_STATUS_ROM_128_CRC) { + xil_printf("EfusePS status bits : 128k CRC check on ROM enabled\n\r"); + }else { + xil_printf("EfusePS status bits : 128k CRC check on ROM disabled\n\r"); + } + + /** + * Write the PS eFUSE as defined in xilskeyinput.h + */ + PsStatus = XilSKey_EfusePs_Write(&PsInstancePtr); + if (PsStatus != XST_SUCCESS) { + printf("PS EFUSE writing failed\n"); + goto EFUSE_ERROR; + } + + u32 Index; + /** + * Clear the structure element of Rsa Key Hash for reading + */ + for(Index=0;Index<32;Index++){ + PsInstancePtr.RsaKeyHashValue[Index]=0; + } + /** + * Read the PS eFUSE RSA Key Hash + */ + PsStatus = XilSKey_EfusePs_Read(&PsInstancePtr); + if (PsStatus != XST_SUCCESS){ + printf("PS EFUSE reading failed\n"); + goto EFUSE_ERROR; + } + + /** + * Print the read PS eFUSE RSA Key Hash + */ + printf("Read RSA Key Hash: \n"); + + for(Index=0;Index<32;Index++){ + printf("%02x",PsInstancePtr.RsaKeyReadback[Index]); + } + printf("\n"); + +#endif /* XSK_EFUSEPS_DRIVER*/ + +#ifdef XSK_EFUSEPL_DRIVER + + XilSKey_EPl PlInstancePtr; + u32 PlStatusBits = 0; + int KeyCnt; + + /** + * Initialize the PL data structure based on the xilskey_input.h values + */ + PlStatus = XilSKey_EfusePl_InitData(&PlInstancePtr); + if( PlStatus != XST_SUCCESS) { + printf("PL Data Initialization Failed\r\n"); + goto EFUSE_ERROR; + } + + /** + * Call the PL eFUSE programming function to program the eFUSE + * based on the user input + */ + PlStatus = XilSKey_EfusePl_Program(&PlInstancePtr); + if(PlStatus != XST_SUCCESS) { + printf("PL eFUSE programming failed\r\n"); + } + + /* + * Read Efuse PL status bits + */ + PlStatus = XilSKey_EfusePl_ReadStatus(&PlInstancePtr, &PlStatusBits); + if( PlStatus != XST_SUCCESS) { + printf("PL efuse status read failed\r\n"); + goto EFUSE_ERROR; + } + + /* + * Print Efuse PL status bits + */ + xil_printf("EfusePL status bits : 0x%x \n\r", PlStatusBits); + + if(PlStatusBits & XSK_EFUSEPL_STATUS_FORCE_PCYCLE_RECONFIG) { + xil_printf("EfusePL status bits : Force power cycle for " + "reconfiguration enabled\n\r"); + }else { + xil_printf("EfusePL status bits : Force power cycle for " + "reconfiguration disabled\n\r"); + } + + if(PlStatusBits & XSK_EFUSEPL_STATUS_DISABLE_KEY_WRITE) { + xil_printf("EfusePL status bits : Key write disabled \n\r"); + }else { + xil_printf("EfusePL status bits : Key write enabled \n\r"); + } + + if(PlStatusBits & XSK_EFUSEPL_STATUS_DISABLE_AES_KEY_READ) { + xil_printf("EfusePL status bits : AES Key read disabled \n\r"); + }else { + xil_printf("EfusePL status bits : AES Key read enabled \n\r"); + } + + if(PlStatusBits & XSK_EFUSEPL_STATUS_DISABLE_USER_KEY_READ) { + xil_printf("EfusePL status bits : User Key read disabled \n\r"); + }else { + xil_printf("EfusePL status bits : User Key read enabled \n\r"); + } + + if(PlStatusBits & XSK_EFUSEPL_STATUS_DISABLE_FUSE_CNTRL_WRITE) { + xil_printf("EfusePL status bits : Fuse Control write disabled \n\r"); + }else { + xil_printf("EfusePL status bits : Fuse Control write enabled \n\r"); + } + + if(PlStatusBits & XSK_EFUSEPL_STATUS_EFUSE_SEC_ENABLE) { + xil_printf("EfusePL status bits : Efuse secure boot enabled \n\r"); + }else { + xil_printf("EfusePL status bits : Efuse secure boot disabled \n\r"); + } + + if(PlStatusBits & XSK_EFUSEPL_STATUS_JTAG_DISABLE) { + xil_printf("EfusePL status bits : Jtag disabled \n\r"); + }else { + xil_printf("EfusePL status bits : Jtag enabled \n\r"); + } + + if(PlStatusBits & XSK_EFUSEPL_STATUS_BBRAM_KEY_DISABLE) { + xil_printf("EfusePL status bits : BBRAM key disabled \n\r"); + }else { + xil_printf("EfusePL status bits : BBRAM key enabled \n\r"); + } + + /* + * Read Efuse PL key + */ + PlStatus = XilSKey_EfusePl_ReadKey(&PlInstancePtr); + if( PlStatus != XST_SUCCESS) { + printf("PL efuse key read failed\r\n"); + goto EFUSE_ERROR; + } + /* + * Print Efuse PL key + */ + xil_printf("EfusePL User key : 0x"); + for(KeyCnt = 3; KeyCnt >= 0; KeyCnt--) + { + xil_printf("%02x", PlInstancePtr.UserKeyReadback[KeyCnt]); + } + xil_printf("\n\r"); + + xil_printf("EfusePL AES key : 0x"); + for(KeyCnt = 31; KeyCnt >= 0; KeyCnt--) + { + xil_printf("%02x", PlInstancePtr.AESKeyReadback[KeyCnt]); + } + xil_printf("\n\r"); + +#endif /*XSK_EFUSEPL_DRIVER*/ + +EFUSE_ERROR: + /** + * Write the error returned in the Reboot Status Register + * Eg: If the reboot status register value is 0xYYYYZZZZ + * then + * - YYYY Represents the PS eFUSE Status. + * - ZZZZ Represents the PL eFUSE Status. + * + * - Value 0x0000ZZZZ + * represents PS eFUSE is successful & PL eFUSE process + * returned with error. + * - Value 0xYYYY0000 + * represents PL eFUSE is successful & PS eFUSE process + * returned with error. + * - Value 0xFFFF0000 + * represents PS eFUSE is not initiated & PL eFUSE is successful. + * - Value 0x0000FFFF + * represents PL eFUSE is not initiated & PS eFUSE is successful. + * - Value 0xFFFFZZZZ + * represents PS eFUSE is not initiated & PL eFUSE is process + * returned with error. + * - Value 0xYYYYFFFF + * represents PL eFUSE is not initiated & PS eFUSE is process + * returned with error. + */ + Status = ((PsStatus << 16) + PlStatus); + + printf("eFUSE operations exit status: %08X\r\n", Status); + + /** + * Writing the Exit Status to Reboot Status Register + */ + Xil_Out32(REBOOT_STATUS_REG_ADDR,Status); + while(1); + return 0; +} + + +#ifdef XSK_EFUSEPS_DRIVER +/****************************************************************************/ +/** +* +* +* Helper functions to properly initialize the PS eFUSE structure instance +* +* +* @param PsInstancePtr - Structure Address to update the structure elements +* +* @return +* +* - XST_SUCCESS - In case of Success +* - XST_FAILURE - If initialization fails +* +* @note +* +*****************************************************************************/ + +u32 XilSKey_EfusePs_InitData(XilSKey_EPs *PsInstancePtr) +{ + u32 PsStatus; + + PsStatus = XST_SUCCESS; + + /** + * Copy the xilskeyinput.h values into PS structure elements + */ + PsInstancePtr->EnableWriteProtect = XSK_EFUSEPS_ENABLE_WRITE_PROTECT; + PsInstancePtr->EnableRsaAuth = XSK_EFUSEPS_ENABLE_RSA_AUTH; + PsInstancePtr->EnableRom128Crc = XSK_EFUSEPS_ENABLE_ROM_128K_CRC; + PsInstancePtr->EnableRsaKeyHash = XSK_EFUSEPS_ENABLE_RSA_KEY_HASH; + + if (PsInstancePtr->EnableRsaKeyHash == TRUE) { + /** + * Validation of RSA Hash + */ + PsStatus = XilSKey_Efuse_ValidateKey( + (char *)XSK_EFUSEPS_RSA_KEY_HASH_VALUE, + XSK_EFUSEPL_RSA_KEY_HASH_STRING_SIZE); + if(PsStatus != XST_SUCCESS) { + return PsStatus; + } + + /** + * Convert the input RSA Key Hash string into Hex buffer + */ + PsStatus = XilSKey_Efuse_ConvertStringToHexBE( + XSK_EFUSEPS_RSA_KEY_HASH_VALUE, + &(PsInstancePtr->RsaKeyHashValue[0]), 64); + if(PsStatus != XST_SUCCESS) { + return PsStatus; + } + } + return PsStatus; +} +#endif /* XSK_EFUSEPS_DRIVER*/ + + +#ifdef XSK_EFUSEPL_DRIVER +/****************************************************************************/ +/** +* +* +* Helper functions to properly initialize the PL eFUSE structure instance +* +* +* @param PlInstancePtr - Structure Address to update the structure elements +* +* @return +* +* - XST_SUCCESS - In case of Success +* - XST_FAILURE - If initialization fails +* +* @note +* +*****************************************************************************/ + +u32 XilSKey_EfusePl_InitData(XilSKey_EPl *PlInstancePtr) +{ + + u32 PlStatus; + + PlStatus = XST_SUCCESS; + + + /** + * Copy the xilskeyinput.h values into PL eFUSE structure elements + */ + + /** + * Assign FUSE CNTRL bits[1:5] to the PL eFUSE structure elements. + */ + + PlInstancePtr->ForcePowerCycle = XSK_EFUSEPL_FORCE_PCYCLE_RECONFIG; + PlInstancePtr->KeyWrite = XSK_EFUSEPL_DISABLE_KEY_WRITE; + PlInstancePtr->AESKeyRead = XSK_EFUSEPL_DISABLE_AES_KEY_READ; + PlInstancePtr->UserKeyRead = XSK_EFUSEPL_DISABLE_USER_KEY_READ; + PlInstancePtr->CtrlWrite = XSK_EFUSEPL_DISABLE_FUSE_CNTRL_WRITE; + /** + * Assign the FUSE CNTRL bits[8:10] into the PL eFUSE structure elements + */ + PlInstancePtr->UseAESOnly = XSK_EFUSEPL_FORCE_USE_AES_ONLY; + PlInstancePtr->JtagDisable = XSK_EFUSEPL_DISABLE_JTAG_CHAIN; + PlInstancePtr->AESKeyExclusive = XSK_EFUSEPL_BBRAM_KEY_DISABLE; + + PlInstancePtr->JtagMioTDI = XSK_EFUSEPL_MIO_JTAG_TDI; + PlInstancePtr->JtagMioTDO = XSK_EFUSEPL_MIO_JTAG_TDO; + PlInstancePtr->JtagMioTCK = XSK_EFUSEPL_MIO_JTAG_TCK; + PlInstancePtr->JtagMioTMS = XSK_EFUSEPL_MIO_JTAG_TMS; + PlInstancePtr->JtagMioMuxSel = XSK_EFUSEPL_MIO_JTAG_MUX_SELECT; + PlInstancePtr->JtagMuxSelLineDefVal = XSK_EFUSEPL_MIO_MUX_SEL_DEFAULT_VAL; + + /* + * Variable to check whether internal system initialization is done. + */ + PlInstancePtr->SystemInitDone = 0; + + /** + * Assign the user selection for AES & USER Low Key (or) + * User High Key (or) both + */ + PlInstancePtr->ProgAESandUserLowKey = + XSK_EFUSEPL_PROGRAM_AES_AND_USER_LOW_KEY; + PlInstancePtr->ProgUserHighKey = XSK_EFUSEPL_PROGRAM_USER_HIGH_KEY; + + if (PlInstancePtr->ProgAESandUserLowKey == TRUE) { + /** + * Validation of AES Key + */ + PlStatus = XilSKey_Efuse_ValidateKey((char *)XSK_EFUSEPL_AES_KEY, + XSK_EFUSEPL_AES_KEY_STRING_SIZE); + if(PlStatus != XST_SUCCESS) { + goto PL_INIT_ERROR; + } + /** + * Validation of User Low Key + */ + PlStatus = XilSKey_Efuse_ValidateKey((char *)XSK_EFUSEPL_USER_LOW_KEY, + XSK_EFUSEPL_USER_LOW_KEY_STRING_SIZE); + if(PlStatus != XST_SUCCESS) { + goto PL_INIT_ERROR; + } + + /** + * Assign the AES Key Value + */ + XilSKey_Efuse_ConvertStringToHexLE((char *)XSK_EFUSEPL_AES_KEY , + &PlInstancePtr->AESKey[0], + XSK_EFUSEPL_AES_KEY_SIZE_IN_BITS); + + /** + * Assign the User Low key [7:0] bits + */ + XilSKey_Efuse_ConvertStringToHexLE((char *)XSK_EFUSEPL_USER_LOW_KEY , + &PlInstancePtr->UserKey[0], + XSK_EFUSEPL_USER_LOW_KEY_SIZE_IN_BITS); + } + + if (PlInstancePtr->ProgUserHighKey == TRUE) { + /** + * Validation of User High Key + */ + PlStatus = XilSKey_Efuse_ValidateKey( + (char *)XSK_EFUSEPL_USER_HIGH_KEY, + XSK_EFUSEPL_USER_HIGH_KEY_STRING_SIZE); + if(PlStatus != XST_SUCCESS) { + goto PL_INIT_ERROR; + } + /** + * Assign the User High key [31:8] bits + */ + XilSKey_Efuse_ConvertStringToHexLE((char *)XSK_EFUSEPL_USER_HIGH_KEY , + &PlInstancePtr->UserKey[1], + XSK_EFUSEPL_USER_HIGH_KEY_SIZE_IN_BITS); + } + +PL_INIT_ERROR: + return PlStatus; +} + +#endif /*XSK_EFUSEPL_DRIVER*/ diff --git a/lib/sw_services/xilskey/examples/xilskey_input.h b/lib/sw_services/xilskey/examples/xilskey_input.h new file mode 100644 index 00000000..45cc0df7 --- /dev/null +++ b/lib/sw_services/xilskey/examples/xilskey_input.h @@ -0,0 +1,396 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xilskey_input.h +* +* +* @note +* +* User configurable parameters for PS eFUSE +* --------------------------------------------------------------------------- +* #define XSK_EFUSEPS_ENABLE_WRITE_PROTECT FALSE +* +* TRUE to burn the write protect bits in eFUSE array. Write protect +* has two bits, when any of the bit is blown, it is considered as write +* protected. So, while burning the Write protect bits, even if one bit is +* blown, write API returns success. Note that, POR reset is required after +* burning, for write protection of the eFUSE bits to come into effect. +* It is recommended to do the POR reset after write protection. +* Also note that, once write protect bits are burned, no more eFUSE writes +* are possible. So, please be sure when burning the write protect bits. +* If the Write protect macro is TRUE with other macros, write protect will +* be burned in the last, after burning all the defined values, so that for +* any error while burning other macros will not effect the total eFUSE array. +* FALSE will not modify the write protect bits. +* +* #define XSK_EFUSEPS_ENABLE_RSA_AUTH FALSE +* +* TRUE to burn the RSA enable bit in PS eFUSE array. After enabling the bit, +* every successive boot must be RSA enabled apart from JTAG. Before burning +* this bit, make sure that eFUSE array has the valid PPK hash.If the PPK hash +* burning is enabled, only after writing the hash successfully, RSA enable +* bit will be blown. Note that, for RSA enable bit to take effect, POR reset +* is required. +* FALSE will not modify the RSA enable bit. +* +* #define XSK_EFUSEPS_ENABLE_ROM_128K_CRC FALSE +* TRUE will burn the ROM 128k crc bit. Every successive boot after this, +* BootROM will calculate 128k crc. FALSE will not modify the ROM CRC128K bit. +* +* #define XSK_EFUSEPS_ENABLE_RSA_KEY_HASH FALSE +* TRUE will burn the eFUSE hash, that is given in XSK_EFUSEPS_RSA_KEY_HASH_VALUE +* when write API is used. TRUE will read the eFUSE hash when read API is used +* and will be read into structure. FALSE will ignore the value given. +* +* #define XSK_EFUSEPS_RSA_KEY_HASH_VALUE +* "c8bb4d9e1fcdbd27b99d48a3df5720b98f35bafabb1e10333a78322fb82ce63d" +* +* The value mentioned in this will be converted to hex buffer and written +* into the PS eFUSE array when write API used. This value should be the +* PPK(Primary Public Key) hash given in string format. It should be 64 +* characters long, valid characters are 0-9,a-f,A-F. Any other character +* is considered as invalid string and will not burn RSA hash. +* +* Note: When XilSKey_EfusePs_Write() API is used, above mentioned RSA hash +* is written and XSK_EFUSEPS_ENABLE_RSA_KEY_HASH should have TRUE value. +* +* User configurable parameters for PL eFUSE +* ----------------------------------------------------------------------- +* #define XSK_EFUSEPL_FORCE_PCYCLE_RECONFIG FALSE +* TRUE then part has to be power cycled to be able to be reconfigured. +* FALSE will not set the eFUSE control bit. +* +* #define XSK_EFUSEPL_DISABLE_KEY_WRITE FALSE +* TRUE will disable eFUSE write to FUSE_AES and FUSE_USER blocks +* XFLASE will enable eFUSE write to FUSE_AES and FUSE_USER blocks +* +* #define XSK_EFUSEPL_DISABLE_AES_KEY_READ FALSE +* TRUE will disable the write to FUSE_AES & FUSE_USER key & disables +* read of FUSE_AES. +* FALSE will enable eFUSE read from & write to FUSE_AES and FUSE_USER blocks +* +* #define XSK_EFUSEPL_DISABLE_USER_KEY_READ FALSE +* TRUE will disable the write to FUSE_AES & FUSE_USER key & disables read of +* FUSE_USER +* FALSE will enable eFUSE read from & write to FUSE_AES and FUSE_USER blocks +* +* Note: If any one of the above two definitions are FALSE then reading of +* FUSE_AES & FUSE_USER is not possible +* +* #define XSK_EFUSEPL_DISABLE_FUSE_CNTRL_WRITE FALSE +* TRUE will disable the eFUSE write to FUSE_CTRL block +* FALSE will not set the eFUSE control bit, so that user can write into +* FUSE_CTRL block later. +* +* #define XSK_EFUSEPL_FORCE_USE_AES_ONLY FALSE +* TRUE will force to use secure boot with eFUSE AES key only +* FALSE will not set the eFUSE control bit so that user can use non-secure +* boot. +* +* #define XSK_EFUSEPL_DISABLE_JTAG_CHAIN FALSE +* If TRUE then permanently sets the Zynq ARM DAP controller in bypass mode. +* FALSE will allow Zynq ARM DAP visible through JTAG. +* +* #define XSK_EFUSEPL_BBRAM_KEY_DISABLE FALSE +* XTURE will force eFUSE key to be used if booting Secure Image. +* FALSE will not set the eFUSE control bit so that user can use secure boot +* with BBRAM key. +* +* Following are the MIO pins used for PL JTAG operations. +* User can change these pins as their discretion. +* #define XSK_EFUSEPL_MIO_JTAG_TDI (17) +* #define XSK_EFUSEPL_MIO_JTAG_TDO (18) +* #define XSK_EFUSEPL_MIO_JTAG_TCK (19) +* #define XSK_EFUSEPL_MIO_JTAG_TMS (20) +* +* MUX selection pin: +* #define XSK_EFUSEPL_MIO_JTAG_MUX_SELECT (21) +* This pin is used to select between the external JTAG or MIO driving JTAG +* operations. +* +* #define XSK_EFUSEPL_MIO_MUX_SEL_DEFAULT_VAL LOW +* LOW writes zero on the mux select line before writing the PL eFUSE +* HIGH writes one on the mux select line before writing the PL eFUSE +* +* #define XSK_EFUSEPL_PROGRAM_AES_AND_USER_LOW_KEY FALSE +* TRUE will burn the AES & User Low hash key, that is given in +* XSK_EFUSEPL_AES_KEY & XSK_EFUSEPL_USER_LOW_KEY respectively. +* FALSE will ignore the values given. +* +* Note: User cannot write AES Key & User Low Key separately. +* +* #define XSK_EFUSEPL_PROGRAM_USER_HIGH_KEY FALSE +* TRUE will burn the User High hash key, that is given in +* XSK_EFUSEPL_AES_KEY & XSK_EFUSEPL_USER_LOW_KEY respectively. +* FALSE will ignore the values given. +* +* #define XSK_EFUSEPL_AES_KEY +* "0000000000000000000000000000000000000000000000000000000000000000" +* The value mentioned in this will be converted to hex buffer and written +* into the PL eFUSE array when write API used. This value should be the +* PPK(Primary Public Key) hash given in string format. It should be 64 +* characters long, valid characters are 0-9,a-f,A-F. Any other character +* is considered as invalid string and will not burn AES Key. Note that, +* for writing the AES Key, XSK_EFUSEPL_PROGRAM_AES_AND_USER_LOW_KEY should +* have TRUE value. +* +* #define XSK_EFUSEPL_USER_LOW_KEY "00" +* The value mentioned in this will be converted to hex buffer and written +* into the PL eFUSE array when write API used. This value should be the +* User Low Key given in string format. It should be 2 characters long, valid +* characters are 0-9,a-f,A-F. Any other character is considered as invalid +* string and will not burn User Low Key. Note that, for writing the AES Key, +* XSK_EFUSEPL_PROGRAM_AES_AND_USER_LOW_KEY should have TRUE value. +* +* +* #define XSK_EFUSEPL_USER_HIGH_KEY "000000" +* The value mentioned in this will be converted to hex buffer and written +* into the PL eFUSE array when write API used. This value should be the User +* High Key given in string format. It should be 6 characters long, valid +* characters are 0-9,a-f,A-F. Any other character is considered as invalid +* string and will not burn User High Key. Note that, for writing the AES +* Key, XSK_EFUSEPL_PROGRAM_USER_HIGH_KEY should have TRUE value. +* +* BBRAM related definitions: +*----------------------------------------------------------------------------- +* #define XSK_BBRAM_FORCE_PCYCLE_RECONFIG FALSE +* If TRUE then part has to be power cycled to be +* able to be reconfigured +* #define XSK_BBRAM_DISABLE_JTAG_CHAIN FALSE +* If TRUE then permanently sets the Zynq +* ARM DAP controller in bypass mode +* MIO pins used for JTAG signals. Can be changed as per hardware. +* #define XSK_BBRAM_MIO_JTAG_TDI (17) +* #define XSK_BBRAM_MIO_JTAG_TDO (21) +* #define XSK_BBRAM_MIO_JTAG_TCK (19) +* #define XSK_BBRAM_MIO_JTAG_TMS (20) +* #define XSK_BBRAM_MIO_JTAG_MUX_SELECT (11) +* #define XSK_BBRAM_MIO_MUX_SEL_DEFAULT_VAL LOW +* Default value to enable the PL JTAG +* This is the 256 bit key to be programmed into BBRAM. +* This should entered by user in HEX. +* #define XSK_BBRAM_AES_KEY +* "349de4571ae6d88de23de65489acf67000ff5ec901ae3d409aabbce4549812dd" +* #define XSK_BBRAM_AES_KEY_SIZE_IN_BITS 256 +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ---- 	-------- --------------------------------------------------------
+* 1.00a rpoolla 04/26/13 First release
+* 1.01a hk      09/18/13 Added BBRAM related definitions
+* 
+* +* +******************************************************************************/ + +#ifndef XILSKEY_INPUT_H +#define XILSKEY_INPUT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +/************************** Constant Definitions *****************************/ +/**************************** Type Definitions ******************************/ +/***************** Macros (Inline Functions) Definitions ********************/ +#define XSK_EFUSEPL_DRIVER +#define XSK_EFUSEPS_DRIVER + +#ifdef XSK_EFUSEPL_DRIVER + +/** + * Voltage level definitions + */ +#define LOW 0 +#define HIGH 1 + +/** + * Following defines should be defined either TRUE or FALSE. + * -------------------------------------------------------- + */ + +#define XSK_EFUSEPL_FORCE_PCYCLE_RECONFIG FALSE /**< If TRUE then part + * has to be power cycled to be + * able to be reconfigured + */ +#define XSK_EFUSEPL_DISABLE_KEY_WRITE FALSE /**< If TRUE will disable + * eFUSE write to FUSE_AES and + * FUSE_USER blocks + */ +#define XSK_EFUSEPL_DISABLE_AES_KEY_READ FALSE /**< If TRUE will disable + * eFUSE read to FUSE_AES block and + * also disables eFUSEwrite to + * FUSE_AES and FUSE_USER blocks + */ +#define XSK_EFUSEPL_DISABLE_USER_KEY_READ FALSE /**< If TRUE will disable + * eFUSE read to FUSE_USER block + * and also disables eFUSE write + * to FUSE_AES and FUSE_USER + * blocks + */ +#define XSK_EFUSEPL_DISABLE_FUSE_CNTRL_WRITE FALSE /**< If TRUE will + * disable eFUSE write to + * FUSE_CNTRL block + */ +#define XSK_EFUSEPL_FORCE_USE_AES_ONLY FALSE /**< If TRUE will force + * to use Secure boot with eFUSE + * key only + */ +#define XSK_EFUSEPL_DISABLE_JTAG_CHAIN FALSE /**< If TRUE then + * permanently sets the Zynq + * ARM DAP controller in bypass + * mode + */ +#define XSK_EFUSEPL_BBRAM_KEY_DISABLE FALSE /**< If TRUE will force + * eFUSE key to be used if + * booting Secure Image + */ + +/** + * Following defines should be given in the decimal/hexa-decimal values. + * For example : + * XSK_EFUSEPL_MIO_JTAG_TCK 34 OR 0x22 + * XSK_EFUSEPL_MIO_JTAG_TMS 35 OR 0x23 + * etc... + */ + +#define XSK_EFUSEPL_MIO_JTAG_TDI (17) /**< JTAG MIO pin for TDI */ +#define XSK_EFUSEPL_MIO_JTAG_TDO (21) /**< JTAG MIO pin for TDO */ +#define XSK_EFUSEPL_MIO_JTAG_TCK (19) /**< JTAG MIO pin for TCK */ +#define XSK_EFUSEPL_MIO_JTAG_TMS (20) /**< JTAG MIO pin for TMS */ +#define XSK_EFUSEPL_MIO_JTAG_MUX_SELECT (11) /**< JTAG MIO pin for + * MUX selection line + */ +/** + * + */ +#define XSK_EFUSEPL_MIO_MUX_SEL_DEFAULT_VAL LOW /**< Default value to + * enable the PL JTAG + */ + +/** + * Following is the define to select if the user wants to select AES key and USER + * low key OR USER high key or BOTH + */ + +#define XSK_EFUSEPL_PROGRAM_AES_AND_USER_LOW_KEY FALSE /**< TRUE burns + * the AES & user low key + */ +#define XSK_EFUSEPL_PROGRAM_USER_HIGH_KEY FALSE /**< TRUE burns + * the user high key + */ +/** + * Following defines should be given in the form of hex string. + * The length of AES_KEY string must me 64 and for USER_KEY must be 8. + */ +#define XSK_EFUSEPL_AES_KEY "0000000000000000000000000000000000000000000000000000000000000000" +#define XSK_EFUSEPL_USER_LOW_KEY "00" +#define XSK_EFUSEPL_USER_HIGH_KEY "000000" + +#endif /*XSK_EFUSEPL_DRIVER*/ + + +/** + * Similarly we can define PS eFUSE related data + * --------------------------------------------- + */ +#ifdef XSK_EFUSEPS_DRIVER + +#define XSK_EFUSEPS_ENABLE_WRITE_PROTECT FALSE /**< Enable the eFUSE Array + * write protection + */ +#define XSK_EFUSEPS_ENABLE_RSA_AUTH FALSE /**< Enable the RSA + * Authentication eFUSE Bit + */ +#define XSK_EFUSEPS_ENABLE_ROM_128K_CRC FALSE /**< Enable the ROM + * code 128K crc eFUSE Bit + */ +#define XSK_EFUSEPS_ENABLE_RSA_KEY_HASH FALSE /**< Enabling this + * RsaKeyHashValue[64] is + * written to eFUSE array + */ +#define XSK_EFUSEPS_RSA_KEY_HASH_VALUE "0000000000000000000000000000000000000000000000000000000000000000" + +#endif /* End of XSK_EFUSEPS_DRIVER */ + +/* + * Definitions for BBRAM + */ + +/**< If TRUE then part + * has to be power cycled to be + * able to be reconfigured + */ +#define XSK_BBRAM_FORCE_PCYCLE_RECONFIG FALSE + +/**< If TRUE then + * permanently sets the Zynq + * ARM DAP controller in bypass + * mode + */ +#define XSK_BBRAM_DISABLE_JTAG_CHAIN FALSE + +#define XSK_BBRAM_MIO_JTAG_TDI (17) /**< JTAG MIO pin for TDI */ +#define XSK_BBRAM_MIO_JTAG_TDO (21) /**< JTAG MIO pin for TDO */ +#define XSK_BBRAM_MIO_JTAG_TCK (19) /**< JTAG MIO pin for TCK */ +#define XSK_BBRAM_MIO_JTAG_TMS (20) /**< JTAG MIO pin for TMS */ +#define XSK_BBRAM_MIO_JTAG_MUX_SELECT (11) /**< JTAG MIO pin for + * MUX selection line + */ +/**< Default value to + * enable the PL JTAG + */ +#define XSK_BBRAM_MIO_MUX_SEL_DEFAULT_VAL 0 +/** + * This is the 256 bit key to be programmed into BBRAM. + * This should entered by user in HEX. + */ +#define XSK_BBRAM_AES_KEY "349de4571ae6d88de23de65489acf67000ff5ec901ae3d409aabbce4549812dd" + +#define XSK_BBRAM_AES_KEY_SIZE_IN_BITS 256 + +/* + * End of definitions for BBRAM + */ + +/************************** Function Prototypes *****************************/ +/****************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /*XILSKEY_INPUT_H*/ diff --git a/lib/sw_services/xilskey/src/Makefile b/lib/sw_services/xilskey/src/Makefile new file mode 100644 index 00000000..9170a092 --- /dev/null +++ b/lib/sw_services/xilskey/src/Makefile @@ -0,0 +1,91 @@ +############################################################################### +# +# Copyright (C) 2013 - 2014 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. +# +# Use of the Software is limited solely to applications: +# (a) running on a Xilinx device, or +# (b) that interact with a Xilinx device through a bus or interconnect. +# +# 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 +# XILINX CONSORTIUM 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. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +############################################################################### + +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I${INCLUDEDIR} +SKEY_DIR = . + +LIB_SRCS = $(SKEY_DIR)/xilskey_eps.c \ + $(SKEY_DIR)/xilskey_epl.c \ + $(SKEY_DIR)/xilskey_utils.c \ + $(SKEY_DIR)/xilskey_jslib.c \ + $(SKEY_DIR)/xilskey_jscmd.c \ + $(SKEY_DIR)/xilskey_bbram.c + +# create ISF_SRCS based on configured options + +SKEY_SRCS = $(LIB_SRCS) + +SKEY_OBJS = $(SKEY_SRCS:%.c=%.o) + + +EXPORT_INCLUDE_FILES = $(SKEY_DIR)/include/xilskey_eps.h \ + $(SKEY_DIR)/include/xilskey_epl.h \ + $(SKEY_DIR)/include/xilskey_utils.h \ + $(SKEY_DIR)/include/xilskey_bbram.h + + +libs: libxilskey.a + cp libxilskey.a $(RELEASEDIR) + make clean + +include: + @for i in $(EXPORT_INCLUDE_FILES); do \ + echo ${CP} -r $$i ${INCLUDEDIR}; \ + ${CP} -r $$i ${INCLUDEDIR}; \ + done + +clean: + rm -rf obj/*.o + rmdir obj + rm libxilskey.a + + +libxilskey.a: obj_dir print_msg_isf_base $(SKEY_OBJS) + @echo "Creating archive $@" + $(ARCHIVER) rc $@ obj/*.o + +obj_dir: + mkdir obj + +print_msg_isf_base: + @echo "Compiling Xilinx Secure Key Library..." + +.c.o: + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) -c $< -o obj/$(@F) diff --git a/lib/sw_services/xilskey/src/changelog.txt b/lib/sw_services/xilskey/src/changelog.txt new file mode 100755 index 00000000..3fa21828 --- /dev/null +++ b/lib/sw_services/xilskey/src/changelog.txt @@ -0,0 +1,25 @@ +/***************************************************************************** + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- --------------------------------------------------- + * + * 1.02a hk 10/28/13 PS eFuse: + * Added API to read status register: + * u32 XilSKey_EfusePs_ReadStatus( + * XilSKey_EPs *InstancePtr, u32 *StatusBits) + * RSA key read back is stored in RsaKeyReadback in + * Instance structure instead of RsaKeyHashValue - + * Change in API: + * u32 XilSKey_EfusePs_Read(XilSKey_EPs *PsInstancePtr) + * PL eFUSE: + * Added API's to read status bits and key : + * u32 XilSKey_EfusePl_ReadKey(XilSKey_EPl *InstancePtr) + * u32 XilSKey_EfusePl_ReadKey(XilSKey_EPl *InstancePtr) + * 2.00 hk 23/01/14 Corrected PL voltage checks to VCCINT and VCCAUX. + * CR#768077 + * Changed PS efuse error codes for voltage out of range + * 2.00 hk 02/12/14 Changed makefile to remove '-p' option with mkdir. + * CR#773090 + * + ********************************************************************************/ diff --git a/lib/sw_services/xilskey/src/include/xilskey_bbram.h b/lib/sw_services/xilskey/src/include/xilskey_bbram.h new file mode 100644 index 00000000..89065b22 --- /dev/null +++ b/lib/sw_services/xilskey/src/include/xilskey_bbram.h @@ -0,0 +1,203 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file +* +* xilskey_bbram.h +* @note +* Contains the function prototypes, defines and macros for +* BBRAM functionality. +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- -------------------------------------------------------- +* 1.01a hk 09/18/13 First release +* +****************************************************************************/ +#ifndef XILSKEY_BBRAM_H +#define XILSKEY_BBRAM_H + +#ifdef __cplusplus +extern "C" { +#endif +/***************************** Include Files *********************************/ +/************************** Constant Definitions *****************************/ +/**************************** Type Definitions ******************************/ +/***************** Macros (Inline Functions) Definitions ********************/ +/************************** Variable Definitions ****************************/ +typedef struct { + + /** + * If XTRUE then part has to be power cycled to be able to be reconfigured + */ + u32 ForcePowerCycle; + /** + * If XTRUE then permanently sets the Zynq ARM DAP controller in bypass mode + */ + u32 JtagDisable; + /** + * This is for the aes_key value + */; + u8 AESKey[32]; + /** + * TDI MIO Pin Number + */ + u32 JtagMioTDI; + /** + * TDO MIO Pin Number + */ + u32 JtagMioTDO; + /** + * TCK MIO Pin Number + */ + u32 JtagMioTCK; + /** + * TMS MIO Pin Number + */ + u32 JtagMioTMS; + /** + * MUX Selection MIO Pin Number + */ + u32 JtagMioMuxSel; + /** + * Value on the MUX Selection line + */ + u32 JtagMuxSelLineDefVal; + +}XilSKey_Bbram; +/************************** Constant Definitions *****************************/ +/* + * Constant definitions for instruction used in BBRAM key program and verify + */ +#define JPROGRAM 0x0B +#define ISC_NOOP 0x14 +#define ISC_ENABLE 0x10 +#define ISC_PROGRAM_KEY 0x12 +#define ISC_PROGRAM 0x11 +#define ISC_READ 0x15 +#define ISC_DISABLE 0x16 +#define BYPASS 0x3F + +/* + * Pre and post pads + */ +#define IRHEADER 0 +#define IRTRAILER 4 +#define DRHEADER 0 +#define DRTRAILER 1 + +/* + * Pre and post pads for BYPASS in de-init + */ +#define IRHEADER_BYP 0 +#define IRTRAILER_BYP 0 +#define DRHEADER_BYP 0 +#define DRTRAILER_BYP 0 + +/* + * Instruction load length + */ +#define IRLENGTH 6 + +/* + * Data register lengths for program + */ +#define DRLENGTH_PROGRAM 32 +/* + * Data register lengths for verify + */ +#define DRLENGTH_VERIFY 37 +/* + * Data register lengths for data load after ISC_ENABLE + */ +#define DRLENGTH_EN 5 +/* + * Data register load after ISC_ENABLE + */ +#define DR_EN 0x15 + +/* + * Timer function load for 100msec + */ +#define TIMER_100MS 1000000 + +/* + * IRCAPTURE status - init complete mask + */ +#define INITCOMPLETEMASK 0x10 + +/* + * Number of char's in a KEY + */ +#define NUMCHARINKEY 32 +/* + * Number of words in a KEY + */ +#define NUMWORDINKEY 8 + +/* + * Data register shift before key verify + */ +#define DATAREGCLEAR 0x1FFFFFFFE0 + +/* + * Number of LSB status bits in 37 bit read to shifted out + */ +#define NUMLSBSTATUSBITS 5 + +/* + * Data and instruction loads in de-init + */ +#define IRDEINIT_H 0x03 +#define IRDEINIT_L 0xFF +#define DRDEINIT 0x00 + +/* + * Data and instruction lenghts in de-init + */ +#define IRDEINITLEN 10 +#define DRDEINITLEN 2 + +/************************** Function Prototypes *****************************/ +/* + * Function for BBRAM program and vefiry algorithm + */ +int XilSKey_Bbram_Program(XilSKey_Bbram *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* End of XILSKEY_BBRAM_H */ diff --git a/lib/sw_services/xilskey/src/include/xilskey_epl.h b/lib/sw_services/xilskey/src/include/xilskey_epl.h new file mode 100644 index 00000000..29d3a734 --- /dev/null +++ b/lib/sw_services/xilskey/src/include/xilskey_epl.h @@ -0,0 +1,193 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file +* +* xilskey_epl.h +* @note +* Contains the function prototypes, defines and macros for the PL eFUSE +* functionality. +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- -------------------------------------------------------- +* 1.00a rpoolla 04/26/13 First release +* 1.02a hk 10/28/13 Added API's to read status bits and key : +* u32 XilSKey_EfusePl_ReadKey(XilSKey_EPl *InstancePtr) +* u32 XilSKey_EfusePl_ReadKey(XilSKey_EPl *InstancePtr) +* 2.00 hk 22/01/14 Corrected PL voltage checks to VCCINT and VCCAUX. +* CR#768077 +* +* +****************************************************************************/ +#ifndef XILSKEY_EPL_H +#define XILSKEY_EPL_H + +#ifdef __cplusplus +extern "C" { +#endif +/***************************** Include Files *********************************/ + +/************************** Constant Definitions *****************************/ +/** + * AES Key size in Bytes + */ +#define XSK_EFUSEPL_AES_KEY_SIZE_IN_BYTES (32) +/** + * User Key size in Bytes + */ +#define XSK_EFUSEPL_USER_KEY_SIZE_IN_BYTES (4) +/**************************** Type Definitions ******************************/ +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +/** + * XSK_EfusePl is the PL eFUSE driver instance. Using this + * structure, user can define the eFUSE bits to be + * blown. + */ +typedef struct { + /** + * Following are the FUSE CNTRL bits[1:5, 8-10] + */ + + /** + * If XTRUE then part has to be power cycled to be able to be reconfigured + */ + u32 ForcePowerCycle; + /** + * If XTRUE will disable eFUSE write to FUSE_AES and FUSE_USER blocks + */ + u32 KeyWrite; + /** + * If XTRUE will disable eFUSE read to FUSE_AES block and also disables + * eFUSE write to FUSE_AES and FUSE_USER blocks + */ + u32 AESKeyRead; + /** + * If XTRUE will disable eFUSE read to FUSE_USER block and also disables + * eFUSE write to FUSE_AES and FUSE_USER blocks + */ + u32 UserKeyRead; + /** + * If XTRUE will disable eFUSE write to FUSE_CNTRL block + */ + u32 CtrlWrite; + /** + * If XTRUE will force eFUSE key to be used if booting Secure Image + */ + u32 AESKeyExclusive; + /** + * If XTRUE then permanently sets the Zynq ARM DAP controller in bypass mode + */ + u32 JtagDisable; + /** + * If XTRUE will force to use Secure boot with eFUSE key only + */ + u32 UseAESOnly; + /** + * Following is the define to select if the user wants to select AES key + * and User Low Ley + */ + u32 ProgAESandUserLowKey; + /** + * Following is the define to select if the user wants to select + * User Low Ley + */ + u32 ProgUserHighKey; + /** + * This is the REF_CLK value in Hz + */ + /*u32 RefClk;*/ + /** + * This is for the aes_key value + */ + u8 AESKey[XSK_EFUSEPL_AES_KEY_SIZE_IN_BYTES]; + /** + * This is for the user_key value + */ + u8 UserKey[XSK_EFUSEPL_USER_KEY_SIZE_IN_BYTES]; + /** + * TDI MIO Pin Number + */ + u32 JtagMioTDI; + /** + * TDO MIO Pin Number + */ + u32 JtagMioTDO; + /** + * TCK MIO Pin Number + */ + u32 JtagMioTCK; + /** + * TMS MIO Pin Number + */ + u32 JtagMioTMS; + /** + * MUX Selection MIO Pin Number + */ + u32 JtagMioMuxSel; + /** + * Value on the MUX Selection line + */ + u32 JtagMuxSelLineDefVal; + /** + * AES key read + */ + u8 AESKeyReadback[XSK_EFUSEPL_AES_KEY_SIZE_IN_BYTES]; + /** + * User key read + */ + u8 UserKeyReadback[XSK_EFUSEPL_USER_KEY_SIZE_IN_BYTES]; + /** + * Internal variable to check if timer, XADC and JTAG are initialized. + */ + u32 SystemInitDone; + +}XilSKey_EPl; +/************************** Function Prototypes *****************************/ +/************************** Constant Definitions *****************************/ + +u32 XilSKey_EfusePl_Program(XilSKey_EPl *PlInstancePtr); + +u32 XilSKey_EfusePl_ReadStatus(XilSKey_EPl *InstancePtr, u32 *StatusBits); + +u32 XilSKey_EfusePl_ReadKey(XilSKey_EPl *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* End of XILSKEY_EPL_H */ diff --git a/lib/sw_services/xilskey/src/include/xilskey_eps.h b/lib/sw_services/xilskey/src/include/xilskey_eps.h new file mode 100644 index 00000000..2266de26 --- /dev/null +++ b/lib/sw_services/xilskey/src/include/xilskey_eps.h @@ -0,0 +1,105 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * @file xilskey_eps.h + * + * + * @note None. + * + * + * MODIFICATION HISTORY: + * +* Ver Who Date Changes +* ----- ---- -------- -------------------------------------------------------- +* 1.00a rpoolla 04/26/13 First release +* 1.02a hk 10/28/13 Added API to read status register: +* u32 XilSKey_EfusePs_ReadStatus( +* XilSKey_EPs *InstancePtr, u32 *StatusBits) +* RSA key read back is stored in RsaKeyReadback in +* Instance structure instead of RsaKeyHashValue - +* Change in API: +* u32 XilSKey_EfusePs_Read(XilSKey_EPs *PsInstancePtr) +* 2.00 hk 23/01/14 Changed PS efuse error codes for voltage out of range +* +* +*****************************************************************************/ + +#ifndef XILSKEY_EPS_H +#define XILSKEY_EPS_H + +/** + * Key length definition for RSA KEY Hash + */ +#define XSK_EFUSEPS_RSA_KEY_HASH_LEN_IN_BYTES (32) + +/** + * XSKEfusePs is the PS eFUSE driver instance. Using this + * structure, user can define the eFUSE bits to be + * blown. + */ +typedef struct { + /** + * EnableWriteProtect:Enable the eFUSE Array write protection + */ + u32 EnableWriteProtect; + /** + * EnableRsaAuth: Enable the RSA Authentication eFUSE Bit + */ + u32 EnableRsaAuth; + /** + * Enable the ROM code 128K crc eFUSE Bit + */ + u32 EnableRom128Crc; + /** + * EnableRsaKeyHash: Enabling this RsaKeyHashValue[32] is written to + * eFUSE array + */ + u32 EnableRsaKeyHash; + /** + * RsaKeyHashValue: RSA key Hash + */ + u8 RsaKeyHashValue[XSK_EFUSEPS_RSA_KEY_HASH_LEN_IN_BYTES]; + /** + * Rsa key read + */ + u8 RsaKeyReadback[XSK_EFUSEPS_RSA_KEY_HASH_LEN_IN_BYTES]; +} XilSKey_EPs; + +/** + * PS eFUSE interface functions + */ +u32 XilSKey_EfusePs_Write(XilSKey_EPs *PsInstancePtr); +u32 XilSKey_EfusePs_Read (XilSKey_EPs *PsInstancePtr); +u32 XilSKey_EfusePs_ReadStatus(XilSKey_EPs *InstancePtr, u32 *StatusBits); + +#endif /* XILSKEY_EPS_H */ diff --git a/lib/sw_services/xilskey/src/include/xilskey_utils.h b/lib/sw_services/xilskey/src/include/xilskey_utils.h new file mode 100644 index 00000000..4ca12dee --- /dev/null +++ b/lib/sw_services/xilskey/src/include/xilskey_utils.h @@ -0,0 +1,463 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * @file xilskey_utils.h + * + * + * @note None. + * + * + * MODIFICATION HISTORY: + * +* Ver Who Date Changes +* ----- ---- -------- -------------------------------------------------------- +* 1.00a rpoolla 04/26/13 First release +* 2.00 hk 23/01/14 Corrected PL voltage checks to VCCINT and VCCAUX. +* CR#768077. +* Changed PS efuse error codes for voltage out of range +* + *****************************************************************************/ + +#ifndef XILSKEY_UTILS_H +#define XILSKEY_UTILS_H +/***************************** Include Files ********************************/ +#include "xadcps.h" +/************************** Constant Definitions ****************************/ +/**************************** Type Definitions ******************************/ +/***************** Macros (Inline Functions) Definitions ********************/ +/** + * The following constants map to the XPAR parameters created in the + * xparameters.h file. They are defined here such that a user can easily + * change all the needed parameters in one place. + */ +#define XADC_DEVICE_ID XPAR_XADCPS_0_DEVICE_ID + +/** + * Temperature and voltage range for PS eFUSE reading and programming + * Temperature in Celsius('C) and Voltage(V) is in volts + */ +#define XSK_EFUSEPS_TEMP_MIN (-40) +#define XSK_EFUSEPS_TEMP_MAX (125) +#define XSK_EFUSEPS_READ_VPAUX_MIN (1.71) +#define XSK_EFUSEPS_READ_VPAUX_MAX (1.98) +#define XSK_EFUSEPS_WRITE_VPAUX_MIN (1.71) +#define XSK_EFUSEPS_WRITE_VPAUX_MAX (1.98) + +/** + * Converting the celsius temperature to equivalent Binary data for xAdc + */ +#define XSK_EFUSEPS_TEMP_MIN_RAW (XAdcPs_TemperatureToRaw(XSK_EFUSEPS_TEMP_MIN)) +#define XSK_EFUSEPS_TEMP_MAX_RAW (XAdcPs_TemperatureToRaw(XSK_EFUSEPS_TEMP_MAX)) + +/** + * Converting the voltage to equivalent Binary data for xAdc + */ +#define XSK_EFUSEPS_READ_VPAUX_MIN_RAW (XAdcPs_VoltageToRaw(XSK_EFUSEPS_READ_VPAUX_MIN)) +#define XSK_EFUSEPS_READ_VPAUX_MAX_RAW (XAdcPs_VoltageToRaw(XSK_EFUSEPS_READ_VPAUX_MAX)) +#define XSK_EFUSEPS_WRITE_VPAUX_MIN_RAW (XAdcPs_VoltageToRaw(XSK_EFUSEPS_WRITE_VPAUX_MIN)) +#define XSK_EFUSEPS_WRITE_VPAUX_MAX_RAW (XAdcPs_VoltageToRaw(XSK_EFUSEPS_WRITE_VPAUX_MAX)) + +/** + * Temperature and voltage range for PL eFUSE reading and programming + * Temperature in Celsius('C) and Voltage(V) is in volts + */ + +/** + * PL eFUSE write Min and Max Temperature and Voltages + */ +#define XSK_EFUSEPL_WRITE_TEMP_MIN (15) +#define XSK_EFUSEPL_WRITE_TEMP_MAX (125) + +#define XSK_EFUSEPL_WRITE_VOLTAGE_VCCAUX_MIN (1.71) +#define XSK_EFUSEPL_WRITE_VOLTAGE_VCCAUX_MAX (1.98) + +#define XSK_EFUSEPL_WRITE_VOLTAGE_VCCINT_MIN (.87) +#define XSK_EFUSEPL_WRITE_VOLTAGE_VCCINT_MAX (1.1) + +/** + * PL eFUSE read Min and Max Temperature and Voltages + */ +#define XSK_EFUSEPL_READ_TEMP_MIN (-55) +#define XSK_EFUSEPL_READ_TEMP_MAX (125) +#define XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MIN (1.62) +#define XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MAX (1.98) + +#define XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MIN (.795) +#define XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MAX (1.1) + + +/** + * PL eFUSE write Min and Max Temperature and Voltages + */ + +/** + * Converting the celsius temperature to equivalent Binary data for xAdc + */ +#define XSK_EFUSEPL_WRITE_TEMP_MIN_RAW (XAdcPs_TemperatureToRaw(XSK_EFUSEPL_WRITE_TEMP_MIN)) +#define XSK_EFUSEPL_WRITE_TEMP_MAX_RAW (XAdcPs_TemperatureToRaw(XSK_EFUSEPL_WRITE_TEMP_MAX)) + +/** + * Converting the voltage to equivalent Binary data for xAdc + */ +#define XSK_EFUSEPL_WRITE_VOLTAGE_VCCAUX_MIN_RAW (XAdcPs_VoltageToRaw(XSK_EFUSEPL_WRITE_VOLTAGE_VCCAUX_MIN)) +#define XSK_EFUSEPL_WRITE_VOLTAGE_VCCAUX_MAX_RAW (XAdcPs_VoltageToRaw(XSK_EFUSEPL_WRITE_VOLTAGE_VCCAUX_MAX)) + +/** + * Converting the voltage to equivalent Binary data for xAdc + */ +#define XSK_EFUSEPL_WRITE_VOLTAGE_VCCINT_MIN_RAW (XAdcPs_VoltageToRaw(XSK_EFUSEPL_WRITE_VOLTAGE_VCCINT_MIN)) +#define XSK_EFUSEPL_WRITE_VOLTAGE_VCCINT_MAX_RAW (XAdcPs_VoltageToRaw(XSK_EFUSEPL_WRITE_VOLTAGE_VCCINT_MAX)) + +/** + * PL eFUSE read Min and Max Temperature and Voltages + */ + +/** + * Converting the celsius temperature to equivalent Binary data for xAdc + */ +#define XSK_EFUSEPL_READ_TEMP_MIN_RAW (XAdcPs_TemperatureToRaw(XSK_EFUSEPL_READ_TEMP_MIN)) +#define XSK_EFUSEPL_READ_TEMP_MAX_RAW (XAdcPs_TemperatureToRaw(XSK_EFUSEPL_READ_TEMP_MAX)) + +/** + * Converting the voltage to equivalent Binary data for xAdc + */ + +#define XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MIN_RAW (XAdcPs_VoltageToRaw(XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MIN)) +#define XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MAX_RAW (XAdcPs_VoltageToRaw(XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MAX)) + +/** + * Converting the voltage to equivalent Binary data for xAdc + */ +#define XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MIN_RAW (XAdcPs_VoltageToRaw(XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MIN)) +#define XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MAX_RAW (XAdcPs_VoltageToRaw(XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MAX)) + +/** + * Different voltage types that can be read from xAdc + */ +#define XSK_EFUSEPS_VPINT (1) +#define XSK_EFUSEPS_VPAUX (2) +#define XSK_EFUSEPS_VPDRO (3) +#define XSK_EFUSEPS_VINT (4) +#define XSK_EFUSEPS_VAUX (5) + +#define XSK_EFUSE_DEBUG_GENERAL 0x00000001 /* general debug messages */ + +#if defined (XSK_EFUSE_DEBUG) +#define xeFUSE_dbg_current_types (XSK_EFUSE_DEBUG_GENERAL) +#else +#define xeFUSE_dbg_current_types 0 +#endif +#ifdef STDOUT_BASEADDRESS +#define xeFUSE_printf(type,...) \ + if (((type) & xeFUSE_dbg_current_types)) {xil_printf (__VA_ARGS__); } +#else +#define xeFUSE_printf(type, ...) +#endif + +#define XSK_GLOBAL_TIMER_BASE_ADDRESS (0xF8F00000) + +/** + * Global_Timer_Counter _Register0 (0xf8f00200) + */ +#define XSK_GLOBAL_TIMER_COUNT_REG_LOW (XSK_GLOBAL_TIMER_BASE_ADDRESS + 0x200) + +/** + * Global_Timer_Counter _Register1 (0xf8f00204) + */ +#define XSK_GLOBAL_TIMER_COUNT_REG_HIGH (XSK_GLOBAL_TIMER_BASE_ADDRESS + 0x204) + +/** + * Global_Timer_Control_Register (0xf8f00208) + */ +#define XSK_GLOBAL_TIMER_CTRL_REG (XSK_GLOBAL_TIMER_BASE_ADDRESS + 0x208) + + +/** + * System Level Control Registers Start Addr + */ +#define XSK_SLCR_START_ADDRESS (0xF8000000) +/** + * ARM PLL Control Register + */ +#define XSK_ARM_PLL_CTRL_REG (XSK_SLCR_START_ADDRESS + 0x100) +/** + * ARM Clock Control Register + */ +#define XSK_ARM_CLK_CTRL_REG (XSK_SLCR_START_ADDRESS + 0x120) + +/** + * PL eFUSE aes key size in characters + */ +#define XSK_EFUSEPL_AES_KEY_STRING_SIZE (64) +/** + * PL eFUSE user low key size in characters + */ +#define XSK_EFUSEPL_USER_LOW_KEY_STRING_SIZE (2) +/** + * PL eFUSE user high key size in characters + */ +#define XSK_EFUSEPL_USER_HIGH_KEY_STRING_SIZE (6) +/** + * AES Key size in Bytes + */ +#define XSK_EFUSEPL_AES_KEY_SIZE_IN_BYTES (32) +/** + * User Key size in Bytes + */ +#define XSK_EFUSEPL_USER_KEY_SIZE_IN_BYTES (4) +/** + * AES Key size in Bits + */ +#define XSK_EFUSEPL_AES_KEY_SIZE_IN_BITS (256) +/** + * User Low Key size in Bytes + */ +#define XSK_EFUSEPL_USER_LOW_KEY_SIZE_IN_BITS (8) +/** + * User High Key size in Bytes + */ +#define XSK_EFUSEPL_USER_HIGH_KEY_SIZE_IN_BITS (24) +/** + * Key length definition for RSA KEY Hash + */ +#define XSK_EFUSEPS_RSA_KEY_HASH_LEN_IN_BYTES (32) +/** + * PS eFUSE RSA key Hash size in characters + */ +#define XSK_EFUSEPL_RSA_KEY_HASH_STRING_SIZE (64) +/************************** Variable Definitions ****************************/ +/** + * XADC Structure + */ +typedef struct +{ + /** + * Current temperature + */ + u32 Temp; + /** + * Minimum temperature + */ + u32 TempMin; + /** + * Maximum temperature + */ + u32 TempMax; + /** + * Voltage type to read to select from VCCPINT, VCCPAUX, VCCPDRO + */ + u32 VType; + /** + * Current voltage of Vtype + */ + u32 V; + /** + * Minimum voltage of Vtype + */ + u32 VMin; + /** + * Maximum voltage of Vtype + */ + u32 VMax; +} XSKEfusePs_XAdc; + +/** + * PL EFUSE error codes + */ +typedef enum { + XSK_EFUSEPL_ERROR_NONE = 0, + + /** + * EFUSE Read error codes + */ + XSK_EFUSEPL_ERROR_ROW_NOT_ZERO = 0x10, + XSK_EFUSEPL_ERROR_READ_ROW_OUT_OF_RANGE, + XSK_EFUSEPL_ERROR_READ_MARGIN_OUT_OF_RANGE, + XSK_EFUSEPL_ERROR_READ_BUFFER_NULL, + XSK_EFUSEPL_ERROR_READ_BIT_VALUE_NOT_SET, + XSK_EFUSEPL_ERROR_READ_BIT_OUT_OF_RANGE, + XSK_EFUSEPL_ERROR_READ_TMEPERATURE_OUT_OF_RANGE, + XSK_EFUSEPL_ERROR_READ_VCCAUX_VOLTAGE_OUT_OF_RANGE, + XSK_EFUSEPL_ERROR_READ_VCCINT_VOLTAGE_OUT_OF_RANGE, + + /** + * EFUSE Write error codes + */ + XSK_EFUSEPL_ERROR_WRITE_ROW_OUT_OF_RANGE, + XSK_EFUSEPL_ERROR_WRITE_BIT_OUT_OF_RANGE, + XSK_EFUSEPL_ERROR_WRITE_TMEPERATURE_OUT_OF_RANGE, + XSK_EFUSEPL_ERROR_WRITE_VCCAUX_VOLTAGE_OUT_OF_RANGE, + XSK_EFUSEPL_ERROR_WRITE_VCCINT_VOLTAGE_OUT_OF_RANGE, + + /** + * EFUSE CNTRL error codes + */ + XSK_EFUSEPL_ERROR_FUSE_CNTRL_WRITE_DISABLED, + XSK_EFUSEPL_ERROR_CNTRL_WRITE_BUFFER_NULL, + + /** + * EFUSE KEY error codes + */ + XSK_EFUSEPL_ERROR_NOT_VALID_KEY_LENGTH, + XSK_EFUSEPL_ERROR_ZERO_KEY_LENGTH, + XSK_EFUSEPL_ERROR_NOT_VALID_KEY_CHAR, + XSK_EFUSEPL_ERROR_NULL_KEY, + + /** + * XSKEfusepl_Program_Efuse() error codes + */ + XSK_EFUSEPL_ERROR_KEY_VALIDATION = 0xF000, + XSK_EFUSEPL_ERROR_PL_STRUCT_NULL = 0x1000, + XSK_EFUSEPL_ERROR_JTAG_SERVER_INIT = 0x1100, + XSK_EFUSEPL_ERROR_READING_FUSE_CNTRL = 0x1200, + XSK_EFUSEPL_ERROR_DATA_PROGRAMMING_NOT_ALLOWED = 0x1300, + XSK_EFUSEPL_ERROR_FUSE_CTRL_WRITE_NOT_ALLOWED = 0x1400, + XSK_EFUSEPL_ERROR_READING_FUSE_AES_ROW = 0x1500, + XSK_EFUSEPL_ERROR_AES_ROW_NOT_EMPTY = 0x1600, + XSK_EFUSEPL_ERROR_PROGRAMMING_FUSE_AES_ROW = 0x1700, + XSK_EFUSEPL_ERROR_READING_FUSE_USER_DATA_ROW = 0x1800, + XSK_EFUSEPL_ERROR_USER_DATA_ROW_NOT_EMPTY = 0x1900, + XSK_EFUSEPL_ERROR_PROGRAMMING_FUSE_DATA_ROW = 0x1A00, + XSK_EFUSEPL_ERROR_PROGRAMMING_FUSE_CNTRL_ROW = 0x1B00, + XSK_EFUSEPL_ERROR_XADC = 0x1C00, + XSK_EFUSEPL_ERROR_INVALID_REF_CLK= 0x3000 +}XSKEfusePl_ErrorCodes; + + +/** + * PS EFUSE error codes + */ +typedef enum { + XSK_EFUSEPS_ERROR_NONE = 0, + + /** + * EFUSE Read error codes + */ + XSK_EFUSEPS_ERROR_ADDRESS_XIL_RESTRICTED = 0x01, + XSK_EFUSEPS_ERROR_READ_TMEPERATURE_OUT_OF_RANGE, + XSK_EFUSEPS_ERROR_READ_VCCPAUX_VOLTAGE_OUT_OF_RANGE, + XSK_EFUSEPS_ERROR_READ_VCCPINT_VOLTAGE_OUT_OF_RANGE, + + /** + * EFUSE Write error codes + */ + XSK_EFUSEPS_ERROR_WRITE_TEMPERATURE_OUT_OF_RANGE, + XSK_EFUSEPS_ERROR_WRITE_VCCPAUX_VOLTAGE_OUT_OF_RANGE, + XSK_EFUSEPS_ERROR_WRITE_VCCPINT_VOLTAGE_OUT_OF_RANGE, + XSK_EFUSEPS_ERROR_VERIFICATION, + XSK_EFUSEPS_ERROR_RSA_HASH_ALREADY_PROGRAMMED, + + /** + * FUSE CNTRL error codes + */ + XSK_EFUSEPS_ERROR_CONTROLLER_MODE, + XSK_EFUSEPS_ERROR_REF_CLOCK, + XSK_EFUSEPS_ERROR_READ_MODE, + + /** + * XADC Error Codes + */ + XSK_EFUSEPS_ERROR_XADC_CONFIG, + XSK_EFUSEPS_ERROR_XADC_INITIALIZE, + XSK_EFUSEPS_ERROR_XADC_SELF_TEST, + + /** + * Utils Error Codes + */ + XSK_EFUSEPS_ERROR_PARAMETER_NULL, + XSK_EFUSEPS_ERROR_STRING_INVALID, + + + /** + * XSKEfuse_Write/Read()common error codes + */ + XSK_EFUSEPS_ERROR_PS_STRUCT_NULL=0x8100, + XSK_EFUSEPS_ERROR_XADC_INIT=0x8200, + XSK_EFUSEPS_ERROR_CONTROLLER_LOCK=0x8300, + XSK_EFUSEPS_ERROR_EFUSE_WRITE_PROTECTED=0x8400, + XSK_EFUSEPS_ERROR_CONTROLLER_CONFIG=0x8500, + XSK_EFUSEPS_ERROR_PS_PARAMETER_WRONG=0x8600, + + /** + * XSKEfusePs_Write() error codes + */ + XSK_EFUSEPS_ERROR_WRITE_128K_CRC_BIT=0x9100, + XSK_EFUSEPS_ERROR_WRITE_NONSECURE_INITB_BIT=0x9200, + XSK_EFUSEPS_ERROR_WRITE_UART_STATUS_BIT=0x9300, + XSK_EFUSEPS_ERROR_WRITE_RSA_HASH=0x9400, + XSK_EFUSEPS_ERROR_WRITE_RSA_AUTH_BIT=0x9500, + XSK_EFUSEPS_ERROR_WRITE_WRITE_PROTECT_BIT=0x9600, + XSK_EFUSEPS_ERROR_READ_HASH_BEFORE_PROGRAMMING=0x9700, + + /** + * XSKEfusePs_Read() error codes + */ + XSK_EFUSEPS_ERROR_READ_RSA_HASH=0xA100, + +}XSKEfusePs_ErrorCodes; + +/* + * For backward compatibility with old error codes + */ + +#define XSK_EFUSEPS_ERROR_READ_VCCAUX_VOLTAGE_OUT_OF_RANGE XSK_EFUSEPS_ERROR_READ_VCCPAUX_VOLTAGE_OUT_OF_RANGE +#define XSK_EFUSEPS_ERROR_READ_VCCINT_VOLTAGE_OUT_OF_RANGE XSK_EFUSEPS_ERROR_READ_VCCPINT_VOLTAGE_OUT_OF_RANGE +#define XSK_EFUSEPS_ERROR_WRITE_VCCAUX_VOLTAGE_OUT_OF_RANGE XSK_EFUSEPS_ERROR_WRITE_VCCPAUX_VOLTAGE_OUT_OF_RANGE +#define XSK_EFUSEPS_ERROR_WRITE_VCCINT_VOLTAGE_OUT_OF_RANGE XSK_EFUSEPS_ERROR_WRITE_VCCPINT_VOLTAGE_OUT_OF_RANGE + + + +/************************** Function Prototypes *****************************/ +u32 XilSKey_EfusePs_XAdcInit (void ); +void XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(XSKEfusePs_XAdc *XAdcInstancePtr); +void XilSKey_Efuse_StartTimer(u32 RefClk); +u64 XilSKey_Efuse_GetTime(); +void XilSKey_Efuse_SetTimeOut(volatile u64* t, u64 us); +u8 XilSKey_Efuse_IsTimerExpired(u64 t); +void XilSKey_Efuse_ConvertBitsToBytes(const u8 * Bits, u8 * Bytes, u32 Len); +void XilSKey_EfusePs_ConvertBytesToBits(const u8 * Bits, u8 * Bytes, u32 Len); +void XilSKey_EfusePs_ConvertBytesBeToLe(const u8 *Be, u8 *Le, u32 Len); +u32 XilSKey_Efuse_ValidateKey(const char *key, u32 len); +u32 XilSKey_Efuse_IsValidChar(const char *c); +/** + * Common functions + */ +u32 XilSKey_Efuse_ConvertStringToHexLE(const char * Str, u8 * Buf, u32 Len); +u32 XilSKey_Efuse_ConvertStringToHexBE(const char * Str, u8 * Buf, u32 Len); +u32 XilSKey_Efuse_ValidateKey(const char *Key, u32 Len); + +/***************************************************************************/ + + + +#endif /* XILSKEY_UTILS_H */ diff --git a/lib/sw_services/xilskey/src/xilskey_bbram.c b/lib/sw_services/xilskey/src/xilskey_bbram.c new file mode 100644 index 00000000..5e997c1f --- /dev/null +++ b/lib/sw_services/xilskey/src/xilskey_bbram.c @@ -0,0 +1,172 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file +* xilskey_bbram.c +* @note +* +* . +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- -------------------------------------------------------- +* 1.01a hk 09/18/13 First release +* +****************************************************************************/ +/***************************** Include Files *********************************/ +#include "xparameters.h" +#include "xil_types.h" +#include "xilskey_utils.h" +#include "xilskey_bbram.h" + +/************************** Constant Definitions *****************************/ +/**************************** Type Definitions ******************************/ +/***************** Macros (Inline Functions) Definitions ********************/ +/************************** Variable Definitions ****************************/ +/************************** Function Prototypes *****************************/ +/** + * JTAG Server Initialization routine for Bbram + */ +extern int JtagServerInitBbram(XilSKey_Bbram *InstancePtr); + +/** + * BBRAM Algorithm - Initialization + */ +extern int Bbram_Init(XilSKey_Bbram *InstancePtr); + +/** + * BBRAM Algorithm - Program key + */ +extern int Bbram_ProgramKey(XilSKey_Bbram *InstancePtr); + +/** + * BBRAM Algorithm - Verify key + */ +extern int Bbram_VerifyKey(XilSKey_Bbram *InstancePtr); + +/** + * De-initialization + */ +extern void Bbram_DeInit(void); + +/***************************************************************************/ +/****************************************************************************/ +/** +* +* This function implements the BBRAM algorithm for programming and +* verifying key. The program and verify will only work together in and +* in that order. +* +* @param BBRAM instance pointer +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note +* +*****************************************************************************/ +int XilSKey_Bbram_Program(XilSKey_Bbram *InstancePtr) +{ + u32 ArmPllFdiv; + u32 ArmClkDivisor; + u32 RefClk; + int Status; + + if(NULL == InstancePtr) { + return XST_FAILURE; + } + + /** + * Extract PLL FDIV value from ARM PLL Control Register + */ + ArmPllFdiv = (Xil_In32(XSK_ARM_PLL_CTRL_REG)>>12 & 0x7F); + + /** + * Extract Clock divisor value from ARM Clock Control Register + */ + ArmClkDivisor = (Xil_In32(XSK_ARM_CLK_CTRL_REG)>>8 & 0x3F); + + /** + * Initialize the variables + */ + RefClk = ((XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ * ArmClkDivisor)/ + ArmPllFdiv); + + /* + * Initialize and start the timer + */ + XilSKey_Efuse_StartTimer(RefClk); + + /* + * JTAG server initialization + */ + if(JtagServerInitBbram(InstancePtr) != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * BBRAM Algorithm initialization + */ + Status = Bbram_Init(InstancePtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * BBRAM - Program key + */ + Status = Bbram_ProgramKey(InstancePtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * BBRAM - Verify key + */ + Status = Bbram_VerifyKey(InstancePtr); + if(Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * De-initialization + */ + Bbram_DeInit(); + + return XST_SUCCESS; +} diff --git a/lib/sw_services/xilskey/src/xilskey_epl.c b/lib/sw_services/xilskey/src/xilskey_epl.c new file mode 100644 index 00000000..3ee2d171 --- /dev/null +++ b/lib/sw_services/xilskey/src/xilskey_epl.c @@ -0,0 +1,1342 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file +* xilskey_epl.c +* @note +* +* Contains the function definitions for the PL eFUSE functionality. +* +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- -------------------------------------------------------- +* 1.00a rpoolla 04/26/13 First release +* 1.02a hk 10/28/13 Added API's to read status bits and key.PR# 735957 +* 2.00 hk 22/01/14 Corrected PL voltage checks to VCCINT and VCCAUX. +* CR#768077 +* +* +****************************************************************************/ +/***************************** Include Files *********************************/ +#include "xparameters.h" +#include "xil_types.h" +#include "xilskey_utils.h" +#include "xilskey_epl.h" +/************************** Constant Definitions *****************************/ +#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW (0) /**< Fuse Ctrl Row*/ +#define XSK_EFUSEPL_ARRAY_FUSE_AES_KEY_SIZE (256) /**< AES Key size*/ +#define XSK_EFUSEPL_ARRAY_FUSE_USER_KEY_SIZE (32) /**< User key size*/ +#define XSK_EFUSEPL_ARRAY_MAX_ROW (32) /**< PLeFUSE Max Rows*/ +#define XSK_EFUSEPL_ARRAY_MAX_COL (32) /**< PLeFUSE Max Columns*/ +#define XSK_EFUSEPL_ARRAY_AES_DATA_ROW_START (20) /**< AES Data Start Row*/ +#define XSK_EFUSEPL_ARRAY_AES_DATA_ROW_END (30) /**< AES Data End Row*/ +#define XSK_EFUSEPL_ARRAY_USER_DATA_START_ROW (31) /**< User Data Start Row*/ +#define XSK_EFUSEPL_ARRAY_AES_DATA_BITS_IN_30th_ROW (16) /**< AES Data bits + * count in 30th Row + */ +#define XSK_EFUSEPL_ARRAY_USER_DATA_BITS_IN_30th_ROW (8) /**< User Data bits + * count in 30th Row + */ +#define XSK_EFUSEPL_ARRAY_MAX_PAYLAOD_BITS_IN_A_ROW (24)/**< Max Pay load + * in Row + */ +#define XSK_EFUSEPL_ARRAY_MAX_ECC_BITS_IN_A_ROW (6) /**< Max ECC bits + * in a Row + */ +#define XSK_EFUSEPL_ARRAY_ECC_START_BIT_IN_A_ROW (24)/**< ECC Start Bit + * position in + * a Row + */ +#define XSK_EFUSEPL_ARRAY_ECC_END_BIT_IN_A_ROW (29)/**< ECC End Bit + * position in + * a Row + */ +#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_MAX_BITS (11)/**< Fuse Control max + * bits + */ +#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_INDEX (14)/**< Redundant bit + * Index + */ +#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_START_BIT (0) /**< Fuse Control + * Start bit + */ +#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_END_BIT (10) /**< Fuse Control + * Start bit + */ +#define XSK_EFUSEPL_ARRAY_UNSUPPORTED_BIT6 (6) /**< Unsupported bit*/ +#define XSK_EFUSEPL_ARRAY_UNSUPPORTED_BIT7 (7) /**< Unsupporte bit*/ +#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_START_BIT (14)/**< Redundant + * bit start Index + */ +#define XSK_EFUSEPL_ARRAY_UNSUPPORTED_RED_FOR_BIT6 (20)/**< Unsupported bit*/ +#define XSK_EFUSEPL_ARRAY_UNSUPPORTED_RED_FOR_BIT7 (21)/**< Unsupported bit*/ +#define XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_END_BIT (24)/**< Redundant bit + * End Index + */ +#define XSK_EFUSEPL_MAX_REF_CLK_FREQ 60000000 /**< Max Ref Clk Frequency */ +#define XSK_EFUSEPL_MIN_REF_CLK_FREQ 20000000 /**< Min Ref Clk Frequency */ +/**************************** Type Definitions ******************************/ +/** + * Read or Write eFUSE Margin Options + */ +typedef enum { + XSK_EFUSEPL_READ_NORMAL = 0x1, /**< Margin 1*/ + XSK_EFUSEPL_READ_MARGIN_1 = 0x2, /**< Margin 2*/ + XSK_EFUSEPL_READ_MARGIN_2 = 0x4, /**< Margin 4*/ + XSK_EFUSEPL_READ_MARGIN_MAX = 0x7 /**< Max Margin 7*/ +}XSK_EfusePl_MarginOption; +/** + * Fuse Control Row Bit Indices + */ +typedef enum { + XSK_EFUSEPL_CNTRL_FORCE_PCYCLE_RECONFIG = 0x01,/**< Bit1 of Fuse Ctrl Row*/ + XSK_EFUSEPL_CNTRL_DISABLE_KEY_WRITE, /**< Bit2 of Fuse Ctrl Row*/ + XSK_EFUSEPL_CNTRL_DISABLE_AES_KEY_READ, /**< Bit3 of Fuse Ctrl Row*/ + XSK_EFUSEPL_CNTRL_DISABLE_USER_KEY_READ, /**< Bit4 of Fuse Ctrl Row*/ + XSK_EFUSEPL_CNTRL_DISABLE_FUSE_CNTRL_WRITE, /**< Bit5 of Fuse Ctrl Row*/ + XSK_EFUSEPL_CNTRL_FORCE_USE_AES_ONLY = 0x08, /**< Bit8 of Fuse Ctrl Row*/ + XSK_EFUSEPL_CNTRL_JTAG_CHAIN_DISABLE, /**< Bit9 of Fuse Ctrl Row*/ + XSK_EFUSEPL_CNTRL_BBRAM_KEY_DISABLE /**< Bit10 of Fuse Ctrl Row*/ +}XSKEfusePl_FuseCntrlBits; +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Variable Definitions ****************************/ +u32 ErrorCode; /**< Global variable which holds the error key*/ +static u8 AesDataInBytes[XSK_EFUSEPL_ARRAY_FUSE_AES_KEY_SIZE]; +static u8 UserDataInBytes[XSK_EFUSEPL_ARRAY_FUSE_USER_KEY_SIZE]; + +/************************** Function Prototypes *****************************/ +/** + * PL eFUSE interface functions + */ +static u8 XilSKey_EfusePl_ProgramBit(u8 Row, u8 Bit); + +static u8 XilSKey_EfusePl_ProgramRow(u8 Row, u8 *RowData); + +static u8 XilSKey_EfusePl_ProgramControlRegister(u8 *CtrlData); + +static u8 XilSKey_EfusePl_ReadBit(u8 Row, u8 Bit, u8 MarginOption, u8 *BitData); + +static u8 XilSKey_EfusePl_ReadRow(u32 Row, u8 MarginOption, u8 *RowData); + +static u8 XilSKey_EfusePl_ReadControlRegister(u8 *CtrlData); + +static u8 XilSKey_EfusePl_VerifyBit(u8 Row, u8 Bit, u8 MarginOption); + +static u8 XilSKey_EfusePl_IsVectorAllZeros(u8 *RowDataPtr); + +static void XilSKey_EfusePl_CalculateEcc(u8 *RowData, u8 *ECCData); +/** + * JTAG Server Initialization routine + */ +extern int JtagServerInit(XilSKey_EPl *PlInstancePtr); +/** + * JTAG Server Write routine + */ +extern void JtagWrite(unsigned char row, unsigned char bit); +/** + * JTAG Server Read routine + */ +extern void JtagRead(unsigned char row, unsigned int * row_data, unsigned char marginOption); +/***************************************************************************/ +/****************************************************************************/ +/** +* +* +* Programs PL eFUSE with input data given +* +* +* @param InstancePtr - Input data to be written to PL eFUSE +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note Updates the global variable ErrorCode with error code(if any). +* +*****************************************************************************/ +u32 XilSKey_EfusePl_Program(XilSKey_EPl *InstancePtr) +{ + u32 Row = 0; + u8 RowData[XSK_EFUSEPL_ARRAY_MAX_COL]={0}; + u8 CtrlData[XSK_EFUSEPL_ARRAY_FUSE_CNTRL_MAX_BITS]={0}; + u32 Index = 0; + u32 Status; + u32 RefClk; + u32 ArmPllFDiv,ArmClkDivisor; + ErrorCode = XSK_EFUSEPL_ERROR_NONE; + + + if(NULL == InstancePtr) { + return XSK_EFUSEPL_ERROR_PL_STRUCT_NULL; + } + + if(!(InstancePtr->SystemInitDone)) + { + /** + * Extract PLL FDIV value from ARM PLL Control Register + */ + ArmPllFDiv = (Xil_In32(XSK_ARM_PLL_CTRL_REG)>>12 & 0x7F); + + /** + * Extract Clock divisor value from ARM Clock Control Register + */ + ArmClkDivisor = (Xil_In32(XSK_ARM_CLK_CTRL_REG)>>8 & 0x3F); + + /** + * Initialize the variables + */ + RefClk = ((XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ * + ArmClkDivisor)/ ArmPllFDiv); + + /** + * Return error if the reference clock frequency is not in + * between 20 & 60MHz + */ + if((RefClk < XSK_EFUSEPL_MIN_REF_CLK_FREQ) || + (RefClk > XSK_EFUSEPL_MAX_REF_CLK_FREQ)) { + return XSK_EFUSEPL_ERROR_INVALID_REF_CLK; + } + /** + * Initialize the system , + * which means initialize the timer, xadc, and jtag + * server using the passed info. + */ + + XilSKey_Efuse_StartTimer(RefClk); + + Status = XilSKey_EfusePs_XAdcInit(); + if(Status != XST_SUCCESS) { + ErrorCode = Status; + return (XSK_EFUSEPL_ERROR_XADC + ErrorCode); + } + /** + * Start using the Jtag server to read the JTAG ID and + * compare with the stored ID, if it not matches return with + * unique error code. + * By reading the Jtag ID we will be sure that the JTAG related + * stuff is working as expected. + */ + if(JtagServerInit(InstancePtr) != XST_SUCCESS) { + return XSK_EFUSEPL_ERROR_JTAG_SERVER_INIT; + } + + InstancePtr->SystemInitDone = 1; + + } + + /** + * Read the FUSE_CNTL register bits [5:2], and if any of them is found to + * be set to 1 then we can not write to the eFUSE, so return with unique + * error. + * + * If everything is well above then start programming with FUSE_AES key as + * passed to this function, followed by FUSE_USER if selected. + * + * AES key is 256 bits, but has to be written across many rows, in the PL + * eFUSE each row has 24 bits of data bits and 6 bits of ecc bits. + * So for 256 bits we will need full 10 rows(240 bits) and extra 1 row for + * remaining 16 bits, but rest 8 bits will be taken from the FUSE_USER key + * value[7:0] + * + * check if FUSE_CNTRL allows us to read and write the AES and USER eFUSE + * array. + */ + + + if(XilSKey_EfusePl_ReadControlRegister(CtrlData) != XST_SUCCESS) { + return (XSK_EFUSEPL_ERROR_READING_FUSE_CNTRL + ErrorCode); + } + + if (((CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_AES_KEY_READ] == TRUE) || + (CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_USER_KEY_READ] == TRUE)|| + (CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_KEY_WRITE]== TRUE)) && + ((InstancePtr->ProgAESandUserLowKey == TRUE) || + (InstancePtr->ProgUserHighKey == TRUE))) { + return (XSK_EFUSEPL_ERROR_DATA_PROGRAMMING_NOT_ALLOWED + ErrorCode); + } + + if((CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_KEY_WRITE] == TRUE) && + ((InstancePtr->ForcePowerCycle == TRUE)|| + (InstancePtr->KeyWrite == TRUE)|| + (InstancePtr->AESKeyRead == TRUE)|| + (InstancePtr->UserKeyRead == TRUE)|| + (InstancePtr->UseAESOnly == TRUE)|| + (InstancePtr->JtagDisable == TRUE)|| + (InstancePtr->AESKeyExclusive == TRUE))) { + return (XSK_EFUSEPL_ERROR_FUSE_CTRL_WRITE_NOT_ALLOWED + ErrorCode); + } + /** + * convert each aes data bits to bytes. + */ + XilSKey_Efuse_ConvertBitsToBytes(&InstancePtr->AESKey[0], + AesDataInBytes, + XSK_EFUSEPL_ARRAY_FUSE_AES_KEY_SIZE); + + /** + * convert each user data bits to bytes. + */ + XilSKey_Efuse_ConvertBitsToBytes(&InstancePtr->UserKey[0], + UserDataInBytes, + XSK_EFUSEPL_ARRAY_FUSE_USER_KEY_SIZE); + + + if(InstancePtr->ProgAESandUserLowKey == TRUE) { + /** + * check if row 20 to 30 are empty before programming AES and + * USER low key. + */ + for(Row=XSK_EFUSEPL_ARRAY_AES_DATA_ROW_START; + Row<=XSK_EFUSEPL_ARRAY_AES_DATA_ROW_END; + Row++) { + if(XilSKey_EfusePl_ReadRow(Row, XSK_EFUSEPL_READ_NORMAL, + RowData) != XST_SUCCESS) { + return (XSK_EFUSEPL_ERROR_READING_FUSE_AES_ROW + ErrorCode); + } + if(XilSKey_EfusePl_IsVectorAllZeros(RowData) != XST_SUCCESS) { + return (XSK_EFUSEPL_ERROR_AES_ROW_NOT_EMPTY + ErrorCode); + } + } + + /** + * program AES_KEY 256 bits and USER_KEY lower 8 bits first. + */ + for(Row=XSK_EFUSEPL_ARRAY_AES_DATA_ROW_START; + Row<=XSK_EFUSEPL_ARRAY_AES_DATA_ROW_END; + Row++) { + if(Row < XSK_EFUSEPL_ARRAY_AES_DATA_ROW_END) { + /** + * prepare row data for row from 20 to 29. + */ + for(Index=0; + IndexProgUserHighKey == TRUE) { + /** + * check if 31 is empty before programming USER high key. + */ + if(XilSKey_EfusePl_ReadRow(XSK_EFUSEPL_ARRAY_USER_DATA_START_ROW, + XSK_EFUSEPL_READ_NORMAL, RowData) != + XST_SUCCESS) { + return (XSK_EFUSEPL_ERROR_READING_FUSE_USER_DATA_ROW + ErrorCode); + } + + + if(XilSKey_EfusePl_IsVectorAllZeros(RowData) != XST_SUCCESS) { + return (XSK_EFUSEPL_ERROR_USER_DATA_ROW_NOT_EMPTY + ErrorCode); + } + + /** + * Program USER_KEY high 24 bits next. + * Prepare row data for row 31. + */ + + for(Index=0; IndexForcePowerCycle; + CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_KEY_WRITE] = InstancePtr->KeyWrite; + CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_AES_KEY_READ] = InstancePtr->AESKeyRead; + CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_USER_KEY_READ] = InstancePtr->UserKeyRead; + CtrlData[XSK_EFUSEPL_CNTRL_DISABLE_FUSE_CNTRL_WRITE] = InstancePtr->CtrlWrite; + CtrlData[XSK_EFUSEPL_CNTRL_FORCE_USE_AES_ONLY] = InstancePtr->UseAESOnly; + CtrlData[XSK_EFUSEPL_CNTRL_JTAG_CHAIN_DISABLE] = InstancePtr->JtagDisable; + CtrlData[XSK_EFUSEPL_CNTRL_BBRAM_KEY_DISABLE] = InstancePtr->AESKeyExclusive; + + if(XilSKey_EfusePl_ProgramControlRegister(CtrlData) != XST_SUCCESS) { + return (XSK_EFUSEPL_ERROR_PROGRAMMING_FUSE_CNTRL_ROW + ErrorCode); + } + /** + * If everything is ok then return PASS. + */ + return XST_SUCCESS; +} +/****************************************************************************/ +/** +* +* Checks whether data bits (0-29) of an PL eFUSE row are all zeroes or not +* +* +* +* @param RowDataPtr - row data pointer +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* @note None. +* +*****************************************************************************/ +u8 XilSKey_EfusePl_IsVectorAllZeros(u8 *RowDataPtr) +{ + u32 Index; + for(Index=0; Index<=XSK_EFUSEPL_ARRAY_ECC_END_BIT_IN_A_ROW; Index++) { + if(RowDataPtr[Index] != 0) { + return XST_FAILURE; + } + } + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* Programs a bit of PL eFUSE row +* +* +* +* @param Row - row number +* @param Bit - bit position +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note Updates the global variable ErrorCode with error code(if any). +* +*****************************************************************************/ +u8 XilSKey_EfusePl_ProgramBit(u8 Row, u8 Bit) +{ + XSKEfusePs_XAdc PL_XAdc; + /** + *Check if the row position is valid. + */ + if( (Row > XSK_EFUSEPL_ARRAY_USER_DATA_START_ROW) || + ( (Row > XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW) + && (Row < XSK_EFUSEPL_ARRAY_AES_DATA_ROW_START) + ) + ) + { + ErrorCode = XSK_EFUSEPL_ERROR_WRITE_ROW_OUT_OF_RANGE; + return XST_FAILURE; + } + + /** + * Check if the bit position is valid. + */ + if((Bit < XSK_EFUSEPL_ARRAY_FUSE_CNTRL_START_BIT) || + (Bit > XSK_EFUSEPL_ARRAY_ECC_END_BIT_IN_A_ROW)) { + ErrorCode = XSK_EFUSEPL_ERROR_WRITE_BIT_OUT_OF_RANGE; + return XST_FAILURE; + } + + /** + * If row=0 then bit should be either 1 to 5 and 8 to 10, 15 to 19 and + * 22 to 24 rest all are not supported + */ + if(Row == XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW) { + + if((Bit == XSK_EFUSEPL_ARRAY_FUSE_CNTRL_START_BIT) || + (Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_BIT6) || + (Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_BIT7)|| + (Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_RED_FOR_BIT6)|| + (Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_RED_FOR_BIT7)) { + ErrorCode = XSK_EFUSEPL_ERROR_WRITE_BIT_OUT_OF_RANGE; + return XST_FAILURE; + } + + if((Bit > XSK_EFUSEPL_ARRAY_FUSE_CNTRL_END_BIT) && + (Bit < XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_START_BIT)) { + ErrorCode = XSK_EFUSEPL_ERROR_WRITE_BIT_OUT_OF_RANGE; + return XST_FAILURE; + } + + if(Bit > XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_END_BIT){ + ErrorCode = XSK_EFUSEPL_ERROR_WRITE_BIT_OUT_OF_RANGE; + return XST_FAILURE; + } + } + + /** + * Monitor the Voltage and temperature using XADC, if out of range return + * unique error. + */ + PL_XAdc.VType = XSK_EFUSEPS_VAUX; + XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc); + if((PL_XAdc.Temp < XSK_EFUSEPL_WRITE_TEMP_MIN_RAW) || + (PL_XAdc.Temp > XSK_EFUSEPL_WRITE_TEMP_MAX_RAW)) { + ErrorCode = XSK_EFUSEPL_ERROR_WRITE_TMEPERATURE_OUT_OF_RANGE; + return XST_FAILURE; + } + + if((PL_XAdc.V < XSK_EFUSEPL_WRITE_VOLTAGE_VCCAUX_MIN_RAW) || + (PL_XAdc.V > XSK_EFUSEPL_WRITE_VOLTAGE_VCCAUX_MAX_RAW)) { + ErrorCode = XSK_EFUSEPL_ERROR_WRITE_VCCAUX_VOLTAGE_OUT_OF_RANGE; + return XST_FAILURE; + } + + PL_XAdc.VType = XSK_EFUSEPS_VINT; + XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc); + if((PL_XAdc.V < XSK_EFUSEPL_WRITE_VOLTAGE_VCCINT_MIN_RAW) || + (PL_XAdc.V > XSK_EFUSEPL_WRITE_VOLTAGE_VCCINT_MAX_RAW)) { + ErrorCode = XSK_EFUSEPL_ERROR_WRITE_VCCINT_VOLTAGE_OUT_OF_RANGE; + return XST_FAILURE; + } + + JtagWrite(Row, Bit); + return XST_SUCCESS; +} +/****************************************************************************/ +/** +* +* Programs PL eFUSE row +* +* +* +* @param Row - row number +* @param RowData- row data pointer +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note Updates the global variable ErrorCode with error code(if any). +* +*****************************************************************************/ + +u8 XilSKey_EfusePl_ProgramRow(u8 Row, u8 *RowData) +{ + u32 Bit = 0; + u8 ECCData[XSK_EFUSEPL_ARRAY_MAX_ECC_BITS_IN_A_ROW] = {0}; + + /** + * check if row_data is not NULL + */ + if(NULL == RowData) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_BUFFER_NULL; + return XST_FAILURE; + } + + if(Row == XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW) { + ErrorCode = XSK_EFUSEPL_ERROR_WRITE_ROW_OUT_OF_RANGE; + return XST_FAILURE; + } + + for(Bit=0; Bit < XSK_EFUSEPL_ARRAY_MAX_PAYLAOD_BITS_IN_A_ROW ; Bit++ ) { + if(RowData[Bit]) { + if(XilSKey_EfusePl_ProgramBit(Row, Bit) != XST_SUCCESS) { + return XST_FAILURE; + } + + if(XilSKey_EfusePl_VerifyBit(Row, Bit, XSK_EFUSEPL_READ_NORMAL) + != XST_SUCCESS) { + return XST_FAILURE; + } + + if(XilSKey_EfusePl_VerifyBit(Row,Bit,XSK_EFUSEPL_READ_MARGIN_1) + != XST_SUCCESS) { + return XST_FAILURE; + } + } + } + + XilSKey_EfusePl_CalculateEcc(RowData, ECCData); + for(Bit=XSK_EFUSEPL_ARRAY_ECC_START_BIT_IN_A_ROW; + Bit <= XSK_EFUSEPL_ARRAY_ECC_END_BIT_IN_A_ROW; + Bit++) { + if(ECCData[Bit - XSK_EFUSEPL_ARRAY_ECC_START_BIT_IN_A_ROW]) { + if(XilSKey_EfusePl_ProgramBit(Row, Bit) != XST_SUCCESS) { + return XST_FAILURE; + } + + if(XilSKey_EfusePl_VerifyBit(Row, Bit, XSK_EFUSEPL_READ_NORMAL) + != XST_SUCCESS) { + return XST_FAILURE; + } + + if(XilSKey_EfusePl_VerifyBit(Row,Bit,XSK_EFUSEPL_READ_MARGIN_1) + != XST_SUCCESS) { + return XST_FAILURE; + } + + } + } + + return XST_SUCCESS; +} +/****************************************************************************/ +/** +* +* Programs PL eFUSE Control Register +* +* +* +* @param CtrlData - Control data pointer +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note Updates the global variable ErrorCode with error code(if any). +* +*****************************************************************************/ +u8 XilSKey_EfusePl_ProgramControlRegister(u8 *CtrlData) +{ + u8 TmpCtrlData[XSK_EFUSEPL_ARRAY_FUSE_CNTRL_MAX_BITS]={0}; + u32 Index = 0; + + /** + * check if cntrl_data is not NULL + */ + if(NULL == CtrlData) { + ErrorCode = XSK_EFUSEPL_ERROR_CNTRL_WRITE_BUFFER_NULL; + return XST_FAILURE; + } + + /** + * Read the FUSE_CNTRL register + */ + if(XilSKey_EfusePl_ReadControlRegister(TmpCtrlData) != XST_SUCCESS) { + return XST_FAILURE; + } + + /** + * check if FUSE_CNTRL allows us to write FUSE_CNTRL eFUSE array. + */ + if(TmpCtrlData[XSK_EFUSEPL_CNTRL_DISABLE_FUSE_CNTRL_WRITE] == TRUE) { + /** + * This means we cannot program FUSE_CNTRL register + */ + ErrorCode = XSK_EFUSEPL_ERROR_FUSE_CNTRL_WRITE_DISABLED; + return XST_FAILURE; + } + + + for(Index=1;Index XSK_EFUSEPL_ARRAY_ECC_END_BIT_IN_A_ROW)) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_BIT_OUT_OF_RANGE; + return XST_FAILURE; + } + + + /** + * If row=0 then bit should be either 1 to 5 and 8 to 10, 15 to 19 and + * 22 to 24 rest all are not supported + */ + if(Row == XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW) { + + if((Bit == XSK_EFUSEPL_ARRAY_FUSE_CNTRL_START_BIT) || + (Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_BIT6) || + (Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_BIT7)|| + (Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_RED_FOR_BIT6)|| + (Bit == XSK_EFUSEPL_ARRAY_UNSUPPORTED_RED_FOR_BIT7)) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_BIT_OUT_OF_RANGE; + return XST_FAILURE; + } + + if((Bit > XSK_EFUSEPL_ARRAY_FUSE_CNTRL_END_BIT) && + (Bit < XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_START_BIT)) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_BIT_OUT_OF_RANGE; + return XST_FAILURE; + } + + if(Bit > XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_END_BIT) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_BIT_OUT_OF_RANGE; + return XST_FAILURE; + } + } + + if(XilSKey_EfusePl_ReadRow(Row, MarginOption,RowData) != XST_SUCCESS) { + return XST_FAILURE; + } + + *BitData = RowData[Bit]; + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* Reads row data of a specified row +* +* +* @param Row - row number +* @param MarginOption - Margin Option(One of the reading method of PLeFUSE) +* @param RowDataBytes - To store the read data bytes of specified row. +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note Read data will be stored @row_data_bytes +* +*****************************************************************************/ + +u8 XilSKey_EfusePl_ReadRow(u32 Row, u8 MarginOption, u8 *RowDataBytes) +{ + XSKEfusePs_XAdc PL_XAdc; + u32 RowDataBits=0; + + /** + * Check if the row position is valid. + */ + if((Row > XSK_EFUSEPL_ARRAY_USER_DATA_START_ROW) || + ((Row > XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW) && + (Row < XSK_EFUSEPL_ARRAY_AES_DATA_ROW_START))) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_ROW_OUT_OF_RANGE; + return XST_FAILURE; + } + + /** + * Check the read margin option. + */ + if( (MarginOption != XSK_EFUSEPL_READ_NORMAL ) && + (MarginOption != XSK_EFUSEPL_READ_MARGIN_1)&& + (MarginOption != XSK_EFUSEPL_READ_MARGIN_2)) + { + ErrorCode = XSK_EFUSEPL_ERROR_READ_MARGIN_OUT_OF_RANGE; + return XST_FAILURE; + } + + /** + * check if row_data is not NULL + */ + if(NULL == RowDataBytes) + { + ErrorCode = XSK_EFUSEPL_ERROR_READ_BUFFER_NULL; + return XST_FAILURE; + } + + + /** + * Monitor the Voltage and temperature using XADC, if out of range return + * unique error. + */ + PL_XAdc.VType = XSK_EFUSEPS_VAUX; + XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc); + if((PL_XAdc.Temp < XSK_EFUSEPL_READ_TEMP_MIN_RAW) || + (PL_XAdc.Temp > XSK_EFUSEPL_READ_TEMP_MAX_RAW)) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_TMEPERATURE_OUT_OF_RANGE; + return XST_FAILURE; + } + + if((PL_XAdc.V < XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MIN_RAW) || + (PL_XAdc.V > XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MAX_RAW)) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCAUX_VOLTAGE_OUT_OF_RANGE; + return XST_FAILURE; + } + + PL_XAdc.VType = XSK_EFUSEPS_VINT; + XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc); + if((PL_XAdc.V < XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MIN_RAW) || + (PL_XAdc.V > XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MAX_RAW)) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCINT_VOLTAGE_OUT_OF_RANGE; + return XST_FAILURE; + } + + /** + * Here we have to use the impact algorithm to read the eFUSE row. + * and return the data in row_data. + */ + + if((MarginOption & XSK_EFUSEPL_READ_NORMAL) == XSK_EFUSEPL_READ_NORMAL) { + + JtagRead(Row, (unsigned int *)&RowDataBits, 0); + } + else if((MarginOption & XSK_EFUSEPL_READ_MARGIN_1) == + XSK_EFUSEPL_READ_MARGIN_1) { + JtagRead(Row, (unsigned int *)&RowDataBits, 1); + } + else if((MarginOption & XSK_EFUSEPL_READ_MARGIN_2) == + XSK_EFUSEPL_READ_MARGIN_2) { + JtagRead(Row, (unsigned int *)&RowDataBits, 2); + } + + XilSKey_Efuse_ConvertBitsToBytes((u8 *)&RowDataBits, RowDataBytes, 32); + + return XST_SUCCESS; +} +/****************************************************************************/ +/** +* +* Reads PL eFUSE Control Register data +* +* +* @param CtrlData - Place holder to store the read data (control register) +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note Updates the global variable ErrorCode with error code (if any) +* +*****************************************************************************/ + +u8 XilSKey_EfusePl_ReadControlRegister(u8 *CtrlData) +{ + u8 RowData[XSK_EFUSEPL_ARRAY_MAX_COL]={0}; + u32 Index=0; + + /** + * check if cntrl_data is not NULL + */ + if(NULL == CtrlData) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_BUFFER_NULL; + return XST_FAILURE; + } + + if(XilSKey_EfusePl_ReadRow(XSK_EFUSEPL_ARRAY_FUSE_CNTRL_ROW, + XSK_EFUSEPL_READ_NORMAL, + RowData) != XST_SUCCESS) + { + return XST_FAILURE; + } + + for(Index=0; Index < XSK_EFUSEPL_ARRAY_FUSE_CNTRL_MAX_BITS; Index++) + { + CtrlData[Index] = RowData[Index] | + RowData[Index + + XSK_EFUSEPL_ARRAY_FUSE_CNTRL_REDUNDENT_START_BIT]; + } + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** +* +* +* Verify the PL eFUSE bit blown by reading it back +* +* +* @param Row - row number +* @param Bit - bit position of the specified row +* @param MarginOption - Margin Option(One of the reading method of PLeFUSE) +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note Updates the global variable ErrorCode with error code(if any). +* +*****************************************************************************/ +u8 XilSKey_EfusePl_VerifyBit(u8 Row, u8 Bit, u8 MarginOption) +{ + u8 BitData = 0; + if(XilSKey_EfusePl_ReadBit(Row, Bit, MarginOption, &BitData) + != XST_SUCCESS) { + return XST_FAILURE; + } + + if(BitData == FALSE) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_BIT_VALUE_NOT_SET; + return XST_FAILURE; + } + return XST_SUCCESS; +} +/****************************************************************************/ +/** +* +* Calculates and stores the ECC data of row data +* +* +* @param RowData - Pointer to row data on which ECC will be calculated +* @param ECCData - Pointer to store the calculated ECC +* +* @return +* +* None +* +* @note None. +* +*****************************************************************************/ +void XilSKey_EfusePl_CalculateEcc(u8 *RowData, u8 *ECCData) +{ + ECCData[0] = RowData[0] ^ RowData[1] ^ RowData[2] ^ + RowData[3] ^ RowData[8] ^ RowData[9] ^ + RowData[10] ^ RowData[11] ^ RowData[12] ^ + RowData[13] ^ RowData[14] ^ RowData[15] ^ + RowData[16] ^ RowData[17]; + + ECCData[1] = RowData[1] ^ RowData[2] ^ RowData[3] ^ + RowData[5] ^ RowData[6] ^ RowData[7] ^ + RowData[11] ^ RowData[12] ^ RowData[13] ^ + RowData[14] ^ RowData[18] ^ RowData[19] ^ + RowData[20]; + + ECCData[2] = RowData[0] ^ RowData[2] ^ RowData[3] ^ + RowData[4] ^ RowData[6] ^ RowData[7] ^ + RowData[9] ^ RowData[10] ^ RowData[13] ^ + RowData[15] ^ RowData[18] ^ RowData[21] ^ + RowData[22]; + + ECCData[3] = RowData[0] ^ RowData[1] ^ RowData[3] ^ + RowData[4] ^ RowData[5] ^ RowData[7] ^ + RowData[8] ^ RowData[10] ^ RowData[12] ^ + RowData[16] ^ RowData[19] ^ RowData[21] ^ + RowData[23]; + + ECCData[4] = RowData[0] ^ RowData[1] ^ RowData[2] ^ + RowData[4] ^ RowData[5] ^ RowData[6] ^ + RowData[8] ^ RowData[9] ^ RowData[11] ^ + RowData[17] ^ RowData[20] ^ RowData[22] ^ + RowData[23]; + + /** + * This is the DED data + */ + + ECCData[5] = RowData[0] ^ RowData[1] ^ RowData[2] ^ + RowData[3] ^ RowData[4] ^ RowData[5] ^ + RowData[6] ^ RowData[7] ^ RowData[8] ^ + RowData[9] ^ RowData[10] ^ RowData[11] ^ + RowData[12] ^ RowData[13] ^ RowData[14] ^ + RowData[15] ^ RowData[16] ^ RowData[17] ^ + RowData[18] ^ RowData[19] ^ RowData[20] ^ + RowData[21] ^ RowData[22] ^ RowData[23] ^ + ECCData[0] ^ ECCData[1] ^ ECCData[2] ^ + ECCData[3] ^ ECCData[4]; +} + +/****************************************************************************/ +/** +* +* +* Reads the PL efuse status bits +* +* +* @param InstancePtr - Input data to be written to PL eFUSE +* @param StatusBits - Variable to store the status bits read. +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note Updates the global variable ErrorCode with error code(if any). +* +*****************************************************************************/ +u32 XilSKey_EfusePl_ReadStatus(XilSKey_EPl *InstancePtr, u32 *StatusBits) +{ + u32 RefClk; + u32 ArmPllFdiv; + u32 ArmClkDivisor; + unsigned int RowData; + u32 Status; + XSKEfusePs_XAdc PL_XAdc; + + if(NULL == InstancePtr) { + return XSK_EFUSEPL_ERROR_PL_STRUCT_NULL; + } + + if(!(InstancePtr->SystemInitDone)) + { + + /** + * Extract PLL FDIV value from ARM PLL Control Register + */ + ArmPllFdiv = (Xil_In32(XSK_ARM_PLL_CTRL_REG)>>12 & 0x7F); + + /** + * Extract Clock divisor value from ARM Clock Control Register + */ + ArmClkDivisor = (Xil_In32(XSK_ARM_CLK_CTRL_REG)>>8 & 0x3F); + + /** + * Initialize the variables + */ + RefClk = ((XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ * ArmClkDivisor)/ + ArmPllFdiv); + + /** + * Return error if the reference clock frequency is not in + * between 20 & 60MHz + */ + if((RefClk < XSK_EFUSEPL_MIN_REF_CLK_FREQ) || + (RefClk > XSK_EFUSEPL_MAX_REF_CLK_FREQ)) { + return XSK_EFUSEPL_ERROR_INVALID_REF_CLK; + } + + /** + * Initialize the timer, XADC and jtag server + */ + + XilSKey_Efuse_StartTimer(RefClk); + + Status = XilSKey_EfusePs_XAdcInit(); + if(Status != XST_SUCCESS) { + ErrorCode = Status; + return (XSK_EFUSEPL_ERROR_XADC + ErrorCode); + } + + if(JtagServerInit(InstancePtr) != XST_SUCCESS) { + return XSK_EFUSEPL_ERROR_JTAG_SERVER_INIT; + } + + InstancePtr->SystemInitDone = 1; + + } + + /** + * Monitor the Voltage and temperature using XADC, if out of range return + * unique error. + */ + PL_XAdc.VType = XSK_EFUSEPS_VAUX; + XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc); + if((PL_XAdc.Temp < XSK_EFUSEPL_READ_TEMP_MIN_RAW) || + (PL_XAdc.Temp > XSK_EFUSEPL_READ_TEMP_MAX_RAW)) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_TMEPERATURE_OUT_OF_RANGE; + return XST_FAILURE; + } + + if((PL_XAdc.V < XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MIN_RAW) || + (PL_XAdc.V > XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MAX_RAW)) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCAUX_VOLTAGE_OUT_OF_RANGE; + return XST_FAILURE; + } + PL_XAdc.VType = XSK_EFUSEPS_VINT; + XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc); + if((PL_XAdc.V < XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MIN_RAW) || + (PL_XAdc.V > XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MAX_RAW)) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCINT_VOLTAGE_OUT_OF_RANGE; + return XST_FAILURE; + } + + /* + * Read row 0 for status bits + */ + JtagRead(0, &RowData, 0); + + *StatusBits = RowData & 0xFFFFFF; + + return XST_SUCCESS; + +} + +/****************************************************************************/ +/** +* +* +* Reads the PL efuse key (AES and user) +* +* +* @param InstancePtr - Input data to be written to PL eFUSE +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note Updates the global variable ErrorCode with error code(if any). +* +*****************************************************************************/ +u32 XilSKey_EfusePl_ReadKey(XilSKey_EPl *InstancePtr) +{ + u32 RefClk; + u32 ArmPllFdiv; + u32 ArmClkDivisor; + u32 RowCount; + unsigned int RowData; + u32 KeyCnt; + u32 Status; + XSKEfusePs_XAdc PL_XAdc; + + if(NULL == InstancePtr) { + return XSK_EFUSEPL_ERROR_PL_STRUCT_NULL; + } + + if(!(InstancePtr->SystemInitDone)) + { + + /** + * Extract PLL FDIV value from ARM PLL Control Register + */ + ArmPllFdiv = (Xil_In32(XSK_ARM_PLL_CTRL_REG)>>12 & 0x7F); + + /** + * Extract Clock divisor value from ARM Clock Control Register + */ + ArmClkDivisor = (Xil_In32(XSK_ARM_CLK_CTRL_REG)>>8 & 0x3F); + + /** + * Initialize the variables + */ + RefClk = ((XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ * ArmClkDivisor)/ + ArmPllFdiv); + + /** + * Return error if the reference clock frequency is not in + * between 20 & 60MHz + */ + if((RefClk < XSK_EFUSEPL_MIN_REF_CLK_FREQ) || + (RefClk > XSK_EFUSEPL_MAX_REF_CLK_FREQ)) { + return XSK_EFUSEPL_ERROR_INVALID_REF_CLK; + } + + /** + * Initialize the timer and jtag server + */ + + XilSKey_Efuse_StartTimer(RefClk); + + Status = XilSKey_EfusePs_XAdcInit(); + if(Status != XST_SUCCESS) { + ErrorCode = Status; + return (XSK_EFUSEPL_ERROR_XADC + ErrorCode); + } + + if(JtagServerInit(InstancePtr) != XST_SUCCESS) { + return XSK_EFUSEPL_ERROR_JTAG_SERVER_INIT; + } + + InstancePtr->SystemInitDone = 1; + + } + + /** + * Monitor the Voltage and temperature using XADC, if out of range return + * unique error. + */ + PL_XAdc.VType = XSK_EFUSEPS_VAUX; + XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc); + if((PL_XAdc.Temp < XSK_EFUSEPL_READ_TEMP_MIN_RAW) || + (PL_XAdc.Temp > XSK_EFUSEPL_READ_TEMP_MAX_RAW)) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_TMEPERATURE_OUT_OF_RANGE; + return XST_FAILURE; + } + + if((PL_XAdc.V < XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MIN_RAW) || + (PL_XAdc.V > XSK_EFUSEPL_READ_VOLTAGE_VCCAUX_MAX_RAW)) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCAUX_VOLTAGE_OUT_OF_RANGE; + return XST_FAILURE; + } + + PL_XAdc.VType = XSK_EFUSEPS_VINT; + XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc); + if((PL_XAdc.V < XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MIN_RAW) || + (PL_XAdc.V > XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MAX_RAW)) { + ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCINT_VOLTAGE_OUT_OF_RANGE; + return XST_FAILURE; + } + + /* + * Read AES key and User Key and + * store them in the variables in instance structure + */ + + /* + * AES key 4 bytes + */ + KeyCnt = 0; + + /* + * Read row 20 to 29 + */ + for(RowCount = 20; RowCount <= 29; RowCount++) + { + JtagRead(RowCount, &RowData, 0); + InstancePtr->AESKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF); + RowData = RowData >> 8; + InstancePtr->AESKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF); + RowData = RowData >> 8; + InstancePtr->AESKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF); + } + + /* + * Read row 30 + */ + JtagRead(30, &RowData, 0); + InstancePtr->AESKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF); + RowData = RowData >> 8; + InstancePtr->AESKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF); + + /* + * User key 4 bytes + */ + KeyCnt = 0; + RowData = RowData >> 8; + InstancePtr->UserKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF); + + /* + * Read row 31 + */ + JtagRead(31, &RowData, 0); + InstancePtr->UserKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF); + RowData = RowData >> 8; + InstancePtr->UserKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF); + RowData = RowData >> 8; + InstancePtr->UserKeyReadback[KeyCnt++] = (u8)(RowData & 0xFF); + + return XST_SUCCESS; + +} \ No newline at end of file diff --git a/lib/sw_services/xilskey/src/xilskey_eps.c b/lib/sw_services/xilskey/src/xilskey_eps.c new file mode 100644 index 00000000..702d51a8 --- /dev/null +++ b/lib/sw_services/xilskey/src/xilskey_eps.c @@ -0,0 +1,1521 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * @file xilskey_eps.c + * This file contains the PS eFUSE API's to program/read the eFUSE array. + * + * @note None. + * + * + * MODIFICATION HISTORY: + * +* Ver Who Date Changes +* ----- ---- -------- -------------------------------------------------------- +* 1.00a rpoolla 04/26/13 First release +* 1.02a hk 10/28/13 Added API to read status register.PR# 735957 +* 2.00 hk 23/01/14 Changed PS efuse error codes for voltage out of range. +* +* +*****************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xil_io.h" +#include "xil_types.h" +#include "xstatus.h" +#include "xilskey_utils.h" +#include "xilskey_epshw.h" +#include "xilskey_eps.h" +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +u8 Matrix[31][5]; /**< PS eFUSE Matrix*/ +u8 ErrorCodeIndex[32]; /**< Error Code Array */ +/************************** Function Prototypes *****************************/ +static u32 XilSKey_EfusePs_WriteWithXadcCheckAndVerify(u32 EfuseAddress, u32 RefClk); +static u32 XilSKey_EfusePs_WriteRsaKeyHash(u8 *RsaKeyHashBuf, u32 RefClk); +static u32 XilSKey_EfusePs_ReadRsaKeyHash(u8 *RsaKeyHashBuf, u32 RefClk); +static u32 XilSKey_EfusePs_ReadWithXadcCheck(u32 EfuseAddress, u32 RefClk, u8 *Data); +static u32 XilSKey_EfusePs_VerifyWithXadcCheck(u32 EfuseAddress, u32 RefClk); +static u32 XilSKey_EfusePs_CheckRsaHashForAllZeros(u32 RefClk); +static void XilSKey_EfusePs_SetControllerMode (u8 Mode); +static void XilSKey_EfusePs_SetControllerReadMode (u8 ReadMode); +static u8 XilSKey_EfusePs_IsReadModeSupported (u8 ReadMode); + +/***************************************************************************/ +/** +* This function is used to write to the PS eFUSE. +* +* @param InstancePtr is the pointer to the PsEfuseHandle which describes +* which PS eFUSE bit should be burned. +* +* @return +* - XST_SUCCESS. +* - Incase of error, value is as defined in xeFUSE_error.h. +* Error value is a combination of Upper 8 bit value and +* Lower 8 bit value. For example, 0x8A03 should be checked +* in error.h as 0x8A00 and 0x03. Upper 8 bit value signifies +* the major error and lower 8 bit values tells more precisely. +* +****************************************************************************/ +u32 XilSKey_EfusePs_Write(XilSKey_EPs *InstancePtr) +{ + u32 Status, StatusRedundantBit, RetValue; + u32 RefClk; + u32 ArmPllFDiv,ArmClkDivisor; + + RetValue = XST_SUCCESS; + + + if (NULL == InstancePtr) { + return XSK_EFUSEPS_ERROR_PS_STRUCT_NULL; + } + + /** + * Extract PLL FDIV value from ARM PLL Control Register + */ + ArmPllFDiv = (Xil_In32(XSK_ARM_PLL_CTRL_REG)>>12 & 0x7F); + /** + * Extract Clock divisor value from ARM Clock Control Register + */ + ArmClkDivisor = (Xil_In32(XSK_ARM_CLK_CTRL_REG)>>8 & 0x3F); + + /** + * Initialize the variables + */ + RefClk = ((XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ * ArmClkDivisor)/ + ArmPllFDiv); + + /** + * Check the variables + */ + + if (((InstancePtr->EnableWriteProtect != TRUE) && + (InstancePtr->EnableWriteProtect != FALSE)) || + ((InstancePtr->EnableRsaAuth != TRUE) && + (InstancePtr->EnableRsaAuth != FALSE)) || + ((InstancePtr->EnableRom128Crc != TRUE) && + (InstancePtr->EnableRom128Crc != FALSE)) || + ((InstancePtr->EnableRsaKeyHash != TRUE) && + (InstancePtr->EnableRsaKeyHash != FALSE)) ) { + return XSK_EFUSEPS_ERROR_PS_PARAMETER_WRONG; + } + + /** + * XAdc Initialization + */ + Status = XilSKey_EfusePs_XAdcInit(); + if (Status != XST_SUCCESS) { + RetValue = XSK_EFUSEPS_ERROR_XADC_INIT; + goto ExitFinal; + } + + xeFUSE_printf(XSK_EFUSE_DEBUG_GENERAL,"Writing PS EFUSE \n"); + /** + * Unlock the eFUSE controller + */ + XSK_EFUSEPS_CONTROLER_UNLOCK(); + + /** + * Check if the controller is unlocked + */ + if (XSK_EFUSEPS_CONTROLER_LOCK_STATUS() == TRUE) { + RetValue = XSK_EFUSEPS_ERROR_CONTROLLER_LOCK; + goto ExitFinal; + } + + /** + * If eFUSE Array is write protected + * no more writes are possible + */ + + if (XilSKey_EfusePs_IsEfuseWriteProtected() == TRUE) { + RetValue = XSK_EFUSEPS_ERROR_EFUSE_WRITE_PROTECTED; + goto ExitCtrlLock; + } + + /** + * Configure the eFUSE controller with mode, strobe width values. + */ + Status = XilSKey_EfusePs_ControllerConfig(XSK_EFUSEPS_SINGLE_MODE, + RefClk, XSK_EFUSEPS_READ_MODE_NORMAL); + if (Status != XST_SUCCESS) { + RetValue = XSK_EFUSEPS_ERROR_CONTROLLER_CONFIG + Status; + goto ExitCtrlResetStatus; + } + + /** + * Enable Programming, write and read + */ + XilSKey_EfusePs_ControllerSetReadWriteEnable(XSK_EFUSEPS_ENABLE_PROGRAMMING | + XSK_EFUSEPS_ENABLE_READ | XSK_EFUSEPS_ENABLE_WRITE); + + /** + * Initialize the timer for delay while programming the eFUSE + */ + XilSKey_Efuse_StartTimer(RefClk); + + /** + * Program the eFUSE based + * on the structure values + */ + + /** + * Program the eFUSE bit 0xA to enable + * ROM 128K CRC + */ + if (InstancePtr->EnableRom128Crc) { + Status = XilSKey_EfusePs_WriteWithXadcCheckAndVerify( + XSK_EFUSEPS_APB_ROM_128K_CRC_ENABLE, RefClk); + if (Status != XST_SUCCESS) { + RetValue = XSK_EFUSEPS_ERROR_WRITE_128K_CRC_BIT + Status; + goto ExitCtrlResetStatus; + } + } + + /** + * Program the RSA key Hash value in eFUSE Array \ + */ + if (InstancePtr->EnableRsaKeyHash) { + /** + * Check if all the hash eFUSE bits are zero or not + */ + /* NEW: Changed the ReadRsaKeyHash to new function + * XilSKey_EfusePs_CheckRsaHashForAllZeros because of 2 bugs + * 1. If we are using ReadRsaKeyHash function here, if only 1 bit is + * written it will correct it and allow to write + * 2. Controller is in SINGLE mode, so even if 2nd half is written + * we will continue to write + * */ + Status = XilSKey_EfusePs_CheckRsaHashForAllZeros(RefClk); + if (Status != XST_SUCCESS) { + + RetValue = XSK_EFUSEPS_ERROR_READ_HASH_BEFORE_PROGRAMMING + Status; + goto ExitCtrlResetStatus; + } + + /** + * Program the RSA hash + */ + Status = XilSKey_EfusePs_WriteRsaKeyHash( + InstancePtr->RsaKeyHashValue, RefClk); + if (Status != XST_SUCCESS) { + RetValue = XSK_EFUSEPS_ERROR_WRITE_RSA_HASH + Status; + goto ExitCtrlResetStatus; + } + } + + /** + * Program the eFUSE bit 0xB to enable + * RSA authentication + */ + if (InstancePtr->EnableRsaAuth) { + Status = XilSKey_EfusePs_WriteWithXadcCheckAndVerify( + XSK_EFUSEPS_APB_RSA_AUTH_ENABLE, RefClk); + if (Status != XST_SUCCESS) { + RetValue = XSK_EFUSEPS_ERROR_WRITE_RSA_AUTH_BIT + Status; + goto ExitCtrlResetStatus; + } + } + + /** + * Program the eFUSE bit 0x8,0x9 to enable + * eFUSE Array Write Protection + * + * Once enabled the write protection, we will not be + * able to program any PS eFUSE afterwards + */ + + /** + * SLCR reset is required for write protect + * to take into effect + */ + if (InstancePtr->EnableWriteProtect) { + Status = XilSKey_EfusePs_WriteWithXadcCheckAndVerify( + XSK_EFUSEPS_APB_WRITE_PROTECTION_ADDR_1, RefClk); + + StatusRedundantBit = XilSKey_EfusePs_WriteWithXadcCheckAndVerify( + XSK_EFUSEPS_APB_WRITE_PROTECTION_ADDR_2, RefClk); + + + /* NEW: Error only if burning of the both the bits are not success */ + if ((Status != XST_SUCCESS) && (StatusRedundantBit != XST_SUCCESS)) { + RetValue = XSK_EFUSEPS_ERROR_WRITE_WRITE_PROTECT_BIT + Status; + goto ExitCtrlResetStatus; + } + } + +ExitCtrlResetStatus: + /** + * Disable Programming, write and read + */ + XilSKey_EfusePs_ControllerSetReadWriteEnable(0); + +ExitCtrlLock: + /** + * Lock the eFUSE controller + */ + XSK_EFUSEPS_CONTROLER_LOCK(); + +ExitFinal: + return RetValue; +} + +/***************************************************************************/ +/** +* This function is used to read the PS eFUSE. +* +* @param InstancePtr is the pointer to the PsEfuseHandle which describes +* which PS eFUSE should be burned. +* +* @return +* - XST_SUCCESS no errors occured. +* - Incase of error, value is as defined in xeFUSE_error.h. +* Error value is a combination of Upper 8 bit value and +* Lower 8 bit value. For example, 0x8A03 should be checked +* in error.h as 0x8A00 and 0x03. Upper 8 bit value signifies +* the major error and lower 8 bit values tells more precisely. +* +****************************************************************************/ +u32 XilSKey_EfusePs_Read(XilSKey_EPs *InstancePtr) +{ + + u32 Status, RetValue; + u32 RefClk; + u32 ArmPllFDiv,ArmClkDivisor; + + RetValue = XST_SUCCESS; + + + if (NULL == InstancePtr) { + return XSK_EFUSEPS_ERROR_PS_STRUCT_NULL; + } + + /** + * Extract PLL FDIV value from ARM PLL Control Register + */ + ArmPllFDiv = (Xil_In32(XSK_ARM_PLL_CTRL_REG)>>12 & 0x7F); + /** + * Extract Clock divisor value from ARM Clock Control Register + */ + ArmClkDivisor = (Xil_In32(XSK_ARM_CLK_CTRL_REG)>>8 & 0x3F); + + /** + * Initialize the variables + */ + RefClk = ((XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ * ArmClkDivisor)/ + ArmPllFDiv); + + /** + * Check the variables + */ + + if ((InstancePtr->EnableRsaKeyHash != TRUE) && + (InstancePtr->EnableRsaKeyHash != FALSE)) { + return XSK_EFUSEPS_ERROR_PS_PARAMETER_WRONG; + } + + /** + * XAdc Initialization + */ + Status = XilSKey_EfusePs_XAdcInit(); + if (Status != XST_SUCCESS) { + RetValue = XSK_EFUSEPS_ERROR_XADC_INIT; + goto ExitFinal; + } + + /** + * Unlock the eFUSE controller + */ + XSK_EFUSEPS_CONTROLER_UNLOCK(); + + /** + * Check if the controller is unlocked + */ + if (XSK_EFUSEPS_CONTROLER_LOCK_STATUS() == TRUE) { + RetValue = XSK_EFUSEPS_ERROR_CONTROLLER_LOCK; + goto ExitFinal; + } + + /** + * Configure the eFUSE controller with mode, strobe width values + */ + Status = XilSKey_EfusePs_ControllerConfig(XSK_EFUSEPS_REDUNDANCY_MODE, + RefClk, XSK_EFUSEPS_READ_MODE_NORMAL); + if (Status != XST_SUCCESS) { + RetValue = XSK_EFUSEPS_ERROR_CONTROLLER_CONFIG + Status; + goto ExitCtrlLock; + } + + /** + * Enable eFUSE reading only + */ + XilSKey_EfusePs_ControllerSetReadWriteEnable(XSK_EFUSEPS_ENABLE_READ); + + /** + * Read the eFUSE + */ + + /** + * Read the RSA key Hash value from eFUSE Array + */ + if (InstancePtr->EnableRsaKeyHash) { + Status = XilSKey_EfusePs_ReadRsaKeyHash( + InstancePtr->RsaKeyReadback, RefClk); + if (Status != XST_SUCCESS) { + RetValue = XSK_EFUSEPS_ERROR_READ_RSA_HASH + Status; + goto ExitCtrlResetStatus; + } + } + +ExitCtrlResetStatus: + /** + * Disable Programming, write and read + */ + XilSKey_EfusePs_ControllerSetReadWriteEnable(0); + +ExitCtrlLock: + /** + * Lock the eFUSE controller + */ + XSK_EFUSEPS_CONTROLER_LOCK(); + +ExitFinal: + return RetValue; +} + +/***************************************************************************/ +/** +* This function is used to check the RSA Hash for all zeros. +* +* @param RefClk is the reference clock frequency. Clock frequency can be +* between 20MHz to 60MHz specified in Hz +* +* @return +* - XST_SUCCESS if RSA Hash eFUSE bits are all zeros. +* - XSK_EFUSEPS_ERROR_RSA_HASH_ALREADY_PROGRAMMED if any RSA hash +* eFUSE bit is set +* - Other errors because of internal controller functions and +* can be checked in xeFUSE_error.h +* +****************************************************************************/ + +static u32 XilSKey_EfusePs_CheckRsaHashForAllZeros(u32 RefClk) +{ + u32 EfuseAddress,Status,RetValue; + u32 LoopIndex; + u8 Data; + + RetValue = XST_SUCCESS; + + /** + * Set the controller to read in redundancy mode + */ + Status = XilSKey_EfusePs_ControllerConfig(XSK_EFUSEPS_REDUNDANCY_MODE, + RefClk, XSK_EFUSEPS_READ_MODE_NORMAL); + if (Status != XST_SUCCESS) { + return Status; + } + + /** + * Check the Hash eFUSE Bits for all Zero's + */ + LoopIndex = 0; + EfuseAddress=XSK_EFUSEPS_APB_CUSTOMER_KEY_FIRST_HALF_START_ADDR; + while (LoopIndex < (XSK_EFUSEPS_HAMMING_LOOPS*XSK_EFUSEPS_HAMMING_LENGTH)) { + /** + * Escape the Xilinx Reserved Bits + */ + while (XilSKey_EfusePs_IsAddressXilRestricted(EfuseAddress) == TRUE) { + EfuseAddress += 4; + } + Status = XilSKey_EfusePs_ReadWithXadcCheck(EfuseAddress, RefClk, &Data); + if (Status != XST_SUCCESS) { + RetValue = Status; + goto ExitControllerReset; + } + /** + * Data value of 1 indicates Hash is already written + */ + if (Data != 0) { + RetValue = XSK_EFUSEPS_ERROR_RSA_HASH_ALREADY_PROGRAMMED; + goto ExitControllerReset; + } + EfuseAddress += 4; + LoopIndex++; + } /* End of while (LoopIndex < (XSK_EFUSEPS_HAMMING_LOOPS* ....) */ + +ExitControllerReset: + /** + * Set the controller back to single mode + */ + Status = XilSKey_EfusePs_ControllerConfig(XSK_EFUSEPS_SINGLE_MODE, + RefClk, XSK_EFUSEPS_READ_MODE_NORMAL); + if (Status != XST_SUCCESS) { + return Status; + } + + return RetValue; +} + +/***************************************************************************/ +/** +* This function is used to to write the Single eFUSE which checks for +* XADC temperature and voltage and verifies the written bit in the eFUSE +* Verification of the bit is done by reading the bit in margin 1 mode and +* normal mode. +* Temperature and voltage are read from XADC and verified for the +* correct range +* +* @param EfuseAddress is the address of the eFUSE bit to be written +* @param RefClk is the reference clock frequency. Clock frequency can be +* between 20MHz to 60MHz specified in Hz +* @return +* - XST_SUCCESS no errors occured +* - an error XSK_EFUSEPS_ERROR_WRITE_VCCPAUX_VOLTAGE_OUT_OF_RANGE when +* voltage not in range +* - an error XSK_EFUSEPS_ERROR_WRITE_TEMPERATURE_OUT_OF_RANGE when +* temperature not in range +* - Other errors because of internal functions and +* can be checked in xeFUSE_error.h +****************************************************************************/ +static u32 +XilSKey_EfusePs_WriteWithXadcCheckAndVerify(u32 EfuseAddress, u32 RefClk) +{ + XSKEfusePs_XAdc XAdcInstancePtr; + u32 Status, StatusLowerAddr, RedundantEfuseAddress; + + /** + * If the eFUSE bit is already programmed, no need to program again. + * That is taken care in eFUSE controller write function + */ + XAdcInstancePtr.VType = XSK_EFUSEPS_VPAUX; + XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&XAdcInstancePtr); + + /** + * Check the temperature and voltage + */ + if ((XAdcInstancePtr.Temp < XSK_EFUSEPS_TEMP_MIN_RAW) || + ((XAdcInstancePtr.Temp > XSK_EFUSEPS_TEMP_MAX_RAW))) { + return XSK_EFUSEPS_ERROR_WRITE_TEMPERATURE_OUT_OF_RANGE; + } + + if ((XAdcInstancePtr.V < XSK_EFUSEPS_WRITE_VPAUX_MIN_RAW) || + ((XAdcInstancePtr.V > XSK_EFUSEPS_WRITE_VPAUX_MAX_RAW))) { + return XSK_EFUSEPS_ERROR_WRITE_VCCPAUX_VOLTAGE_OUT_OF_RANGE; + } + + /** + * Write the eFUSE bit + */ + StatusLowerAddr = XilSKey_EfusePs_WriteEfuseBit(EfuseAddress); + + /** + * verify only if programming is success + * verification of lower address is checked while + * higher address verification + */ + if (StatusLowerAddr == XST_SUCCESS) { + StatusLowerAddr = XilSKey_EfusePs_VerifyWithXadcCheck(EfuseAddress, + RefClk); + } + + /** + * Write the Redundant eFUSE bit address + */ + RedundantEfuseAddress = XSK_EFUSEPS_APB_MIRROR_ADDRESS(EfuseAddress); + Status = XilSKey_EfusePs_WriteEfuseBit(RedundantEfuseAddress); + if (Status != XST_SUCCESS) { + /** + * if higher address is not success, check lower address and return + */ + if (StatusLowerAddr != XST_SUCCESS) { + return Status; + } else { + /** + * Successfully written lower address, so success + */ + return XST_SUCCESS; + } + } + + Status = XilSKey_EfusePs_VerifyWithXadcCheck(RedundantEfuseAddress, + RefClk); + if (Status != XST_SUCCESS) { + /** + * if higher address is not success, check lower address and return + */ + if (StatusLowerAddr != XST_SUCCESS) { + return Status; + } else { + /** + * Succesfully written lower address, so success + */ + return XST_SUCCESS; + } + } + + /** + * Ideal case where lower and higher address is written properly + */ + return XST_SUCCESS; +} + + +/***************************************************************************/ +/** +* This function is used to write the RSA hash in the eFUSE Array in Little +* Endian. +* +* @param RsaKeyHashBuf is the buffer containing the RSA hash to be written +* to the eFUSE array. +* @param RefClk is the reference clock frequency. Clock frequency can be +* between 20MHz to 60MHz specified in Hz +* @return +* - XST_SUCCESS no errors occurred. +* - Other errors because of internal controller functions and +* can be checked in xeFUSE_error.h +* +****************************************************************************/ +static u32 XilSKey_EfusePs_WriteRsaKeyHash(u8 *RsaKeyHashBuf, u32 RefClk) +{ + int LoopIndex,BitIndex; + u8 DataBytes[XSK_EFUSEPS_RSA_KEY_HASH_LEN_BITS], Ecc[32]; + u32 EfuseAddress, Status; + + + /** + * Convert the RSA Key hash to bit data + */ + XilSKey_Efuse_ConvertBitsToBytes(RsaKeyHashBuf, DataBytes, + (XSK_EFUSEPS_RSA_KEY_HASH_LEN_IN_BYTES*8)); + + /** + * Prepare the hamming matrix for encoding the RSA Key hash + */ + XilSKey_EfusePs_GenerateMatrixMap(); + + /** + * Encode the RSA Key hash with (31,26) hamming and write into + * the eFUSE array + */ + LoopIndex=0; + EfuseAddress=XSK_EFUSEPS_APB_CUSTOMER_KEY_FIRST_HALF_START_ADDR; + while (LoopIndex < XSK_EFUSEPS_HAMMING_LOOPS) { + /** + * Encode the data + */ + XilSKey_EfusePs_EccEncode(DataBytes + (LoopIndex*26), Ecc); + /* Write 31 bit Row in eFUSE Array */ + for (BitIndex=0;BitIndex<31;BitIndex++) { + /** + * Escape the Xilinx Reserved Bits + */ + if (XilSKey_EfusePs_IsAddressXilRestricted(EfuseAddress) == TRUE) { + xeFUSE_printf(XSK_EFUSE_DEBUG_GENERAL, + "Discarding eFUSE Address %0x\n", + EfuseAddress); + EfuseAddress = EfuseAddress+4; + } + + /** + * Write the eFUSE bit only if the value is one + */ + if (Ecc[BitIndex] & 0x1) { + xeFUSE_printf(XSK_EFUSE_DEBUG_GENERAL, + "Writing eFUSE Addr %0x, LoopIndex %0x, " + "BitIndex %0x\n", + EfuseAddress, LoopIndex, BitIndex); + Status = XilSKey_EfusePs_WriteWithXadcCheckAndVerify( + EfuseAddress, RefClk); + if (Status != XST_SUCCESS) { + return Status; + } + } /* End of (Ecc[BitIndex] & 0x1) */ + /** + * Ready for next eFUSE Bit + */ + EfuseAddress += 4; + + } /* End of for(BitIndex=0;BitIndex<31;BitIndex++) */ + LoopIndex++; + } /* End of while(LoopIndex < XSK_EFUSEPS_HAMMING_LOOPS) */ + + return XST_SUCCESS; +} + +/***************************************************************************/ +/** +* This function is used to Read the RSA hash in the eFUSE Array in Little +* Endian. +* +* @param RsaKeyHashBuf is the output buffer where RSA hash is copied +* from the eFUSE array after hamming decode. +* @param RefClk is the reference clock frequency. Clock frequency can be +* between 20MHz to 60MHz specified in Hz +* @return +* - XST_SUCCESS no errors occurred. +* - Other errors because of internal controller functions and +* can be checked in xeFUSEutils.h +****************************************************************************/ +static u32 XilSKey_EfusePs_ReadRsaKeyHash(u8 *RsaKeyHashBuf, u32 RefClk) +{ + int LoopIndex, BitIndex, Index; + u8 DataBytes[260], Recover[32], Syndrome[5], Pos; + u32 EfuseAddress, Status; + + /** + * Prepare the hamming matrix for encoding the RSA Key hash + */ + XilSKey_EfusePs_GenerateMatrixMap(); + + /** + * Encode the RSA Key hash with (31,26) hamming and write to + * the eFUSE array + */ + LoopIndex=0; + EfuseAddress=XSK_EFUSEPS_APB_CUSTOMER_KEY_FIRST_HALF_START_ADDR; + while (LoopIndex < XSK_EFUSEPS_HAMMING_LOOPS) { + /** + * Write 31 bit Row in eFUSE Array + */ + for (BitIndex=0;BitIndex<31;BitIndex++) { + /** + * Escape the Xilinx Reserved Bits + */ + if (XilSKey_EfusePs_IsAddressXilRestricted(EfuseAddress) == TRUE) { + xeFUSE_printf(XSK_EFUSE_DEBUG_GENERAL, + "Discarding eFUSE Address %0x\n", + EfuseAddress); + EfuseAddress += 4; + } + xeFUSE_printf(XSK_EFUSE_DEBUG_GENERAL, + "Reading eFUSE Addr %0x, LoopIndex %0x, " + "BitIndex %0x\n", + EfuseAddress, LoopIndex, BitIndex); + Status = XilSKey_EfusePs_ReadWithXadcCheck( + EfuseAddress, + RefClk, + Recover+BitIndex); + if (Status != XST_SUCCESS) { + return Status; + } + EfuseAddress += 4; + } /* End of for(BitIndex=0;BitIndex<31;BitIndex++) */ + + /** + * Decode the data + */ + Pos = XilSKey_EfusePs_EccDecode(Recover, Syndrome); + /** + * Repair the corrupt bit + */ + if(Pos < 31) + { + Recover[Pos] = (Recover[Pos] + 1)% 2; + } + /** + * Copy the data + */ + for(Index=0;Index<26;Index++) + { + *(DataBytes + (LoopIndex * 26) + Index) = Recover[Index]; + } + LoopIndex++; + } /* End of while(LoopIndex < XSK_EFUSEPS_HAMMING_LOOPS) */ + + /** + * Convert the bit data to RSA key hash + */ + XilSKey_EfusePs_ConvertBytesToBits(DataBytes, + RsaKeyHashBuf, + (XSK_EFUSEPS_RSA_KEY_HASH_LEN_BITS)); + + return XST_SUCCESS; +} + +/***************************************************************************/ +/** +* This function is used to read the PS eFUSE bit. Reading of the eFUSE bit +* is done in NORMAL read mode. Temperature and voltage must be in specified +* range for reading. +* +* @param EfuseAddress is the address of the eFUSE bit +* @param RefClk is the reference clock frequency. Clock frequency can be +* between 20MHz to 60MHz specified in Hz +* @param Data is where the read data is stored. It will have values 0 or 1 +* @return +* - XST_SUCCESS no errors occurred. +* - an error XSK_EFUSEPS_ERROR_READ_VCCPAUX_VOLTAGE_OUT_OF_RANGE when +* voltage not in range +* - an error XSK_EFUSEPS_ERROR_READ_TMEPERATURE_OUT_OF_RANGE when +* temperature not in range +* - Other errors because of internal controller functions and +* can be checked in xeFUSE_error.h +****************************************************************************/ +static u32 +XilSKey_EfusePs_ReadWithXadcCheck(u32 EfuseAddress, u32 RefClk, u8 *Data) +{ + XSKEfusePs_XAdc XAdcInstancePtr; + u32 Status; + + XAdcInstancePtr.VType = XSK_EFUSEPS_VPAUX; + XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&XAdcInstancePtr); + + /** + * Check the temperature and voltage + */ + if ((XAdcInstancePtr.Temp < XSK_EFUSEPS_TEMP_MIN_RAW) || + ((XAdcInstancePtr.Temp > XSK_EFUSEPS_TEMP_MAX_RAW))) { + return XSK_EFUSEPS_ERROR_READ_TMEPERATURE_OUT_OF_RANGE; + } + + if ((XAdcInstancePtr.V < XSK_EFUSEPS_READ_VPAUX_MIN_RAW) || + ((XAdcInstancePtr.V > XSK_EFUSEPS_READ_VPAUX_MAX_RAW))) { + return XSK_EFUSEPS_ERROR_READ_VCCPAUX_VOLTAGE_OUT_OF_RANGE; + } + + /** + * Read the eFUSE bit + */ + Status = XilSKey_EfusePs_ReadEfuseBit(EfuseAddress, Data); + if (Status != XST_SUCCESS) { + return Status; + } + + return XST_SUCCESS; +} + +/***************************************************************************/ +/** +* This function is used to verify the written eFUSE bit. It is checked +* against the value of 1 only. Verification of the eFUSE bit is done by reading +* in MARGIN 2 mode which was highest margin. +* +* @param EfuseAddress is the address of the eFUSE bit +* @param RefClk is the reference clock frequency. Clock frequency can be +* between 20MHz to 60MHz specified in Hz +* @return +* - XST_SUCCESS no errors occurred. +* - XST_FAILURE an error occurred during verifying the PS eFUSE. +* - an error XSK_EFUSEPS_ERROR_READ_VCCPAUX_VOLTAGE_OUT_OF_RANGE when +* voltage not in range +* - an error XSK_EFUSEPS_ERROR_READ_TMEPERATURE_OUT_OF_RANGE when +* temperature not in range +* - an error XSK_EFUSEPS_ERROR_VERIFICATION when verification fails +* - Other errors because of internal controller functions and +* can be checked in xeFUSE_error.h +****************************************************************************/ +static u32 XilSKey_EfusePs_VerifyWithXadcCheck(u32 EfuseAddress, u32 RefClk) +{ + XSKEfusePs_XAdc XAdcInstancePtr; + u32 Status; + u8 Data; + + XAdcInstancePtr.VType = XSK_EFUSEPS_VPAUX; + XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&XAdcInstancePtr); + + /** + * Check the temperature and voltage + */ + if ((XAdcInstancePtr.Temp < XSK_EFUSEPS_TEMP_MIN_RAW) || + ((XAdcInstancePtr.Temp > XSK_EFUSEPS_TEMP_MAX_RAW))) { + return XSK_EFUSEPS_ERROR_READ_TMEPERATURE_OUT_OF_RANGE; + } + + if ((XAdcInstancePtr.V < XSK_EFUSEPS_READ_VPAUX_MIN_RAW) || + ((XAdcInstancePtr.V > XSK_EFUSEPS_READ_VPAUX_MAX_RAW))) { + return XSK_EFUSEPS_ERROR_READ_VCCPAUX_VOLTAGE_OUT_OF_RANGE; + } + + + /** + * Read the eFUSE bit in Margin_1 mode + */ + Status = XilSKey_EfusePs_ControllerConfig(XSK_EFUSEPS_SINGLE_MODE, + RefClk, XSK_EFUSEPS_READ_MODE_MARGIN_1); + if (Status != XST_SUCCESS) { + return Status; + } + Status = XilSKey_EfusePs_ReadEfuseBit(EfuseAddress, &Data); + if (Status != XST_SUCCESS) { + return Status; + } + + if (0 == ((Data) & 0x1)) { + return XSK_EFUSEPS_ERROR_VERIFICATION; + } + + + /** + * Read the eFUSE bit in Normal Mode + */ + Status = XilSKey_EfusePs_ControllerConfig(XSK_EFUSEPS_SINGLE_MODE, + RefClk, XSK_EFUSEPS_READ_MODE_NORMAL); + if (Status != XST_SUCCESS) { + return Status; + } + + Status = XilSKey_EfusePs_ReadEfuseBit(EfuseAddress, &Data); + if (Status != XST_SUCCESS) { + return Status; + } + + if (0 == ((Data) & 0x1)) { + return XSK_EFUSEPS_ERROR_VERIFICATION; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function is used to generate the matrix map of the G and H for +* hamming code (31,26). G is [31,5] and defined as [A|I], I is identity +* matrix of [5,5]. +* +* @return None +* +* TDD Cases: +* Check the generated matrix +* Check the memory corruption of the generated matrix +* +****************************************************************************/ + +void XilSKey_EfusePs_GenerateMatrixMap() +{ + + u8 y, x, Index; + u8 DataIndex, ParityIndex; + + /* Matrix[31][5]={0} */ + for(y = 0; y < 5; y++) { + for(x = 0; x < 31; x++) { + Matrix[x][y] = 0; + } + } + + /* Generate Hamming Code Matrix for both Encoding and Decoding */ + for(y = 0; y < 5; y++) { + Index = 0; + for(x = 1; x < 32; x++) { + if ((x != 1) && (x != 2) && (x != 4) && (x != 8) && (x != 16)) { + if ( ((x & (1 << y)) >> y) == 1) + Matrix[Index++][y] = 1; + else + Matrix[Index++][y] = 0; + } + } + } + + /* Fill Identity Matrix */ + for(y = 0; y < 5; y++) { + for(x = 0; x < 5; x++) { + if (x == y) Matrix[26+x][y] = 1; + else Matrix[26+x][y] = 0; + } + } +#if 0 +// Print out format index + for(x = 1; x < 27; x++) { + printf("%*dd", 3, x); + } + printf("\n"); + + for(y = 0; y < 5; y++) { + for(x = 0; x < 31; x++) { + printf("%*d", 4, Matrix[x][y]); + } + printf("\n"); + } + +#endif + + /* Create Error Code Map Index */ + ErrorCodeIndex[0] = -1; /* No Error */ + DataIndex = 0; + ParityIndex = 26; + for(x = 1; x < 32; x++) { + if ((x != 1) && (x!= 2) && (x!= 4) && (x!= 8) && (x != 16)) { + ErrorCodeIndex[x] = DataIndex; + DataIndex ++; + } else { + ErrorCodeIndex[x] = ParityIndex; + ParityIndex ++; + } + } +} + + +/***************************************************************************/ +/** +* This function is used to encode the incoming data byte. It uses +* hamming (31,26) algorithm. 26 bits are encoded to 31 bits +* +* @param InData is 26 bit input data with each bit represented in one byte +* +* @param Ecc is the 31 bit encoded data with each bit represented in one byte +* +* @return None +* +* TDD Cases: +* Check the parameters +* Check the encoded data for different input data +* Check the input data for boundary cases +* Check for memory corruption +* +****************************************************************************/ +void XilSKey_EfusePs_EccEncode(const u8 *InData, u8 *Ecc) +{ + u8 x, y, Index; + + for(x = 0; x < 26; x++) + Ecc[x] = InData[x]; + for(y = 0; y < 5; y++) { + Ecc[y+26] = 0; + for( Index =0; Index < 26; Index++) + Ecc[y+26] += Matrix[Index][y] * InData[Index]; + Ecc[y+26] %= 2; + } +} + + +/***************************************************************************/ +/** +* This function is used to decode the incoming encoded byte. +* +* @param Corrupt is the input encoded data. It has 26 bit data with +* 5 bit parity data +* +* @param Syndrome is the output updated with the parity error +* information. +* +* @return position of the error in the data byte +* +* TDD Cases: +* Check the parameters +* Check the decode with out any error +* Check the decode with 1 bit error +* Check the decode with 2 bit error +* Check the decode for boundary cases +* Check for memory corruption +* +****************************************************************************/ +u8 XilSKey_EfusePs_EccDecode(const u8 *Corrupt, u8 *Syndrome) +{ + u8 x, y; + u8 Pos; + + // Calculate Error Syndrome + for(y = 0; y < 5; y++) { + Syndrome[y] = 0; + for( x =0; x < 31; x++) + Syndrome[y] += Matrix[x][y] * Corrupt[x]; + Syndrome[y] %= 2; + } + Pos = (Syndrome[4] << 4) + (Syndrome[3] << 3) + + (Syndrome[2] << 2) + (Syndrome[1] << 1) + Syndrome[0]; + Pos = ErrorCodeIndex[Pos]; + + return Pos; +} + +/***************************************************************************/ +/** +* This function is used to set the controller mode to Redundancy/Single mode. +* +* @param Mode is mode of the controller to the set. +* - REDUNDANCY_MODE +* - SINGLE_MODE +* +* @return None +* +****************************************************************************/ + +static void XilSKey_EfusePs_SetControllerMode (u8 Mode) +{ + u32 RegVal; + if(Mode == XSK_EFUSEPS_REDUNDANCY_MODE) { + /** + * Configuration Reg - Redundancy Mode + */ + RegVal = Xil_In32(XSK_EFUSEPS_CONFIG_REG); + RegVal |= XSK_EFUSEPS_CONFIG_REDUNDANCY; + Xil_Out32(XSK_EFUSEPS_CONFIG_REG, RegVal); + } + else if(Mode == XSK_EFUSEPS_SINGLE_MODE) { + /** + * Configuration Reg - Single Mode + */ + RegVal = Xil_In32(XSK_EFUSEPS_CONFIG_REG); + RegVal &= ~XSK_EFUSEPS_CONFIG_REDUNDANCY; + Xil_Out32(XSK_EFUSEPS_CONFIG_REG, RegVal); + } + return ; +} + + +/***************************************************************************/ +/** +* This function is used to set the controller read mode to +* Normal/Margin 1/Margin 2. +* +* @param ReadMode is the read mode of the controller +* - XSK_EFUSEPS_READ_MODE_NORMAL +* - XSK_EFUSEPS_READ_MODE_MARGIN_1 +* - XSK_EFUSEPS_READ_MODE_MARGIN_2 +* +* @return None +* +****************************************************************************/ + +static void XilSKey_EfusePs_SetControllerReadMode (u8 ReadMode) +{ + + u32 RegVal; + + /** + * Read Configuration Reg + */ + RegVal = Xil_In32(XSK_EFUSEPS_CONFIG_REG); + /** + * Reset the read mode + */ + RegVal &= ~XSK_EFUSEPS_CONFIG_MARGIN_RD; + if (ReadMode == XSK_EFUSEPS_READ_MODE_NORMAL) { + /** + * Set to Normal read mode + */ + RegVal |= XSK_EFUSEPS_CONFIG_RD_NORMAL; + } + else if (ReadMode == XSK_EFUSEPS_READ_MODE_MARGIN_1) { + /** + * Set to Margin 1 read mode + */ + RegVal |= XSK_EFUSEPS_CONFIG_RD_MARGIN_1; + } + else if (ReadMode == XSK_EFUSEPS_READ_MODE_MARGIN_2) { + /** + * Set to Margin 2 read mode + */ + RegVal |= XSK_EFUSEPS_CONFIG_RD_MARGIN_2; + } + Xil_Out32(XSK_EFUSEPS_CONFIG_REG, RegVal); + return ; +} + +/***************************************************************************/ +/** +* This function is used to check the read mode supported +* +* @param ReadMode is input read mode to be checked against +* +* @return +* - XST_SUCCESS if read mode is supported +* - XST_FAILURE if read mode is not supported +* +****************************************************************************/ + +static u8 XilSKey_EfusePs_IsReadModeSupported (u8 ReadMode) +{ + if ((ReadMode == XSK_EFUSEPS_READ_MODE_NORMAL) || + (ReadMode == XSK_EFUSEPS_READ_MODE_MARGIN_1) || + (ReadMode == XSK_EFUSEPS_READ_MODE_MARGIN_2)) { + return TRUE; + } + + return FALSE; +} + + +/***************************************************************************/ +/** +* This function is used to set the controller mode, read mode along with +* the read and program strobe width values based on the reference clock. +* +* @param CtrlMode is the mode of the controller +* - XSK_EFUSEPS_REDUNDANCY_MODE +* - XSK_EFUSEPS_SINGLE_MODE +* +* @param RefClk is the CPU 1x reference clock frequency. Clock frequency can be +* between 20MHz to 100MHz specified in Hz +* +* @param ReadMode is the read mode of the controller +* - XSK_EFUSEPS_READ_MODE_NORMAL +* - XSK_EFUSEPS_READ_MODE_MARGIN_1 +* - XSK_EFUSEPS_READ_MODE_MARGIN_2 +* +* @return +* - XST_SUCCESS no errors occured. +* - an error when controller mode is not supported +* - an error when reference clock is not supported +* - an error when read mode is not supported +* +* Test Cases: + Check single mode in CFG Reg + Check redundancy mode in CFG Reg + Check strobe width values for write mode + Check strobe width values for various read mode + Check Normal Read mode setting in CFG Reg + Check Margin 1 Read mode setting in CFG Reg + Check Margin 2 Read mode setting in CFG Reg + Boundary Conditions + +* +****************************************************************************/ +u32 XilSKey_EfusePs_ControllerConfig(u8 CtrlMode, u32 RefClk, u8 ReadMode) +{ + u32 RdStrWdthVal=0, PrgmStrWdthVal=0; + + /** + * Check the parameters + * Mode can be Single or Redundancy mode + */ + + if ((CtrlMode != XSK_EFUSEPS_SINGLE_MODE) && + (CtrlMode != XSK_EFUSEPS_REDUNDANCY_MODE)) { + return XSK_EFUSEPS_ERROR_CONTROLLER_MODE; + } + + + /** + * Ref Clock should be between 20MHz - 60MHz + */ + if ((RefClk < XSK_EFUSEPS_REFCLK_LOW_FREQ) || + (RefClk > XSK_EFUSEPS_REFCLK_HIGH_FREQ)) { + return XSK_EFUSEPS_ERROR_REF_CLOCK; + } + + /** + * 3 read modes are supported + */ + if (!XilSKey_EfusePs_IsReadModeSupported(ReadMode)) { + return XSK_EFUSEPS_ERROR_READ_MODE; + } + + /** + * Set the controller mode + */ + XilSKey_EfusePs_SetControllerMode(CtrlMode); + + /** + * Set the controller read mode + */ + XilSKey_EfusePs_SetControllerReadMode(ReadMode); + + +#if 0 + u32 RegVal; + /* Commented as we are not supporting Reference Freq > 60MHz */ + /** + * Set TSU_H_A to 1 if RefClk > 80MHz + */ + RegVal = Xil_In32(XSK_EFUSEPS_CONFIG_REG); + if (RefClk > 80000000) { + RegVal |= XSK_EFUSEPS_CONFIG_TSU_H_A; + } + Xil_Out32(XSK_EFUSEPS_CONFIG_REG, RegVal); +#endif + /** + * Program the Strobe width values for read and write + * 12ms is required for write and 150ns is required for read + * PGM_STBW = ceiling(12us/ref_clk period) + * RD_STBW = ceiling(150ns/ref_clk period) + */ + PrgmStrWdthVal = XSK_EFUSEPS_PRGM_STROBE_WIDTH(RefClk); + Xil_Out32(XSK_EFUSEPS_PGM_STBW_REG, PrgmStrWdthVal); + + RdStrWdthVal = XSK_EFUSEPS_RD_STROBE_WIDTH(RefClk); + Xil_Out32(XSK_EFUSEPS_RD_STBW_REG, RdStrWdthVal); + + return XST_SUCCESS; +} + +/***************************************************************************/ +/** +* This function is used to check whether eFuse bit is xilinx reserved bit or +* not +* +* @param Addr is the address of the eFuse bit. +* +* @return +* - XST_SUCCESS if address corresponds to restricted eFuse bit. +* - XST_FAILURE is address corresponds to non-restricted eFuse bit. +* +* Test Cases: +* with different address values +* Boundary values for addr +* +****************************************************************************/ + +u8 XilSKey_EfusePs_IsAddressXilRestricted (u32 Addr) +{ + /** + * Check for xilinx test bits + */ + if( (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x20) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x41) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x62) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x83) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_xA4) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_xC5) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_xE6) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x107) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x128) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x149) || + + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x23F) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x25E) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x27D) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x29C) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x2BB) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x2DA) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x2F9) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x318) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x337) || + (Addr == XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x356) ) + { + return TRUE; + } + + /** + * Check for xilinx reserved bits + */ + if ( ((Addr >= XSK_EFUSEPS_APB_TRIM_BITS_START_ADDR) && + (Addr <= XSK_EFUSEPS_APB_TRIM_BITS_END_ADDR)) || + ((Addr >= XSK_EFUSEPS_APB_XILINX_RSVD_BITS_START_ADDR) && + (Addr <= XSK_EFUSEPS_APB_XILINX_RSVD_BITS_END_ADDR)) || + ((Addr >= XSK_EFUSEPS_APB_BISR_BITS_START_ADDR) && + (Addr <= XSK_EFUSEPS_APB_BISR_BITS_END_ADDR)) || + ((Addr >= XSK_EFUSEPS_APB_TRIM_BITS_START_ADDR_2ND_HALF) && + (Addr <= XSK_EFUSEPS_APB_TRIM_BITS_END_ADDR_2ND_HALF)) || + ((Addr >= XSK_EFUSEPS_APB_XILINX_RSVD_BITS_START_ADDR_2ND_HALF) && + (Addr <= XSK_EFUSEPS_APB_XILINX_RSVD_BITS_END_ADDR_2ND_HALF)) || + ((Addr >= XSK_EFUSEPS_APB_BISR_BITS_START_ADDR_2ND_HALF) && + (Addr <= XSK_EFUSEPS_APB_BISR_BITS_END_ADDR_2ND_HALF)) + ) { + return TRUE; + } + + return FALSE; +} + +/***************************************************************************/ +/** +* This function is used to enable the read/write/program the eFUSE +* array. +* +* @param ReadWriteEnable +* 0x1 - Enable programming +* 0x2 - Enable read +* 0x4 - Enable write +* @return +* +* Test Cases +* +****************************************************************************/ + +void XilSKey_EfusePs_ControllerSetReadWriteEnable(u32 ReadWriteEnable) +{ + u32 RegVal; + + RegVal = Xil_In32(XSK_EFUSEPS_CONTROL_REG); + + /** + * Reset the values + * Disable programming + * Disable reading + * Disable writing + */ + RegVal &= ~XSK_EFUSEPS_CONTROL_PS_EN; + RegVal |= XSK_EFUSEPS_CONTROL_RD_DIS | XSK_EFUSEPS_CONTROL_WR_DIS; + + if (ReadWriteEnable & XSK_EFUSEPS_ENABLE_PROGRAMMING) { + RegVal |= XSK_EFUSEPS_CONTROL_PS_EN; + } + + if (ReadWriteEnable & XSK_EFUSEPS_ENABLE_READ) { + RegVal &= ~XSK_EFUSEPS_CONTROL_RD_DIS; + } + + if (ReadWriteEnable & XSK_EFUSEPS_ENABLE_WRITE) { + RegVal &= ~XSK_EFUSEPS_CONTROL_WR_DIS; + } + + Xil_Out32(XSK_EFUSEPS_CONTROL_REG, RegVal); + + return; +} + + +/***************************************************************************/ +/** +* This function is used to read the eFuse bit value. Before using this +* function set the controller mode and read mode as required. Also, strobe +* width values are to be set properly based on the reference clock for +* successful reading +* +* @param Addr is the address of the eFuse bit. +* +* @param Data has the read eFuse value stored in it. +* +* @return +* - XST_SUCCESS for succesfully reading the value. +* - an error when addr is restricted +* +* Test Cases + Read in Single mode + Read in redundancy mode + Read for restricted address + Boundary Checks for address +* +****************************************************************************/ + +u32 XilSKey_EfusePs_ReadEfuseBit(u32 Addr, u8 *Data) +{ + if(XilSKey_EfusePs_IsAddressXilRestricted(Addr) != FALSE) { + return XSK_EFUSEPS_ERROR_ADDRESS_XIL_RESTRICTED; + } + + *Data = Xil_In32(Addr) & 0x1; + + xeFUSE_printf(XSK_EFUSE_DEBUG_GENERAL,"Reading Addr %0x, Data %0x\n", Addr, *Data); + + return XST_SUCCESS; +} + +/***************************************************************************/ +/** +* This function is used to program the eFuse bit value. Before using this +* function set the controller mode and read mode as required. Also, strobe +* width values are to be set properly based on the reference clock for +* successful programming +* +* @param Addr is the address of the eFuse bit. +* +* @return +* - XST_SUCCESS after successful writing. +* - an error when addr is restricted +* +* Test Cases + Write in Single mode + Write in redundancy mode + Write for restricted address + Boundary Checks for address + Strobe width are not proper (Check if it makes sense) +* +****************************************************************************/ + +u32 XilSKey_EfusePs_WriteEfuseBit(u32 Addr) +{ + + u64 time = 0; + + /** + * Check if Address is restricted + */ + + if(XilSKey_EfusePs_IsAddressXilRestricted(Addr) != FALSE) { + return XSK_EFUSEPS_ERROR_ADDRESS_XIL_RESTRICTED; + } + + /** + * Send success when bit is already programmed + */ + if ((Xil_In32(Addr)&0x1) == 1) { + xeFUSE_printf(XSK_EFUSE_DEBUG_GENERAL, + "Addr %0x already programmed\n", Addr); + return XST_SUCCESS; + } + + Xil_Out32(Addr, 0x1); + + /** + * Providing 15us delay + * Timer takes 100ns as slice. 15us = 150 * 100ns + */ + XilSKey_Efuse_SetTimeOut(&time, 150); + while(1) { + if(XilSKey_Efuse_IsTimerExpired(time) == 1) + break; + } + + xeFUSE_printf(XSK_EFUSE_DEBUG_GENERAL, + "Writing Addr %0x, Data %0x\n", Addr, Xil_In32(Addr)); + + return XST_SUCCESS; +} + +/***************************************************************************/ +/** +* This function is used to read the PS efuse status register. +* +* @param InstancePtr is the pointer to the PsEfuseHandle which describes +* which PS eFUSE bit should be burned. +* @param StatusBits - variable to store the status register read. +* +* @return +* - XST_SUCCESS. +* - XST_FAILURE +* +****************************************************************************/ +u32 XilSKey_EfusePs_ReadStatus(XilSKey_EPs *InstancePtr, u32 *StatusBits) +{ + u32 RetValue; + + RetValue = XST_SUCCESS; + + /** + * Unlock the eFUSE controller + */ + XSK_EFUSEPS_CONTROLER_UNLOCK(); + + /** + * Check if the controller is unlocked + */ + if (XSK_EFUSEPS_CONTROLER_LOCK_STATUS() == TRUE) { + RetValue = XSK_EFUSEPS_ERROR_CONTROLLER_LOCK; + goto ExitFinal; + } + + /** + * Read the eFUSE status + */ + *StatusBits = Xil_In32(XSK_EFUSEPS_STATUS_REG); + +ExitFinal: + return RetValue; +} diff --git a/lib/sw_services/xilskey/src/xilskey_epshw.h b/lib/sw_services/xilskey/src/xilskey_epshw.h new file mode 100644 index 00000000..1647a635 --- /dev/null +++ b/lib/sw_services/xilskey/src/xilskey_epshw.h @@ -0,0 +1,484 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * @file xilskey_epshw.h + * + * + * @note None. + * + * + * MODIFICATION HISTORY: + * +* Ver Who Date Changes +* ----- ---- -------- -------------------------------------------------------- +* 1.00a rpoolla 04/26/13 First release + * + *****************************************************************************/ + +#ifndef XILSKEY_EPSHW_H +#define XILSKEY_EPSHW_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_types.h" +#include "xilskey_utils.h" + +/** + * Rsa Key hash length in bytes + */ +#define XSK_EFUSEPS_RSA_KEY_HASH_LEN_BITS (256) + +#define XSK_EFUSEPS_HAMMING_LOOPS (10) +#define XSK_EFUSEPS_HAMMING_LENGTH (31) +#define XSK_EFUSEPS_HAMMING_DATA (26) + +#define XSK_EFUSEPS_SINGLE_MODE (0x0) +#define XSK_EFUSEPS_REDUNDANCY_MODE (0x1) + +#define XSK_EFUSEPS_READ_MODE_NORMAL (0x1) +#define XSK_EFUSEPS_READ_MODE_MARGIN_1 (0x2) +#define XSK_EFUSEPS_READ_MODE_MARGIN_2 (0x3) + +#define XSK_EFUSEPS_ENABLE_PROGRAMMING (0x1) +#define XSK_EFUSEPS_ENABLE_READ (0x2) +#define XSK_EFUSEPS_ENABLE_WRITE (0x4) + +#define XSK_EFUSEPS_PRGM_STROBE_WIDTH(RefClk) ((12 * (RefClk))/1000000) +/** + * Modified to have max of 32 bit value + */ +#define XSK_EFUSEPS_RD_STROBE_WIDTH(RefClk) ((15 * (RefClk))/100000000) + + +#define XSK_EFUSEPS_REFCLK_LOW_FREQ (20000000) +#define XSK_EFUSEPS_REFCLK_HIGH_FREQ (60000000) + +/** + * PSS eFUSE Register addresses + */ +/** + * eFuse base address + */ +#define XSK_EFUSEPS_BASE_ADDRESS (0xF800D000) + +#define XSK_EFUSEPS_WR_LOCK_REG_OFFSET (0x0) + /** + * WR_UNLOCK Write 0xDF0D to allow write offset + */ +#define XSK_EFUSEPS_WR_UNLOCK_REG_OFFSET (0x4) + /** + * WR_LOCKSTA Write protection status offset + */ +#define XSK_EFUSEPS_WR_LOCK_STATUS_REG_OFFSET (0x8) + /** + * CFG Configuration register offset + */ +#define XSK_EFUSEPS_CONFIG_REG_OFFSET (0xC) + /** + * STATUS Status register offset + */ +#define XSK_EFUSEPS_STATUS_REG_OFFSET (0x10) + /** + * CONTROL Control register offset + */ +#define XSK_EFUSEPS_CONTROL_REG_OFFSET (0x14) + /** + * PGM_STBW eFuse program strobe width register offset + */ +#define XSK_EFUSEPS_PGM_STBW_REG_OFFSET (0x18) + /** + * RD_STBW eFuse read strobe width register offset + */ +#define XSK_EFUSEPS_RD_STBW_REG_OFFSET (0x1C) + /* WR_LOCK Write 0x767B to disallow write */ + +#define XSK_EFUSEPS_WR_LOCK_REG (XSK_EFUSEPS_BASE_ADDRESS + XSK_EFUSEPS_WR_LOCK_REG_OFFSET) + /** + * WR_UNLOCK Write 0xDF0D to allow write + */ +#define XSK_EFUSEPS_WR_UNLOCK_REG (XSK_EFUSEPS_BASE_ADDRESS + XSK_EFUSEPS_WR_UNLOCK_REG_OFFSET) + /** + * WR_LOCKSTA Write protection status + */ +#define XSK_EFUSEPS_WR_LOCK_STATUS_REG (XSK_EFUSEPS_BASE_ADDRESS + XSK_EFUSEPS_WR_LOCK_STATUS_REG_OFFSET) + /** + * CFG Configuration register + */ +#define XSK_EFUSEPS_CONFIG_REG (XSK_EFUSEPS_BASE_ADDRESS + XSK_EFUSEPS_CONFIG_REG_OFFSET) + /** + * STATUS Status register + */ +#define XSK_EFUSEPS_STATUS_REG (XSK_EFUSEPS_BASE_ADDRESS + XSK_EFUSEPS_STATUS_REG_OFFSET) + /** + * CONTROL Control register + */ +#define XSK_EFUSEPS_CONTROL_REG (XSK_EFUSEPS_BASE_ADDRESS + XSK_EFUSEPS_CONTROL_REG_OFFSET) + /** + * PGM_STBW eFuse program strobe width register + */ +#define XSK_EFUSEPS_PGM_STBW_REG (XSK_EFUSEPS_BASE_ADDRESS + XSK_EFUSEPS_PGM_STBW_REG_OFFSET) + /** + * RD_STBW eFuse read strobe width register + */ +#define XSK_EFUSEPS_RD_STBW_REG (XSK_EFUSEPS_BASE_ADDRESS + XSK_EFUSEPS_RD_STBW_REG_OFFSET) + + +/**< PSS eFUSE register bit defines & description */ + +/**< XSK_EFUSEPS_WR_LOCK_STATUS_REG (Write Protection Status Register) */ +/** Current state of write protection mode of eFuse subsystem:- +* 0 Region is writable +* 1 Region is not writable. Any attempted writes are ignored, but reads will complete as normal. +*/ +#define XSK_EFUSEPS_WR_LOCK_STATUS_BIT (0x1) +/**< XSK_EFUSEPS_CONFIG_REG (Configuration Register) */ +/** Redundancy mode, if set, else single mode. +* This bit only applies to APB access. +* BISR and eFuse reader always work in redundancy mode. +*/ +#define XSK_EFUSEPS_CONFIG_REDUNDANCY (0x00010000) +/** eFuse read/program setup/hold control between address and strobe assert +* 1 b0 1 ref clock cycle +* 1 b1 2 ref clock cycles +*/ +#define XSK_EFUSEPS_CONFIG_TSU_H_A (0x00002000) +/** eFuse read/program setup/hold control between csb and strobe assert +* 1 b0 1 ref clock cycle +* 1 b1 2 ref clock cycles +*/ +#define XSK_EFUSEPS_CONFIG_TSU_H_CS (0x00001000) +/**< eFuse program setup/hold control between ps and csb active.*/ +#define XSK_EFUSEPS_CONFIG_TSU_H_PS (0x00000F00) +/** eFuse read margin control: +* 00 normal, 01 margin 1, 10 margin 2, 11 - undefined +*/ +#define XSK_EFUSEPS_CONFIG_MARGIN_RD (0x00000030) +#define XSK_EFUSEPS_CONFIG_RD_NORMAL (0x00000000) +#define XSK_EFUSEPS_CONFIG_RD_MARGIN_1 (0x00000010) +#define XSK_EFUSEPS_CONFIG_RD_MARGIN_2 (0x00000020) +/** Reference clock scaler +* 2 b00 bypass clock divider +* 2 b01 div 2 +* 2 b10 div 4 +* 2 h11 div 8 +*/ +#define XSK_EFUSEPS_CONFIG_CLK_DIV (0x00000003) + + +/**< XSK_EFUSEPS_STATUS_REG (Status Register)*/ +/** Status Register containing BISR Controller status, trim value, +* and security debug info. +*/ + +/** + * Build in self test finished at boot time + */ +#define XSK_EFUSEPS_STATUS_BISR_DONE (0x80000000) +/** + * Build in self test finished successfully + */ +#define XSK_EFUSEPS_STATUS_BISR_GO (0x40000000) +/** + * eFuse box is blank, i.e., not yet been written to, if set + */ +#define XSK_EFUSEPS_STATUS_BISR_BLANK (0x00100000) +/** Security debug status, with authentication +* 0 security debug enabled +* 1 security debug disabled +*/ +#define XSK_EFUSEPS_STATUS_SDEBUG_DIS (0x00010000) +/** eFuse write protection, if either bit is set, + * writes to the eFuse box are disabled + */ +#define XSK_EFUSEPS_STATUS_WR_PROTECT (0x00003000) +/** + * Analog trim value + */ +#define XSK_EFUSEPS_STATUS_TRIM (0x000000FC) + + +/** + * XSK_EFUSEPS_CONTROL_REG (Control register for eFuse program, + * read and write control) + * eFuse ps control, enable programming if set. + */ +#define XSK_EFUSEPS_CONTROL_PS_EN (0x00000010) +/** + * eFuse write disable, if set. + */ +#define XSK_EFUSEPS_CONTROL_WR_DIS (0x00000002) +/** + * eFuse read disable, if set + */ +#define XSK_EFUSEPS_CONTROL_RD_DIS (0x00000001) + + +#define XSK_EFUSEPS_APB_START_ADDR_OFFSET (0x1000) +/** + * eFuse memory APB Customer key second half start address offset + */ +#define XSK_EFUSEPS_APB_WRITE_PROTECTION_ADDR_1_OFFSET (0x20) +/** + * eFuse memory APB Customer key second half start address offset + */ +#define XSK_EFUSEPS_APB_WRITE_PROTECTION_ADDR_2_OFFSET (0x24) +/** + * eFUSE APB address for ROM 128k CRC enable offset + */ +#define XSK_EFUSEPS_APB_ROM_128K_CRC_ENABLE_OFFSET (0x28) +/** + * eFUSE APB address for RSA authentication enable offset + */ +#define XSK_EFUSEPS_APB_RSA_AUTH_ENABLE_OFFSET (0x2C) +/** + * eFUSE APB address for RSA uart status enable on MIO48 offset + */ +#define XSK_EFUSEPS_APB_ROM_UART_STATUS_ENABLE_OFFSET (0x5C0) +/** + * eFUSE APB address for non-secure INIT_B signaling offset + */ +#define XSK_EFUSEPS_APB_ROM_NONSECURE_INITB_ENABLE_OFFSET (0x5C4) + +/** eFUSE bits from 0 to 0x1F and 0x180 to 0x1FF in the First half, +* and bits from 0x200 to 0x21F and 0x380 to 0x3FF in the +* Second half(if Single mode is enabled) +*/ +/** + * If Redundant mode is enabled only First half addresses are valid. + * eFuse memory APB Customer key first half start address + */ +#define XSK_EFUSEPS_APB_CUSTOMER_KEY_FIRST_HALF_START_ADDR_OFFSET (0x80) +/** + * eFuse memory APB Customer key first half end address + */ +#define XSK_EFUSEPS_APB_CUSTOMER_KEY_FIRST_HALF_END_ADDR_OFFSET (0x580) +/** + * If Single mode is enabled both First and Second half addresses are valid. + * eFuse memory APB Customer key second half start address + */ +#define XSK_EFUSEPS_APB_CUSTOMER_KEY_SECND_HALF_START_ADDR_OFFSET (0x880) +/** + * eFuse memory APB Customer key second half end address + */ +#define XSK_EFUSEPS_APB_CUSTOMER_KEY_SECND_HALF_END_ADDR_OFFSET (0xE00) +/** + * Mirror Address = addr + 2nd half start address + mirror offset + */ +#define XSK_EFUSEPS_APB_MIRROR_ADDRESS(Addr) (Addr + 0x87C - (2*(Addr%128))) + +/** + * Following are the Xilinx reserved Tests bits in the First half of the eFUSE block. + */ +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x20_OFFSET (0x80) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x41_OFFSET (0x104) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x62_OFFSET (0x188) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x83_OFFSET (0x20C) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_xA4_OFFSET (0x290) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_xC5_OFFSET (0x314) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_xE6_OFFSET (0x398) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x107_OFFSET (0x41C) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x128_OFFSET (0x4A0) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x149_OFFSET (0x524) + +/** + * Following are the Xilinx reserved Tests bits in the First half of the eFUSE block. + */ +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x23F_OFFSET (0x8FC) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x25E_OFFSET (0x978) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x27D_OFFSET (0x9F4) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x29C_OFFSET (0xA70) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x2BB_OFFSET (0xAEC) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x2DA_OFFSET (0xB68) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x2F9_OFFSET (0xBE4) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x318_OFFSET (0xC60) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x337_OFFSET (0xCDC) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x356_OFFSET (0xD58) + +#define XSK_EFUSEPS_APB_TRIM_BITS_END_ADDR_OFFSET (0x1C) +#define XSK_EFUSEPS_APB_XILINX_RSVD_BITS_START_ADDR_OFFSET (0x40) +#define XSK_EFUSEPS_APB_XILINX_RSVD_BITS_END_ADDR_OFFSET (0x7C) +#define XSK_EFUSEPS_APB_BISR_BITS_START_ADDR_OFFSET (0x600) +#define XSK_EFUSEPS_APB_BISR_BITS_END_ADDR_OFFSET (0x7FC) + +/** + * Following are the Xilinx reserved Tests bits in the Second half of the eFUSE block. + */ +#define XSK_EFUSEPS_APB_TRIM_BITS_START_ADDR_2ND_HALF_OFFSET (0x860) +#define XSK_EFUSEPS_APB_TRIM_BITS_END_ADDR_2ND_HALF_OFFSET (0x87C) +#define XSK_EFUSEPS_APB_XILINX_RSVD_BITS_START_ADDR_2ND_HALF_OFFSET (0x800) +#define XSK_EFUSEPS_APB_XILINX_RSVD_BITS_END_ADDR_2ND_HALF_OFFSET (0x83C) +#define XSK_EFUSEPS_APB_BISR_BITS_START_ADDR_2ND_HALF_OFFSET (0xE00) +#define XSK_EFUSEPS_APB_BISR_BITS_END_ADDR_2ND_HALF_OFFSET (0xFFC) + + + + +/** + * eFuse memory APB start address + */ +#define XSK_EFUSEPS_APB_START_ADDR (XSK_EFUSEPS_BASE_ADDRESS + XSK_EFUSEPS_APB_START_ADDR_OFFSET) +/* + * eFuse memory APB Customer key second half start address + */ +#define XSK_EFUSEPS_APB_WRITE_PROTECTION_ADDR_1 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_WRITE_PROTECTION_ADDR_1_OFFSET) +/* + * eFuse memory APB Customer key second half start address + */ +#define XSK_EFUSEPS_APB_WRITE_PROTECTION_ADDR_2 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_WRITE_PROTECTION_ADDR_2_OFFSET) +/* + * eFUSE APB address for ROM 128k CRC enable + */ +#define XSK_EFUSEPS_APB_ROM_128K_CRC_ENABLE (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_ROM_128K_CRC_ENABLE_OFFSET) +/* + * eFUSE APB address for RSA authentication enable + */ +#define XSK_EFUSEPS_APB_RSA_AUTH_ENABLE (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_RSA_AUTH_ENABLE_OFFSET) +/* + * eFUSE APB address for RSA uart status enable on MIO48 + */ +#define XSK_EFUSEPS_APB_ROM_UART_STATUS_ENABLE (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_ROM_UART_STATUS_ENABLE_OFFSET) +/* + * eFUSE APB address for non-secure INIT_B signaling + */ +#define XSK_EFUSEPS_APB_ROM_NONSECURE_INITB_ENABLE (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_ROM_NONSECURE_INITB_ENABLE_OFFSET) + +/** eFUSE bits from 0 to 0x1F and 0x180 to 0x1FF in the First half, +* and bits from 0x200 to 0x21F and 0x380 to 0x3FF in the +* Second half(if Single mode is enabled) +*/ +/** + * If Redundant mode is enabled only First half addresses are valid. + * + * eFuse memory APB Customer key first half start address + */ +#define XSK_EFUSEPS_APB_CUSTOMER_KEY_FIRST_HALF_START_ADDR (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_CUSTOMER_KEY_FIRST_HALF_START_ADDR_OFFSET) +/** + * eFuse memory APB Customer key first half end address + */ +#define XSK_EFUSEPS_APB_CUSTOMER_KEY_FIRST_HALF_END_ADDR (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_CUSTOMER_KEY_FIRST_HALF_END_ADDR_OFFSET) +/** + * If Single mode is enabled both First and Second half addresses are valid. + * + * eFuse memory APB Customer key second half start address + */ +#define XSK_EFUSEPS_APB_CUSTOMER_KEY_SECND_HALF_START_ADDR (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_CUSTOMER_KEY_SECND_HALF_START_ADDR_OFFSET) +/* + * eFuse memory APB Customer key second half end address + */ +#define XSK_EFUSEPS_APB_CUSTOMER_KEY_SECND_HALF_END_ADDR (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_CUSTOMER_KEY_SECND_HALF_END_ADDR_OFFSET) +/* + * Mirror Address = addr + 2nd half start address + mirror offset + */ +#define XSK_EFUSEPS_APB_MIRROR_ADDRESS(Addr) (Addr + 0x87C - (2*(Addr%128))) + +/** + * Following are the Xilinx reserved Tests bits in the First half of the eFUSE block. + */ +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x20 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x20_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x41 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x41_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x62 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x62_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x83 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x83_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_xA4 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_xA4_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_xC5 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_xC5_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_xE6 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_xE6_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x107 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x107_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x128 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x128_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x149 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x149_OFFSET) + +/** + * Following are the Xilinx reserved Tests bits in the First half of the eFUSE block. + */ +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x23F (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x23F_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x25E (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x25E_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x27D (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x27D_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x29C (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x29C_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x2BB (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x2BB_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x2DA (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x2DA_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x2F9 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x2F9_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x318 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x318_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x337 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x337_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x356 (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_TEST_BIT_x356_OFFSET) + +/** + * Following are the Xilinx reserved Tests bits in the First half of the eFUSE block. + */ +#define XSK_EFUSEPS_APB_TRIM_BITS_START_ADDR (XSK_EFUSEPS_APB_START_ADDR) +#define XSK_EFUSEPS_APB_TRIM_BITS_END_ADDR (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_TRIM_BITS_END_ADDR_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_BITS_START_ADDR (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_BITS_START_ADDR_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_BITS_END_ADDR (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_BITS_END_ADDR_OFFSET) +#define XSK_EFUSEPS_APB_BISR_BITS_START_ADDR (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_BISR_BITS_START_ADDR_OFFSET) +#define XSK_EFUSEPS_APB_BISR_BITS_END_ADDR (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_BISR_BITS_END_ADDR_OFFSET) + +/** + * Following are the Xilinx reserved Tests bits in the Second half of the eFUSE block. + */ +#define XSK_EFUSEPS_APB_TRIM_BITS_START_ADDR_2ND_HALF (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_TRIM_BITS_START_ADDR_2ND_HALF_OFFSET) +#define XSK_EFUSEPS_APB_TRIM_BITS_END_ADDR_2ND_HALF (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_TRIM_BITS_END_ADDR_2ND_HALF_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_BITS_START_ADDR_2ND_HALF (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_BITS_START_ADDR_2ND_HALF_OFFSET) +#define XSK_EFUSEPS_APB_XILINX_RSVD_BITS_END_ADDR_2ND_HALF (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_XILINX_RSVD_BITS_END_ADDR_2ND_HALF_OFFSET) +#define XSK_EFUSEPS_APB_BISR_BITS_START_ADDR_2ND_HALF (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_BISR_BITS_START_ADDR_2ND_HALF_OFFSET) +#define XSK_EFUSEPS_APB_BISR_BITS_END_ADDR_2ND_HALF (XSK_EFUSEPS_APB_START_ADDR + XSK_EFUSEPS_APB_BISR_BITS_END_ADDR_2ND_HALF_OFFSET) + +/***************** Macros (Inline Functions) Definitions ********************/ +#define XSK_EFUSEPS_CONTROLER_LOCK() Xil_Out32(XSK_EFUSEPS_WR_LOCK_REG,0x767B) +#define XSK_EFUSEPS_CONTROLER_UNLOCK() Xil_Out32(XSK_EFUSEPS_WR_UNLOCK_REG,0xDF0D) +#define XSK_EFUSEPS_CONTROLER_LOCK_STATUS() (Xil_In32(XSK_EFUSEPS_WR_LOCK_STATUS_REG) & 0x1) +#define XSK_EFUSEPS_CONTROLER_OP_MODE() ((Xil_In32(XSK_EFUSEPS_CONFIG_REG) & XSK_EFUSEPS_CONFIG_REDUNDANCY)? 1 : 0) + +/***************************************************************************/ +/** +* This macro is used to check whether eFuse is write protected or not +* +* @return +* - TRUE if eFuse is write protected. +* - FALSE is eFuse is not write protected. +****************************************************************************/ + +#define XilSKey_EfusePs_IsEfuseWriteProtected() ((Xil_In32(XSK_EFUSEPS_STATUS_REG) & XSK_EFUSEPS_STATUS_WR_PROTECT)? TRUE : FALSE) +/************************** Function Prototypes ******************************/ +void XilSKey_EfusePs_GenerateMatrixMap(); +u8 XilSKey_EfusePs_EccDecode(const u8 *Corrupt, u8 *Syndrome); +void XilSKey_EfusePs_EccEncode(const u8 *InData, u8 *Ecc); +u32 XilSKey_EfusePs_ControllerConfig(u8 CtrlMode, u32 RefClk, u8 ReadMode); +u8 XilSKey_EfusePs_IsAddressXilRestricted (u32 Addr); +void XilSKey_EfusePs_ControllerSetReadWriteEnable(u32 ReadWriteEnable); +u32 XilSKey_EfusePs_ReadEfuseBit(u32 Addr, u8 *Data); +u32 XilSKey_EfusePs_WriteEfuseBit(u32 Addr); + +#ifdef __cplusplus +} +#endif + +#endif /* End of XILSKEY_EPSHW_H */ diff --git a/lib/sw_services/xilskey/src/xilskey_js.h b/lib/sw_services/xilskey/src/xilskey_js.h new file mode 100644 index 00000000..f9469d1e --- /dev/null +++ b/lib/sw_services/xilskey/src/xilskey_js.h @@ -0,0 +1,391 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/* + * JTAG server interface + * + * This interface is intended to be a common abstraction of JTAG cable + * implementations. + * + * Interface usage steps: + * + * 1. Initialize server implementation instance using implementation + * specific js_init_*() function. + * + * 2. Enumerate available ports using js_get_port_descr_list(). + * + * 3. Open selected port using js_open_port(). + * + * 4. Optional: get or set properties using js_get_property() or + * js_set_property(). + * + * 5. Optional: enumerate scan chain using js_detect_taps() or + * manually. Add nodes for each TAP controller (API TDB). + * + * 6. Build command sequence(s) object using + * js_create_command_sequence(), js_add_state_change(), and + * js_add_shift(). + * + * 7. Run sequence using js_run_command_sequence(). + * + * 8. Repeat #6 and #7 as needed, possibly deleting or clearing + * command sequence objects as needed using + * js_delete_command_sequence() and js_clear_command_sequence(). + * + * 9. Close port using js_close_port(). + * + * 10. Delete server using js_deinit_server(). + */ + +#ifndef XILSKEY_JS_H +#define XILSKEY_JS_H + +#include + +#if defined(_MSC_VER) && _MSC_VER < 1600 + typedef signed __int8 int8_t; + typedef unsigned __int8 uint8_t; + typedef signed __int16 int16_t; + typedef unsigned __int16 uint16_t; + typedef signed __int32 int32_t; + typedef unsigned __int32 uint32_t; + typedef signed __int64 int64_t; + typedef unsigned __int64 uint64_t; +#else +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * IEEE 1149.1 defined dummy idcode value. + */ +#define JS_DUMMY_IDCODE 0x000000ff + +typedef struct js_server_struct js_server_t; +typedef struct js_port_descr_struct js_port_descr_t; +typedef struct js_port_struct js_port_t; +typedef struct js_node_struct js_node_t; +typedef struct js_command_sequence_struct js_command_sequence_t; + + +/* + * JTAG property kinds + */ +typedef enum { + JS_PROP_FREQUENCY +} js_property_kind_t; + +typedef long js_property_value_t; + + +/* + * JTAG port description + * + * This is retrieved by calling js_get_port_descr_list(), and is needed for + * js_open_port() to indicate which port to use. + */ +struct js_port_descr_struct { + char manufacturer[64]; + char serial[64]; + char port[64]; + char description[128]; + void *handle; +}; + + +/* + * JTAG port + * + * This is retrieved by calling js_open_port(). + */ +struct js_port_struct { + /* Server associated with port */ + js_server_t *server; + + /* Node representing the whole scan chain */ + js_node_t *root_node; +}; + + +/* + * JTAG node information + * + * Nodes typically represent a TAP controller. A node can also + * represent a collection of TAP controllers, i.e. the whole scan + * chain or a device containing multiple TAP controllers. For scan + * chains containing JTAG multiplexers a node can represent the + * branches on the multiplexer. + */ +struct js_node_struct { + /* Associated port */ + js_port_t *port; + + /* Node represents one or more TAP controllers */ + int is_tap:1; + + /* Node is a multiplexer (child nodes are branches) */ + int is_mux:1; + + /* Node is a branch on a multiplexer */ + int is_branch:1; + + /* This branch is part of the scan chain */ + int is_active:1; + + /* IDCODE of the TAP (JS_DUMMY_IDCODE if unknown or NA) */ + uint32_t idcode; + + /* Instruction register length in bits */ + int irlen; + + /* Name of node */ + const char *name; + + /* Parent node */ + js_node_t **parent; + + /* Child nodes */ + js_node_t **child_list; + unsigned int child_count; +}; + + +/* + * JTAG states + * + * To simply the interface only a subset of the JTAG states are make + * accessible. + */ +/*typedef enum { + JS_RESET, + JS_IDLE, + JS_SHIFT_DR, + JS_PAUSE_DR, + JS_SHIFT_IR, + JS_PAUSE_IR, + JS_STATE_MAX +} js_state_t;*/ +typedef enum { + JS_RESET, + JS_IDLE, + JS_DRSELECT, + JS_DRCAPTURE, + JS_DRSHIFT, + JS_DREXIT1, + JS_DRPAUSE, + JS_DREXIT2, + JS_DRUPDATE, + JS_IRSELECT, + JS_IRCAPTURE, + JS_IRSHIFT, + JS_IREXIT1, + JS_IRPAUSE, + JS_IREXIT2, + JS_IRUPDATE, + JS_STATE_MAX +} js_state_t; + + + +/* + * JTAG command sequence object + * + * Commands are added to this object for later execution. + */ +struct js_command_sequence_struct { + js_node_t *node; +}; + + +/*********************************************************************** + * JTAG server implementation specific functions + ***********************************************************************/ + +/* + * Get list of available JTAG ports supported by this server + */ +extern int js_get_port_descr_list( + js_server_t *server, + js_port_descr_t **port_listp); + +/* + * Open a specific JTAG port for this server instance + */ +extern int js_open_port( + js_server_t *server, + js_port_descr_t *port_descr, + js_port_t **port); + +/* + * Delete server instance + */ +extern void js_deinit_server( + js_server_t *server); + +/* + * Get property value + */ +extern int js_get_property( + js_port_t *port, + js_property_kind_t kind, + js_property_value_t *valuep); + +/* + * Set property value + */ +extern int js_set_property( + js_port_t *port, + js_property_kind_t kind, + js_property_value_t value); + +/* + * Execute pending commands + */ +extern int js_run_command_sequence( + js_command_sequence_t *commands); + +/* + * Open a specific JTAG port for this server instance + */ +extern int js_close_port( + js_port_t *port); + + +/*********************************************************************** + * JTAG server library functions + ***********************************************************************/ + +/* + * Retrieve information about the last error as a string. + * + * Returns NULL if no error occured since last call to + * set_last_error(server, NULL). + */ +const char *js_get_last_error( + js_server_t *server); + + +/* + * Set error information + */ +void js_set_last_error( + js_server_t *server, + const char *fmt, + ...); + + +/* + * Allocate command sequence object + */ +extern js_command_sequence_t *js_create_command_sequence( + js_node_t *node); + + +/* + * CLear command sequence + * + * This function allows a command sequence object to be reused for a + * difference sequence. + */ +extern int js_clear_command_sequence( + js_command_sequence_t *cmdseq); + + +/* + * Delete command sequence + */ +extern int js_delete_command_sequence( + js_command_sequence_t *cmdseq); + + +/* + * Adds command to move JTAG state machine to and cycle TCK + * times. The argument is only applicable for when + * is one of the stable states JS_RESET, JS_IDLE, JS_PAUSE_IR + * or JS_PAUSE_DR. + */ +extern int js_add_state_change( + js_command_sequence_t *cmdseq, + js_state_t state, + unsigned int clocks); + +/* + * Adds command to + * 1. move state machine to either JS_SHIFT_IR if ( & + * JS_TO_IR) != 0 or JS_SHIFT_DR if ( & JS_TO_IR) == 0, + * 2. shift number of bits in from tdi_buffer to TDI and out + * from TDO to tdo_buffer, and + * 3. move state machine to . + * + * If is NULL then number of ones if ( & + * JS_ONES) != 0 or zeroes if ( & JS_ONES) == 0 are shifted + * to TDI. + * + * If is NULL then TDO bits are ignored. + * + * Both state transtions are optional if the state machine is + * already in the correct state. + */ +enum { + JS_TO_IR = 1, + JS_ONES = 2 +}; +extern int js_add_shift( + js_command_sequence_t *cmdseq, + unsigned int flags, + size_t bits, + unsigned char **tdi_buffer, + unsigned char **tdo_buffer, + js_state_t state); + + +/* + * Auto detect TAPs on scan chain. + * + * This typically involes a reset of the scan chain followed by + * reading data registers. + * + * The result is allocated using malloc() and the caller is resposible + * for freeing the buffer when it is no longer needed. + */ +extern int js_detect_taps( + js_port_t *port, + uint32_t **resultp); + +#ifdef __cplusplus +} +#endif + +#endif /* XILSKEY_JS_H */ diff --git a/lib/sw_services/xilskey/src/xilskey_jscmd.c b/lib/sw_services/xilskey/src/xilskey_jscmd.c new file mode 100644 index 00000000..ee0eadc5 --- /dev/null +++ b/lib/sw_services/xilskey/src/xilskey_jscmd.c @@ -0,0 +1,1810 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* @file xilskey_jscmd.c +* +* Contains jtag, efuse and bbram related API's +* +* @note +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  	Date     Changes
+* ----- ---- 	-------- --------------------------------------------------------
+* 1.00a rpoolla 04/26/13 First release
+* 1.01a hk      09/18/13 Added BBRAM functionality. Following API's added:
+*                        int JtagServerInitBbram(XilSKey_Bbram *InstancePtr)
+*                        int Bbram_Init(XilSKey_Bbram *InstancePtr)
+*                        int Bbram_ProgramKey(XilSKey_Bbram *InstancePtr)
+*                        int Bbram_VerifyKey(XilSKey_Bbram *InstancePtr)
+*                        void Bbram_DeInit(void)
+*
+* 
+* +* +******************************************************************************/ + +#include +#include +#include +#include +#ifdef _WIN32 +#include + +#if defined(_MSC_VER) +# pragma warning(disable:4996) /* 'strcpy': This function or variable may be unsafe */ +#endif + +typedef long ssize_t; +#else +#include +#endif +#include "xilskey_utils.h" +#include "xilskey_jslib.h" +#include "xilskey_jscmd.h" +#include "xgpiops.h" +#include "xilskey_bbram.h" + +//#define DEBUG_PRINT + +#ifdef DEBUG_PRINT +#define js_printf printf +#else +void dummy_printf(const char *ctrl1, ...); +#define js_printf dummy_printf +#endif + +#define DEFAULT_FREQUENCY 10000000 +#define MAX_FREQUENCY 30000000 +#define ZYNQ_DAP_ID 0x4ba00477 + +#define set_last_error(JS, ...) js_set_last_error(&(JS)->js.base, __VA_ARGS__) + +typedef struct js_port_impl_struct js_port_impl_t; +typedef struct js_command_impl_struct js_command_impl_t; +typedef struct ftd_async_transfer_struct ftd_async_transfer_t; + +static js_port_t *g_port = NULL; +static js_server_t *g_js = NULL; +static js_port_descr_t *g_useport = NULL; +extern u32 TimerTicksfor100ns; + +void dummy_printf(const char *ctrl1, ...) +{ + return; +} +static int close_port( + js_lib_port_t *port_arg); + + +struct js_command_impl_struct { + /* Command to execute */ + js_lib_command_t lib; + + /* Intermediatre command processing state */ + size_t byte_offset; + js_state_t start_state; + js_state_t end_state; + unsigned int write_bytes; + unsigned int read_bytes; + unsigned int partial_bytes; + int state_bits; +}; + + +struct js_zynq { + /* Base class - must be first. */ + js_lib_server_t js; + + /* Port list */ + js_port_descr_t *port_list; + unsigned int port_count; + unsigned int port_max; +}; + + +struct js_port_impl_struct { + /* Base class - must be first. */ + js_lib_port_t lib; + + /* Command sequence after normalization */ + js_lib_command_sequence_t *cmdseq; + + /* Current JTAG state */ + js_state_t state; + + int irPrePadBits; + int irPostPadBits; + int drPrePadBits; + int drPostPadBits; + + js_node_t root_node_obj; +}; + + + +static XGpioPs structXGpioPs; + +int setPin (int pin, int value); +int readPin (int pin); + +u32 Bbram_ReadKey[8]; + +void GpioConfig(unsigned long addr, unsigned long mask, unsigned long val) +{ + unsigned long current_val = *(volatile unsigned long *)addr; + *(volatile unsigned long *) addr = ( val & mask ) | ( current_val & ~mask); +} + +void JtagInitGpio () +{ + js_printf("===== Initializing PS GPIO pins...\n\r"); + XGpioPs_Config *ptrConfigPtrPs = XGpioPs_LookupConfig(0); + XGpioPs_CfgInitialize(&structXGpioPs,ptrConfigPtrPs,ptrConfigPtrPs->BaseAddr); + + /* Unlock the SLCR block */ + Xil_Out32 (0xF8000000 + 0x8, 0xDF0D); + + GpioConfig((GPIO_BASE_ADDR+(g_mio_jtag_tdi*4)),GPIO_MASK_VAL, GPIO_TDI_VAL); + GpioConfig((GPIO_BASE_ADDR+(g_mio_jtag_tdo*4)),GPIO_MASK_VAL, GPIO_TDO_VAL); + GpioConfig((GPIO_BASE_ADDR+(g_mio_jtag_tck*4)),GPIO_MASK_VAL, GPIO_TCK_VAL); + GpioConfig((GPIO_BASE_ADDR+(g_mio_jtag_tms*4)),GPIO_MASK_VAL, GPIO_TMS_VAL); + GpioConfig((GPIO_BASE_ADDR+(g_mio_jtag_mux_sel*4)),GPIO_MASK_VAL, GPIO_MUX_SEL_VAL); + + XGpioPs_SetDirectionPin(&structXGpioPs,MIO_TCK,1); + XGpioPs_SetOutputEnablePin(&structXGpioPs,MIO_TCK,1); + + XGpioPs_SetDirectionPin(&structXGpioPs,MIO_TMS,1); + XGpioPs_SetOutputEnablePin(&structXGpioPs,MIO_TMS,1); + + XGpioPs_SetDirectionPin(&structXGpioPs,MIO_TDI,1); + XGpioPs_SetOutputEnablePin(&structXGpioPs,MIO_TDI,1); + + XGpioPs_SetDirectionPin(&structXGpioPs,MIO_MUX_SELECT,1); + XGpioPs_SetOutputEnablePin(&structXGpioPs,MIO_MUX_SELECT,1); + XGpioPs_WritePin(&structXGpioPs, MIO_MUX_SELECT, g_mux_sel_def_val); + + XGpioPs_SetDirectionPin(&structXGpioPs,MIO_TDO,0); + XGpioPs_SetOutputEnablePin(&structXGpioPs,MIO_TDO,0); +} /* initGpio() */ + +int getByteCountFromBitCount (int bitCount) +{ + int byteCount = bitCount / 8; + if (bitCount % 8) + { + byteCount++; + } + return (byteCount); +} + +// File generated by JTAG.EXE. This are the tms values and +// the corresponding bit counts to navigate quickly from any state +// to any state. +const unsigned int JTAGNavigateTable [256] = +{ + 0x0101, // Start=00, End=00, TMSValue=01, BitCount= 1 + 0x0001, // Start=00, End=01, TMSValue=00, BitCount= 1 + 0x0202, // Start=00, End=02, TMSValue=02, BitCount= 2 + 0x0203, // Start=00, End=03, TMSValue=02, BitCount= 3 + 0x0204, // Start=00, End=04, TMSValue=02, BitCount= 4 + 0x0A04, // Start=00, End=05, TMSValue=0A, BitCount= 4 + 0x0A05, // Start=00, End=06, TMSValue=0A, BitCount= 5 + 0x2A06, // Start=00, End=07, TMSValue=2A, BitCount= 6 + 0x1A05, // Start=00, End=08, TMSValue=1A, BitCount= 5 + 0x0603, // Start=00, End=09, TMSValue=06, BitCount= 3 + 0x0604, // Start=00, End=10, TMSValue=06, BitCount= 4 + 0x0605, // Start=00, End=11, TMSValue=06, BitCount= 5 + 0x1605, // Start=00, End=12, TMSValue=16, BitCount= 5 + 0x1606, // Start=00, End=13, TMSValue=16, BitCount= 6 + 0x5607, // Start=00, End=14, TMSValue=56, BitCount= 7 + 0x3606, // Start=00, End=15, TMSValue=36, BitCount= 6 + 0x0703, // Start=01, End=00, TMSValue=07, BitCount= 3 + 0x0001, // Start=01, End=01, TMSValue=00, BitCount= 1 + 0x0101, // Start=01, End=02, TMSValue=01, BitCount= 1 + 0x0102, // Start=01, End=03, TMSValue=01, BitCount= 2 + 0x0103, // Start=01, End=04, TMSValue=01, BitCount= 3 + 0x0503, // Start=01, End=05, TMSValue=05, BitCount= 3 + 0x0504, // Start=01, End=06, TMSValue=05, BitCount= 4 + 0x1505, // Start=01, End=07, TMSValue=15, BitCount= 5 + 0x0D04, // Start=01, End=08, TMSValue=0D, BitCount= 4 + 0x0302, // Start=01, End=09, TMSValue=03, BitCount= 2 + 0x0303, // Start=01, End=10, TMSValue=03, BitCount= 3 + 0x0304, // Start=01, End=11, TMSValue=03, BitCount= 4 + 0x0B04, // Start=01, End=12, TMSValue=0B, BitCount= 4 + 0x0B05, // Start=01, End=13, TMSValue=0B, BitCount= 5 + 0x2B06, // Start=01, End=14, TMSValue=2B, BitCount= 6 + 0x1B05, // Start=01, End=15, TMSValue=1B, BitCount= 5 + 0x0302, // Start=02, End=00, TMSValue=03, BitCount= 2 + 0x0303, // Start=02, End=01, TMSValue=03, BitCount= 3 + 0x0B04, // Start=02, End=02, TMSValue=0B, BitCount= 4 + 0x0001, // Start=02, End=03, TMSValue=00, BitCount= 1 + 0x0002, // Start=02, End=04, TMSValue=00, BitCount= 2 + 0x0202, // Start=02, End=05, TMSValue=02, BitCount= 2 + 0x0203, // Start=02, End=06, TMSValue=02, BitCount= 3 + 0x0A04, // Start=02, End=07, TMSValue=0A, BitCount= 4 + 0x0603, // Start=02, End=08, TMSValue=06, BitCount= 3 + 0x0101, // Start=02, End=09, TMSValue=01, BitCount= 1 + 0x0102, // Start=02, End=10, TMSValue=01, BitCount= 2 + 0x0103, // Start=02, End=11, TMSValue=01, BitCount= 3 + 0x0503, // Start=02, End=12, TMSValue=05, BitCount= 3 + 0x0504, // Start=02, End=13, TMSValue=05, BitCount= 4 + 0x1505, // Start=02, End=14, TMSValue=15, BitCount= 5 + 0x0D04, // Start=02, End=15, TMSValue=0D, BitCount= 4 + 0x1F05, // Start=03, End=00, TMSValue=1F, BitCount= 5 + 0x0303, // Start=03, End=01, TMSValue=03, BitCount= 3 + 0x0703, // Start=03, End=02, TMSValue=07, BitCount= 3 + 0x0704, // Start=03, End=03, TMSValue=07, BitCount= 4 + 0x0001, // Start=03, End=04, TMSValue=00, BitCount= 1 + 0x0101, // Start=03, End=05, TMSValue=01, BitCount= 1 + 0x0102, // Start=03, End=06, TMSValue=01, BitCount= 2 + 0x0503, // Start=03, End=07, TMSValue=05, BitCount= 3 + 0x0302, // Start=03, End=08, TMSValue=03, BitCount= 2 + 0x0F04, // Start=03, End=09, TMSValue=0F, BitCount= 4 + 0x0F05, // Start=03, End=10, TMSValue=0F, BitCount= 5 + 0x0F06, // Start=03, End=11, TMSValue=0F, BitCount= 6 + 0x2F06, // Start=03, End=12, TMSValue=2F, BitCount= 6 + 0x2F07, // Start=03, End=13, TMSValue=2F, BitCount= 7 + 0xAF08, // Start=03, End=14, TMSValue=AF, BitCount= 8 + 0x6F07, // Start=03, End=15, TMSValue=6F, BitCount= 7 + 0x1F05, // Start=04, End=00, TMSValue=1F, BitCount= 5 + 0x0303, // Start=04, End=01, TMSValue=03, BitCount= 3 + 0x0703, // Start=04, End=02, TMSValue=07, BitCount= 3 + 0x0704, // Start=04, End=03, TMSValue=07, BitCount= 4 + 0x0001, // Start=04, End=04, TMSValue=00, BitCount= 1 + 0x0101, // Start=04, End=05, TMSValue=01, BitCount= 1 + 0x0102, // Start=04, End=06, TMSValue=01, BitCount= 2 + 0x0503, // Start=04, End=07, TMSValue=05, BitCount= 3 + 0x0302, // Start=04, End=08, TMSValue=03, BitCount= 2 + 0x0F04, // Start=04, End=09, TMSValue=0F, BitCount= 4 + 0x0F05, // Start=04, End=10, TMSValue=0F, BitCount= 5 + 0x0F06, // Start=04, End=11, TMSValue=0F, BitCount= 6 + 0x2F06, // Start=04, End=12, TMSValue=2F, BitCount= 6 + 0x2F07, // Start=04, End=13, TMSValue=2F, BitCount= 7 + 0xAF08, // Start=04, End=14, TMSValue=AF, BitCount= 8 + 0x6F07, // Start=04, End=15, TMSValue=6F, BitCount= 7 + 0x0F04, // Start=05, End=00, TMSValue=0F, BitCount= 4 + 0x0102, // Start=05, End=01, TMSValue=01, BitCount= 2 + 0x0302, // Start=05, End=02, TMSValue=03, BitCount= 2 + 0x0303, // Start=05, End=03, TMSValue=03, BitCount= 3 + 0x0203, // Start=05, End=04, TMSValue=02, BitCount= 3 + 0x0B04, // Start=05, End=05, TMSValue=0B, BitCount= 4 + 0x0001, // Start=05, End=06, TMSValue=00, BitCount= 1 + 0x0202, // Start=05, End=07, TMSValue=02, BitCount= 2 + 0x0101, // Start=05, End=08, TMSValue=01, BitCount= 1 + 0x0703, // Start=05, End=09, TMSValue=07, BitCount= 3 + 0x0704, // Start=05, End=10, TMSValue=07, BitCount= 4 + 0x0705, // Start=05, End=11, TMSValue=07, BitCount= 5 + 0x1705, // Start=05, End=12, TMSValue=17, BitCount= 5 + 0x1706, // Start=05, End=13, TMSValue=17, BitCount= 6 + 0x5707, // Start=05, End=14, TMSValue=57, BitCount= 7 + 0x3706, // Start=05, End=15, TMSValue=37, BitCount= 6 + 0x1F05, // Start=06, End=00, TMSValue=1F, BitCount= 5 + 0x0303, // Start=06, End=01, TMSValue=03, BitCount= 3 + 0x0703, // Start=06, End=02, TMSValue=07, BitCount= 3 + 0x0704, // Start=06, End=03, TMSValue=07, BitCount= 4 + 0x0102, // Start=06, End=04, TMSValue=01, BitCount= 2 + 0x0503, // Start=06, End=05, TMSValue=05, BitCount= 3 + 0x0001, // Start=06, End=06, TMSValue=00, BitCount= 1 + 0x0101, // Start=06, End=07, TMSValue=01, BitCount= 1 + 0x0302, // Start=06, End=08, TMSValue=03, BitCount= 2 + 0x0F04, // Start=06, End=09, TMSValue=0F, BitCount= 4 + 0x0F05, // Start=06, End=10, TMSValue=0F, BitCount= 5 + 0x0F06, // Start=06, End=11, TMSValue=0F, BitCount= 6 + 0x2F06, // Start=06, End=12, TMSValue=2F, BitCount= 6 + 0x2F07, // Start=06, End=13, TMSValue=2F, BitCount= 7 + 0xAF08, // Start=06, End=14, TMSValue=AF, BitCount= 8 + 0x6F07, // Start=06, End=15, TMSValue=6F, BitCount= 7 + 0x0F04, // Start=07, End=00, TMSValue=0F, BitCount= 4 + 0x0102, // Start=07, End=01, TMSValue=01, BitCount= 2 + 0x0302, // Start=07, End=02, TMSValue=03, BitCount= 2 + 0x0303, // Start=07, End=03, TMSValue=03, BitCount= 3 + 0x0001, // Start=07, End=04, TMSValue=00, BitCount= 1 + 0x0202, // Start=07, End=05, TMSValue=02, BitCount= 2 + 0x0203, // Start=07, End=06, TMSValue=02, BitCount= 3 + 0x0A04, // Start=07, End=07, TMSValue=0A, BitCount= 4 + 0x0101, // Start=07, End=08, TMSValue=01, BitCount= 1 + 0x0703, // Start=07, End=09, TMSValue=07, BitCount= 3 + 0x0704, // Start=07, End=10, TMSValue=07, BitCount= 4 + 0x0705, // Start=07, End=11, TMSValue=07, BitCount= 5 + 0x1705, // Start=07, End=12, TMSValue=17, BitCount= 5 + 0x1706, // Start=07, End=13, TMSValue=17, BitCount= 6 + 0x5707, // Start=07, End=14, TMSValue=57, BitCount= 7 + 0x3706, // Start=07, End=15, TMSValue=37, BitCount= 6 + 0x0703, // Start=08, End=00, TMSValue=07, BitCount= 3 + 0x0001, // Start=08, End=01, TMSValue=00, BitCount= 1 + 0x0101, // Start=08, End=02, TMSValue=01, BitCount= 1 + 0x0102, // Start=08, End=03, TMSValue=01, BitCount= 2 + 0x0103, // Start=08, End=04, TMSValue=01, BitCount= 3 + 0x0503, // Start=08, End=05, TMSValue=05, BitCount= 3 + 0x0504, // Start=08, End=06, TMSValue=05, BitCount= 4 + 0x1505, // Start=08, End=07, TMSValue=15, BitCount= 5 + 0x0D04, // Start=08, End=08, TMSValue=0D, BitCount= 4 + 0x0302, // Start=08, End=09, TMSValue=03, BitCount= 2 + 0x0303, // Start=08, End=10, TMSValue=03, BitCount= 3 + 0x0304, // Start=08, End=11, TMSValue=03, BitCount= 4 + 0x0B04, // Start=08, End=12, TMSValue=0B, BitCount= 4 + 0x0B05, // Start=08, End=13, TMSValue=0B, BitCount= 5 + 0x2B06, // Start=08, End=14, TMSValue=2B, BitCount= 6 + 0x1B05, // Start=08, End=15, TMSValue=1B, BitCount= 5 + 0x0101, // Start=09, End=00, TMSValue=01, BitCount= 1 + 0x0102, // Start=09, End=01, TMSValue=01, BitCount= 2 + 0x0503, // Start=09, End=02, TMSValue=05, BitCount= 3 + 0x0504, // Start=09, End=03, TMSValue=05, BitCount= 4 + 0x0505, // Start=09, End=04, TMSValue=05, BitCount= 5 + 0x1505, // Start=09, End=05, TMSValue=15, BitCount= 5 + 0x1506, // Start=09, End=06, TMSValue=15, BitCount= 6 + 0x5507, // Start=09, End=07, TMSValue=55, BitCount= 7 + 0x3506, // Start=09, End=08, TMSValue=35, BitCount= 6 + 0x0D04, // Start=09, End=09, TMSValue=0D, BitCount= 4 + 0x0001, // Start=09, End=10, TMSValue=00, BitCount= 1 + 0x0002, // Start=09, End=11, TMSValue=00, BitCount= 2 + 0x0202, // Start=09, End=12, TMSValue=02, BitCount= 2 + 0x0203, // Start=09, End=13, TMSValue=02, BitCount= 3 + 0x0A04, // Start=09, End=14, TMSValue=0A, BitCount= 4 + 0x0603, // Start=09, End=15, TMSValue=06, BitCount= 3 + 0x1F05, // Start=10, End=00, TMSValue=1F, BitCount= 5 + 0x0303, // Start=10, End=01, TMSValue=03, BitCount= 3 + 0x0703, // Start=10, End=02, TMSValue=07, BitCount= 3 + 0x0704, // Start=10, End=03, TMSValue=07, BitCount= 4 + 0x0705, // Start=10, End=04, TMSValue=07, BitCount= 5 + 0x1705, // Start=10, End=05, TMSValue=17, BitCount= 5 + 0x1706, // Start=10, End=06, TMSValue=17, BitCount= 6 + 0x5707, // Start=10, End=07, TMSValue=57, BitCount= 7 + 0x3706, // Start=10, End=08, TMSValue=37, BitCount= 6 + 0x0F04, // Start=10, End=09, TMSValue=0F, BitCount= 4 + 0x0F05, // Start=10, End=10, TMSValue=0F, BitCount= 5 + 0x0001, // Start=10, End=11, TMSValue=00, BitCount= 1 + 0x0101, // Start=10, End=12, TMSValue=01, BitCount= 1 + 0x0102, // Start=10, End=13, TMSValue=01, BitCount= 2 + 0x0503, // Start=10, End=14, TMSValue=05, BitCount= 3 + 0x0302, // Start=10, End=15, TMSValue=03, BitCount= 2 + 0x1F05, // Start=11, End=00, TMSValue=1F, BitCount= 5 + 0x0303, // Start=11, End=01, TMSValue=03, BitCount= 3 + 0x0703, // Start=11, End=02, TMSValue=07, BitCount= 3 + 0x0704, // Start=11, End=03, TMSValue=07, BitCount= 4 + 0x0705, // Start=11, End=04, TMSValue=07, BitCount= 5 + 0x1705, // Start=11, End=05, TMSValue=17, BitCount= 5 + 0x1706, // Start=11, End=06, TMSValue=17, BitCount= 6 + 0x5707, // Start=11, End=07, TMSValue=57, BitCount= 7 + 0x3706, // Start=11, End=08, TMSValue=37, BitCount= 6 + 0x0F04, // Start=11, End=09, TMSValue=0F, BitCount= 4 + 0x0F05, // Start=11, End=10, TMSValue=0F, BitCount= 5 + 0x0001, // Start=11, End=11, TMSValue=00, BitCount= 1 + 0x0101, // Start=11, End=12, TMSValue=01, BitCount= 1 + 0x0102, // Start=11, End=13, TMSValue=01, BitCount= 2 + 0x0503, // Start=11, End=14, TMSValue=05, BitCount= 3 + 0x0302, // Start=11, End=15, TMSValue=03, BitCount= 2 + 0x0F04, // Start=12, End=00, TMSValue=0F, BitCount= 4 + 0x0102, // Start=12, End=01, TMSValue=01, BitCount= 2 + 0x0302, // Start=12, End=02, TMSValue=03, BitCount= 2 + 0x0303, // Start=12, End=03, TMSValue=03, BitCount= 3 + 0x0304, // Start=12, End=04, TMSValue=03, BitCount= 4 + 0x0B04, // Start=12, End=05, TMSValue=0B, BitCount= 4 + 0x0B05, // Start=12, End=06, TMSValue=0B, BitCount= 5 + 0x2B06, // Start=12, End=07, TMSValue=2B, BitCount= 6 + 0x1B05, // Start=12, End=08, TMSValue=1B, BitCount= 5 + 0x0703, // Start=12, End=09, TMSValue=07, BitCount= 3 + 0x0704, // Start=12, End=10, TMSValue=07, BitCount= 4 + 0x0203, // Start=12, End=11, TMSValue=02, BitCount= 3 + 0x0A04, // Start=12, End=12, TMSValue=0A, BitCount= 4 + 0x0001, // Start=12, End=13, TMSValue=00, BitCount= 1 + 0x0202, // Start=12, End=14, TMSValue=02, BitCount= 2 + 0x0101, // Start=12, End=15, TMSValue=01, BitCount= 1 + 0x1F05, // Start=13, End=00, TMSValue=1F, BitCount= 5 + 0x0303, // Start=13, End=01, TMSValue=03, BitCount= 3 + 0x0703, // Start=13, End=02, TMSValue=07, BitCount= 3 + 0x0704, // Start=13, End=03, TMSValue=07, BitCount= 4 + 0x0705, // Start=13, End=04, TMSValue=07, BitCount= 5 + 0x1705, // Start=13, End=05, TMSValue=17, BitCount= 5 + 0x1706, // Start=13, End=06, TMSValue=17, BitCount= 6 + 0x5707, // Start=13, End=07, TMSValue=57, BitCount= 7 + 0x3706, // Start=13, End=08, TMSValue=37, BitCount= 6 + 0x0F04, // Start=13, End=09, TMSValue=0F, BitCount= 4 + 0x0F05, // Start=13, End=10, TMSValue=0F, BitCount= 5 + 0x0102, // Start=13, End=11, TMSValue=01, BitCount= 2 + 0x0503, // Start=13, End=12, TMSValue=05, BitCount= 3 + 0x0001, // Start=13, End=13, TMSValue=00, BitCount= 1 + 0x0101, // Start=13, End=14, TMSValue=01, BitCount= 1 + 0x0302, // Start=13, End=15, TMSValue=03, BitCount= 2 + 0x0F04, // Start=14, End=00, TMSValue=0F, BitCount= 4 + 0x0102, // Start=14, End=01, TMSValue=01, BitCount= 2 + 0x0302, // Start=14, End=02, TMSValue=03, BitCount= 2 + 0x0303, // Start=14, End=03, TMSValue=03, BitCount= 3 + 0x0304, // Start=14, End=04, TMSValue=03, BitCount= 4 + 0x0B04, // Start=14, End=05, TMSValue=0B, BitCount= 4 + 0x0B05, // Start=14, End=06, TMSValue=0B, BitCount= 5 + 0x2B06, // Start=14, End=07, TMSValue=2B, BitCount= 6 + 0x1B05, // Start=14, End=08, TMSValue=1B, BitCount= 5 + 0x0703, // Start=14, End=09, TMSValue=07, BitCount= 3 + 0x0704, // Start=14, End=10, TMSValue=07, BitCount= 4 + 0x0001, // Start=14, End=11, TMSValue=00, BitCount= 1 + 0x0202, // Start=14, End=12, TMSValue=02, BitCount= 2 + 0x0203, // Start=14, End=13, TMSValue=02, BitCount= 3 + 0x0A04, // Start=14, End=14, TMSValue=0A, BitCount= 4 + 0x0101, // Start=14, End=15, TMSValue=01, BitCount= 1 + 0x0703, // Start=15, End=00, TMSValue=07, BitCount= 3 + 0x0001, // Start=15, End=01, TMSValue=00, BitCount= 1 + 0x0101, // Start=15, End=02, TMSValue=01, BitCount= 1 + 0x0102, // Start=15, End=03, TMSValue=01, BitCount= 2 + 0x0103, // Start=15, End=04, TMSValue=01, BitCount= 3 + 0x0503, // Start=15, End=05, TMSValue=05, BitCount= 3 + 0x0504, // Start=15, End=06, TMSValue=05, BitCount= 4 + 0x1505, // Start=15, End=07, TMSValue=15, BitCount= 5 + 0x0D04, // Start=15, End=08, TMSValue=0D, BitCount= 4 + 0x0302, // Start=15, End=09, TMSValue=03, BitCount= 2 + 0x0303, // Start=15, End=10, TMSValue=03, BitCount= 3 + 0x0304, // Start=15, End=11, TMSValue=03, BitCount= 4 + 0x0B04, // Start=15, End=12, TMSValue=0B, BitCount= 4 + 0x0B05, // Start=15, End=13, TMSValue=0B, BitCount= 5 + 0x2B06, // Start=15, End=14, TMSValue=2B, BitCount= 6 + 0x1B05, // Start=15, End=15, TMSValue=1B, BitCount= 5 +}; + +unsigned int getNavigateTAPValue (unsigned char startState, unsigned char endState) +{ + unsigned char index; + unsigned int tableValue; + + index = (startState << 4) & 0xF0; + index |= endState; + + tableValue = JTAGNavigateTable [index]; + + return (tableValue); +} + +void navigateTAP (unsigned char startState, unsigned char endState) +{ + unsigned int tableValue = getNavigateTAPValue (startState, endState); + unsigned char tmsValue = (tableValue >> 8) & 0x00FF; + unsigned char bitCount = tableValue & 0x00FF; + + unsigned char mask = 0x01; + + js_printf ("navigate - start=%d, end=%d\n", startState, endState); + js_printf ("tmsvalue = 0x%02X, bitCount = %d\n", tmsValue, bitCount); + + if (endState == JS_RESET) + { + // initialize state to JS_RESET + setPin (MIO_TMS, 1); + + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + + return; + } + + if (startState != endState) + { + while (bitCount) + { + if (tmsValue & mask) + { + setPin (MIO_TMS, 1); + } + else + { + setPin (MIO_TMS, 0); + } + // pulse tck pin + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + + mask <<= 1; + bitCount--; + } + } + else + { + js_printf ("startState == endState; navigateTAP not executed."); + } +} + +int setPin (int pin, int value) +{ + int status = 1; + XGpioPs_WritePin(&structXGpioPs, pin, value); + return (status); +} + +int readPin (int pin) +{ + int retVal = XGpioPs_ReadPin(&structXGpioPs, pin); + return (retVal); +} + +void jtagShiftTDI (unsigned char tdiData, unsigned char* tdoData, int clkCount, int exitState) +{ + int count = clkCount; + unsigned char mask = 0x01; + + while (count) + { + if (tdoData) // read tdo bit + { + if (readPin (MIO_TDO)) + { + *(unsigned char*)tdoData |= mask; + } + else + { + *(unsigned char*)tdoData &= ~mask; + } + } + if (tdiData & mask) + { + setPin (MIO_TDI, 1); + } + else + { + setPin (MIO_TDI, 0); + } + if (exitState == 1) + { + if (count == 1) + { + setPin (MIO_TMS, 1); + } + } + + // pulse tck pin + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + + mask <<= 1; + count--; + } +} + +// This function will be used to shift long bits. Returns a 1 if shift state is to be exited. +// If tdoBuf != NULL, data will be read from device. +int jtagShiftTDIBits (unsigned char* tdiBuf, unsigned char* tdoBuf, int bitCount, js_state_t endState, unsigned int flags) +{ + unsigned char* tdoByte = NULL; + int count = 8; + int exitState = 0; + int currentByteCount = getByteCountFromBitCount (bitCount); + int byteCount = currentByteCount; + int index = 0; + unsigned char TdiTemp = 0x0; + int bitsLeft = 8; + if (bitCount % 8) + { + bitsLeft = bitCount % 8; + } + + if(flags | JS_ONES) + TdiTemp = 0xFF; + + while (index < byteCount) + { + currentByteCount--; + if (currentByteCount == 0) // last byte + { + if (bitsLeft != 8) + { + count = bitsLeft; + } + if (flags & JS_TO_IR) + { + if (endState != JS_IRSHIFT) + { + exitState = 1; + } + } + else + { + if (endState != JS_DRSHIFT) + { + exitState = 1; + } + } + } + + if (tdoBuf) // read tdo data + { + tdoByte = &tdoBuf [index]; + } + + if(tdiBuf != NULL) + jtagShiftTDI (tdiBuf [index], tdoByte, count, exitState); + else + jtagShiftTDI (TdiTemp, tdoByte, count, exitState); + + if (tdoBuf) + js_printf ("tdoBuf=0x%02X\n", *tdoByte); + + index++; + } + + return (exitState); +} + +int jtag_setPreAndPostPads (js_port_t *port_arg, int irPrePadBits, int irPostPadBits, int drPrePadBits, int drPostPadBits) +{ + int status = 0; + js_port_impl_t *port = (js_port_impl_t *)port_arg; + port->irPrePadBits = irPrePadBits; + port->irPostPadBits = irPostPadBits; + port->drPrePadBits = drPrePadBits; + port->drPostPadBits = drPostPadBits; + return (status); +} + +int jtag_navigate (js_port_t *port, js_state_t state) +{ + int status = 0; + js_command_sequence_t *cmds = js_create_command_sequence(port->root_node); + if (cmds == NULL) + { + return -1; + } + js_add_state_change(cmds, state, 0); + status = js_run_command_sequence(cmds); + js_delete_command_sequence(cmds); + return (status); +} + +// This function takes care of padding +// Must be set up with pre/post ir/dr info + +int jtag_shift (js_port_t *port_arg, unsigned char mode, int bits, unsigned char* wrBuffer, unsigned char* rdBuffer, js_state_t state) +{ + int status = 0; + unsigned char* rdPtr; + unsigned char* wrPtr; + + js_command_sequence_t *cmds = js_create_command_sequence(port_arg->root_node); + if (cmds == NULL) + { + return -1; + } + + js_port_impl_t *port = (js_port_impl_t *)port_arg; + + if (mode == ATOMIC_IR_SCAN) + { + if (port->irPrePadBits > 0) + { + js_add_shift (cmds, JS_TO_IR | JS_ONES, port->irPrePadBits, NULL, NULL, JS_IRSHIFT); + } + if (port->irPostPadBits == 0) + { + js_add_shift (cmds, JS_TO_IR, bits, ((wrBuffer == NULL) ? NULL : &wrPtr), ((rdBuffer == NULL) ? NULL : &rdPtr), state); + } + else + { + js_add_shift (cmds, JS_TO_IR, bits, ((wrBuffer == NULL) ? NULL : &wrPtr), ((rdBuffer == NULL) ? NULL : &rdPtr), JS_IRSHIFT); + js_add_shift (cmds, JS_TO_IR | JS_ONES, port->irPostPadBits, NULL, NULL, state); + } + } + else + { + if (port->drPrePadBits > 0) + { + js_add_shift (cmds, 0, port->drPrePadBits, NULL, NULL, JS_DRSHIFT); + } + if (port->drPostPadBits == 0) + { + js_add_shift (cmds, 0, bits, ((wrBuffer == NULL) ? NULL : &wrPtr), ((rdBuffer == NULL) ? NULL : &rdPtr), state); + } + else + { + js_add_shift (cmds, 0, bits, ((wrBuffer == NULL) ? NULL : &wrPtr), ((rdBuffer == NULL) ? NULL : &rdPtr), JS_DRSHIFT); + js_add_shift (cmds, 0, port->drPostPadBits, NULL, NULL, state); + } + } + + if (wrBuffer) // copy input tdi data to cmd tdi buffer. + { + memcpy (wrPtr, wrBuffer, getByteCountFromBitCount (bits)); + } + + status = js_run_command_sequence(cmds); + + if (rdBuffer) // copy cmd tdo buffer to tdo buffer. + { + memcpy (rdBuffer, rdPtr, getByteCountFromBitCount (bits)); + } + + js_delete_command_sequence(cmds); + return (status); +} + + +/*static int update_clock_frequency( + js_port_impl_t *port) +{ + return 0; +}*/ + + +static int get_property( + js_lib_port_t *port_arg, + js_property_kind_t kind, + js_property_value_t *valuep) +{ + js_port_impl_t *port = (js_port_impl_t *)port_arg; + + js_set_last_error(port->lib.base.server, "unsupported property"); + return -1; +} + + +static int set_property( + js_lib_port_t *port_arg, + js_property_kind_t kind, + js_property_value_t value) +{ + js_port_impl_t *port = (js_port_impl_t *)port_arg; + + js_set_last_error(port->lib.base.server, "unsupported property"); + return -1; +} + +static int run_command_sequence( + js_lib_command_sequence_t *cmds) +{ + js_port_impl_t *port = (js_port_impl_t *)cmds->base.node->port; + js_command_impl_t *cmd_start; + js_command_impl_t *cmd_end; + + if (js_clear_command_sequence(&port->cmdseq->base) < 0 || + js_lib_normalize_command_sequence(port->cmdseq, cmds) < 0) + return -1; + + cmd_start = (js_command_impl_t *)port->cmdseq->cmd_list; + cmd_end = cmd_start + port->cmdseq->cmd_count; + + js_command_impl_t *cmd = cmd_start; + js_state_t state = port->state; + + while (cmd < cmd_end) + { + js_command_kind_t kind = cmd->lib.kind; + + switch (kind) + { + case JS_CMD_SET_STATE: + { + navigateTAP (state, cmd->lib.state); + state = cmd->lib.state; // save current state + break; + } + case JS_CMD_SHIFT: + { + if (cmd->lib.flags & JS_TO_IR) + { + navigateTAP (state, JS_IRSHIFT); + state = JS_IRSHIFT; + } + else + { + navigateTAP (state, JS_DRSHIFT); + state = JS_DRSHIFT; + } + + if (jtagShiftTDIBits (cmd->lib.tdi_buf, cmd->lib.tdo_buf, cmd->lib.count, cmd->lib.state, cmd->lib.flags)) + { + /* Handle state change after scan */ + if (state != cmd->lib.state) + { + if (cmd->lib.flags & JS_TO_IR) + { + state = JS_IREXIT1; + } + else + { + state = JS_DREXIT1; + } + navigateTAP (state, cmd->lib.state); + state = cmd->lib.state; + } + } + break; + } + default: + fprintf(stderr, "write_commands: unsupported command %d\n", kind); + break; + } + cmd++; + } + + port->state = state; // save current state + + return 0; +} + +static int get_port_descr_list( + js_lib_server_t *server, + js_port_descr_t **port_listp) +{ + return 1; +} + + +int open_port( + js_lib_server_t *server, + js_port_descr_t *port_descr, + js_lib_port_t **result) +{ + + struct js_zynq *js = (struct js_zynq *)server; + + js_port_impl_t *port; + js_node_t *node; + + port = (js_port_impl_t *)malloc(sizeof *port); + if (port == NULL) { + js_set_last_error(&server->base, "end of memory"); + return -1; + } + memset(port, 0, sizeof *port); + port->lib.base.server = &server->base; + + /* Initialize root node */ + port->lib.base.root_node = node = &port->root_node_obj; + node->port = &port->lib.base; + node->is_tap = 1; + node->is_active = 1; + node->idcode = JS_DUMMY_IDCODE; + node->name = "whole scan chain"; + + port->lib.get_property = get_property; + port->lib.set_property = set_property; + port->lib.run_command_sequence = run_command_sequence; + port->lib.close_port = close_port; + + if ((port->cmdseq = (js_lib_command_sequence_t *)js_create_command_sequence(node)) == NULL) { + set_last_error(js, "end of memory"); + goto error; + } + port->cmdseq->cmd_size = sizeof(js_command_impl_t); + + port->irPrePadBits = 0; + port->irPostPadBits = 0; + port->drPrePadBits = 0; + port->drPostPadBits = 0; + + // Initialize JTAG drivers + setPin (MIO_TCK, 0); + setPin (MIO_TMS, 0); + setPin (MIO_TDI, 0); + + // initialize state to JS_RESET + port->state = JS_RESET; + jtag_navigate (node->port, JS_RESET); + + *result = &port->lib; + return 0; + + error: + + return -1; +} + + +static int close_port( + js_lib_port_t *port_arg) +{ + + js_printf ("\n\nClosing Port.\n\n"); + js_port_impl_t *port = (js_port_impl_t *)port_arg; + int ret = 0; + + setPin (MIO_TDI, 0); + setPin (MIO_TMS, 0); + setPin (MIO_TCK, 0); + + js_delete_command_sequence(&port->cmdseq->base); + + free (port); + + return ret; +} + + +static void deinit_server( + js_lib_server_t *server) +{ + struct js_zynq *js = (struct js_zynq *)server; + + if (js->port_list) + free(js->port_list); + free(js); +} + + +js_server_t *js_init_zynq() +{ + struct js_zynq *js; + + if ((js = (struct js_zynq *)malloc(sizeof *js)) == NULL) { + return NULL; + } + memset(js, 0, sizeof *js); + js->js.get_port_descr_list = get_port_descr_list; + js->js.open_port = open_port; + js->js.deinit_server = deinit_server; + + return &js->js.base; +} + +void JtagWrite(unsigned char row, unsigned char bit) +{ + + /* Following is the method to program FUSE register in Direct Macro Access way. + Go to TLR to clear FUSE_CTS + Load FUSE_CTS instruction on IR + Step to CDR/SDR to shift in the command word + dma=1; pgm=1; a_row<4:0> & a_bit<4:0> + Continuously shift in MAGIC_CTS_WRITE + Loop back to E1DR/UDR/SDS/CDR/E1DR/UDR + Go to RTI and stay in RTI EXACTLY Tpgm = 12 us (tbd) and immediately exit to SDS + Go to TLR to clear FUSE_CTS + */ + unsigned char wrBuffer [8]; + int bits = 0; + unsigned long long time = 0; + unsigned long long time_start = 0; + unsigned long long time_end = 0; + unsigned int delay = 0; + + // program FUSE_USER bit in row 31 bit 0 + //Go to TLR to clear FUSE_CTS + jtag_navigate (g_port, JS_RESET); + + //Load FUSE_CTS instruction on IR + jtag_setPreAndPostPads (g_port, 0, ZYNQ_DAP_IR_LENGTH, 0, 1); + bits = ZYNQ_TAP_IR_LENGTH; // xc7z020 ir length + wrBuffer [0] = 0x30; // FUSE_CTS instruction + jtag_shift (g_port, ATOMIC_IR_SCAN, bits, wrBuffer, NULL, JS_DRSELECT); + + //prepare FUSE_CTS data. + wrBuffer [0] = (unsigned char)((row<<3)| 0x3); //Enable DMA, program and select row. + wrBuffer [1] = bit; //bit position + wrBuffer [2] = 0x00; + wrBuffer [3] = 0x00; + //Magic word. + wrBuffer [4] = 0xAC; + wrBuffer [5] = 0x28; + wrBuffer [6] = 0x8A; + wrBuffer [7] = 0xA0; + + bits = 64; // fuse_cts data length + + /* Step to CDR/SDR to shift in the command word + * dma=1; pgm=1; a_row<4:0> & a_bit<4:0> + * Continuously shift in MAGIC_CTS_WRITE + */ + jtag_shift (g_port, ATOMIC_DR_SCAN, bits, wrBuffer, NULL, JS_DRSELECT); + + jtag_navigate (g_port, JS_DRCAPTURE); + jtag_navigate (g_port, JS_DREXIT1); + jtag_navigate (g_port, JS_DRUPDATE); + + //Go to RTI and stay in RTI EXACTLY Tpgm = 12 us (tbd) and immediately exit to SDS + time_start = XilSKey_Efuse_GetTime(); + jtag_navigate (g_port, JS_IDLE); + time_end = XilSKey_Efuse_GetTime(); + delay = (u32)((time_end - time_start)/(TimerTicksfor100ns)); + + //Here we will be providing 12us delay. + if(delay < 110) + { + + XilSKey_Efuse_SetTimeOut(&time, 110-delay); + while(1) + { + if(XilSKey_Efuse_IsTimerExpired(time) == 1) + break; + } + } + + jtag_navigate (g_port, JS_DRSELECT); + jtag_navigate (g_port, JS_IRSELECT); + jtag_navigate (g_port, JS_RESET); +} + + +void JtagRead(unsigned char row, unsigned int * row_data, unsigned char marginOption) +{ + /* Following is the method to read FUSE register in Direct Macro Access way. + Go to TLR to clear FUSE_CTS + Load FUSE_CTS instruction on IR + Step to CDR/SDR to shift in 32-bits FUSE_CTS command word + a_row<4:0>; dma=1; pgm=0; tp_sel<1:0>; ecc_dma + Shift in MAGIC_CTS_WRITE "A08A28AC" + Step to E1DR/UDR to update FUSE_CTS reg + Step to SDS/CDR/SDR to shift out captured row, while shifting in a new command with next row address w/ or w/o new tp_sel or ecc_dma setting + Captured macro word (32 bits) is stored in jtag_dr[63:32] + If ecc_dma = 1, jtag_dr[61:32] = {DED check-sum, SEC syndrome, decoded payload} + */ + unsigned char wrBuffer [8]; + unsigned char rdBuffer [8]; + int bits = 8; + unsigned char * row_data_ptr = (unsigned char *)row_data; + + // read 64-bit eFUSE dna + //Go to TLR to clear FUSE_CTS + jtag_navigate (g_port, JS_RESET); + + //Load FUSE_CTS instruction on IR + jtag_setPreAndPostPads (g_port, 0, ZYNQ_DAP_IR_LENGTH, 0, 1); + bits = ZYNQ_TAP_IR_LENGTH; // xc7z020 ir length + wrBuffer [0] = 0x30; // FUSE_CTS instruction + jtag_shift (g_port, ATOMIC_IR_SCAN, bits, wrBuffer, NULL, JS_DRSELECT); + //prepare FUSE_CTS data. + + wrBuffer [0] = (unsigned char)((row<<3)| 0x1); //Enable DMA and select the row number. + wrBuffer [1] = (unsigned char)(marginOption<<5); + wrBuffer [2] = 0x00; + wrBuffer [3] = 0x00; + //Magic word. + wrBuffer [4] = 0xAC; + wrBuffer [5] = 0x28; + wrBuffer [6] = 0x8A; + wrBuffer [7] = 0xA0; + + bits = 64; // fuse_cts data length + jtag_shift (g_port, ATOMIC_DR_SCAN, bits, wrBuffer, NULL, JS_DRSELECT); + + jtag_shift (g_port, ATOMIC_DR_SCAN, bits, NULL, rdBuffer, JS_DRSELECT); + + row_data_ptr[0] = rdBuffer [4]; + row_data_ptr[1] = rdBuffer [5]; + row_data_ptr[2] = rdBuffer [6]; + row_data_ptr[3] = rdBuffer [7]; +} +int JtagValidateMioPins(void) +{ + /* + * Make sure that each every MIO pin defined is valid + */ + if((g_mio_jtag_tdi < 0) || (g_mio_jtag_tdi > 53)) + return 1; + if((g_mio_jtag_tdo < 0) || (g_mio_jtag_tdo > 53)) + return 1; + if((g_mio_jtag_tck < 0) || (g_mio_jtag_tck > 53)) + return 1; + if((g_mio_jtag_tms < 0) || (g_mio_jtag_tms > 53)) + return 1; + if((g_mio_jtag_mux_sel < 0) || (g_mio_jtag_mux_sel > 53)) + return 1; + + /* + * Make sure that MIO pins defined for JTAG operation are unique among themselves + */ + if((g_mio_jtag_tdi == g_mio_jtag_tdo)|| + (g_mio_jtag_tdi == g_mio_jtag_tck)|| + (g_mio_jtag_tdi == g_mio_jtag_tms)|| + (g_mio_jtag_tdi == g_mio_jtag_mux_sel)) + return 1; + + if((g_mio_jtag_tdo == g_mio_jtag_tck)|| + (g_mio_jtag_tdo == g_mio_jtag_tms)|| + (g_mio_jtag_tdo == g_mio_jtag_mux_sel)) + return 1; + + if((g_mio_jtag_tck == g_mio_jtag_tms)|| + (g_mio_jtag_tck == g_mio_jtag_mux_sel)) + return 1; + + if(g_mio_jtag_tms == g_mio_jtag_mux_sel) + return 1; + + return 0; +} + +int JtagServerInit(XilSKey_EPl *InstancePtr) +{ + int retval=0, i=0, num_taps=0, status=0; + unsigned long *tap_codes = NULL; + + g_mio_jtag_tdi = InstancePtr->JtagMioTDI; + g_mio_jtag_tdo = InstancePtr->JtagMioTDO; + g_mio_jtag_tck = InstancePtr->JtagMioTCK; + g_mio_jtag_tms = InstancePtr->JtagMioTMS; + g_mio_jtag_mux_sel = InstancePtr->JtagMioMuxSel; + g_mux_sel_def_val = InstancePtr->JtagMuxSelLineDefVal; + + status = JtagValidateMioPins(); + if(status != 0) + { + return 1; + } + + if((g_mux_sel_def_val != 0) && (g_mux_sel_def_val != 1)) + { + return 1; + } + JtagInitGpio(); + + g_js = js_init_zynq(); + if (g_js == NULL) { + fprintf(stderr, "cannot create JTAG server\n"); + return 1; + } + + if (js_open_port(g_js, g_useport, &g_port) < 0) { + js_printf("%s\n", js_get_last_error(g_js)); + retval = 1; + goto do_deinit; + } + + if ((num_taps = js_detect_taps(g_port, &tap_codes)) < 0) { + js_printf("detect_taps error: %s\n", js_get_last_error(g_js)); + retval = 1; + goto do_deinit; + } + + + js_printf("idcodes: "); + for (i = num_taps; i > 0; i--) { + if (i != num_taps){ + js_printf(" "); + } + js_printf("%08x", (unsigned int)tap_codes[i - 1]); + } + js_printf("\n"); + + + //Check if one of the tap code is for Zynq DAP ID: 4ba00477 + + for (i = 0; i < num_taps; i++) { + if(tap_codes[i] == ZYNQ_DAP_ID){ + break; + } + } + + if(i == num_taps) + { + retval = 1; + } + + + if (tap_codes){ + free(tap_codes); + } + return retval; + +do_deinit: + if (g_port != NULL) + js_close_port(g_port); + + js_deinit_server(g_js); + + return retval; +} + +/****************************************************************************/ +/** +* +* This function initializes JTAG server for use in BBRAM algorithm +* +* @param BBRAM instance pointer +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note +* +*****************************************************************************/ +int JtagServerInitBbram(XilSKey_Bbram *InstancePtr) +{ + int retval=0, i=0, num_taps=0, status=0; + unsigned long *tap_codes = NULL; + + g_mio_jtag_tdi = InstancePtr->JtagMioTDI; + g_mio_jtag_tdo = InstancePtr->JtagMioTDO; + g_mio_jtag_tck = InstancePtr->JtagMioTCK; + g_mio_jtag_tms = InstancePtr->JtagMioTMS; + g_mio_jtag_mux_sel = InstancePtr->JtagMioMuxSel; + g_mux_sel_def_val = InstancePtr->JtagMuxSelLineDefVal; + + status = JtagValidateMioPins(); + if(status != 0) + { + return 1; + } + + if((g_mux_sel_def_val != 0) && (g_mux_sel_def_val != 1)) + { + return 1; + } + + JtagInitGpio(); + + g_js = js_init_zynq(); + if (g_js == NULL) { + fprintf(stderr, "cannot create JTAG server\n"); + return 1; + } + + if (js_open_port(g_js, g_useport, &g_port) < 0) { + js_printf("%s\n", js_get_last_error(g_js)); + retval = 1; + goto do_deinit; + } + + if ((num_taps = js_detect_taps(g_port, &tap_codes)) < 0) { + js_printf("detect_taps error: %s\n", js_get_last_error(g_js)); + retval = 1; + goto do_deinit; + } + + js_printf("idcodes: "); + for (i = num_taps; i > 0; i--) { + if (i != num_taps){ + js_printf(" "); + } + js_printf("%08x", (unsigned int)tap_codes[i - 1]); + } + js_printf("\n"); + + + //Check if one of the tap code is for Zynq DAP ID: 4ba00477 + + for (i = 0; i < num_taps; i++) { + if(tap_codes[i] == ZYNQ_DAP_ID){ + break; + } + } + + if(i == num_taps) + { + retval = 1; + } + + + if (tap_codes){ + free(tap_codes); + } + return retval; + +do_deinit: + if (g_port != NULL) + js_close_port(g_port); + + js_deinit_server(g_js); + + return retval; +} + +/****************************************************************************/ +/** +* +* This function implements the BBRAM algorithm initialization +* +* @param BBRAM instance pointer +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note +* +*****************************************************************************/ +int Bbram_Init(XilSKey_Bbram *InstancePtr) +{ + u8 IRCaptureStatus = 0; + u8 WriteBuffer[4]; + unsigned long long Time = 0; + + jtag_navigate (g_port, JS_RESET); + jtag_navigate (g_port, JS_IDLE); + + /* Load bypass */ + jtag_setPreAndPostPads (g_port, IRHEADER, IRTRAILER, + DRHEADER, DRTRAILER); + WriteBuffer[0] = BYPASS; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRLENGTH, WriteBuffer, + NULL, JS_IDLE); + + /* + * Load JPROGRAM + */ + jtag_setPreAndPostPads (g_port, IRHEADER, IRTRAILER, + DRHEADER, DRTRAILER); + WriteBuffer[0] = JPROGRAM; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRLENGTH, WriteBuffer, + NULL, JS_IDLE); + + /* + * Load ISC_NOOP + */ + WriteBuffer[0] = ISC_NOOP; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRLENGTH, WriteBuffer, + NULL, JS_IDLE); + + /* + * Wait 100 msec + */ + Time = 0; + + XilSKey_Efuse_SetTimeOut(&Time, TIMER_100MS); + while(1){ + if(XilSKey_Efuse_IsTimerExpired(Time) == 1) + break; + } + + /* + * Load ISC_NOOP + */ + WriteBuffer[0] = ISC_NOOP; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRLENGTH, WriteBuffer, + &IRCaptureStatus, JS_IDLE); + + /* + * Read IRCapture status and check for init_complete bit to be set + */ + if((IRCaptureStatus & INITCOMPLETEMASK) != INITCOMPLETEMASK){ + return XST_FAILURE; + } + + return XST_SUCCESS; + +} + +/****************************************************************************/ +/** +* +* This function implements the BBRAM program key +* +* @param BBRAM instance pointer +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note +* +*****************************************************************************/ +int Bbram_ProgramKey(XilSKey_Bbram *InstancePtr) +{ + u32 KeyCnt; + u8 WriteBuffer[4]; + u8 TckCnt; + + /* + * Initial state - RTI + */ + jtag_navigate (g_port, JS_IDLE); + + /* + * Load ISC_ENABLE + */ + jtag_setPreAndPostPads (g_port, IRHEADER, IRTRAILER, + DRHEADER, DRTRAILER); + WriteBuffer[0] = ISC_ENABLE; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRLENGTH, WriteBuffer, + NULL, JS_IRPAUSE); + + /* + * Shift 5 bits (0x15) + */ + WriteBuffer[0] = DR_EN; + jtag_shift (g_port, ATOMIC_DR_SCAN, DRLENGTH_EN, WriteBuffer, + NULL, JS_IDLE); + + /* + * Wait 12 TCK + */ + for(TckCnt = 0; TckCnt < 12; TckCnt++){ + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + } + + /* + * Load ISC_PROGRAM_KEY + */ + WriteBuffer[0] = ISC_PROGRAM_KEY; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRLENGTH, WriteBuffer, + NULL, JS_IRPAUSE); + + /* + * Shift 0xFFFFFFFF + */ + WriteBuffer[0] = 0xFF; + WriteBuffer[1] = 0xFF; + WriteBuffer[2] = 0xFF; + WriteBuffer[3] = 0xFF; + jtag_shift (g_port, ATOMIC_DR_SCAN, DRLENGTH_PROGRAM, + &WriteBuffer[0], NULL, JS_IDLE); + + /* + * Wait 9 TCK + */ + for(TckCnt = 0; TckCnt < 9; TckCnt++){ + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + } + + /* + * Load ISC_PROGRAM + */ + WriteBuffer[0] = ISC_PROGRAM; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRLENGTH, WriteBuffer, + NULL, JS_IRPAUSE); + + /* + * Shift 0xFFFFFFFF + */ + WriteBuffer[0] = 0xFF; + WriteBuffer[1] = 0xFF; + WriteBuffer[2] = 0xFF; + WriteBuffer[3] = 0xFF; + jtag_shift (g_port, ATOMIC_DR_SCAN, DRLENGTH_PROGRAM, + &WriteBuffer[0], NULL, JS_IDLE); + + /* + * Wait 1 TCK + */ + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + + /* + * Program key - 32 bits at a time + */ + KeyCnt = 0; + while(KeyCnt < NUMCHARINKEY){ + /* + * Load ISC_PROGRAM + */ + WriteBuffer[0] = ISC_PROGRAM; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRLENGTH, WriteBuffer, + NULL, JS_IRPAUSE); + + /* + * Copy key from Instance structure + */ + WriteBuffer[3] = InstancePtr->AESKey[KeyCnt++]; + WriteBuffer[2] = InstancePtr->AESKey[KeyCnt++]; + WriteBuffer[1] = InstancePtr->AESKey[KeyCnt++]; + WriteBuffer[0] = InstancePtr->AESKey[KeyCnt++]; + + /* + * Shift 32 bit key + */ + jtag_shift (g_port, ATOMIC_DR_SCAN, DRLENGTH_PROGRAM, + &WriteBuffer[0], NULL, JS_IDLE); + + /* + * Wait 1 TCK + */ + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + } + + /* + * Reset to IDLE + */ + jtag_navigate (g_port, JS_IDLE); + + return XST_SUCCESS; + +} + +/****************************************************************************/ +/** +* +* This function implements the BBRAM verify key. +* Program and verify key have to be done together; +* These API's cannot be used independently. +* +* @param BBRAM instance pointer +* +* @return +* +* - XST_FAILURE - In case of failure +* - XST_SUCCESS - In case of Success +* +* +* @note +* +*****************************************************************************/ +int Bbram_VerifyKey(XilSKey_Bbram *InstancePtr) +{ + u32 KeyCnt; + u32 BufferCnt; + u32 KeyCnt_Char; + u32 ReadKey_Char; + u8 WriteBuffer[5]; + u8 ReadBuffer[5]; + u8 TckCnt; + unsigned long long DataReg = 0; + int Status = XST_SUCCESS; + + /* + * Initial state - RTI + */ + jtag_navigate (g_port, JS_IDLE); + + jtag_setPreAndPostPads (g_port, IRHEADER, IRTRAILER, + DRHEADER, DRTRAILER); + /* + * Load ISC_ENABLE + */ + WriteBuffer[0] = ISC_ENABLE; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRLENGTH, WriteBuffer, + NULL, JS_IRPAUSE); + + /* + * Shift 5 bits (0x15) + */ + WriteBuffer[0] = DR_EN; + jtag_shift (g_port, ATOMIC_DR_SCAN, DRLENGTH_EN, WriteBuffer, + NULL, JS_IDLE); + + /* + * Wait 12 TCK + */ + for(TckCnt = 0; TckCnt < 12; TckCnt++){ + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + } + + /* + * Load ISC_READ + */ + WriteBuffer[0] = ISC_READ; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRLENGTH, WriteBuffer, + NULL, JS_IRPAUSE); + + /* + * Shift 0x1FFFFFFFFF + */ + WriteBuffer[0] = 0xFF; + WriteBuffer[1] = 0xFF; + WriteBuffer[2] = 0xFF; + WriteBuffer[3] = 0xFF; + WriteBuffer[4] = 0x1F; + + /* + * Clear Read Buffer + */ + for(BufferCnt = 0; BufferCnt < 5; BufferCnt++){ + ReadBuffer[BufferCnt] = 0xFF; + } + + /* + * Shift 37 bits and read 37 bits + */ + + jtag_shift (g_port, ATOMIC_DR_SCAN, DRLENGTH_VERIFY, + WriteBuffer, ReadBuffer, JS_IDLE); + + /* + * Combine read bits + */ + DataReg = ReadBuffer[4]; + DataReg = DataReg << 8; + DataReg = DataReg | ReadBuffer[3]; + DataReg = DataReg << 8; + DataReg = DataReg | ReadBuffer[2]; + DataReg = DataReg << 8; + DataReg = DataReg | ReadBuffer[1]; + DataReg = DataReg << 8; + DataReg = DataReg | ReadBuffer[0]; + + if((DataReg & DATAREGCLEAR) != DATAREGCLEAR){ + return XST_FAILURE; + } + + /* + * Wait 9 TCK + */ + for(TckCnt = 0; TckCnt < 9; TckCnt++){ + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + } + + /* + * Shift 37 bits for each 32 bits of key to be read. + * Consider 32 msb bits of the 37 bits read as key. + */ + KeyCnt = 0; + while(KeyCnt < NUMWORDINKEY){ + /* + * Load ISC_READ + */ + WriteBuffer[0] = ISC_READ; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRLENGTH, WriteBuffer, + NULL, JS_IRPAUSE); + + WriteBuffer[0] = 0xFF; + WriteBuffer[1] = 0xFF; + WriteBuffer[2] = 0xFF; + WriteBuffer[3] = 0xFF; + WriteBuffer[4] = 0x1F; + /* + * Clear Read Buffer + */ + for(BufferCnt = 0; BufferCnt < 5; BufferCnt++){ + ReadBuffer[BufferCnt] = 0; + } + + /* + * Shift 37 bits and read 37 bits + */ + jtag_shift (g_port, ATOMIC_DR_SCAN, DRLENGTH_VERIFY, + WriteBuffer, ReadBuffer, JS_IDLE); + + /* + * Wait 1 TCK + */ + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + + /* + * Combine the 8 bit array and shift out the 5 LSB bits + */ + DataReg = ReadBuffer[4]; + DataReg = DataReg << 8; + DataReg = DataReg | ReadBuffer[3]; + DataReg = DataReg << 8; + DataReg = DataReg | ReadBuffer[2]; + DataReg = DataReg << 8; + DataReg = DataReg | ReadBuffer[1]; + DataReg = DataReg << 8; + DataReg = DataReg | ReadBuffer[0]; + + Bbram_ReadKey[KeyCnt++] = DataReg >> NUMLSBSTATUSBITS; + + } + + /* + * Compare read key with programmed key + */ + KeyCnt_Char = 0; + for(KeyCnt = 0; KeyCnt < NUMWORDINKEY; KeyCnt++){ + + ReadKey_Char = Bbram_ReadKey[KeyCnt]; + + if((ReadKey_Char & 0xFF) != + InstancePtr->AESKey[KeyCnt_Char + 3]){ + Status = XST_FAILURE; + break; + } + + ReadKey_Char = ReadKey_Char >> 8; + if((ReadKey_Char & 0xFF) != + InstancePtr->AESKey[KeyCnt_Char + 2]){ + Status = XST_FAILURE; + break; + } + + ReadKey_Char = ReadKey_Char >> 8; + if((ReadKey_Char & 0xFF) != + InstancePtr->AESKey[KeyCnt_Char + 1]){ + Status = XST_FAILURE; + break; + } + + ReadKey_Char = ReadKey_Char >> 8; + if((ReadKey_Char & 0xFF) != + InstancePtr->AESKey[KeyCnt_Char]){ + Status = XST_FAILURE; + break; + } + + KeyCnt_Char = KeyCnt_Char + 4; + } + + /* + * Load ISC_DISABLE + */ + WriteBuffer[0] = ISC_DISABLE; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRLENGTH, WriteBuffer, + NULL, JS_IDLE); + + /* + * Wait 12 TCK + */ + for(TckCnt = 0; TckCnt < 12; TckCnt++){ + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + } + + return Status; + +} + +/****************************************************************************/ +/** +* +* This function does de-initialization +* +* @param none +* +* @return +* +* none +* +* +* @note +* +*****************************************************************************/ +void Bbram_DeInit(void) +{ + u8 WriteBuffer[5]; + + /* + * Load BYPASS + */ + jtag_setPreAndPostPads (g_port, IRHEADER_BYP, IRTRAILER_BYP, + DRHEADER_BYP, DRTRAILER_BYP); + + WriteBuffer[0] = BYPASS; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRLENGTH, WriteBuffer, + NULL, JS_IDLE); + + WriteBuffer[0] = IRDEINIT_L; + WriteBuffer[1] = IRDEINIT_H; + jtag_shift (g_port, ATOMIC_IR_SCAN, IRDEINITLEN, WriteBuffer, + NULL, JS_IDLE); + + WriteBuffer[0] = DRDEINIT; + jtag_shift (g_port, ATOMIC_DR_SCAN, DRDEINITLEN, WriteBuffer, + NULL, JS_IDLE); + + jtag_navigate (g_port, JS_RESET); + jtag_navigate (g_port, JS_IDLE); + + /* + * De-initialization + */ + if (g_port != NULL){ + js_close_port(g_port); + } + + js_deinit_server(g_js); + +} \ No newline at end of file diff --git a/lib/sw_services/xilskey/src/xilskey_jscmd.h b/lib/sw_services/xilskey/src/xilskey_jscmd.h new file mode 100644 index 00000000..0bf73228 --- /dev/null +++ b/lib/sw_services/xilskey/src/xilskey_jscmd.h @@ -0,0 +1,166 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#ifndef XILSKEY_JSCMD_H +#define XILSKEY_JSCMD_H + +#include "xilskey_js.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern js_server_t *js_init_zynq(void); +void initGPIO (); +int jtag_setPreAndPostPads (js_port_t *port_arg, int irPrePadBits, int irPostPadBits, int drPrePadBits, int drPostPadBits); +int jtag_navigate (js_port_t *port, js_state_t state); +int jtag_shift (js_port_t *port, unsigned char mode, int bits, unsigned char* wrBuffer, unsigned char* rdBuffer, js_state_t state); +unsigned int g_mio_jtag_tdi; +unsigned int g_mio_jtag_tdo; +unsigned int g_mio_jtag_tck; +unsigned int g_mio_jtag_tms; +unsigned int g_mio_jtag_mux_sel; +unsigned int g_mux_sel_def_val; + +// MIO assignments +#define MIO_TDI g_mio_jtag_tdi +#define MIO_TDO g_mio_jtag_tdo +#define MIO_TCK g_mio_jtag_tck +#define MIO_TMS g_mio_jtag_tms +#define MIO_MUX_SELECT g_mio_jtag_mux_sel + +#define ZYNQ_TAP_IR_LENGTH (6) +#define ZYNQ_DAP_IR_LENGTH (4) + +#define ATOMIC_DR_SCAN 0x40 +#define ATOMIC_IR_SCAN 0x50 + +#define GPIO_BASE_ADDR 0xF8000700 +#define GPIO_MASK_VAL 0x00003FFFU +#define GPIO_TDI_VAL 0x00001300U +#define GPIO_TDO_VAL 0x00001301U +#define GPIO_TCK_VAL 0x00001300U +#define GPIO_TMS_VAL 0x00001300U +#define GPIO_MUX_SEL_VAL 0x00001300U + +/** + * XEfusePl is the PL eFUSE driver instance. Using this + * structure, user can define the eFUSE bits to be + * blown. + */ +typedef struct { + /** + * Following are the FUSE CNTRL bits[1:5, 8-10] + */ + + /** + * If XTRUE then part has to be power cycled to be able to be reconfigured + */ + u32 ForcePowerCycle; + /** + * If XTRUE will disable eFUSE write to FUSE_AES and FUSE_USER blocks + */ + u32 KeyWrite; + /** + * If XTRUE will disable eFUSE read to FUSE_AES block and also disables eFUSE write to FUSE_AES and FUSE_USER blocks + */ + u32 AESKeyRead; + /** + * If XTRUE will disable eFUSE read to FUSE_USER block and also disables eFUSE write to FUSE_AES and FUSE_USER blocks + */ + u32 UserKeyRead; + /** + * If XTRUE will disable eFUSE write to FUSE_CNTRL block + */ + u32 CtrlWrite; + /** + * If XTRUE will force eFUSE key to be used if booting Secure Image + */ + u32 AESKeyExclusive; + /** + * If XTRUE then permanently sets the Zynq ARM DAP controller in bypass mode + */ + u32 JtagDisable; + /** + * If XTRUE will force to use Secure boot with eFUSE key only + */ + u32 UseAESOnly; + /** + * Following is the define to select if the user wants to select AES key and USER low key OR USER high key or BOTH + */ + u32 ProgAESandUserLowKey; + u32 ProgUserHighKey; + + /** + * This is the REF_CLK value in Hz + */ + /*u32 RefClk;*/ + /** + * This is for the aes_key value + */ + u8 AESKey[XSK_EFUSEPL_AES_KEY_SIZE_IN_BYTES]; + /** + * This is for the user_key value + */ + u8 UserKey[XSK_EFUSEPL_USER_KEY_SIZE_IN_BYTES]; + /** + * TDI MIO Pin Number + */ + u32 JtagMioTDI; + /** + * TDO MIO Pin Number + */ + u32 JtagMioTDO; + /** + * TCK MIO Pin Number + */ + u32 JtagMioTCK; + /** + * TMS MIO Pin Number + */ + u32 JtagMioTMS; + /** + * MUX Selection MIO Pin Number + */ + u32 JtagMioMuxSel; + /** + * Value on the MUX Selection line + */ + u32 JtagMuxSelLineDefVal; + +}XilSKey_EPl; + +#ifdef __cplusplus +} +#endif + +#endif /*XILSKEY_JSCMD_H*/ diff --git a/lib/sw_services/xilskey/src/xilskey_jslib.c b/lib/sw_services/xilskey/src/xilskey_jslib.c new file mode 100644 index 00000000..1bdd6c5f --- /dev/null +++ b/lib/sw_services/xilskey/src/xilskey_jslib.c @@ -0,0 +1,441 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#include +#include +#include +#include +#include "xilskey_jslib.h" + +#define MAX_TAPS 16 + + +js_lib_state_info_t js_lib_state_info[] = { + /* JS_RESET */ + { + "reset", + { 0x01, 0x00, 0x02, 0x0a, 0x06, 0x16 }, + { 1, 1, 4, 5, 5, 6 }, + JS_RESET + }, + + /* JS_IDLE */ + { + "idle", + { 0x07, 0x00, 0x01, 0x05, 0x03, 0x0b }, + { 3, 1, 3, 4, 4, 5 }, + JS_IDLE + }, + + /* JS_SHIFT_DR */ + { + "shift dr", + { 0x1f, 0x03, 0x05, 0x01, 0x0f, 0x2f }, + { 5, 3, 4, 2, 6, 7 }, + JS_DRPAUSE + }, + + /* JS_PAUSE_DR */ + { + "pause dr", + { 0x1f, 0x03, 0x01, 0x00, 0x0f, 0x2f }, + { 5, 3, 2, 1, 6, 7 }, + JS_DRPAUSE + }, + + /* JS_SHIFT_IR */ + { + "shift ir", + { 0x1f, 0x03, 0x07, 0x01, 0x05, 0x01 }, + { 5, 4, 5, 6, 4, 2 }, + JS_IRPAUSE + }, + + /* JS_PAUSE_IR */ + { + "pause ir", + { 0x1f, 0x03, 0x07, 0x17, 0x01, 0x00 }, + { 5, 3, 5, 6, 2, 1 }, + JS_IRPAUSE + } +}; + + +const char *js_get_last_error( + js_server_t *server) +{ + js_lib_server_t *js = (js_lib_server_t *)server; + + if (js->last_error[0] == '\0') + return NULL; + return js->last_error; +} + + +void js_set_last_error( + js_server_t *server, + const char *fmt, + ...) +{ + js_lib_server_t *js = (js_lib_server_t *)server; + va_list ap; + + va_start(ap, fmt); + vsnprintf(js->last_error, sizeof js->last_error, fmt, ap); + va_end(ap); +} + + +js_command_sequence_t *js_create_command_sequence( + js_node_t *node) +{ + js_lib_command_sequence_t *cmds; + + cmds = (js_lib_command_sequence_t *)malloc(sizeof *cmds); + if (cmds == NULL) + return NULL; + memset(cmds, 0, sizeof *cmds); + cmds->base.node = node; + cmds->cmd_size = sizeof *cmds->cmd_list; + return &cmds->base; +} + + +static void free_buffers( + js_lib_command_buffer_t *buf) +{ + while (buf != NULL) { + js_lib_command_buffer_t *next = buf->next; + free(buf); + buf = next; + } +} + + +int js_clear_command_sequence( + js_command_sequence_t *cmdseq) +{ + js_lib_command_sequence_t *cmds = (js_lib_command_sequence_t *)cmdseq; + js_lib_command_buffer_t *buf = cmds->buf_head; + + cmds->cmd_count = 0; + if (buf) { + /* Free all buffers except to first one. Keep the first one + * since it is the larges and can be reused for future + * commands */ + free_buffers(buf->next); + buf->next = NULL; + buf->buf_free = buf->buf_start; + } + return 0; +} + + +int js_delete_command_sequence( + js_command_sequence_t *cmdseq) +{ + js_lib_command_sequence_t *cmds = (js_lib_command_sequence_t *)cmdseq; + if (cmds->cmd_list) + free(cmds->cmd_list); + free_buffers(cmds->buf_head); + free(cmds); + return 0; +} + + +static js_lib_command_t *get_command( + js_lib_command_sequence_t *cmds) +{ + js_lib_command_t *list = cmds->cmd_list; + unsigned int count = cmds->cmd_count; + + assert(cmds->cmd_size >= sizeof *list); + if (count == cmds->cmd_max) { + unsigned int max = count ? count * 2 : 1; + list = (js_lib_command_t *)realloc(list, max * cmds->cmd_size); + if (list == NULL) { + js_set_last_error(cmds->base.node->port->server, "end of memory"); + return NULL; + } + cmds->cmd_list = list; + cmds->cmd_max = max; + } + cmds->cmd_count = count + 1; + return (js_lib_command_t *)((char *)list + count * cmds->cmd_size); +} + + +int js_add_state_change( + js_command_sequence_t *cmdseq, + js_state_t state, + unsigned int clocks) +{ + js_lib_command_sequence_t *cmds = (js_lib_command_sequence_t *)cmdseq; + js_lib_command_t *cmd = get_command(cmds); + if (cmd == NULL) + return -1; + if (clocks != 0 && js_lib_state_info[state].stable_state != state) { + js_set_last_error(cmds->base.node->port->server, "non zero clocks in unstable state"); + return -1; + } + cmd->kind = JS_CMD_SET_STATE; + cmd->state = state; + cmd->count = clocks; + cmd->tdi_buf = NULL; + cmd->tdo_buf = NULL; + return 0; +} + + +static unsigned char *get_buffer( + js_lib_command_sequence_t *cmds, + size_t size) +{ + js_lib_command_buffer_t *buf = cmds->buf_head; + unsigned char *ret; + + assert(buf == NULL || buf->buf_start <= buf->buf_free); + assert(buf == NULL || buf->buf_free < buf->buf_end); + if (buf == NULL || buf->buf_free + size > buf->buf_end) { + size_t buf_size = buf ? buf->buf_end - buf->buf_start : 1; + while (buf_size < size * 2) + buf_size *= 2; + buf = (js_lib_command_buffer_t *)malloc(buf_size + sizeof *buf); + if (buf == NULL) + return NULL; + buf->buf_free = buf->buf_start; + buf->buf_end = buf->buf_start + buf_size; + buf->next = cmds->buf_head; + cmds->buf_head = buf; + } + ret = buf->buf_free; + buf->buf_free += size; + return ret; +} + + +int js_add_shift( + js_command_sequence_t *cmdseq, + unsigned int flags, + size_t bits, + unsigned char **tdi_buffer, + unsigned char **tdo_buffer, + js_state_t state) +{ + js_lib_command_sequence_t *cmds = (js_lib_command_sequence_t *)cmdseq; + js_lib_command_t *cmd = get_command(cmds); + if (cmd == NULL) + return -1; + if (bits <= 0) { + js_set_last_error(cmds->base.node->port->server, "bits argument must be > 0"); + return -1; + } + cmd->kind = JS_CMD_SHIFT; + cmd->flags = flags; + cmd->state = state; + cmd->count = bits; + if (tdi_buffer != NULL) { + *tdi_buffer = cmd->tdi_buf = get_buffer(cmds, (bits + 7) / 8 + 2); + } else { + cmd->tdi_buf = NULL; + } + if (tdo_buffer != NULL) { + *tdo_buffer = cmd->tdo_buf = get_buffer(cmds, (bits + 7) / 8 + 2); + } else { + cmd->tdo_buf = NULL; + } + return 0; +} + + +int js_detect_taps( + js_port_t *port, + uint32_t **resultp) +{ + js_command_sequence_t *cmds; + unsigned char *dummycodes; + unsigned char *idcodes; + uint32_t *result = NULL; + int max = 0; + int ind = 0; + int i; + + cmds = js_create_command_sequence(port->root_node); + if (cmds == NULL) + return -1; + + if (js_add_state_change(cmds, JS_RESET, 0) < 0 || + js_add_shift(cmds, 0, MAX_TAPS * 4 * 8, &dummycodes, &idcodes, JS_IDLE) < 0) + goto return_error; + + for (i = 0; i < MAX_TAPS; i += 4) { + dummycodes[i+0] = (JS_DUMMY_IDCODE) & 0xff; + dummycodes[i+1] = (JS_DUMMY_IDCODE >> 8) & 0xff; + dummycodes[i+2] = (JS_DUMMY_IDCODE >> 16) & 0xff; + dummycodes[i+3] = (JS_DUMMY_IDCODE >> 24) & 0xff; + } + + if (js_run_command_sequence(cmds) < 0) + goto return_error; + + i = 0; + while (i < MAX_TAPS * 4 * 8) { + int lsb = (idcodes[i / 8] >> (i % 8)) & 1; + uint32_t idcode; + if (lsb) { + int j; + idcode = lsb; + i++; + for (j = 1; j < 32; j++) { + lsb = (idcodes[i / 8] >> (i % 8)) & 1; + idcode |= (uint32_t)lsb << j; + i++; + } + if (idcode == JS_DUMMY_IDCODE) + break; + } else { + /* TAP in BYPASS mode */ + idcode = JS_DUMMY_IDCODE; + i++; + } + + if (ind == max) { + uint32_t *new_result; + max = max ? max * 2 : 1; + new_result = (uint32_t *)realloc(result, max * sizeof *result); + if (new_result == NULL) { + free(result); + goto return_error; + } + result = new_result; + } + result[ind++] = idcode; + } + js_delete_command_sequence(cmds); + *resultp = result; + return ind; + +return_error: + js_delete_command_sequence(cmds); + return -1; +} + + +int js_get_port_descr_list( + js_server_t *server, + js_port_descr_t **port_listp) +{ + js_lib_server_t *js = (js_lib_server_t *)server; + + return js->get_port_descr_list(js, port_listp); +} + + +int js_open_port( + js_server_t *server, + js_port_descr_t *port_descr, + js_port_t **port) +{ + js_lib_server_t *js = (js_lib_server_t *)server; + js_lib_port_t *result; + int ret; + + ret = js->open_port(js, port_descr, &result); + *port = (js_port_t *)result; + return ret; +} + + +void js_deinit_server( + js_server_t *server) +{ + js_lib_server_t *js = (js_lib_server_t *)server; + + return js->deinit_server(js); +} + + +int js_get_property( + js_port_t *port_arg, + js_property_kind_t kind, + js_property_value_t *valuep) +{ + js_lib_port_t *port = (js_lib_port_t *)port_arg; + + return port->get_property(port, kind, valuep); +} + + +int js_set_property( + js_port_t *port_arg, + js_property_kind_t kind, + js_property_value_t value) +{ + js_lib_port_t *port = (js_lib_port_t *)port_arg; + + return port->set_property(port, kind, value); +} + + +int js_run_command_sequence( + js_command_sequence_t *commands) +{ + js_lib_command_sequence_t *cmds = (js_lib_command_sequence_t *)commands; + js_lib_port_t *port = (js_lib_port_t *)commands->node->port; + + return port->run_command_sequence(cmds); +} + + +int js_close_port( + js_port_t *port_arg) +{ + js_lib_port_t *port = (js_lib_port_t *)port_arg; + + return port->close_port(port); +} + + +int js_lib_normalize_command_sequence( + js_lib_command_sequence_t *dest_seq, + js_lib_command_sequence_t *src_seq) +{ + js_lib_command_t *src_cmd = src_seq->cmd_list; + js_lib_command_t *src_end = src_cmd + src_seq->cmd_count; + + while (src_cmd < src_end) { + js_lib_command_t *new_cmd = get_command(dest_seq); + *new_cmd = *src_cmd; + src_cmd++; + } + return 0; +} diff --git a/lib/sw_services/xilskey/src/xilskey_jslib.h b/lib/sw_services/xilskey/src/xilskey_jslib.h new file mode 100644 index 00000000..7a1b03a0 --- /dev/null +++ b/lib/sw_services/xilskey/src/xilskey_jslib.h @@ -0,0 +1,219 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/* + * JTAG server implementation library interface + * + * This library interface is intended to be use by JTAG server + * implementations only, i.e. not used by JTAG server clients. + */ + +#include "xilskey_js.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct js_lib_server_struct js_lib_server_t; +typedef struct js_lib_port_struct js_lib_port_t; +typedef struct js_lib_command_sequence_struct js_lib_command_sequence_t; +typedef struct js_lib_command_struct js_lib_command_t; +typedef struct js_lib_command_buffer_struct js_lib_command_buffer_t; +typedef struct js_lib_state_info_struct js_lib_state_info_t; + + + +/* + * JTAG server object + * + * Server instances are created by implementation specific create + * functions, typically named js_create_. + * + * TODO: Add a way to schedule a command sequence to be repeated at + * regular intervals. This is useful to poll for events, like + * breakpoint hit. + */ +struct js_server_struct { + char dummy; +}; + + +/* + * JTAG server library object + */ +struct js_lib_server_struct { + /* Public part of object */ + js_server_t base; + + /* See js_get_port_descr_list() */ + int (*get_port_descr_list)( + js_lib_server_t *server, + js_port_descr_t **port_listp); + + /* See js_open_port() */ + int (*open_port)( + js_lib_server_t *server, + js_port_descr_t *port_descr, + js_lib_port_t **port); + + /* See js_deinit_server() */ + void (*deinit_server)( + js_lib_server_t *server); + + /* Error of last command */ + char last_error[100]; +}; + +struct js_lib_port_struct { + /* Base class - must be first. */ + js_port_t base; + + /* See js_get_property() */ + int (*get_property)( + js_lib_port_t *port, + js_property_kind_t kind, + js_property_value_t *valuep); + + /* See js_set_property() */ + int (*set_property)( + js_lib_port_t *port, + js_property_kind_t kind, + js_property_value_t value); + + /* See js_run_command_sequence() */ + int (*run_command_sequence)( + js_lib_command_sequence_t *commands); + + /* See js_close_port() */ + int (*close_port)( + js_lib_port_t *port); +}; + + +struct js_lib_command_buffer_struct { + js_lib_command_buffer_t *next; + + /* First available byte in buffer */ + unsigned char *buf_free; + + /* End of buffer */ + unsigned char *buf_end; + + /* Start of buffer (must be last) */ + unsigned char buf_start[1]; +}; + + +/* + * JTAG command sequence library object + */ +struct js_lib_command_sequence_struct { + /* Client visible part */ + js_command_sequence_t base; + + /* Array of commands */ + js_lib_command_t *cmd_list; + + /* Count of added commands */ + unsigned int cmd_count; + + /* Command list capacity */ + unsigned int cmd_max; + + /* Size of command objects */ + unsigned int cmd_size; + + /* Command buffer pool */ + js_lib_command_buffer_t *buf_head; +}; + + +/* + * JTAG command object + * + * Command object are added to JTAG command sequence object using + * js_add_* functions. + * + * TODO: Add commands to get/set GPIO pins, conditional execution and + * loops. + */ +typedef enum { + JS_CMD_SET_STATE, + JS_CMD_SHIFT +} js_command_kind_t; + +struct js_lib_command_struct { + /* Command to execute */ + js_command_kind_t kind; + + /* Flags for command */ + unsigned int flags; + + /* State after command */ + js_state_t state; + + /* Command specific count */ + size_t count; + + /* TDI buffer pointer */ + unsigned char *tdi_buf; + + /* TDO buffer pointer */ + unsigned char *tdo_buf; +}; + + +struct js_lib_state_info_struct { + /* Name of state */ + const char *name; + + /* TMS bits to move to other state */ + unsigned char state_tms[JS_STATE_MAX]; + + /* Clocks to move to other state */ + unsigned char state_clk[JS_STATE_MAX]; + + /* Nearest stable state */ + js_state_t stable_state; +}; + + +extern js_lib_state_info_t js_lib_state_info[JS_STATE_MAX]; + +extern int js_lib_normalize_command_sequence( + js_lib_command_sequence_t *dest, + js_lib_command_sequence_t *src); + +#ifdef __cplusplus +} +#endif diff --git a/lib/sw_services/xilskey/src/xilskey_jtag.h b/lib/sw_services/xilskey/src/xilskey_jtag.h new file mode 100644 index 00000000..de994267 --- /dev/null +++ b/lib/sw_services/xilskey/src/xilskey_jtag.h @@ -0,0 +1,45 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +#ifndef XILSKEY_JTAG_H +#define XILSKEY_JTAG_H + +#include "xil_types.h" + +void JtagInitGpio(); +void GpioConfig(volatile unsigned long *addr, unsigned long mask, unsigned long val); +int JtagServerInit(XilSKey_EPl *PlInstancePtr); +int JtagValidateMioPins(void); +void JtagWrite(unsigned char row, unsigned char bit); +void JtagRead(unsigned char row, unsigned int * row_data, unsigned char marginOption); + +#endif /*XILSKEY_JTAG_H*/ diff --git a/lib/sw_services/xilskey/src/xilskey_utils.c b/lib/sw_services/xilskey/src/xilskey_utils.c new file mode 100644 index 00000000..dd0cd301 --- /dev/null +++ b/lib/sw_services/xilskey/src/xilskey_utils.c @@ -0,0 +1,775 @@ +/****************************************************************************** +* +* Copyright (C) 2013 - 2014 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. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* 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 +* XILINX CONSORTIUM 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. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** + * @file xilskey_utils.c + * + * + * @note None. + * + * + * MODIFICATION HISTORY: + * +* Ver Who Date Changes +* ----- ---- -------- -------------------------------------------------------- +* 1.00a rpoolla 04/26/13 First release +* 2.00 hk 22/01/14 Corrected PL voltage checks to VCCINT and VCCAUX. +* CR#768077 + * + *****************************************************************************/ + +/***************************** Include Files ********************************/ +#include "xil_io.h" +#include "xil_types.h" +#include "xilskey_utils.h" +/************************** Constant Definitions ****************************/ + +/**************************** Type Definitions ******************************/ + +/***************** Macros (Inline Functions) Definitions ********************/ + +/************************** Variable Definitions ****************************/ +static XAdcPs XAdcInst; /**< XADC driver instance */ +u16 XAdcDeviceId; /**< XADC Device ID */ +u32 TimerTicksfor100ns; /**< Global Variable to store ticks/100ns*/ +/************************** Function Prototypes *****************************/ +static u32 XilSKey_EfusePs_ConvertCharToNibble (char InChar, u8 *Num); +/***************************************************************************/ +/** +* This function is used to initialize the XADC driver +* +* @return +* - XST_SUCCESS in case of no errors. +* - XSK_EFUSEPS_ERROR_XADC_CONFIG Error occurred with XADC config. +* - XSK_EFUSEPS_ERROR_XADC_INITIALIZE Error occurred while XADC initialization +* - XSK_EFUSEPS_ERROR_XADC_SELF_TEST Error occurred in XADC self test. +* +* TDD Cases: +* +****************************************************************************/ + +u32 XilSKey_EfusePs_XAdcInit (void ) +{ + u32 Status; + XAdcPs_Config *ConfigPtr; + XAdcPs *XAdcInstPtr = &XAdcInst; + + /** + * specify the Device ID that is + * generated in xparameters.h + */ + XAdcDeviceId=XADC_DEVICE_ID; + + /** + * Initialize the XAdc driver. + */ + ConfigPtr = XAdcPs_LookupConfig(XAdcDeviceId); + if (NULL == ConfigPtr) { + return XSK_EFUSEPS_ERROR_XADC_CONFIG; + } + + Status = XAdcPs_CfgInitialize(XAdcInstPtr, ConfigPtr, + ConfigPtr->BaseAddress); + if (Status != XST_SUCCESS) { + return XSK_EFUSEPS_ERROR_XADC_INITIALIZE; + } + /** + * Self Test the XADC/ADC device + */ + Status = XAdcPs_SelfTest(XAdcInstPtr); + if (Status != XST_SUCCESS) { + return XSK_EFUSEPS_ERROR_XADC_SELF_TEST; + } + + /** + * Disable the Channel Sequencer before configuring the Sequence + * registers. + */ + XAdcPs_SetSequencerMode(XAdcInstPtr, XADCPS_SEQ_MODE_SAFE); + + return XST_SUCCESS; + +} + +/***************************************************************************/ +/** +* This function is used to copy the min, max and current value of the +* temperature and voltage which are read from XADC. +* +* @param XAdcInstancePtr Pointer to the XSKEfusePs_XAdc. User has to +* fill the VType to specify the type of voltage. Valid values +* for VType are +* - XSK_EFUSEPS_VPINT +* - XSK_EFUSEPS_VPDRO +* - XSK_EFUSEPS_VPAUX +* - XSK_EFUSEPS_VINT +* - XSK_EFUSEPS_VAUX +* +* @return none +* +* TDD Cases: +* +****************************************************************************/ + +void XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(XSKEfusePs_XAdc *XAdcInstancePtr) +{ + XAdcPs *XAdcInstPtr = &XAdcInst; + u8 V, VMin, VMax; + + + if (NULL == XAdcInstPtr) { + return; + } + + /** + * Read the on-chip Temperature Data (Current/Maximum/Minimum) + * from the ADC data registers. + */ + XAdcInstancePtr->Temp = XAdcPs_GetAdcData(XAdcInstPtr, XADCPS_CH_TEMP); + + XAdcInstancePtr->TempMin = + XAdcPs_GetMinMaxMeasurement(XAdcInstPtr, XADCPS_MIN_TEMP); + + XAdcInstancePtr->TempMax = + XAdcPs_GetMinMaxMeasurement(XAdcInstPtr, XADCPS_MAX_TEMP); + + xeFUSE_printf(XSK_EFUSE_DEBUG_GENERAL, + "Read Temperature Value: %0x -> %d in Centigrades \n", + XAdcInstancePtr->Temp, + (int )XAdcPs_RawToTemperature(XAdcInstancePtr->Temp)); + + /** + * Read the VccPint Voltage Data (Current/Maximum/Minimum) from the + * ADC data registers. + */ + + switch (XAdcInstancePtr->VType) + { + case XSK_EFUSEPS_VINT: + V = XADCPS_CH_VCCINT; + VMax = XADCPS_MAX_VCCINT; + VMin = XADCPS_MIN_VCCINT; + break; + + case XSK_EFUSEPS_VAUX: + V = XADCPS_CH_VCCAUX; + VMax = XADCPS_MAX_VCCAUX; + VMin = XADCPS_MIN_VCCAUX; + break; + + case XSK_EFUSEPS_VPAUX: + V = XADCPS_CH_VCCPAUX; + VMax = XADCPS_MAX_VCCPAUX; + VMin = XADCPS_MIN_VCCPAUX; + break; + + case XSK_EFUSEPS_VPDRO: + V = XADCPS_CH_VCCPDRO; + VMax = XADCPS_MAX_VCCPDRO; + VMin = XADCPS_MIN_VCCPDRO; + break; + + case XSK_EFUSEPS_VPINT: + default: + V = XADCPS_CH_VCCPINT; + VMax = XADCPS_MAX_VCCPINT; + VMin = XADCPS_MIN_VCCPINT; + break; + } + + XAdcInstancePtr->V = XAdcPs_GetAdcData(XAdcInstPtr, V); + XAdcInstancePtr->VMin = XAdcPs_GetMinMaxMeasurement(XAdcInstPtr, VMin); + XAdcInstancePtr->VMax = XAdcPs_GetMinMaxMeasurement(XAdcInstPtr, VMax); + + xeFUSE_printf(XSK_EFUSE_DEBUG_GENERAL, + "Read Voltage Value: %0x -> %d in Volts \n", + XAdcInstancePtr->V, + (int )XAdcPs_RawToVoltage(XAdcInstancePtr->V)); + + return; +} + +/****************************************************************************/ +/** +* +* Initializes the global timer & starts it. +* Calculates the timer ticks for 1us. +* +* +* +* @param RefClk - reference clock +* +* @return +* +* None +* +* @note None. +* +*****************************************************************************/ +void XilSKey_Efuse_StartTimer(u32 RefClk) +{ + u32 arm_pll_fdiv,arm_clk_divisor; + TimerTicksfor100ns = 0; + /** + * Extract PLL FDIV value from ARM PLL Control Register + */ + arm_pll_fdiv = (Xil_In32(XSK_ARM_PLL_CTRL_REG)>>12 & 0x7F); + /** + * Extract Clock divisor value from ARM Clock Control Register + */ + arm_clk_divisor = (Xil_In32(XSK_ARM_CLK_CTRL_REG)>>8 & 0x3F); + /** + * Calculate the Timer ticks per 100ns + */ + TimerTicksfor100ns = + (((RefClk * arm_pll_fdiv)/arm_clk_divisor)/2)/10000000; + /** + * Disable the Timer counter + */ + Xil_Out32(XSK_GLOBAL_TIMER_CTRL_REG,0); + /** + * Write the lower 32 bit timer counter register. + */ + Xil_Out32(XSK_GLOBAL_TIMER_COUNT_REG_LOW, 0x0); + /** + * Write the upper 32 bit timer counter register. + */ + Xil_Out32(XSK_GLOBAL_TIMER_COUNT_REG_HIGH, 0x0); + /** + * Enable the Timer counter + */ + Xil_Out32(XSK_GLOBAL_TIMER_CTRL_REG,0x1); +} + +/****************************************************************************/ +/** +* +* Returns the timer ticks from start of timer to till now. +* +* @return +* +* t - Timer ticks lapsed till now. +* +* @note None. +* +*****************************************************************************/ + +u64 XilSKey_Efuse_GetTime(void) +{ + volatile u32 t_hi=0, t_lo=0; + volatile u64 t=0; + do { + t_hi = Xil_In32(XSK_GLOBAL_TIMER_COUNT_REG_HIGH); + t_lo = Xil_In32(XSK_GLOBAL_TIMER_COUNT_REG_LOW); + }while(t_hi != Xil_In32(XSK_GLOBAL_TIMER_COUNT_REG_HIGH)); + + t = (((u64) t_hi) << 32) | (u64) t_lo; + return t; +} +/****************************************************************************/ +/** +* +* Calculates the timer ticks to wait to set the time out +* +* @param t - timer ticks to wait to set the timeout +* @param us - Timeout period in us +* +* +* @return +* t - timer ticks to wait to set the timeout +* +* @note None. +* +*****************************************************************************/ +void XilSKey_Efuse_SetTimeOut(volatile u64* t, u64 us) +{ + volatile u64 t_end; + t_end = XilSKey_Efuse_GetTime(); + /** + * us: time to wait in microseconds. Convert to clock ticks and + * add to current time. + */ + t_end += (us * TimerTicksfor100ns); + *t = t_end; +} + +/****************************************************************************/ +/** +* +* Checks whether the timer has been expired or not +* +* @param t - timeout value in us +* +* @return +* +* t_end - Returns the global timer value in case of timer expired +* +* @note None. +* +*****************************************************************************/ + +u8 XilSKey_Efuse_IsTimerExpired(u64 t) +{ + u64 t_end; + t_end = XilSKey_Efuse_GetTime(); + return t_end >= t; +} + +/****************************************************************************/ +/** + * Converts the char into the equivalent nibble. + * Ex: 'a' -> 0xa, 'A' -> 0xa, '9'->0x9 + * + * @param InChar is input character. It has to be between 0-9,a-f,A-F + * @param Num is the output nibble. + * @return + * - XST_SUCCESS no errors occured. + * - XST_FAILURE an error when input parameters are not valid + ****************************************************************************/ +static u32 XilSKey_EfusePs_ConvertCharToNibble (char InChar, u8 *Num) +{ + /** + * Convert the char to nibble + */ + if ((InChar >= '0') && (InChar <= '9')) + *Num = InChar - '0'; + else if ((InChar >= 'a') && (InChar <= 'f')) + *Num = InChar - 'a' + 10; + else if ((InChar >= 'A') && (InChar <= 'F')) + *Num = InChar - 'A' + 10; + else + return XSK_EFUSEPS_ERROR_STRING_INVALID; + + return XST_SUCCESS; +} + +/****************************************************************************/ +/** + * Converts the string into the equivalent Hex buffer. + * Ex: "abc123" -> {0xab, 0xc1, 0x23} + * + * @param Str is a Input String. Will support the lower and upper case values. + * Value should be between 0-9, a-f and A-F + * + * @param Buf is Output buffer. + * @param Len of the input string. Should have even values + * @return + * - XST_SUCCESS no errors occured. + * - XST_FAILURE an error when input parameters are not valid + * - an error when input buffer has invalid values + * + * TDD Test Cases: + ---Initialization--- + Len is odd + Len is zero + Str is NULL + Buf is NULL + ---Functionality--- + Str input with only numbers + Str input with All values in A-F + Str input with All values in a-f + Str input with values in a-f, 0-9, A-F + Str input with values in a-z, 0-9, A-Z + Boundary Cases + Memory Bounds of buffer checking + ****************************************************************************/ + +u32 XilSKey_Efuse_ConvertStringToHexBE(const char * Str, u8 * Buf, u32 Len) +{ + u32 ConvertedLen=0; + u8 LowerNibble, UpperNibble; + + /** + * Check the parameters + */ + if (Str == NULL) + return XSK_EFUSEPS_ERROR_PARAMETER_NULL; + + if (Buf == NULL) + return XSK_EFUSEPS_ERROR_PARAMETER_NULL; + + /** + * Len has to be multiple of 2 + */ + if ((Len == 0) || (Len%2 == 1)) + return XSK_EFUSEPS_ERROR_PARAMETER_NULL; + + ConvertedLen = 0; + while (ConvertedLen < Len) { + /** + * Convert char to nibble + */ + if (XilSKey_EfusePs_ConvertCharToNibble (Str[ConvertedLen],&UpperNibble) + ==XST_SUCCESS) { + /** + * Convert char to nibble + */ + if (XilSKey_EfusePs_ConvertCharToNibble (Str[ConvertedLen+1], + &LowerNibble)==XST_SUCCESS) { + /** + * Merge upper and lower nibble to Hex + */ + Buf[ConvertedLen/2] = + (UpperNibble << 4) | LowerNibble; + } + else { + /** + * Error converting Lower nibble + */ + return XSK_EFUSEPS_ERROR_STRING_INVALID; + } + } + else { + /** + * Error converting Upper nibble + */ + return XSK_EFUSEPS_ERROR_STRING_INVALID; + } + /** + * Converted upper and lower nibbles + */ + xeFUSE_printf(XSK_EFUSE_DEBUG_GENERAL,"Converted %c%c to %0x\n", + Str[ConvertedLen],Str[ConvertedLen+1],Buf[ConvertedLen/2]); + ConvertedLen += 2; + } + + return XST_SUCCESS; +} + + +/****************************************************************************/ +/** + * Converts the string into the equivalent Hex buffer. + * Ex: "abc123" -> {0x23, 0xc1, 0xab} + * + * @param Str is a Input String. Will support the lower and upper case values. + * Value should be between 0-9, a-f and A-F + * + * @param Buf is Output buffer. + * @param Len of the input string. Should have even values + * @return + * - XST_SUCCESS no errors occured. + * - XST_FAILURE an error when input parameters are not valid + * - an error when input buffer has invalid values + * + * TDD Test Cases: + ---Initialization--- + Len is odd + Len is zero + Str is NULL + Buf is NULL + ---Functionality--- + Str input with only numbers + Str input with All values in A-F + Str input with All values in a-f + Str input with values in a-f, 0-9, A-F + Str input with values in a-z, 0-9, A-Z + Boundary Cases + Memory Bounds of buffer checking + ****************************************************************************/ + + +u32 XilSKey_Efuse_ConvertStringToHexLE(const char * Str, u8 * Buf, u32 Len) +{ + u32 ConvertedLen=0; + u8 LowerNibble, UpperNibble; + u32 index; + + /** + * Check the parameters + */ + if (Str == NULL) + return XSK_EFUSEPS_ERROR_PARAMETER_NULL; + + if (Buf == NULL) + return XSK_EFUSEPS_ERROR_PARAMETER_NULL; + + /** + * Len has to be multiple of 2 + */ + if ((Len == 0) || (Len%2 == 1)) + return XSK_EFUSEPS_ERROR_PARAMETER_NULL; + + index = (Len/8) - 1; + ConvertedLen = 0; + while (ConvertedLen < Len) { + /** + * Convert char to nibble + */ + if (XilSKey_EfusePs_ConvertCharToNibble (Str[ConvertedLen], + &UpperNibble) == XST_SUCCESS) { + /** + * Convert char to nibble + */ + if (XilSKey_EfusePs_ConvertCharToNibble (Str[ConvertedLen+1], + &LowerNibble)==XST_SUCCESS) { + /** + * Merge upper and lower nibble to Hex + */ + Buf[index--] = + (UpperNibble << 4) | LowerNibble; + } + else { + /** + * Error converting Lower nibble + */ + return XSK_EFUSEPS_ERROR_STRING_INVALID; + } + } + else { + /** + * Error converting Upper nibble + */ + return XSK_EFUSEPS_ERROR_STRING_INVALID; + } + /** + * Converted upper and lower nibbles + */ + ConvertedLen += 2; + } + + return XST_SUCCESS; +} + +/***************************************************************************/ +/** +* This function is used to convert the Big Endian Byte data to +* Little Endian Byte data +* For ex: 1234567890abcdef -> 78563412efcdab90 +* +* @param Be Big endian data +* @param Le Little endian data +* @param Len Length of data to be converted and it should be multiple of 4 +* @return +* - XST_SUCCESS no errors occurred. +* - XST_FAILURE an error occurred during reading the PS eFUSE. +* +* TDD Test Cases: +* +****************************************************************************/ +void XilSKey_EfusePs_ConvertBytesBeToLe(const u8 *Be, u8 *Le, u32 Len) +{ + u32 Index; + + if ((Be == NULL) || (Le == NULL) || (Len == 0)) + return; + + for (Index=0;Index {0, 0, 1, 1, 1, 0, 1, 0} + * + * @param Bits Input Buffer. + * @param Bytes is Output buffer. + * @param Len of the input buffer in bits + * @return None + Test Cases: + Input with All Zeroes + Input with All Ones + Input Little Endian (General Cases ) + Input Check Big Endian - False case + Check for Len not a multiple of 8 + Check for Len 0 + Memory Bounds of buffer checking + ****************************************************************************/ +void XilSKey_Efuse_ConvertBitsToBytes(const u8 * Bits, u8 * Bytes, u32 Len) +{ + u8 Data=0; + u32 Index=0, BitIndex=0, ByteIndex=0; + + /** + * Make sure the bytes array is 0'ed first. + */ + for(Index=0;Index MSB - Little Endian + */ + Data = (Bits[BitIndex] >> Index) & 0x1; + Bytes[ByteIndex] = Data; + ByteIndex++; + Len--; + /** + * If len is not Byte aligned + */ + if(Len == 0) + return; + } + BitIndex++; + } + return ; +} + +/****************************************************************************/ +/** + * Convert the Bytes to Bits in little endian format + * 0th byte is LSB, 7th byte is MSB + * Ex: {0, 0, 1, 1, 1, 0, 1, 0} -> 0x5C + * + * @param Bytes Input Buffer. + * @param Bits is Output buffer. + * @param Len of the input buffer. + * @return None + Test Cases: + Input with All Zeroes + Input with All Ones + Input Little Endian (General Cases ) + Input Check Big Endian - False case + Check for Len not a multiple of 8 + Check for Len 0 + Memory Bounds of buffer checking + ****************************************************************************/ +void XilSKey_EfusePs_ConvertBytesToBits(const u8 * Bytes, u8 * Bits , u32 Len) +{ + u8 Tmp=0; + u32 Index=0, BitIndex=0, ByteIndex=0; + + /** + * Make sure the bits array is 0 first. + */ + for(Index=0;Index<((Len%8)?((Len/8)+1):(Len/8));Index++) { + Bits[Index] = 0; + } + + while(Len) { + /** + * Convert 1 Bit 8 Bytes to 8 Bit 1 Byte + */ + for(Index=0;Index<8;Index++) { + /** + * Store from LSB -> MSB - Little Endian + */ + Tmp = (Bytes[ByteIndex]) & 0x1; + Bits[BitIndex] |= (Tmp << Index); + ByteIndex++; + Len--; + /** + * If Len is not Byte aligned + */ + if(Len == 0) + return; + } + BitIndex++; + } + return; +} + +/****************************************************************************/ +/** + * Validate the key for proper characters & proper length + * + * + * @param Key - Hash Key + * @param Len - Valid length of key + * + * @return + * XST_SUCCESS - In case of Success + * XST_FAILURE - In case of Failure + ****************************************************************************/ +u32 XilSKey_Efuse_ValidateKey(const char *Key, u32 Len) +{ + int i; + /** + * Make sure passed key is not NULL + */ + if(Key == NULL) { + return (XSK_EFUSEPL_ERROR_KEY_VALIDATION + + XSK_EFUSEPL_ERROR_NULL_KEY); + } + + if(Len == 0) { + return (XSK_EFUSEPL_ERROR_KEY_VALIDATION + + XSK_EFUSEPL_ERROR_ZERO_KEY_LENGTH); + } + + /** + * Make sure the key has valid length + */ + if (strlen(Key) != Len) { + return (XSK_EFUSEPL_ERROR_KEY_VALIDATION + + XSK_EFUSEPL_ERROR_NOT_VALID_KEY_LENGTH); + } + + /** + * Make sure the key has valid characters + */ + for(i=0;i