/** * This function initializes the processor and updates the cluster id * which indicates CPU on which fsbl is running * * @param FsblInstancePtr is pointer to the XFsbl Instance * * @return returns the error codes described in xfsbl_error.h on any error * returns XFSBL_SUCCESS on success * ******************************************************************************/ static u32 XFsbl_ProcessorInit(XFsblPs * FsblInstancePtr) { u32 Status = XFSBL_SUCCESS; //u64 ClusterId=0U; PTRSIZE ClusterId=0U; u32 RegValue; u32 Index=0U; /** * Read the cluster ID and Update the Processor ID * Initialize the processor settings that are not done in * BSP startup code */ #ifdef ARMA53_64 ClusterId = mfcp(MPIDR_EL1); #else ClusterId = mfcp(XREG_CP15_MULTI_PROC_AFFINITY); #endif XFsbl_Printf(DEBUG_INFO,"Cluster ID 0x%0lx\n\r", ClusterId); if (XGet_Zynq_UltraMp_Platform_info() == XPLAT_ZYNQ_ULTRA_MPQEMU) { /** * Remmaping for R5 in QEMU */ if (ClusterId == 0x80000004U) { ClusterId = 0xC0000100U; } else if (ClusterId == 0x80000005U) { /* this corresponds to R5-1 */ Status = XFSBL_ERROR_UNSUPPORTED_CLUSTER_ID; XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_UNSUPPORTED_CLUSTER_ID\n\r"); goto END; } else { /* For MISRA C compliance */ } } /* store the processor ID based on the cluster ID */ if ((ClusterId & XFSBL_CLUSTER_ID_MASK) == XFSBL_A53_PROCESSOR) { XFsbl_Printf(DEBUG_GENERAL,"Running on A53-0 "); FsblInstancePtr->ProcessorID = XIH_PH_ATTRB_DEST_CPU_A53_0; #ifdef __aarch64__ /* Running on A53 64-bit */ XFsbl_Printf(DEBUG_GENERAL,"(64-bit) Processor \n\r"); FsblInstancePtr->A53ExecState = XIH_PH_ATTRB_A53_EXEC_ST_AA64; #else /* Running on A53 32-bit */ XFsbl_Printf(DEBUG_GENERAL,"(32-bit) Processor \n\r"); FsblInstancePtr->A53ExecState = XIH_PH_ATTRB_A53_EXEC_ST_AA32; #endif } else if ((ClusterId & XFSBL_CLUSTER_ID_MASK) == XFSBL_R5_PROCESSOR) { /* A53ExecState is not valid for R5 */ FsblInstancePtr->A53ExecState = XIH_INVALID_EXEC_ST; RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL); if ((RegValue & RPU_RPU_GLBL_CNTL_SLSPLIT_MASK) == 0U) { XFsbl_Printf(DEBUG_GENERAL, "Running on R5 Processor in Lockstep \n\r"); FsblInstancePtr->ProcessorID = XIH_PH_ATTRB_DEST_CPU_R5_L; } else { XFsbl_Printf(DEBUG_GENERAL, "Running on R5-0 Processor \n\r"); FsblInstancePtr->ProcessorID = XIH_PH_ATTRB_DEST_CPU_R5_0; } /** * Update the Vector locations in R5 TCM */ while (Index<32U) { XFsbl_Out32(Index, XFSBL_R5_VECTOR_VALUE); Index += 4; } } else { Status = XFSBL_ERROR_UNSUPPORTED_CLUSTER_ID; XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_UNSUPPORTED_CLUSTER_ID\n\r"); goto END; } /** * Register the exception handlers */ XFsbl_RegisterHandlers(); /* Prints for the perf measurement */ #ifdef XFSBL_PERF #if !defined(ARMR5) if (FsblInstancePtr->ProcessorID == XIH_PH_ATTRB_DEST_CPU_A53_0) { XFsbl_Printf(DEBUG_PRINT_ALWAYS, "Proc: A53-0 Freq: %d Hz", XPAR_CPU_CORTEXA53_0_CPU_CLK_FREQ_HZ); if (FsblInstancePtr->A53ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32) { XFsbl_Printf(DEBUG_PRINT_ALWAYS, " Arch: 32 \r\n"); } else if (FsblInstancePtr->A53ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA64) { XFsbl_Printf(DEBUG_PRINT_ALWAYS, " Arch: 64 \r\n"); } } #else if (FsblInstancePtr->ProcessorID == XIH_PH_ATTRB_DEST_CPU_R5_0) { XFsbl_Printf(DEBUG_PRINT_ALWAYS, "Proc: R5-0 Freq: %d Hz \r\n", XPAR_PSU_CORTEXR5_0_CPU_CLK_FREQ_HZ) } else if (FsblInstancePtr->ProcessorID == XIH_PH_ATTRB_DEST_CPU_R5_L) { XFsbl_Printf(DEBUG_PRINT_ALWAYS, "Proc: R5-Lockstep " "Freq: %d Hz \r\n", XPAR_PSU_CORTEXR5_0_CPU_CLK_FREQ_HZ); } #endif #endif END: return Status; }
/** * 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; }
/****************************************************************************** * * This function is used to notify PMU firmware (if present) that initialization * of all PM related register is completed * * @param None * * @return Success or XFSBL_ERROR_PM_INIT in case of any error * * @note None * *******************************************************************************/ u32 XFsbl_PmInit(void) { u32 UStatus; /* Proceed only if SYSCFG is enabled */ #ifdef XPAR_XILPM_ENABLED #ifdef XPAR_XIPIPSU_0_DEVICE_ID s32 Status ; XIpiPsu IpiInstance; XIpiPsu_Config *Config; u32 Response = 0U; #ifdef __aarch64__ u32 CfgCmd[2U] = {PM_SET_CONFIGURATION, (u32)((u64)&XPm_ConfigObject[0])}; #else u32 CfgCmd[2U] = {PM_SET_CONFIGURATION, (u32)&XPm_ConfigObject[0]}; #endif #endif /** * Mark to the PMU that FSBL has completed with system initialization * This is needed for the JTAG boot mode */ Xil_Out32(PMU_GLOBAL_PERS_GLOB_GEN_STORAGE5, PM_INIT_COMPLETED_KEY); /** * Check if PMU FW is present * If PMU FW is present, but IPI device does not exist, report an error * If IPI device exists, but PMU FW is not present, do not issue IPI */ if ((XFsbl_In32(PMU_GLOBAL_GLOBAL_CNTRL) & PMU_GLOBAL_GLOBAL_CNTRL_FW_IS_PRESENT_MASK) != PMU_GLOBAL_GLOBAL_CNTRL_FW_IS_PRESENT_MASK) { XFsbl_Printf(DEBUG_PRINT_ALWAYS,"PMU-FW is not running, certain applications may not be supported.\n\r"); UStatus = XFSBL_SUCCESS; goto END; } #ifndef XPAR_XIPIPSU_0_DEVICE_ID else { UStatus = XFSBL_ERROR_PM_INIT; XFsbl_Printf(DEBUG_GENERAL, "PMU firmware is present, but IPI is disabled\r\n"); goto END; } #endif #ifdef XPAR_XIPIPSU_0_DEVICE_ID /* Initialize IPI peripheral */ Config = XIpiPsu_LookupConfig(IPI_DEVICE_ID); if (Config == NULL) { UStatus = XFSBL_ERROR_PM_INIT; goto END; } Status = XIpiPsu_CfgInitialize(&IpiInstance, Config, Config->BaseAddress); if (XFSBL_SUCCESS != Status) { UStatus = XFSBL_ERROR_PM_INIT; goto END; } /* Send PM_SET_CONFIGURATION API to the PMU */ Status = XIpiPsu_WriteMessage(&IpiInstance, IPI_PMU_PM_INT_MASK, &CfgCmd[0], 2U, XIPIPSU_BUF_TYPE_MSG); if (XFSBL_SUCCESS != Status) { UStatus = XFSBL_ERROR_PM_INIT; goto END; } Status = XIpiPsu_TriggerIpi(&IpiInstance, IPI_PMU_PM_INT_MASK); if (XFSBL_SUCCESS != Status) { UStatus = XFSBL_ERROR_PM_INIT; goto END; } /* This is a blocking call, wait until IPI is handled by the PMU */ Status = XIpiPsu_PollForAck(&IpiInstance, IPI_PMU_PM_INT_MASK, PM_IPI_TIMEOUT); if (XFSBL_SUCCESS != Status) { UStatus = XFSBL_ERROR_PM_INIT; goto END; } Status = XIpiPsu_ReadMessage(&IpiInstance, IPI_PMU_PM_INT_MASK, &Response, 1, XIPIPSU_BUF_TYPE_RESP); if ((Status != XFSBL_SUCCESS) || (Response != XFSBL_SUCCESS)) { UStatus = XFSBL_ERROR_PM_INIT; goto END; } #endif /** end of IPI related code */ #endif /* End of XPAR_XILPM_ENABLED */ XFsbl_Printf(DEBUG_DETAILED,"PM Init Success\r\n"); UStatus = XFSBL_SUCCESS; END: return UStatus; }
/** * This function authenticates the bitstream in blocks. Sends the data to PCAP * in blocks via AES engine if encryption exists or directly to PCAP by CSUDMA * if an encryption is not enabled. * * @param PartitionParams is pointer to XFsblPs_PlPartition structure * which has to be initialized by required parameters. * * @return * - XFSBL_SUCCESS on success * - Returns error code on failure * * @note Currently SHA2 is not been supported but gave option in * structure and will be used later * ******************************************************************************/ u32 XFsbl_SecPlPartition(XFsblPs * FsblInstancePtr, XFsblPs_PlPartition *PartitionParams) { u32 Status = XFSBL_SUCCESS; u8 Index; u32 Len; UINTPTR SrcAddress = (u64)PartitionParams->StartAddress; UINTPTR CurrentAcOffset = PartitionParams->PlAuth.AcOfset; u8 IsLastBlock = FALSE; u32 RegVal; if (PartitionParams->IsAuthenticated != TRUE) { XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_SECURE_NOT_ENABLED" " for PL partition\r\n"); Status = XFSBL_ERROR_SECURE_NOT_ENABLED; goto END; } /* AES initialization expects IV in required format */ if (PartitionParams->IsEncrypted == TRUE) { PartitionParams->PlEncrypt.NextBlkLen = 0; if (PartitionParams->PlEncrypt.SecureAes == NULL) { XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_SECURE_NOT_ENABLED" " for PL partition \r\n"); Status = XFSBL_ERROR_SECURE_NOT_ENABLED; goto END; } if ((PartitionParams->PlEncrypt.SecureAes->KeySel == XSECURE_CSU_AES_KEY_SRC_KUP) && (PartitionParams->PlEncrypt.SecureAes->Key == NULL)) { XFsbl_Printf(DEBUG_GENERAL, "KUP key is not been provided" " for PL partition\r\n"); Status = XFSBL_FAILURE; goto END; } } /* Enable Simple DMA Mode for ADMA channel 0 */ RegVal = XFsbl_In32(ADMA_CH0_ZDMA_CH_CTRL0); RegVal &= (ADMA_CH0_ZDMA_CH_CTRL0_POINT_TYPE_MASK | ADMA_CH0_ZDMA_CH_CTRL0_MODE_MASK); XFsbl_Out32(ADMA_CH0_ZDMA_CH_CTRL0, RegVal); Xil_DCacheDisable(); /* Loop for traversing all blocks */ for (Len = PartitionParams->PlAuth.BlockSize, Index = 1; SrcAddress < PartitionParams->PlAuth.AcOfset; Index++) { Status = XFsbl_CopyData(PartitionParams, PartitionParams->PlAuth.AuthCertBuf, (u8 *)CurrentAcOffset, XFSBL_AUTH_CERT_MIN_SIZE); if (Status != XFSBL_SUCCESS) { XFsbl_Printf(DEBUG_GENERAL, "Copy of chunk from flash/DDR to OCM failed \r\n"); return Status; } /* * If the block start address + block size exceeds * first AC address it is last block */ if (SrcAddress + PartitionParams->PlAuth.BlockSize > PartitionParams->PlAuth.AcOfset) { /* * Data placed in last block might not be full block size * TotalLen - * (NoofBlocks)*(AC size) - (NoOfBlocks - 1)*BlockSize */ Len = (PartitionParams->TotalLen) - (Index) * (XFSBL_AUTH_CERT_MIN_SIZE) - (Index -1)*(PartitionParams->PlAuth.BlockSize); IsLastBlock = TRUE; } Status = XFsbl_PlBlockAuthentication(FsblInstancePtr, PartitionParams, SrcAddress, Len, (u8 *)PartitionParams->PlAuth.AuthCertBuf); if (Status != XFSBL_SUCCESS) { return Status; } if (IsLastBlock == FALSE) { CurrentAcOffset = CurrentAcOffset + XFSBL_AUTH_CERT_MIN_SIZE; SrcAddress = SrcAddress + PartitionParams->PlAuth.BlockSize; } else { /* Completed last block of bitstream */ break; } } Xil_DCacheEnable(); #ifdef XFSBL_PS_DDR /* Restore reset values for the DMA registers used */ XFsbl_Out32(ADMA_CH0_ZDMA_CH_CTRL0, 0x00000080U); XFsbl_Out32(ADMA_CH0_ZDMA_CH_DST_DSCR_WORD0, 0x00000000U); XFsbl_Out32(ADMA_CH0_ZDMA_CH_DST_DSCR_WORD1, 0x00000000U); XFsbl_Out32(ADMA_CH0_ZDMA_CH_DST_DSCR_WORD2, 0x00000000U); XFsbl_Out32(ADMA_CH0_ZDMA_CH_DST_DSCR_WORD3, 0x00000000U); XFsbl_Out32(ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD0, 0x00000000U); XFsbl_Out32(ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD1, 0x00000000U); XFsbl_Out32(ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD2, 0x00000000U); XFsbl_Out32(ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD3, 0x00000000U); #endif END: return Status; }