/** * * 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; }
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 jtag_dr(unsigned sz, unsigned bits, unsigned *out) { int r; if ((r = jtag_move(SHIFTDR)) < 0) return r; if ((r = jtag_shift(sz, bits, out)) < 0) return r; if ((r = jtag_move(DONE)) < 0) return r; return 0; }
int jtag_ir(unsigned sz, unsigned bits) { int r; if ((r = jtag_move(SHIFTIR)) < 0) return r; if ((r = jtag_shift(sz, bits, 0)) < 0) return r; if ((r = jtag_move(DONE)) < 0) return r; return 0; }
/** * * 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); }
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); }
/** * * 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 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; }