diff --git a/lib/sw_services/xilskey/src/include/xilskey_utils.h b/lib/sw_services/xilskey/src/include/xilskey_utils.h index c7579ef1..d8b5cb6a 100644 --- a/lib/sw_services/xilskey/src/include/xilskey_utils.h +++ b/lib/sw_services/xilskey/src/include/xilskey_utils.h @@ -50,13 +50,20 @@ * Modified efuse PS macro * XSK_EFUSEPS_RSA_KEY_HASH_STRING_SIZE to * XSK_EFUSEPL_RSA_KEY_HASH_STRING_SIZE +* Added efuse functionality for Ultrascale. * *****************************************************************************/ #ifndef XILSKEY_UTILS_H #define XILSKEY_UTILS_H /***************************** Include Files ********************************/ +#include "xparameters.h" +#ifdef XPAR_XSK_MICROBLAZE_PLATFORM +#include "xsysmon.h" +#include "xtmrctr.h" +#else #include "xadcps.h" +#endif /************************** Constant Definitions ****************************/ /**************************** Type Definitions ******************************/ /***************** Macros (Inline Functions) Definitions ********************/ @@ -70,7 +77,31 @@ * xparameters.h file. They are defined here such that a user can easily * change all the needed parameters in one place. */ +#ifdef XSK_ARM_PLATFORM #define XADC_DEVICE_ID XPAR_XADCPS_0_DEVICE_ID +#else +#define XTMRCTR_DEVICE_ID (XPAR_TMRCTR_0_DEVICE_ID) +#define XSK_EFUSEPL_CLCK_FREQ_ULTRA (XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ) +#define XSK_TMRCTR_NUM (0) +#define XSK_GPIO_DEVICE_ID (XPAR_AXI_GPIO_0_DEVICE_ID) +#endif + +#define REVERSE_POLYNOMIAL (0x82F63B78) + /**< Polynomial for calculating CRC */ +/** @name CSU_DMA pause types + * @{ + */ +typedef enum { + XSK_FPGA_SERIES_ULTRA, /**< Ultrascale series */ + XSK_FPGA_SERIES_ZYNQ /**< Zynq series */ +}XSKEfusePl_Fpga; +/*@}*/ + +/** + * Row numbers of Sysmon + */ +#define XSK_SYSMON_TEMP_ROW (0) /**< Row for Temperature */ +#define XSK_SYSMON_VOL_ROW (2) /**< Row for Voltage */ /** * Temperature and voltage range for PS eFUSE reading and programming @@ -82,7 +113,7 @@ #define XSK_EFUSEPS_READ_VPAUX_MAX (1.98) #define XSK_EFUSEPS_WRITE_VPAUX_MIN (1.71) #define XSK_EFUSEPS_WRITE_VPAUX_MAX (1.98) - +#ifdef XSK_ARM_PLATFORM /** * Converting the celsius temperature to equivalent Binary data for xAdc */ @@ -96,7 +127,7 @@ #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)) - +#endif /** * Temperature and voltage range for PL eFUSE reading and programming * Temperature in Celsius('C) and Voltage(V) is in volts @@ -125,11 +156,16 @@ #define XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MIN (.795) #define XSK_EFUSEPL_READ_VOLTAGE_VCCINT_MAX (1.1) +/* Ultrascale Microblaze Voltage range */ +#define XSK_EFUSEPL_VOL_VCCAUX_MIN_ULTRA (1.746) +#define XSK_EFUSEPL_VOL_VCCAUX_MAX_ULTRA (1.854) +#define XSK_EFUSEPL_TEMP_MIN_ULTRA (-40) +#define XSK_EFUSEPL_TEMP_MAX_ULTRA (125) /** * PL eFUSE write Min and Max Temperature and Voltages */ - +#ifdef XSK_ARM_PLATFORM /** * Converting the celsius temperature to equivalent Binary data for xAdc */ @@ -171,6 +207,17 @@ #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)) +#else +/** + * Converting the voltage to equivalent Binary data for xAdc + */ +#define XSK_EFUSEPL_VOL_VCCAUX_MIN_RAW_ULTRA (XSysMon_VoltageToRaw(XSK_EFUSEPL_VOL_VCCAUX_MIN_ULTRA)) +#define XSK_EFUSEPL_VOL_VCCAUX_MAX_RAW_ULTRA (XSysMon_VoltageToRaw(XSK_EFUSEPL_VOL_VCCAUX_MAX_ULTRA)) + +#define XSK_EFUSEPL_TEMP_MIN_RAW_ULTRA (XSysMon_TemperatureToRaw(XSK_EFUSEPL_TEMP_MIN_ULTRA)) +#define XSK_EFUSEPL_TEMP_MAX_RAW_ULTRA (XSysMon_TemperatureToRaw(XSK_EFUSEPL_TEMP_MAX_ULTRA)) + +#endif /** * Different voltage types that can be read from xAdc */ @@ -265,6 +312,11 @@ * PS eFUSE RSA key Hash size in characters */ #define XSK_EFUSEPS_RSA_KEY_HASH_STRING_SIZE (64) +/** + * Ultrascale Efuse PL RSA Key size in Bytes + */ +#define XSK_EFUSEPL_RSA_KEY_HASH_SIZE_IN_BYTES (48) + /************************** Variable Definitions ****************************/ /** * XADC Structure @@ -342,7 +394,15 @@ typedef enum { XSK_EFUSEPL_ERROR_ZERO_KEY_LENGTH, XSK_EFUSEPL_ERROR_NOT_VALID_KEY_CHAR, XSK_EFUSEPL_ERROR_NULL_KEY, + /** + * SECURE KEY error codes + */ + XSK_EFUSEPL_ERROR_FUSE_SEC_WRITE_DISABLED, + XSK_EFUSEPL_ERROR_FUSE_SEC_READ_DISABLED, + XSK_EFUSEPL_ERROR_SEC_WRITE_BUFFER_NULL, + XSK_EFUSEPL_ERROR_READ_PAGE_OUT_OF_RANGE, + XSK_EFUSEPL_ERROR_FUSE_ROW_RANGE, /** * XSKEfusepl_Program_Efuse() error codes */ @@ -360,7 +420,13 @@ typedef enum { 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 + XSK_EFUSEPL_ERROR_INVALID_REF_CLK= 0x3000, + XSK_EFUSEPL_ERROR_FUSE_SEC_WRITE_NOT_ALLOWED = 0x1D00, + XSK_EFUSEPL_ERROR_READING_FUSE_STATUS = 0x1E00, + XSK_EFUSEPL_ERROR_FUSE_BUSY = 0x1F00, + XSK_EFUSEPL_ERROR_READING_FUSE_RSA_ROW = 0x2000, + XSK_EFUSEPL_ERROR_TIMER_INTIALISE_ULTRA = 0x2200, + XSK_EFUSEPL_ERROR_READING_FUSE_SEC = 0x2300 }XSKEfusePl_ErrorCodes; @@ -466,6 +532,9 @@ 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); u32 Xilskey_Timer_Intialise(); +u32 Xilskey_Efuse_ReverseHex(u32 Input); +void Xilskey_StrCpyRange(u8 *Src, u8 *Dst, u32 From, u32 To); +u32 Xilskey_CrcCalculation(u8 *Key); /***************************************************************************/ diff --git a/lib/sw_services/xilskey/src/xilskey_epl.c b/lib/sw_services/xilskey/src/xilskey_epl.c index 247d0128..14e3a118 100644 --- a/lib/sw_services/xilskey/src/xilskey_epl.c +++ b/lib/sw_services/xilskey/src/xilskey_epl.c @@ -47,7 +47,7 @@ * 2.00 hk 22/01/14 Corrected PL voltage checks to VCCINT and VCCAUX. * CR#768077 * 2.1 kvn 04/01/15 Fixed warnings. CR#716453. -* +* 3.00 vns 31/07/15 Added efuse functionality for Ultrascale. * ****************************************************************************/ /***************************** Include Files *********************************/ @@ -138,6 +138,7 @@ typedef enum { 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]; +XSKEfusePl_Fpga PlFpgaFlag; /**< For Storing Fpga series */ /************************** Function Prototypes *****************************/ /** @@ -172,6 +173,11 @@ 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); +extern void JtagWrite_Ultrascale(u8 Row, u8 Bit, u8 Page, u8 Redundant); +extern void JtagRead_Ultrascale(u8 Row, u32 *RowData, u8 MarginOption, + u8 Page, u8 Redundant); +extern void JtagRead_Status_Ultrascale(u32 *Rowdata); +extern u32 JtagAES_Check_Ultrascale(u32 *Crc, u8 MarginOption); /***************************************************************************/ /****************************************************************************/ /** @@ -249,7 +255,7 @@ u32 XilSKey_EfusePl_Program(XilSKey_EPl *InstancePtr) } InstancePtr->SystemInitDone = 1; - + PlFpgaFlag = InstancePtr->FpgaFlag; } /** @@ -473,7 +479,7 @@ u8 XilSKey_EfusePl_IsVectorAllZeros(u8 *RowDataPtr) *****************************************************************************/ u8 XilSKey_EfusePl_ProgramBit(u8 Row, u8 Bit) { - XSKEfusePs_XAdc PL_XAdc; + /** *Check if the row position is valid. */ @@ -526,6 +532,9 @@ u8 XilSKey_EfusePl_ProgramBit(u8 Row, u8 Bit) * Monitor the Voltage and temperature using XADC, if out of range return * unique error. */ +#ifdef XSK_ARM_PLATFORM + XSKEfusePs_XAdc PL_XAdc; + PL_XAdc.VType = XSK_EFUSEPS_VAUX; XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc); if((PL_XAdc.Temp < XSK_EFUSEPL_WRITE_TEMP_MIN_RAW) || @@ -547,6 +556,7 @@ u8 XilSKey_EfusePl_ProgramBit(u8 Row, u8 Bit) ErrorCode = XSK_EFUSEPL_ERROR_WRITE_VCCINT_VOLTAGE_OUT_OF_RANGE; return XST_FAILURE; } +#endif JtagWrite(Row, Bit); return XST_SUCCESS; @@ -866,6 +876,8 @@ u8 XilSKey_EfusePl_ReadRow(u32 Row, u8 MarginOption, u8 *RowDataBytes) * Monitor the Voltage and temperature using XADC, if out of range return * unique error. */ +#ifdef XSK_ARM_PLATFORM + XSKEfusePs_XAdc PL_XAdc; PL_XAdc.VType = XSK_EFUSEPS_VAUX; XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(&PL_XAdc); if((PL_XAdc.Temp < XSK_EFUSEPL_READ_TEMP_MIN_RAW) || @@ -887,7 +899,7 @@ u8 XilSKey_EfusePl_ReadRow(u32 Row, u8 MarginOption, u8 *RowDataBytes) ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCINT_VOLTAGE_OUT_OF_RANGE; return XST_FAILURE; } - +#endif /** * Here we have to use the impact algorithm to read the eFUSE row. * and return the data in row_data. @@ -1122,9 +1134,10 @@ u32 XilSKey_EfusePl_ReadStatus(XilSKey_EPl *InstancePtr, u32 *StatusBits) } InstancePtr->SystemInitDone = 1; - + PlFpgaFlag = InstancePtr->FpgaFlag; } +#ifdef XSK_ARM_PLATFORM /** * Monitor the Voltage and temperature using XADC, if out of range return * unique error. @@ -1156,6 +1169,7 @@ u32 XilSKey_EfusePl_ReadStatus(XilSKey_EPl *InstancePtr, u32 *StatusBits) JtagRead(0, &RowData, 0); *StatusBits = RowData & 0xFFFFFF; +#endif return XST_SUCCESS; @@ -1185,7 +1199,6 @@ u32 XilSKey_EfusePl_ReadKey(XilSKey_EPl *InstancePtr) unsigned int RowData; u32 KeyCnt; u32 Status; - XSKEfusePs_XAdc PL_XAdc; if(NULL == InstancePtr) { return XSK_EFUSEPL_ERROR_PL_STRUCT_NULL; @@ -1224,9 +1237,12 @@ u32 XilSKey_EfusePl_ReadKey(XilSKey_EPl *InstancePtr) } InstancePtr->SystemInitDone = 1; + PlFpgaFlag = InstancePtr->FpgaFlag; } +#ifdef XSK_ARM_PLATFORM + XSKEfusePs_XAdc PL_XAdc = {0}; /** * Monitor the Voltage and temperature using XADC, if out of range return * unique error. @@ -1252,7 +1268,7 @@ u32 XilSKey_EfusePl_ReadKey(XilSKey_EPl *InstancePtr) ErrorCode = XSK_EFUSEPL_ERROR_READ_VCCINT_VOLTAGE_OUT_OF_RANGE; return XST_FAILURE; } - +#endif /* * Read AES key and User Key and * store them in the variables in instance structure diff --git a/lib/sw_services/xilskey/src/xilskey_eps.c b/lib/sw_services/xilskey/src/xilskey_eps.c index 03fd8585..ab6e8368 100644 --- a/lib/sw_services/xilskey/src/xilskey_eps.c +++ b/lib/sw_services/xilskey/src/xilskey_eps.c @@ -510,6 +510,7 @@ XilSKey_EfusePs_WriteWithXadcCheckAndVerify(u32 EfuseAddress, u32 RefClk) /** * Check the temperature and voltage */ +#ifdef XSK_ARM_PLATFORM if ((XAdcInstancePtr.Temp < XSK_EFUSEPS_TEMP_MIN_RAW) || ((XAdcInstancePtr.Temp > XSK_EFUSEPS_TEMP_MAX_RAW))) { return XSK_EFUSEPS_ERROR_WRITE_TEMPERATURE_OUT_OF_RANGE; @@ -519,7 +520,7 @@ XilSKey_EfusePs_WriteWithXadcCheckAndVerify(u32 EfuseAddress, u32 RefClk) ((XAdcInstancePtr.V > XSK_EFUSEPS_WRITE_VPAUX_MAX_RAW))) { return XSK_EFUSEPS_ERROR_WRITE_VCCPAUX_VOLTAGE_OUT_OF_RANGE; } - +#endif /** * Write the eFUSE bit */ @@ -780,6 +781,7 @@ XilSKey_EfusePs_ReadWithXadcCheck(u32 EfuseAddress, u32 RefClk, u8 *Data) /** * Check the temperature and voltage */ +#ifdef XSK_ARM_PLATFORM if ((XAdcInstancePtr.Temp < XSK_EFUSEPS_TEMP_MIN_RAW) || ((XAdcInstancePtr.Temp > XSK_EFUSEPS_TEMP_MAX_RAW))) { return XSK_EFUSEPS_ERROR_READ_TMEPERATURE_OUT_OF_RANGE; @@ -789,7 +791,7 @@ XilSKey_EfusePs_ReadWithXadcCheck(u32 EfuseAddress, u32 RefClk, u8 *Data) ((XAdcInstancePtr.V > XSK_EFUSEPS_READ_VPAUX_MAX_RAW))) { return XSK_EFUSEPS_ERROR_READ_VCCPAUX_VOLTAGE_OUT_OF_RANGE; } - +#endif /** * Read the eFUSE bit */ @@ -833,6 +835,7 @@ static u32 XilSKey_EfusePs_VerifyWithXadcCheck(u32 EfuseAddress, u32 RefClk) /** * Check the temperature and voltage */ +#ifdef XSK_ARM_PLATFORM if ((XAdcInstancePtr.Temp < XSK_EFUSEPS_TEMP_MIN_RAW) || ((XAdcInstancePtr.Temp > XSK_EFUSEPS_TEMP_MAX_RAW))) { return XSK_EFUSEPS_ERROR_READ_TMEPERATURE_OUT_OF_RANGE; @@ -842,7 +845,7 @@ static u32 XilSKey_EfusePs_VerifyWithXadcCheck(u32 EfuseAddress, u32 RefClk) ((XAdcInstancePtr.V > XSK_EFUSEPS_READ_VPAUX_MAX_RAW))) { return XSK_EFUSEPS_ERROR_READ_VCCPAUX_VOLTAGE_OUT_OF_RANGE; } - +#endif /** * Read the eFUSE bit in Margin_1 mode diff --git a/lib/sw_services/xilskey/src/xilskey_jscmd.c b/lib/sw_services/xilskey/src/xilskey_jscmd.c index da4f7b37..bf724227 100644 --- a/lib/sw_services/xilskey/src/xilskey_jscmd.c +++ b/lib/sw_services/xilskey/src/xilskey_jscmd.c @@ -50,6 +50,8 @@ * void Bbram_DeInit(void) * 2.1 kvn 04/01/15 Fixed warnings. CR#716453. * +* 3.00 vns 31/07/15 Added efuse functionality for Ultrascale. +* * * * @@ -73,7 +75,12 @@ typedef long ssize_t; #include "xilskey_utils.h" #include "xilskey_jslib.h" #include "xilskey_jscmd.h" +#ifdef XSK_MICROBLAZE_PLATFORM +#include "xgpio.h" +#else #include "xgpiops.h" +#endif + #include "xilskey_bbram.h" //#define DEBUG_PRINT @@ -88,6 +95,7 @@ void dummy_printf(const char *ctrl1, ...); #define DEFAULT_FREQUENCY 10000000 #define MAX_FREQUENCY 30000000 #define ZYNQ_DAP_ID 0x4ba00477 +#define ULTRA_MB_DAP_ID 0x13822093 /**< Ultrascale microblaze TAP ID */ #define set_last_error(JS, ...) js_set_last_error(&(JS)->js.base, __VA_ARGS__) @@ -99,6 +107,8 @@ 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; +extern u32 TimerTicksfor500ns; +u32 GpoOutValue = 0; void dummy_printf(const char *ctrl1, ...) { @@ -153,8 +163,11 @@ struct js_port_impl_struct { }; - +#ifdef XSK_ARM_PLATFORM static XGpioPs structXGpioPs; +#else +static XGpio structXGpio; +#endif int setPin (int pin, int value); int readPin (int pin); @@ -169,6 +182,7 @@ void GpioConfig(unsigned long addr, unsigned long mask, unsigned long val) void JtagInitGpio () { +#ifdef XSK_ARM_PLATFORM js_printf("===== Initializing PS GPIO pins...\n\r"); XGpioPs_Config *ptrConfigPtrPs = XGpioPs_LookupConfig(0); XGpioPs_CfgInitialize(&structXGpioPs,ptrConfigPtrPs,ptrConfigPtrPs->BaseAddr); @@ -197,6 +211,41 @@ void JtagInitGpio () XGpioPs_SetDirectionPin(&structXGpioPs,MIO_TDO,0); XGpioPs_SetOutputEnablePin(&structXGpioPs,MIO_TDO,0); +#else + u32 DataDirection; + + js_printf("===== Initializing PL GPIO pins...\n\r"); + XGpio_Config *ptrConfigPtr = XGpio_LookupConfig(XSK_GPIO_DEVICE_ID); + XGpio_CfgInitialize(&structXGpio, ptrConfigPtr, + ptrConfigPtr->BaseAddress); + + /* Setting Data direction for GPIO pins */ + if (GpioInPutCh == GpioOutPutCh) { + DataDirection = XGpio_GetDataDirection(&structXGpio, + GpioInPutCh); + DataDirection = DataDirection & (~((1 << GPIO_TDI) | + (1 << GPIO_TCK) | (GPIO_TMS))); + DataDirection = DataDirection | (1 << GPIO_TDO); + XGpio_SetDataDirection(&structXGpio, GpioInPutCh, + DataDirection); + } + else { + DataDirection = XGpio_GetDataDirection(&structXGpio, + GpioOutPutCh); + DataDirection = DataDirection & (~((1 << GPIO_TDI) | + (1 << GPIO_TCK) | (GPIO_TMS))); + XGpio_SetDataDirection(&structXGpio, GpioOutPutCh, + DataDirection); + + DataDirection = XGpio_GetDataDirection(&structXGpio, + GpioInPutCh); + DataDirection = DataDirection | (1 << GPIO_TDO); + XGpio_SetDataDirection(&structXGpio, GpioInPutCh, + DataDirection); + } + + +#endif } /* initGpio() */ int getByteCountFromBitCount (int bitCount) @@ -544,13 +593,28 @@ void navigateTAP (unsigned char startState, unsigned char endState) int setPin (int pin, int value) { int status = 1; +#ifdef XSK_ARM_PLATFORM XGpioPs_WritePin(&structXGpioPs, pin, value); +#else + u32 Mask = (1 << pin); + u32 GpoOut = (value) ? (0xFFFFFFFF) : (0x0); + + GpoOutValue = (GpoOutValue & (~Mask)) | (GpoOut & Mask); + XGpio_DiscreteWrite(&structXGpio, GpioOutPutCh, GpoOutValue); +#endif + return (status); } int readPin (int pin) { +#ifdef XSK_ARM_PLATFORM int retVal = XGpioPs_ReadPin(&structXGpioPs, pin); +#else + int retVal = XGpio_DiscreteRead(&structXGpio, GpioInPutCh); + retVal = retVal ? 1: 0; +#endif + return (retVal); } @@ -1099,6 +1163,7 @@ void JtagRead(unsigned char row, unsigned int * row_data, unsigned char marginOp } int JtagValidateMioPins(void) { +#ifdef XSK_ARM_PLATFORM /* * Make sure that each every MIO pin defined is valid */ @@ -1138,6 +1203,64 @@ int JtagValidateMioPins(void) if(g_mio_jtag_tms == g_mio_jtag_mux_sel) return 1; +#else + /* + * Make sure that each every AXI GPIO pin defined is valid + */ + if (GpioPinMasterJtagTDI > 31) { + return 1; + } + if (GpioPinMasterJtagTDO > 31) { + return 1; + } + if (GpioPinMasterJtagTMS > 31) { + return 1; + } + if (GpioPinMasterJtagTCK > 31) { + return 1; + } + + /* + * Make sure that provided channel numbers of GPIO is valid + */ + if ((GpioInPutCh < XSK_EFUSEPL_GPIO_CH1) || + (GpioInPutCh > XSK_EFUSEPL_GPIO_CH2)) { + return 1; + } + if ((GpioOutPutCh < XSK_EFUSEPL_GPIO_CH1) || + (GpioOutPutCh > XSK_EFUSEPL_GPIO_CH2)) { + return 1; + } + /* + * Make sure that GPIO pins defined for JTAG operation are + * unique among themselves + */ + /* If both input and output channels is same */ + if (GpioInPutCh == GpioOutPutCh) { + if((GpioPinMasterJtagTDI == GpioPinMasterJtagTDO)|| + (GpioPinMasterJtagTDI == GpioPinMasterJtagTMS)|| + (GpioPinMasterJtagTDI == GpioPinMasterJtagTCK)) { + return 1; + } + if((GpioPinMasterJtagTDO == GpioPinMasterJtagTMS)|| + (GpioPinMasterJtagTDO == GpioPinMasterJtagTCK)) { + return 1; + } + if((GpioPinMasterJtagTMS == GpioPinMasterJtagTCK)) { + return 1; + } + } + else { + if((GpioPinMasterJtagTDI == GpioPinMasterJtagTMS)|| + (GpioPinMasterJtagTDI == GpioPinMasterJtagTCK)) { + return 1; + } + if((GpioPinMasterJtagTMS == GpioPinMasterJtagTCK)) { + return 1; + } + } + +#endif return 0; } @@ -1147,10 +1270,11 @@ 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; +#ifdef XSK_ARM_PLATFORM + 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; @@ -1164,6 +1288,22 @@ int JtagServerInit(XilSKey_EPl *InstancePtr) { return 1; } +#else + GpioPinMasterJtagTDI = InstancePtr->JtagGpioTDI; + GpioPinMasterJtagTDO = InstancePtr->JtagGpioTDO; + GpioPinMasterJtagTMS = InstancePtr->JtagGpioTMS; + GpioPinMasterJtagTCK = InstancePtr->JtagGpioTCK; + + GpioInPutCh = InstancePtr->GpioInputCh; + GpioOutPutCh = InstancePtr->GpioOutPutCh; + + status = JtagValidateMioPins(); + if(status != 0) + { + return 1; + } + +#endif JtagInitGpio(); g_js = js_init_zynq(); @@ -1199,6 +1339,11 @@ int JtagServerInit(XilSKey_EPl *InstancePtr) for (i = 0; i < num_taps; i++) { if(tap_codes[i] == ZYNQ_DAP_ID){ + InstancePtr->FpgaFlag = XSK_FPGA_SERIES_ZYNQ; + break; + } + if (tap_codes[i] == ULTRA_MB_DAP_ID) { + InstancePtr->FpgaFlag = XSK_FPGA_SERIES_ULTRA; break; } } @@ -1813,4 +1958,412 @@ void Bbram_DeInit(void) js_deinit_server(g_js); -} \ No newline at end of file +} + +/****************************************************************************/ +/** +* +* This function reads temperature and voltage of Ultrascale +* +* @param Row specifies the row number to read. +* @param Row_Data is a pointer to a variable, to store the read value +* of given row. +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void Jtag_Read_Sysmon(u8 Row, u32 *Row_Data) +{ + + u8 WriteBuf[4]; + u8 ReadBuf[4]; + u8 *DataPtr = (u8 *)Row_Data; + u32 TckCnt; + jtag_navigate (g_port, JS_RESET); + WriteBuf[0] = 0x37; + + jtag_shift (g_port, ATOMIC_IR_SCAN, 6, WriteBuf, + NULL, JS_IREXIT1); + WriteBuf[3] = 0xC4; + WriteBuf[2] = Row; + WriteBuf[1] = 0x00; + WriteBuf[0] = 0x00; + + jtag_shift (g_port, ATOMIC_DR_SCAN, 32, WriteBuf, + NULL, JS_IDLE); + /* + * Wait 12 TCK + */ + for(TckCnt = 0; TckCnt < 12; TckCnt++){ + setPin (MIO_TCK, 1); + setPin (MIO_TCK, 0); + } + + jtag_shift (g_port, ATOMIC_DR_SCAN, 32, NULL, + ReadBuf, JS_IDLE); + + DataPtr[0] = ReadBuf[0]; + DataPtr[1] = ReadBuf[1]; +} + +/****************************************************************************/ +/** +* +* This function blows the fuse of Ultrascale with provided parameters. +* +* @param Row specifies the row number of EFUSE to blow. +* @param Bit Specifies the bit location in the given row. +* @param Page tell the page of EFUSE in which the given row is located. +* @param Redundant is a flag to specify the bit to be programmed is +* Normal bit or Redundant bit. +* - Redundant - XSK_EFUSEPL_REDUNDANT_ULTRA +* - Normal - XSK_EFUSEPL_NORMAL_ULTRA +* +* @return None. +* +* @note None. +* +*****************************************************************************/ +void JtagWrite_Ultrascale(u8 Row, u8 Bit, u8 Page, u8 Redundant) +{ + + u8 wrBuffer [8]; + u32 Bits = 0; + + jtag_navigate (g_port, JS_RESET); + + Bits = TAP_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] = (((Bit & 0x1) << 7) | ((Row << 2)| 0x3)); + wrBuffer [1] = ((Bit >> 1) & 0xF) | ((0x20 << Redundant) | (Page << 4)); + wrBuffer [2] = 0x00; + wrBuffer [3] = 0x00; + /* Magic word */ + wrBuffer [4] = 0xAC; + wrBuffer [5] = 0x28; + wrBuffer [6] = 0xED; + wrBuffer [7] = 0xFE; + + Bits = 64; /* fuse_cts data length */ + + 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); + + XilSKey_Efuse_StartTimer(); + jtag_navigate (g_port, JS_IDLE); + + /* Here we will be providing 5micro seconds delay */ + if (XilSKey_Efuse_GetTime() < TimerTicksfor500ns) { + while(1) { + if(XilSKey_Efuse_IsTimerExpired(TimerTicksfor500ns) == 1) { + break; + } + } + } + jtag_navigate (g_port, JS_DRSELECT); + jtag_navigate (g_port, JS_IRSELECT); + jtag_navigate (g_port, JS_RESET); + +} + +/****************************************************************************/ +/** +* +* This function reads entire row of Ultrascale's EFUSE. +* +* @param Row specifies the row number of EFUSE. +* @param Bit Specifies the bit location in the given row. +* @param MarginOption is a variable which tells the margin option in +* which read operation to be performed. +* @param Page tell the page of EFUSE in which the given row is located. +* @param Redundant is a flag to specify the bit to be programmed is +* Normal bit or Redundant bit. +* - Redundant - XSK_EFUSEPL_REDUNDANT_ULTRA +* - Normal - XSK_EFUSEPL_NORMAL_ULTRA +* +* @return None. +* +* @note 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 +* Shift in MAGIC_CTS_WRITE "FEED28AC" for ultrascale +* Read 64 bit data in IR read state. +* +*****************************************************************************/ +void JtagRead_Ultrascale(u8 Row, u32 *RowData, u8 MarginOption, + u8 Page, u8 Redundant) +{ + + u8 WrBuffer [8]; + u8 RdBuffer [8]; + u32 Bits = 8; + u8 *RowDataPtr = (u8 *)RowData; + + jtag_navigate (g_port, JS_RESET); + + /* Load FUSE_CTS instruction on IR */ + Bits = TAP_IR_LENGTH; /* 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] = ((Row << 2)| 0x1); /* Select the row number */ + WrBuffer [1] = (0x20 << Redundant) | (Page << 4); + /* Page and Redundant/normal bit selection */ + WrBuffer [2] = MarginOption; + WrBuffer [3] = 0x00; + /* Magic word. */ + WrBuffer [4] = 0xAC; + WrBuffer [5] = 0x28; + WrBuffer [6] = 0xED; + WrBuffer [7] = 0xFE; + + Bits = 64; /* Fuse_cts data length */ + jtag_shift (g_port, ATOMIC_DR_SCAN, Bits, WrBuffer, NULL, JS_IDLE); + + jtag_shift (g_port, ATOMIC_DR_SCAN, Bits, NULL, RdBuffer, JS_IDLE); + + /* + * Captured macro word (32 Bits) is stored in [63:32] of + * 64 bit buffer + */ + RowDataPtr[0] = RdBuffer[4]; + RowDataPtr[1] = RdBuffer[5]; + RowDataPtr[2] = RdBuffer[6]; + RowDataPtr[3] = RdBuffer[7]; + +} + +/****************************************************************************/ +/** +* +* This function reads the status row of Ultrascale's EFUSE and updates the +* pointer. +* +* @param Rowdata is a pointer to a 32 bit variable which stores the +* status register value read from EFUSE status register. + +* @return None. +* +* @note Method to read FUSE register in Direct Macro Access way. +* For reading the status values we need send the bitstream +* in shift DR state. +* Shift in MAGIC_CTS_WRITE "FEED28AC" for ultrascale +* Read 64 bit data in IR read state. +* +*****************************************************************************/ +void JtagRead_Status_Ultrascale(u32 *Rowdata) +{ + u8 WrBuffer[32]; + u8 RdBuffer [4]; + u32 Bits = 8; + u8 *RowDataPtr = (u8 *)Rowdata; + + /* Go to TLR to clear FUSE_CTS */ + jtag_navigate (g_port, JS_RESET); + + /* Load FUSE_CTS instruction on IR */ + Bits = TAP_IR_LENGTH; /* ir length */ + + WrBuffer [0] = 0x05; /* FUSE_CTS instruction */ + jtag_shift (g_port, ATOMIC_IR_SCAN, Bits, WrBuffer, NULL, JS_DRSELECT); + + /* prepare Bit stream data */ + WrBuffer[0] = 0xff; + WrBuffer[1] = 0xff; + WrBuffer[2] = 0xff; + WrBuffer[3] = 0xff; + + WrBuffer[4] = 0x55; + WrBuffer[5] = 0x99; + WrBuffer[6] = 0xAA; + WrBuffer[7] = 0x66; + + WrBuffer[8] = 0x0c; + WrBuffer[9] = 0x00; + WrBuffer[10] = 0x01; + WrBuffer[11] = 0x80; + + WrBuffer[12] = 0x0c; + WrBuffer[13] = 0x41; + WrBuffer[14] = 0x04; + WrBuffer[15] = 0xc9; + + WrBuffer [16] = 0x04; + WrBuffer [17] = 0x00; + WrBuffer [18] = 0x00; + WrBuffer [19] = 0x00; + + WrBuffer [20] = 0x14; + WrBuffer [21] = 0xc0; + WrBuffer [22] = 0x05; + WrBuffer [23] = 0x80; + + WrBuffer [24] = 0x04; + WrBuffer [25] = 0x00; + WrBuffer [26] = 0x00; + WrBuffer [27] = 0x00; + + WrBuffer [28] = 0x04; + WrBuffer [29] = 0x00; + WrBuffer [30] = 0x00; + WrBuffer [31] = 0x00; + + Bits = 256; + jtag_shift (g_port, ATOMIC_DR_SCAN, Bits, WrBuffer, NULL, JS_IDLE); + + WrBuffer [0] = 0x04; + Bits = 0x06; + jtag_shift (g_port, ATOMIC_IR_SCAN, Bits, WrBuffer, NULL, JS_DRSELECT); + + Bits = 32; + jtag_shift (g_port, ATOMIC_DR_SCAN, Bits, NULL, RdBuffer, JS_IDLE); + + RowDataPtr[0] = RdBuffer [0]; + RowDataPtr[1] = RdBuffer [1]; + RowDataPtr[2] = RdBuffer [2]; + RowDataPtr[3] = RdBuffer [3]; + + *(u32 *)RowDataPtr = Xilskey_Efuse_ReverseHex(*(u32 *)RowDataPtr); + +} + +/****************************************************************************/ +/** +* +* This function verifies the AES key of Ultrascale's EFUSE with provided CRC +* value. +* +* @param Crc is a pointer to a 32 bit variable which holds the expected +* AES key's CRC. +* @param MarginOption is a variable which tells the margin option in +* which read operation to be performed. +* +* @return Returns XST_FAILURE/XST_SUCCESS +* - XST_SUCCESS - If CRC is correct +* - XST_FAILURE - If CRC is wrong +* +* @note To verify AES key with provided CRC 256 bits need to be written +* with all ZEROS and last 32 bits with CRC. +* And then CTS word should be framed and read 9 rows. +* The keys are stored in 8 rows (20 to 27) but in UltraScale +* the device will read all 1s. +* On the 9th read (row 28), the CRC computation takes +* place. An extra read after the 9th read is required +* to read the computed CRC out (can use last row addr +* of 28 or row 0). The FPGA internally compares the +* computed CRC with the expected CRC loaded through +* the FUSE_KEY operation. If they match, then the expected CRC +* is read. If not, the FPGA will return all 1s. +* +*****************************************************************************/ +u32 JtagAES_Check_Ultrascale(u32 *Crc, u8 MarginOption) +{ + u8 WrBuffer [32]; + u8 RdBuffer [8]; + u32 Bits = 8; + u8 *RowDataPtr = (u8 *)Crc; + u32 Row; + u32 Index; + u8 WrBuf[8]; + + /* Go to TLR to clear FUSE_CTS */ + jtag_navigate (g_port, JS_RESET); + + /* Load FUSE_CTS instruction on IR */ + Bits = TAP_IR_LENGTH; /* 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] = 0x00; + WrBuffer [1] = 0x80; + WrBuffer [2] = MarginOption; + WrBuffer [3] = 0x01; + /* Magic word. */ + WrBuffer [4] = 0xAC; + WrBuffer [5] = 0x28; + WrBuffer [6] = 0xED; + WrBuffer [7] = 0xFE; + + Bits = 64; /* fuse_cts data length */ + jtag_shift (g_port, ATOMIC_DR_SCAN, Bits, WrBuffer, NULL, JS_IDLE); + + Bits = TAP_IR_LENGTH; /* Ir length */ + WrBuffer [0] = 0x31; /* CMD for FUSE Key */ + jtag_shift (g_port, ATOMIC_IR_SCAN, Bits, WrBuffer, NULL, JS_DRSELECT); + + + WrBuffer[0] = RowDataPtr[0]; + WrBuffer[1] = RowDataPtr[1]; + WrBuffer[2] = RowDataPtr[2]; + WrBuffer[3] = RowDataPtr[3]; + for (Index = 4; Index < 32; Index++) { + WrBuffer[Index] = 0; + } + Bits = 256; + jtag_shift (g_port, ATOMIC_DR_SCAN, Bits, WrBuffer, NULL, JS_IDLE); + Bits = TAP_IR_LENGTH; + WrBuffer [0] = 0x30; /* FUSE_CTS instruction */ + jtag_shift (g_port, ATOMIC_IR_SCAN, Bits, WrBuffer, NULL, JS_DRSELECT); + + WrBuffer [0] = 0x01; + WrBuffer [1] = 0x00; + WrBuffer [2] = MarginOption; + WrBuffer [3] = 0x01; + /* Magic word. */ + WrBuffer [4] = 0xAC; + WrBuffer [5] = 0x28; + WrBuffer [6] = 0xED; + WrBuffer [7] = 0xFE; + + Bits = 64; + jtag_shift (g_port, ATOMIC_DR_SCAN, Bits, WrBuffer, NULL, JS_IDLE); + /* + * Repeat for all AES key Rows 20-27 and repeat one extra read + * for getting CRC back. + */ + for (Row = 20; Row < 29; Row++) { + WrBuf[0] = 0x30; + Bits = 6; + jtag_shift (g_port, ATOMIC_IR_SCAN, Bits, WrBuf, NULL, + JS_DRSELECT); + + WrBuffer [0] = (Row << 2) | 0x1; /* Select row number */ + WrBuffer [1] = 0x00; + WrBuffer [2] = MarginOption; + WrBuffer [3] = 0x01; + /* Magic word */ + WrBuffer [4] = 0xAC; + WrBuffer [5] = 0x28; + WrBuffer [6] = 0xED; + WrBuffer [7] = 0xFE; + Bits = 64; + jtag_shift (g_port, ATOMIC_DR_SCAN, Bits, WrBuffer, + RdBuffer, JS_IDLE); + } + + WrBuf[0] = 0x30; + Bits = 6; + jtag_shift(g_port, ATOMIC_IR_SCAN, Bits, WrBuf, NULL, JS_DRSELECT); + Bits = 64; + jtag_shift (g_port, ATOMIC_DR_SCAN, Bits, WrBuffer, RdBuffer, JS_IDLE); + if ((RowDataPtr[0] == RdBuffer[4]) && + (RowDataPtr[1] == RdBuffer[5]) && + (RowDataPtr[2] == RdBuffer[6]) && + (RowDataPtr[3] == RdBuffer[7])) { + return XST_SUCCESS; + } + + return XST_FAILURE; + +} diff --git a/lib/sw_services/xilskey/src/xilskey_jscmd.h b/lib/sw_services/xilskey/src/xilskey_jscmd.h index 104e5fc7..6e41b959 100644 --- a/lib/sw_services/xilskey/src/xilskey_jscmd.h +++ b/lib/sw_services/xilskey/src/xilskey_jscmd.h @@ -91,6 +91,11 @@ u32 GpioOutPutCh; #define GPIO_TMS_VAL 0x00001300U #define GPIO_MUX_SEL_VAL 0x00001300U +/** + * GPIO channel numbers of Ultrascale + */ +#define XSK_EFUSEPL_GPIO_CH1 (1) /**< GPIO channel 1 */ +#define XSK_EFUSEPL_GPIO_CH2 (2) /**< GPIO channel 2 */ /** * XEfusePl is the PL eFUSE driver instance. Using this * structure, user can define the eFUSE bits to be diff --git a/lib/sw_services/xilskey/src/xilskey_jtag.h b/lib/sw_services/xilskey/src/xilskey_jtag.h index b138ec27..2fba0336 100644 --- a/lib/sw_services/xilskey/src/xilskey_jtag.h +++ b/lib/sw_services/xilskey/src/xilskey_jtag.h @@ -41,5 +41,11 @@ 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); +void JtagWrite_Ultrascale(u8 Row, u8 Bit, u8 Page, u8 Redundant); +void JtagRead_Ultrascale(u8 Row, u32 *RowData, u8 MarginOption, + u8 Page, u8 Redundant); +void JtagRead_Status_Ultrascale(u32 *Rowdata); +void Jtag_Read_Sysmon(u8 Row, u32 *Row_Data); +u32 JtagAES_Check_Ultrascale(u32 *Crc, u8 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 index 8e9360bc..8597d5d5 100644 --- a/lib/sw_services/xilskey/src/xilskey_utils.c +++ b/lib/sw_services/xilskey/src/xilskey_utils.c @@ -60,11 +60,18 @@ /***************** Macros (Inline Functions) Definitions ********************/ /************************** Variable Definitions ****************************/ +#ifdef XSK_ARM_PLATFORM static XAdcPs XAdcInst; /**< XADC driver instance */ u16 XAdcDeviceId; /**< XADC Device ID */ +#else +XTmrCtr XTmrCtrInst; +#endif u32 TimerTicksfor100ns; /**< Global Variable to store ticks/100ns*/ +u32 TimerTicksfor500ns; /**< Global Variable for 5 micro secs for microblaze */ /************************** Function Prototypes *****************************/ static u32 XilSKey_EfusePs_ConvertCharToNibble (char InChar, u8 *Num); +extern void Jtag_Read_Sysmon(u8 Row, u32 *Row_Data); +static u32 Xilskey_RowCrcCalculation(u32 PrevCRC, u32 Data, u32 Addr); /***************************************************************************/ /** * This function is used to initialize the XADC driver @@ -82,6 +89,7 @@ static u32 XilSKey_EfusePs_ConvertCharToNibble (char InChar, u8 *Num); u32 XilSKey_EfusePs_XAdcInit (void ) { u32 Status; +#ifdef XSK_ARM_PLATFORM XAdcPs_Config *ConfigPtr; XAdcPs *XAdcInstPtr = &XAdcInst; @@ -118,7 +126,11 @@ u32 XilSKey_EfusePs_XAdcInit (void ) */ XAdcPs_SetSequencerMode(XAdcInstPtr, XADCPS_SEQ_MODE_SAFE); - return XST_SUCCESS; + Status = XST_SUCCESS; +#else + Status = XST_FAILURE; +#endif + return Status; } @@ -144,6 +156,13 @@ u32 XilSKey_EfusePs_XAdcInit (void ) void XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(XSKEfusePs_XAdc *XAdcInstancePtr) { +#ifdef XSK_MICROBLAZE_PLATFORM + /* Temperature */ + Jtag_Read_Sysmon(XSK_SYSMON_TEMP_ROW, &(XAdcInstancePtr->Temp)); + XAdcInstancePtr->Temp = (XAdcInstancePtr->Temp) >> 6; + /* Voltage */ + Jtag_Read_Sysmon(XSK_SYSMON_VOL_ROW, &(XAdcInstancePtr->V)); +#else XAdcPs *XAdcInstPtr = &XAdcInst; u8 V, VMin, VMax; @@ -217,6 +236,8 @@ void XilSKey_EfusePs_XAdcReadTemperatureAndVoltage(XSKEfusePs_XAdc *XAdcInstance XAdcInstancePtr->V, (int )XAdcPs_RawToVoltage(XAdcInstancePtr->V)); +#endif + return; } @@ -256,6 +277,11 @@ void XilSKey_Efuse_StartTimer() * Enable the Timer counter */ Xil_Out32(XSK_GLOBAL_TIMER_CTRL_REG,0x1); +#else + XTmrCtr_SetOptions(&XTmrCtrInst, XSK_TMRCTR_NUM, + XTC_AUTO_RELOAD_OPTION); + XTmrCtr_Start(&XTmrCtrInst, XSK_TMRCTR_NUM); + #endif } @@ -274,14 +300,20 @@ void XilSKey_Efuse_StartTimer() 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)); + volatile u64 t=0; +#ifdef XSK_ARM_PLATFORM + volatile u32 t_hi=0, t_lo=0; - t = (((u64) t_hi) << 32) | (u64) t_lo; + 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; + +#else + t = XTmrCtr_GetValue(&XTmrCtrInst, XSK_TMRCTR_NUM); +#endif return t; } /****************************************************************************/ @@ -830,3 +862,145 @@ u32 Xilskey_Timer_Intialise() return RefClk; } + +/****************************************************************************/ +/** + * Copies one string to other from specified location + * + * @param Src is a pointer to Source string. + * @param Dst is a pointer to Destination string. + * @param From which position to be copied. + * @param To which position to be copied. + * + * @return None. + * + * @note None. + * + ****************************************************************************/ +void Xilskey_StrCpyRange(u8 *Src, u8 *Dst, u32 From, u32 To) +{ + u32 Index,J = 0; + for (Index = From; Index <= To; Index++) { + Dst[J++] = Src[Index]; + } + Dst[J] = '\0'; + +} + +/****************************************************************************/ +/** + * Calculates CRC value of provided key. + * + * @param Key is the string contains AES key in hexa decimal of length + * less than or equal to 64. + * + * @return Crc of AES key value. + * + * @note None. + * + ****************************************************************************/ +u32 Xilskey_CrcCalculation(u8 *Key) +{ + u32 Crc = 0; + u8 Key_8[8]; + u8 Key_Hex[4]; + u32 Index; + u32 Key_32; + u8 FullKey[64] = {0}; + u32 Length = strlen((char *)Key); + + + if (Length > 64) { + return XSK_EFUSEPL_ERROR_NOT_VALID_KEY_LENGTH; + } + if (Length < 64) { + strcpy((char *)&FullKey[64-Length + 1], (char *)Key); + + } + else { + strcpy((char *)FullKey, (char *)Key); + } + + for (Index = 0; Index <8;Index++) { + Xilskey_StrCpyRange(FullKey, Key_8, ((7 - Index)*8), + ((((7 - Index) + 1)*8)-1)); + XilSKey_Efuse_ConvertStringToHexBE((char *)Key_8, Key_Hex, 8); + Key_32 = (Key_Hex[0] << 24) | (Key_Hex[1] << 16) | + (Key_Hex[2] << 8) | (Key_Hex[3]); + Crc = Xilskey_RowCrcCalculation(Crc, Key_32, 20+Index); + } + + return Crc; +} + +/****************************************************************************/ +/** + * Calculates CRC value for each row of AES key. + * + * @param PrevCRC holds the prev row's CRC. + * @param Data holds the present row's key. + * @param Addr stores the current row number. + * + * @return Crc of current row. + * + * @note None. + * + ****************************************************************************/ +u32 Xilskey_RowCrcCalculation(u32 PrevCRC, u32 Data, u32 Addr) +{ + u32 Crc = PrevCRC; + u32 Value = Data; + u32 Row = Addr; + u32 Index; + + for (Index = 0; Index < 32; Index++) { + if ((((Value & 0x1) ^ Crc) & 0x1) != 0) { + Crc = ((Crc >> 1) ^ REVERSE_POLYNOMIAL); + } + else { + Crc = Crc >>1; + } + Value = Value >>1; + } + + for (Index = 0; Index < 5; Index++) { + if ((((Row & 0x1) ^ Crc) & 0x1) != 0) { + Crc = ((Crc >> 1) ^ REVERSE_POLYNOMIAL); + } + else { + Crc = Crc >>1; + } + Row = Row >> 1; + } + + return Crc; + +} + +/****************************************************************************/ +/** + * This API reverse the value. + * + * @param Input is a 32 bit variable + * + * @return Reverse the given value. + * + * @note None. + * + ****************************************************************************/ +u32 Xilskey_Efuse_ReverseHex(u32 Input) +{ + u32 Index = 0; + u32 Rev = 0; + u32 Bit; + + while (Index++ < 32) { + Bit = Input & 1; + Input = Input >> 1; + Rev = Rev ^ Bit; + if (Index < 32) + Rev = Rev << 1; + } + + return Rev; +}