/** * * This function Validate Partition Data by using checksum preset in image * * @param Partition header pointer * @param Partition check sum offset * @return * - XST_SUCCESS if partition data is ok * - XST_FAILURE if partition data is corrupted * * @note None * *******************************************************************************/ u32 ValidateParition(u32 StartAddr, u32 Length, u32 ChecksumOffset) { u8 Checksum[MD5_CHECKSUM_SIZE]; u8 CalcChecksum[MD5_CHECKSUM_SIZE]; u32 Status; u32 Index; #ifdef XPAR_XWDTPS_0_BASEADDR /* * Prevent WDT reset */ XWdtPs_RestartWdt(&Watchdog); #endif /* * Get checksum from flash */ Status = GetPartitionChecksum(ChecksumOffset, &Checksum[0]); if(Status != XST_SUCCESS) { return XST_FAILURE; } fsbl_printf(DEBUG_INFO, "Actual checksum\r\n"); for (Index = 0; Index < MD5_CHECKSUM_SIZE; Index++) { fsbl_printf(DEBUG_INFO, "0x%0x ",Checksum[Index]); } fsbl_printf(DEBUG_INFO, "\r\n"); /* * Calculate checksum for the partition */ Status = CalcPartitionChecksum(StartAddr, Length, &CalcChecksum[0]); if(Status != XST_SUCCESS) { return XST_FAILURE; } fsbl_printf(DEBUG_INFO, "Calculated checksum\r\n"); for (Index = 0; Index < MD5_CHECKSUM_SIZE; Index++) { fsbl_printf(DEBUG_INFO, "0x%0x ",CalcChecksum[Index]); } fsbl_printf(DEBUG_INFO, "\r\n"); /* * Compare actual checksum with the calculated checksum */ for (Index = 0; Index < MD5_CHECKSUM_SIZE; Index++) { if(Checksum[Index] != CalcChecksum[Index]) { fsbl_printf(DEBUG_GENERAL, "Error: " "Partition DataChecksum 0x%0x!= 0x%0x\r\n", Checksum[Index], CalcChecksum[Index]); return XST_FAILURE; } } return XST_SUCCESS; }
/** * * This function loads PL partition using PCAP * * @param SourceDataPtr is a pointer to where the data is read from * @param DestinationDataPtr is a pointer to where the data is written to * @param SourceLength is the length of the data to be moved in words * @param DestinationLength is the length of the data to be moved in words * @param SecureTransfer indicated the encryption key location, 0 for * non-encrypted * * @return * - XST_SUCCESS if the transfer is successful * - XST_FAILURE if the transfer fails * * @note None * ****************************************************************************/ u32 PcapLoadPartition(u32 *SourceDataPtr, u32 *DestinationDataPtr, u32 SourceLength, u32 DestinationLength, u32 SecureTransfer) { u32 Status; u32 IntrStsReg; u32 PcapTransferType = XDCFG_NON_SECURE_PCAP_WRITE; /* * Check for secure transfer */ if (SecureTransfer) { PcapTransferType = XDCFG_SECURE_PCAP_WRITE; } #ifdef FSBL_PERF XTime tXferCur = 0; FsblGetGlobalTime(&tXferCur); #endif /* * Clear the PCAP status registers */ Status = ClearPcapStatus(); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO,"PCAP_CLEAR_STATUS_FAIL \r\n"); return XST_FAILURE; } /* * For Bitstream case destination address will be 0xFFFFFFFF */ DestinationDataPtr = (u32*)XDCFG_DMA_INVALID_ADDRESS; /* * New Bitstream download initialization sequence */ FabricInit(); #ifdef XPAR_XWDTPS_0_BASEADDR /* * Prevent WDT reset */ XWdtPs_RestartWdt(&Watchdog); #endif /* * PCAP single DMA transfer setup */ SourceDataPtr = (u32*)((u32)SourceDataPtr | PCAP_LAST_TRANSFER); DestinationDataPtr = (u32*)((u32)DestinationDataPtr | PCAP_LAST_TRANSFER); /* * Transfer using Device Configuration */ Status = XDcfg_Transfer(DcfgInstPtr, (u8 *)SourceDataPtr, SourceLength, (u8 *)DestinationDataPtr, DestinationLength, PcapTransferType); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO,"Status of XDcfg_Transfer = %d \r \n",Status); return XST_FAILURE; } /* * Dump the PCAP registers */ PcapDumpRegisters(); /* * Poll for the DMA done */ Status = XDcfgPollDone(XDCFG_IXR_DMA_DONE_MASK, MAX_COUNT); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO,"PCAP_DMA_DONE_FAIL \r\n"); return XST_FAILURE; } fsbl_printf(DEBUG_INFO,"DMA Done ! \n\r"); /* * Poll for FPGA Done */ Status = XDcfgPollDone(XDCFG_IXR_PCFG_DONE_MASK, MAX_COUNT); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO,"PCAP_FPGA_DONE_FAIL\r\n"); return XST_FAILURE; } fsbl_printf(DEBUG_INFO,"FPGA Done ! \n\r"); /* * Check for errors */ IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr); if (IntrStsReg & FSBL_XDCFG_IXR_ERROR_FLAGS_MASK) { fsbl_printf(DEBUG_INFO,"Errors in PCAP \r\n"); return XST_FAILURE; } /* * For Performance measurement */ #ifdef FSBL_PERF XTime tXferEnd = 0; fsbl_printf(DEBUG_GENERAL,"Time taken is "); FsblMeasurePerfTime(tXferCur,tXferEnd); #endif return XST_SUCCESS; }
/** * * This function Authenticate Partition Signature * * @param Partition header pointer * * @return * - XST_SUCCESS if Authentication passed * - XST_FAILURE if Authentication failed * * @note None * ******************************************************************************/ u32 AuthenticatePartition(u8 *Buffer, u32 Size) { u8 DecryptSignature[256]; u8 HashSignature[32]; u8 *SpkModular; u8 *SpkModularEx; u32 SpkExp; u8 *SignaturePtr; u32 Status; #ifdef XPAR_XWDTPS_0_BASEADDR /* * Prevent WDT reset */ XWdtPs_RestartWdt(&Watchdog); #endif /* * Point to Authentication Certificate */ SignaturePtr = (u8 *)(Buffer + Size - RSA_SIGNATURE_SIZE); /* * Increment the pointer by authentication Header size */ SignaturePtr += RSA_HEADER_SIZE; /* * Increment the pointer by Magic word size */ SignaturePtr += RSA_MAGIC_WORD_SIZE; /* * Increment the pointer beyond the PPK */ SignaturePtr += RSA_PPK_MODULAR_SIZE; SignaturePtr += RSA_PPK_MODULAR_EXT_SIZE; SignaturePtr += RSA_PPK_EXPO_SIZE; /* * Calculate Hash Signature */ sha_256((u8 *)SignaturePtr, (RSA_SPK_MODULAR_EXT_SIZE + RSA_SPK_EXPO_SIZE + RSA_SPK_MODULAR_SIZE), HashSignature); FsblPrintArray(HashSignature, 32, "SPK Hash Calculated"); /* * Extract SPK signature */ SpkModular = (u8 *)SignaturePtr; SignaturePtr += RSA_SPK_MODULAR_SIZE; SpkModularEx = (u8 *)SignaturePtr; SignaturePtr += RSA_SPK_MODULAR_EXT_SIZE; SpkExp = *((u32 *)SignaturePtr); SignaturePtr += RSA_SPK_EXPO_SIZE; /* * Decrypt SPK Signature */ rsa2048_pubexp((RSA_NUMBER)DecryptSignature, (RSA_NUMBER)SignaturePtr, (u32)PpkExp, (RSA_NUMBER)PpkModular, (RSA_NUMBER)PpkModularEx); FsblPrintArray(DecryptSignature, RSA_SPK_SIGNATURE_SIZE, "SPK Decrypted Hash"); Status = RecreatePaddingAndCheck(DecryptSignature, HashSignature); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO, "Partition SPK Signature " "Authentication failed\r\n"); return XST_FAILURE; } SignaturePtr += RSA_SPK_SIGNATURE_SIZE; /* * Decrypt Partition Signature */ rsa2048_pubexp((RSA_NUMBER)DecryptSignature, (RSA_NUMBER)SignaturePtr, (u32)SpkExp, (RSA_NUMBER)SpkModular, (RSA_NUMBER)SpkModularEx); FsblPrintArray(DecryptSignature, RSA_PARTITION_SIGNATURE_SIZE, "Partition Decrypted Hash"); /* * Partition Authentication * Calculate Hash Signature */ sha_256((u8 *)Buffer, (Size - RSA_PARTITION_SIGNATURE_SIZE), HashSignature); FsblPrintArray(HashSignature, 32, "Partition Hash Calculated"); Status = RecreatePaddingAndCheck(DecryptSignature, HashSignature); if (Status != XST_SUCCESS) { fsbl_printf(DEBUG_INFO, "Partition Signature " "Authentication failed\r\n"); return XST_FAILURE; } return XST_SUCCESS; }
/****************************************************************************** * * This function is used to restart Watchdog * * @param None * * @return None * * @note None * *******************************************************************************/ void XFsbl_RestartWdt(void) { XWdtPs_RestartWdt(&Watchdog); }
/** * This function is used to initialize the system * * @param None * * @return None * *****************************************************************************/ u32 XFsbl_InitWdt(void) { s32 Status; u32 UStatus; XWdtPs_Config *ConfigPtr; /* Config structure of the WatchDog Timer */ u32 CounterValue; u32 RegValue; /** * Initialize the WDT timer */ ConfigPtr = XWdtPs_LookupConfig(XFSBL_WDT_DEVICE_ID); if(ConfigPtr==NULL) { UStatus = XFSBL_WDT_INIT_FAILED; goto END; } Status = XWdtPs_CfgInitialize(&Watchdog, ConfigPtr, ConfigPtr->BaseAddress); if (Status != XFSBL_SUCCESS) { XFsbl_Printf(DEBUG_INFO, "XFSBL_WDT_INIT_FAILED\n\r"); UStatus = XFSBL_WDT_INIT_FAILED; goto END; } /** * Setting the divider value */ XWdtPs_SetControlValue(&Watchdog, XWDTPS_CLK_PRESCALE, XWDTPS_CCR_PSCALE_4096); /** * Convert time to Watchdog counter reset value */ CounterValue = XFsbl_ConvertTime_WdtCounter(XFSBL_WDT_EXPIRE_TIME); /** * Set the Watchdog counter reset value */ XWdtPs_SetControlValue(&Watchdog, XWDTPS_COUNTER_RESET, CounterValue); /** * enable reset output, as we are only using this as a basic counter */ XWdtPs_EnableOutput(&Watchdog, XWDTPS_RESET_SIGNAL); /* Enable generation of system reset by PMU due to LPD SWDT */ RegValue = XFsbl_In32(PMU_GLOBAL_ERROR_SRST_EN_1); RegValue |= PMU_GLOBAL_ERROR_SRST_EN_1_LPD_SWDT_MASK; XFsbl_Out32(PMU_GLOBAL_ERROR_SRST_EN_1, RegValue); /* Enable LPD System Watchdog Timer Error */ RegValue = XFsbl_In32(PMU_GLOBAL_ERROR_EN_1); RegValue |= PMU_GLOBAL_ERROR_EN_1_LPD_SWDT_MASK; XFsbl_Out32(PMU_GLOBAL_ERROR_EN_1, RegValue); /** * Start the Watchdog timer */ XWdtPs_Start(&Watchdog); XWdtPs_RestartWdt(&Watchdog); UStatus = XFSBL_SUCCESS; END: return UStatus; }