/** * * This function is the interrupt handler for the CSU_DMA driver. * * This handler reads the interrupt status from the Status register, determines * the source of the interrupts, calls according callbacks, and finally clears * the interrupts. * * @param CallBackRef is the callback reference passed from the interrupt * handler, which in our case is a pointer to the driver instance. * * @return None. * * @note None. * ******************************************************************************/ void IntrHandler(void *CallBackRef) { u32 SrcPending; u32 DstPending; XCsuDma *XCsuDmaPtr = NULL; XCsuDmaPtr = (XCsuDma *)((void *)CallBackRef); /* Handling interrupt */ /* Getting pending interrupts of source */ SrcPending = XCsuDma_IntrGetStatus(XCsuDmaPtr, XCSUDMA_SRC_CHANNEL); XCsuDma_IntrClear(XCsuDmaPtr, XCSUDMA_SRC_CHANNEL, SrcPending); SrcPending &= (~XCsuDma_GetIntrMask(XCsuDmaPtr, XCSUDMA_SRC_CHANNEL)); /* Getting pending interrupts of destination */ DstPending = XCsuDma_IntrGetStatus(XCsuDmaPtr, XCSUDMA_DST_CHANNEL); XCsuDma_IntrClear(XCsuDmaPtr, XCSUDMA_DST_CHANNEL, DstPending); DstPending &= (~XCsuDma_GetIntrMask(XCsuDmaPtr, XCSUDMA_DST_CHANNEL)); if (SrcPending != 0x00) { SrcHandler(XCsuDmaPtr, SrcPending); } if (DstPending != 0x00) { DstHandler(XCsuDmaPtr, DstPending); } }
/** This is the function to write data to PCAP interface * * @param WrSize: Number of 32bit words that the DMA should write to * the PCAP interface * @param WrAddr: Linear memory space from where CSUDMA will read * the data to be written to PCAP interface * * @return None * *****************************************************************************/ u32 XFsbl_WriteToPcap(u32 WrSize, u8 *WrAddr) { u32 RegVal; u32 Status = XFSBL_SUCCESS; /* * Setup the SSS, setup the PCAP to receive from DMA source */ RegVal = XFsbl_In32(CSU_CSU_SSS_CFG) & CSU_CSU_SSS_CFG_PCAP_SSS_MASK; RegVal = RegVal | (XFSBL_CSU_SSS_SRC_SRC_DMA << CSU_CSU_SSS_CFG_PCAP_SSS_SHIFT); XFsbl_Out32(CSU_CSU_SSS_CFG, RegVal); /* Setup the source DMA channel */ XCsuDma_Transfer(&CsuDma, XCSUDMA_SRC_CHANNEL, (PTRSIZE) WrAddr, WrSize, 0); /* wait for the SRC_DMA to complete and the pcap to be IDLE */ XCsuDma_WaitForDone(&CsuDma, XCSUDMA_SRC_CHANNEL); /* Acknowledge the transfer has completed */ XCsuDma_IntrClear(&CsuDma, XCSUDMA_SRC_CHANNEL, XCSUDMA_IXR_DONE_MASK); XFsbl_Printf(DEBUG_GENERAL, "DMA transfer done \r\n"); Status = XFsbl_PcapWaitForDone(); if (Status != XFSBL_SUCCESS) { goto END; } END: return Status; }
/****************************************************************************** * * This function decrypts the secure header when key rolling is enabled * * @param InstancePtr is an instance AES engine. * @param SrcAddr holds the address of secure header * @param Size holds size * * @return * Error code on failure * XFSBL_SUCESS on success * * @note None * ******************************************************************************/ static u32 XFsbl_DecrypSecureHdr(XSecure_Aes *InstancePtr, u64 SrcAddr, u32 Size) { XCsuDma_Configure ConfigurValues = {0}; u32 GcmStatus; XCsuDma_GetConfig(InstancePtr->CsuDmaPtr, XCSUDMA_SRC_CHANNEL, &ConfigurValues); ConfigurValues.EndianType = 1U; XCsuDma_SetConfig(InstancePtr->CsuDmaPtr, XCSUDMA_SRC_CHANNEL, &ConfigurValues); /* * Push secure header before that configure to * push IV and key to csu engine */ XSecure_WriteReg(InstancePtr->BaseAddress, XSECURE_CSU_AES_KUP_WR_OFFSET, XSECURE_CSU_AES_IV_WR | XSECURE_CSU_AES_KUP_WR); XCsuDma_IntrClear(InstancePtr->CsuDmaPtr, XCSUDMA_SRC_CHANNEL, XCSUDMA_IXR_DONE_MASK); /* PUSH Secure hdr */ XFsbl_DmaPlCopy(InstancePtr->CsuDmaPtr, SrcAddr, XSECURE_SECURE_HDR_SIZE/4, 1); /* Restore Key write register to 0. */ XSecure_WriteReg(InstancePtr->BaseAddress, XSECURE_CSU_AES_KUP_WR_OFFSET, 0x0); /* Push the GCM tag. */ XFsbl_DmaPlCopy(InstancePtr->CsuDmaPtr, SrcAddr + XSECURE_SECURE_HDR_SIZE, XSECURE_SECURE_GCM_TAG_SIZE/4, 1); /* Disable CSU DMA Src channel for byte swapping. */ XCsuDma_GetConfig(InstancePtr->CsuDmaPtr, XCSUDMA_SRC_CHANNEL, &ConfigurValues); ConfigurValues.EndianType = 0U; XCsuDma_SetConfig(InstancePtr->CsuDmaPtr, XCSUDMA_SRC_CHANNEL, &ConfigurValues); XSecure_PcapWaitForDone(); XSecure_AesWaitForDone(InstancePtr); /* Get the AES status to know if GCM check passed. */ GcmStatus = XSecure_ReadReg(InstancePtr->BaseAddress, XSECURE_CSU_AES_STS_OFFSET) & XSECURE_CSU_AES_STS_GCM_TAG_OK; if (GcmStatus == 0) { XFsbl_Printf(DEBUG_GENERAL, "XFSBL_DECRYPT:" "XFSBL_ERROR_BITSTREAM_GCM_TAG_MISMATCH\r\n"); return XFSBL_ERROR_BITSTREAM_GCM_TAG_MISMATCH; } return XFSBL_SUCCESS; }
/****************************************************************************** * * This function is used to copy data to AES/PL. * * @param InstancePtr is an instance of CSUDMA * @param Src holds the source Address * @param Size of the data * @param EnLast - 0 or 1 * * @return None * * @note None * ******************************************************************************/ static void XFsbl_DmaPlCopy(XCsuDma *InstancePtr, UINTPTR Src, u32 Size, u8 EnLast) { /* Data transfer */ XCsuDma_Transfer(InstancePtr, XCSUDMA_SRC_CHANNEL, (UINTPTR)Src, Size, EnLast); /* Polling for transfer to be done */ XCsuDma_WaitForDone(InstancePtr, XCSUDMA_SRC_CHANNEL); /* To acknowledge the transfer has completed */ XCsuDma_IntrClear(InstancePtr, XCSUDMA_SRC_CHANNEL, XCSUDMA_IXR_DONE_MASK); }
/** * * Update hash for new input data block * * @param InstancePtr is a pointer to the XSecure_Sha3 instance. * @param Data is the pointer to the input data for hashing * @param Size of the input data in bytes * * @return None * * @note None * ******************************************************************************/ void XSecure_Sha3Update(XSecure_Sha3 *InstancePtr, const u8 *Data, const u32 Size) { /* Asserts validate the input arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Size != (u32)0x00U); InstancePtr->Sha3Len += Size; XCsuDma_Transfer(InstancePtr->CsuDmaPtr, XCSUDMA_SRC_CHANNEL, (UINTPTR)Data, (u32)Size/4, 0); /* Checking the CSU DMA done bit should be enough. */ XCsuDma_WaitForDone(InstancePtr->CsuDmaPtr, XCSUDMA_SRC_CHANNEL); /* Acknowledge the transfer has completed */ XCsuDma_IntrClear(InstancePtr->CsuDmaPtr, XCSUDMA_SRC_CHANNEL, XCSUDMA_IXR_DONE_MASK); }
/** * * This function performs data transfer in loop back mode in polled mode * and verify the data. * * @param DeviceId is the XPAR_<CSUDMA Instance>_DEVICE_ID value from * xparameters.h. * * @return * - XST_SUCCESS if successful. * - XST_FAILURE if failed. * * @note None. * ******************************************************************************/ int XCsuDma_PolledExample(u16 DeviceId) { int Status; XCsuDma_Config *Config; u32 Index = 0; u32 *SrcPtr = (u32 *)SRC_ADDR; u32 *DstPtr = (u32 *)DST_ADDR; u32 Test_Data = 0xABCD1234; u32 *Ptr = (u32 *)SRC_ADDR; u32 EnLast = 0; /* * Initialize the CsuDma driver so that it's ready to use * look up the configuration in the config table, * then initialize it. */ Config = XCsuDma_LookupConfig(DeviceId); if (NULL == Config) { return XST_FAILURE; } Status = XCsuDma_CfgInitialize(&CsuDma, Config, Config->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Performs the self-test to check hardware build. */ Status = XCsuDma_SelfTest(&CsuDma); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Setting CSU_DMA in loop back mode. */ Xil_Out32(XCSU_BASEADDRESS + CSU_SSS_CONFIG_OFFSET, ((Xil_In32(XCSU_BASEADDRESS + CSU_SSS_CONFIG_OFFSET) & 0xF0000) | CSUDMA_LOOPBACK_CFG)); /* Data writing at source address location */ for(Index = 0; Index < SIZE; Index++) { *Ptr = Test_Data; Test_Data += 0x1; Ptr++; } /* Data transfer in loop back mode */ XCsuDma_Transfer(&CsuDma, XCSUDMA_DST_CHANNEL, DST_ADDR, SIZE, EnLast); XCsuDma_Transfer(&CsuDma, XCSUDMA_SRC_CHANNEL, SRC_ADDR, SIZE, EnLast); /* Polling for transfer to be done */ XCsuDma_WaitForDone(&CsuDma, XCSUDMA_DST_CHANNEL); /* To acknowledge the transfer has completed */ XCsuDma_IntrClear(&CsuDma, XCSUDMA_SRC_CHANNEL, XCSUDMA_IXR_DONE_MASK); XCsuDma_IntrClear(&CsuDma, XCSUDMA_DST_CHANNEL, XCSUDMA_IXR_DONE_MASK); /* * Verifying data of transfered by comparing data at source * and address locations. */ for (Index = 0; Index < SIZE; Index++) { if (*SrcPtr != *DstPtr) { return XST_FAILURE; } else { SrcPtr++; DstPtr++; } } return XST_SUCCESS; }
/** * * This function performs data transfer in loop back mode in interrupt mode * and verify the data. * * @param DeviceId is the XPAR_<CSUDMA Instance>_DEVICE_ID value from * xparameters.h. * * @return * - XST_SUCCESS if successful. * - XST_FAILURE if failed. * * @note None. * ******************************************************************************/ int XCsuDma_IntrExample(u16 DeviceId) { int Status; XCsuDma_Config *Config; u32 Index = 0; u32 *SrcPtr = (u32 *)SRC_ADDR; u32 *DstPtr = (u32 *)DST_ADDR; u32 Test_Data = 0xABCD1234; u32 *Ptr = (u32 *)SRC_ADDR; u32 EnLast = 0; /* * Initialize the CsuDma driver so that it's ready to use * look up the configuration in the config table, * then initialize it. */ Config = XCsuDma_LookupConfig(DeviceId); if (NULL == Config) { return XST_FAILURE; } Status = XCsuDma_CfgInitialize(&CsuDma, Config, Config->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Performs the self-test to check hardware build. */ Status = XCsuDma_SelfTest(&CsuDma); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Connect to the interrupt controller. */ Status = SetupInterruptSystem(&Intc, &CsuDma, INTG_CSUDMA_INTR_DEVICE_ID); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* Enable interrupts */ XCsuDma_EnableIntr(&CsuDma, XCSUDMA_DST_CHANNEL, XCSUDMA_IXR_DONE_MASK); /* * Setting CSU_DMA in loop back mode. */ Xil_Out32(XCSU_BASEADDRESS + CSU_SSS_CONFIG_OFFSET, (Xil_In32(XCSU_BASEADDRESS + CSU_SSS_CONFIG_OFFSET) | CSUDMA_LOOPBACK_CFG)); /* Data writing at source address location */ for(Index = 0; Index < SIZE; Index++) { *Ptr = Test_Data; Test_Data += 0x1; Ptr++; } /* Data transfer in loop back mode */ XCsuDma_Transfer(&CsuDma, XCSUDMA_DST_CHANNEL, DST_ADDR, SIZE, EnLast); XCsuDma_Transfer(&CsuDma, XCSUDMA_SRC_CHANNEL, SRC_ADDR, SIZE, EnLast); /* Wait for generation of destination work is done */ while(DstDone == 0); /* Disable interrupts */ XCsuDma_DisableIntr(&CsuDma, XCSUDMA_DST_CHANNEL, XCSUDMA_IXR_DONE_MASK); /* To acknowledge the transfer has completed */ XCsuDma_IntrClear(&CsuDma, XCSUDMA_SRC_CHANNEL, XCSUDMA_IXR_DONE_MASK); XCsuDma_IntrClear(&CsuDma, XCSUDMA_DST_CHANNEL, XCSUDMA_IXR_DONE_MASK); /* * Verifying data of transfered by comparing data at * source and address locations. */ for (Index = 0; Index < SIZE; Index++) { if (*SrcPtr != *DstPtr) { return XST_FAILURE; } else { SrcPtr++; DstPtr++; } } return XST_SUCCESS; }