예제 #1
0
/**
 * This function is initializes the processor and system.
 *
 * @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
 *
 *****************************************************************************/
u32 XFsbl_Initialize(XFsblPs * FsblInstancePtr)
{
	u32 Status = XFSBL_SUCCESS;
	u32 ResetReason;

	ResetReason = XFsbl_GetResetReason();
	if (ResetReason == PS_ONLY_RESET) {
		FsblInstancePtr->ResetReason = PS_ONLY_RESET;
	}

	/**
	 * Configure the system as in PSU
	 */
	Status = XFsbl_SystemInit(FsblInstancePtr);
	if (XFSBL_SUCCESS != Status) {
		goto END;
	}

	/**
	 * Print the FSBL banner
	 */
	XFsbl_PrintFsblBanner();

	/* Do ECC Initialization of DDR if required */
	Status = XFsbl_DdrEccInit();
	if (XFSBL_SUCCESS != Status) {
		goto END;
	}

	/* Do board specific initialization if any */
	Status = XFsbl_BoardInit();
	if (XFSBL_SUCCESS != Status) {
		goto END;
	}
	/**
	 * Initialize the processor
	 */
	Status = XFsbl_ProcessorInit(FsblInstancePtr);
	if (XFSBL_SUCCESS != Status) {
		goto END;
	}

	/**
	 * Validate the reset reason
	 */
	Status = XFsbl_ResetValidation(FsblInstancePtr);
	if (XFSBL_SUCCESS != Status) {
		goto END;
	}

	XFsbl_Printf(DEBUG_INFO,"Processor Initialization Done \n\r");
END:
	return Status;
}
예제 #2
0
void XFsbl_PrintFsblBanner(void )
{
	/**
	 * Print the FSBL Banner
	 */
	XFsbl_Printf(DEBUG_PRINT_ALWAYS,
                 "Xilinx Zynq MP First Stage Boot Loader \n\r");
	XFsbl_Printf(DEBUG_PRINT_ALWAYS,
                 "Release %d.%d   %s  -  %s\r\n",
                 SDK_RELEASE_YEAR, SDK_RELEASE_QUARTER,__DATE__,__TIME__);
	/**
	 * Print the platform
	 */
	if (XFSBL_PLATFORM == XFSBL_PLATFORM_QEMU)
	{
		XFsbl_Printf(DEBUG_GENERAL, "Platform: QEMU, ");
	} else  if (XFSBL_PLATFORM == XFSBL_PLATFORM_REMUS)
	{
		XFsbl_Printf(DEBUG_GENERAL, "Platform: REMUS, ");
	} else  if (XFSBL_PLATFORM == XFSBL_PLATFORM_SILICON)
	{
		XFsbl_Printf(DEBUG_GENERAL, "Platform: Silicon, ");
	} else {
		XFsbl_Printf(DEBUG_GENERAL, "Platform Not identified \r\n");
	}

	return ;
}
/**
 *
 *
 *
 * @param	None
 *
 * @return	None
 *
 ******************************************************************************/
void XFsbl_MakeSdFileName(char *XFsbl_SdEmmcFileName,
		u32 MultibootReg, u32 DrvNum)
{

	u32 Index;
	u32 Value;
	u32 FileNameLen;
	u32 MultiBootNum = MultibootReg;

	if (0x0U == MultiBootNum)
	{
		/* SD file name is BOOT.BIN when Multiboot register value is 0 */
		if (DrvNum == XFSBL_SD_DRV_NUM_0) {
			(void)XFsbl_Strcpy(XFsbl_SdEmmcFileName, "BOOT.BIN");
		}
		else {
			/* For second SD instance, include drive number 1 as well */
			(void)XFsbl_Strcpy(XFsbl_SdEmmcFileName, "1:/BOOT.BIN");
		}
	}
	else
	{
		/* set default SD file name as BOOT0000.BIN */
		if (DrvNum == XFSBL_SD_DRV_NUM_0) {
			(void)XFsbl_Strcpy(XFsbl_SdEmmcFileName, "BOOT0000.BIN");
			FileNameLen = XFSBL_BASE_FILE_NAME_LEN_SD_0;
		}
		else {
			/* For second SD instance, include drive number 1 as well */
			(void)XFsbl_Strcpy(XFsbl_SdEmmcFileName, "1:/BOOT0000.BIN");
			FileNameLen = XFSBL_BASE_FILE_NAME_LEN_SD_1;
		}

		/* Update file name (to BOOTXXXX.BIN) based on Multiboot register value */
		for(Index = FileNameLen - 1U;
				Index >= (FileNameLen - XFSBL_NUM_DIGITS_IN_FILE_NAME);
				Index--)
		{
			Value = MultiBootNum % 10U;
			MultiBootNum = MultiBootNum / 10U;
			XFsbl_SdEmmcFileName[Index] += (char)Value;
			if (MultiBootNum == 0U)
			{
				break;
			}
		}
	}

	XFsbl_Printf(DEBUG_INFO,
			"File name is %s\r\n",XFsbl_SdEmmcFileName);
}
static u32 XFsbl_ResetValidation(XFsblPs * FsblInstancePtr)
{
	u32 Status =  XFSBL_SUCCESS;
	u32 FsblErrorStatus=0U;
	u32 ResetReasonValue=0U;
	u32 ErrStatusRegValue;

	/**
	 *  Read the Error Status register
	 *  If WDT reset, do fallback
	 */
	FsblErrorStatus = XFsbl_In32(XFSBL_ERROR_STATUS_REGISTER_OFFSET);

	ResetReasonValue = XFsbl_In32(CRL_APB_RESET_REASON);
	ErrStatusRegValue = XFsbl_In32(PMU_GLOBAL_ERROR_STATUS_1);

	/**
	 * Check if the reset is due to system WDT during
	 * previous FSBL execution
	 */
	if (((ResetReasonValue & CRL_APB_RESET_REASON_PMU_SYS_RESET_MASK)
			== CRL_APB_RESET_REASON_PMU_SYS_RESET_MASK) &&
			((ErrStatusRegValue & PMU_GLOBAL_ERROR_STATUS_1_LPD_SWDT_MASK)
			== PMU_GLOBAL_ERROR_STATUS_1_LPD_SWDT_MASK) &&
			(FsblErrorStatus == XFSBL_RUNNING)) {
		/**
		 * reset is due to System WDT.
		 * Do a fallback
		 */
		Status = XFSBL_ERROR_SYSTEM_WDT_RESET;
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_SYSTEM_WDT_RESET\n\r");
		goto END;
	}

	/**
	 * Mark FSBL running in error status register to
	 * detect the WDT reset while FSBL execution
	 */
	if (FsblErrorStatus != XFSBL_RUNNING) {
		XFsbl_Out32(XFSBL_ERROR_STATUS_REGISTER_OFFSET,
						  XFSBL_RUNNING);
	}

	/**
	 *  Read system error status register
	 * 	provide FsblHook function for any action
	 */

END:
	return Status;
}
예제 #5
0
/**
 * This function waits for PL Done bit to be set or till timeout and resets
 * PCAP after this.
 *
 * @param	None
 *
 * @return	error status based on implemented functionality (SUCCESS by default)
 *
 *****************************************************************************/
u32 XFsbl_PLWaitForDone(void) {
	u32 Status = XFSBL_SUCCESS;
	u32 PollCount;
	u32 RegVal;

	PollCount = (PL_DONE_POLL_COUNT);
	while (PollCount) {
		/* Read PCAP Status register and check for PL_DONE bit */
		RegVal = XFsbl_In32(CSU_PCAP_STATUS);
		RegVal &= CSU_PCAP_STATUS_PL_DONE_MASK;
		if (RegVal == CSU_PCAP_STATUS_PL_DONE_MASK) {
			break;
		}
		PollCount--;
	}

	if (RegVal == CSU_PCAP_STATUS_PL_DONE_MASK) {
		XFsbl_Printf(DEBUG_GENERAL, "PL Configuration done successfully \r\n");
	} else {
		Status = XFSBL_ERROR_BITSTREAM_LOAD_FAIL;
		XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_BITSTREAM_LOAD_FAIL\r\n");
		goto END;
	}

	/* Reset PCAP after data transfer */
	RegVal = XFsbl_In32(CSU_PCAP_RESET);
	RegVal = RegVal | CSU_PCAP_RESET_RESET_MASK;
	XFsbl_Out32(CSU_PCAP_RESET, RegVal);

	do {
		RegVal = XFsbl_In32(CSU_PCAP_RESET);
		RegVal = RegVal & CSU_PCAP_RESET_RESET_MASK;
	} while (RegVal != CSU_PCAP_RESET_RESET_MASK);

	END:
	return Status;
}
void XFsbl_EccInitialize(u32 Address, u32 Length)
{
	u32 Index=0U;

	/* Disable cache to ensure proper ECC initialization */
	Xil_DCacheDisable();
	while (Index<Length)
	{
		XFsbl_Out32(Address+Index, 1U) ;
		Index += 4U;
	}
	Xil_DCacheEnable();

	XFsbl_Printf(DEBUG_INFO,
	  "Address 0x%0lx, Length %0lx, ECC initialized \r\n",
		Address, Length);

	return ;
}
예제 #7
0
/**
 * In Fallback,  soft reset is applied to the system after incrementing
 * the multiboot register. A hook is provided to before the fallback so
 * that users can write their own code before soft reset
 *
 * @param none
 *
 * @return none
 *
 * @note We will not return from this function as it does soft reset
 *****************************************************************************/
void XFsbl_FallBack(void)
{
	u32 RegValue;

#ifdef XFSBL_WDT_PRESENT
	/* Stop WDT as we are restarting */
	XFsbl_StopWdt();
#endif

	/* Hook before FSBL Fallback */
	XFsbl_HookBeforeFallback();

	/* Read the Multiboot register */
	RegValue = XFsbl_In32(CSU_CSU_MULTI_BOOT);

	XFsbl_Printf(DEBUG_GENERAL,"Performing FSBL FallBack\n\r");

	XFsbl_UpdateMultiBoot(RegValue+1);

	return;
}
예제 #8
0
void XFsbl_UpdateMultiBoot(u32 MultiBootValue)
{
	u32 RegValue;

	XFsbl_Out32(CSU_CSU_MULTI_BOOT, MultiBootValue);

	/* make sure every thing completes */
	dsb();
	isb();

	/* Soft reset the system */
	XFsbl_Printf(DEBUG_GENERAL,"Performing System Soft Reset\n\r");
	RegValue = XFsbl_In32(CRL_APB_RESET_CTRL);
	XFsbl_Out32(CRL_APB_RESET_CTRL,
			RegValue|CRL_APB_RESET_CTRL_SOFT_RESET_MASK);

	/* wait here until reset happens */
	while(1);

	return;

}
/**
 * FSBL exit function before the assembly code
 *
 * @param HandoffAddress is handoff address for the FSBL running cpu
 *
 * @param Flags is to determine whether to handoff to applicatio or
 * 			to be in wfe state
 *
 * @return None
 *
 *
 *****************************************************************************/
void XFsbl_HandoffExit(u64 HandoffAddress, u32 Flags)
{

	/**
	 * Flush the L1 data cache and L2 cache, Disable Data Cache
	 */
	Xil_DCacheDisable();

	XFsbl_Printf(DEBUG_GENERAL,"Exit from FSBL \n\r");

	/**
	 * Exit to handoff address
	 * PTRSIZE is used since handoff is in same running cpu
	 * and address is of PTRSIZE
	 */
	XFsbl_Exit((PTRSIZE) HandoffAddress, Flags);

	/**
	 * should not reach here
	 */
	return ;

}
/**
 * This function is initializes the processor and system.
 *
 * @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
 *
 *****************************************************************************/
u32 XFsbl_Initialize(XFsblPs * FsblInstancePtr)
{
	u32 Status = XFSBL_SUCCESS;

	/**
	 * Configure the system as in PSU
	 */
	Status = XFsbl_SystemInit(FsblInstancePtr);
	if (XFSBL_SUCCESS != Status) {
		goto END;
	}

	/**
	 * Print the FSBL banner
	 */
	XFsbl_PrintFsblBanner();

	/**
	 * Initialize the processor
	 */
	Status = XFsbl_ProcessorInit(FsblInstancePtr);
	if (XFSBL_SUCCESS != Status) {
		goto END;
	}

	/**
	 * Validate the reset reason
	 */
	Status = XFsbl_ResetValidation(FsblInstancePtr);
	if (XFSBL_SUCCESS != Status) {
		goto END;
	}

	XFsbl_Printf(DEBUG_INFO,"Processor Initialization Done \n\r");
END:
	return Status;
}
/**
*
* @param
*
* @return
*
* @note
*
*
*****************************************************************************/
static void XFsbl_UndefHandler (void)
{
	XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_UNDEFINED_EXCEPTION\n\r");
	XFsbl_ErrorLockDown(XFSBL_ERROR_UNDEFINED_EXCEPTION);
}
예제 #12
0
/**
 * 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;
}
예제 #13
0
/**
 * This function is used to perform GT configuration for ZCU102 board.
 * It also provides reset to GEM, enables FMC ADJ
 *
 * @param none
 *
 * @return
 * 		- XFSBL_SUCCESS for successful configuration
 * 		- errors as mentioned in xfsbl_error.h
 *
 *****************************************************************************/
static s32 XFsbl_BoardConfig(void)
{

	u8 WriteBuffer[BUF_LEN] = {0};
	XIicPs_Config *I2c0CfgPtr;
	s32 Status = XFSBL_SUCCESS;
	u32 ICMCfg0;
	u32 ICMCfg1;

	/* Initialize the IIC0 driver so that it is ready to use */
	I2c0CfgPtr = XIicPs_LookupConfig(XPAR_XIICPS_0_DEVICE_ID);
	if (I2c0CfgPtr == NULL) {
		Status = XFSBL_ERROR_I2C_INIT;
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_I2C_INIT\r\n");
		goto END;
	}

	Status = XIicPs_CfgInitialize(&I2c0InstancePtr, I2c0CfgPtr,
			I2c0CfgPtr->BaseAddress);
	if (Status != XST_SUCCESS) {
		Status = XFSBL_ERROR_I2C_INIT;
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_I2C_INIT\r\n");
		goto END;
	}

	/* Set the IIC serial clock rate */
	XIicPs_SetSClk(&I2c0InstancePtr, IIC_SCLK_RATE_IOEXP);

	/* Configure I/O pins as Output */
	WriteBuffer[0] = CMD_CFG_0_REG;
	WriteBuffer[1] = DATA_OUTPUT;
	Status = XIicPs_MasterSendPolled(&I2c0InstancePtr,
			WriteBuffer, 2, IOEXPANDER1_ADDR);
	if (Status != XST_SUCCESS) {
		Status = XFSBL_ERROR_I2C_WRITE;
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_I2C_WRITE\r\n");
		goto END;
	}

	/* Wait until bus is idle to start another transfer */
	while (XIicPs_BusIsBusy(&I2c0InstancePtr));

	/*
	 * Deasserting I2C_MUX_RESETB
	 * And GEM3 Resetb
	 * Selecting lanes based on configuration
	 */
	WriteBuffer[0] = CMD_OUTPUT_0_REG;

	/* Populate WriteBuffer[1] based on ICM_CFG configuration */
	ICMCfg0 = XFsbl_In32(SERDES_ICM_CFG0) &
			(SERDES_ICM_CFG0_L0_ICM_CFG_MASK | SERDES_ICM_CFG0_L1_ICM_CFG_MASK);

	ICMCfg1 = XFsbl_In32(SERDES_ICM_CFG1) &
			(SERDES_ICM_CFG1_L2_ICM_CFG_MASK | SERDES_ICM_CFG1_L3_ICM_CFG_MASK);

	if ((ICMCfg0 == ICM_CFG0_PCIE_DP) && (ICMCfg1 == ICM_CFG1_USB_SATA))
	{
		/* gt1110 */
		WriteBuffer[1] = DATA_COMMON_CFG | DATA_GT_1110_CFG;
	}
	else
	if ((ICMCfg0 == ICM_CFG0_DP_DP) && (ICMCfg1 == ICM_CFG1_USB_SATA))
	{
		/* gt1111 */
		WriteBuffer[1] = DATA_COMMON_CFG | DATA_GT_1111_CFG;
	}
	else
	if ((ICMCfg0 == ICM_CFG0_PCIE_PCIE) && (ICMCfg1 == ICM_CFG1_USB_SATA))
	{
		/* gt1100 */
		WriteBuffer[1] = DATA_COMMON_CFG | DATA_GT_1100_CFG;
	}
	else
	{
		/* gt0000 or no GT configuration */
		WriteBuffer[1] = DATA_COMMON_CFG | DATA_GT_0000_CFG;
	}

	/* Send the Data */
	Status = XIicPs_MasterSendPolled(&I2c0InstancePtr,
			WriteBuffer, 2, IOEXPANDER1_ADDR);
	if (Status != XST_SUCCESS) {
		Status = XFSBL_ERROR_I2C_WRITE;
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_I2C_WRITE\r\n");
		goto END;
	}

	/* Wait until bus is idle */
	while (XIicPs_BusIsBusy(&I2c0InstancePtr));

	/* Change the IIC serial clock rate */
	XIicPs_SetSClk(&I2c0InstancePtr, IIC_SCLK_RATE_I2CMUX);

	/* Set I2C Mux for channel-2 (MAXIM_PMBUS) */
	WriteBuffer[0] = CMD_CH_2_REG;
	Status = XIicPs_MasterSendPolled(&I2c0InstancePtr,
			WriteBuffer, 1, PCA9544A_ADDR);
	if (Status != XST_SUCCESS) {
		Status = XFSBL_ERROR_I2C_WRITE;
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_I2C_WRITE\r\n");
		goto END;
	}

	/* Wait until bus is idle */
	while (XIicPs_BusIsBusy(&I2c0InstancePtr));

	/* Enable Regulator (FMC ADJ) */
	WriteBuffer[0] = CMD_ON_OFF_CFG;
	WriteBuffer[1] = ON_OFF_CFG_VAL;
	Status = XIicPs_MasterSendPolled(&I2c0InstancePtr,
			WriteBuffer, 2, MAX15301_ADDR);
	if (Status != XST_SUCCESS) {
		Status = XFSBL_ERROR_I2C_WRITE;
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_I2C_WRITE\r\n");
		goto END;
	}

	/* Wait until bus is idle */
	while (XIicPs_BusIsBusy(&I2c0InstancePtr));

	XFsbl_Printf(DEBUG_INFO,"Board Configuration successful \n\r");

END:

	return Status;

}
/**
 * This function validates the partition
 *
 * @param	FsblInstancePtr is pointer to the XFsbl Instance
 *
 * @param	PartitionNum is the partition number in the image to be loaded
 *
 * @return	returns the error codes described in xfsbl_error.h on any error
 * 			returns XFSBL_SUCCESS on success
 *
 *****************************************************************************/
static u32 XFsbl_PartitionValidation(XFsblPs * FsblInstancePtr,
						u32 PartitionNum)
{
	u32 Status=XFSBL_SUCCESS;
	u32 ChecksumType=0U;
	s32 IsEncryptionEnabled=FALSE;
	s32 IsAuthenticationEnabled=FALSE;
	u32 DestinationDevice=0U;
	u32 DestinationCpu=0U;
	u32 ExecState=0U;
	u32 CpuNo=0U;
	XFsblPs_PartitionHeader * PartitionHeader;
#if defined(XFSBL_RSA)
	u32 HashLen=0U;
#endif
#if defined(XFSBL_AES)
	u32 ImageOffset = 0U;
	u32 FsblIv[XIH_BH_IV_LENGTH / 4U];
	u32 UnencryptedLength = 0;
	u32 IvLocation;
#endif
#if defined(XFSBL_RSA) || defined(XFSBL_AES)
	u32 Length=0U;
#endif
#if defined(XFSBL_RSA) || defined(XFSBL_AES) || defined(XFSBL_BS)
	PTRSIZE LoadAddress=0U;
#endif
#if defined(XFSBL_BS)
	u32 BitstreamWordSize = 0;
#endif

	/**
	 * Update the variables
	 */
	PartitionHeader =
	    &FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum];
	ChecksumType = XFsbl_GetChecksumType(PartitionHeader);

	/**
	 * Check the encryption status
	 */
	if (XFsbl_IsEncrypted(PartitionHeader) ==
			XIH_PH_ATTRB_ENCRYPTION )
	{
		IsEncryptionEnabled = TRUE;

#ifdef XFSBL_AES
		/* Copy the Iv from Flash into local memory */
		IvLocation = ImageOffset + XIH_BH_IV_OFFSET;

		Status = FsblInstancePtr->DeviceOps.DeviceCopy(IvLocation,
				(PTRSIZE) FsblIv, XIH_BH_IV_LENGTH);

		if (Status != XFSBL_SUCCESS) {
			XFsbl_Printf(DEBUG_GENERAL,
					"XFSBL_ERROR_DECRYPTION_IV_COPY_FAIL \r\n");
			Status = XFSBL_ERROR_DECRYPTION_IV_COPY_FAIL;
			goto END;
		}
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_AES_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_AES_NOT_ENABLED;
		goto END;
#endif
	}

	/**
	 * check the authentication status
	 */
	if (XFsbl_IsRsaSignaturePresent(PartitionHeader) ==
			XIH_PH_ATTRB_RSA_SIGNATURE )
	{
		IsAuthenticationEnabled = TRUE;
	}
	DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader);
	DestinationCpu = XFsbl_GetDestinationCpu(PartitionHeader);


	/**
         * Get the execution state
         */
        ExecState = XFsbl_GetA53ExecState(PartitionHeader);

	/**
	 * if destination cpu is not present, it means it is for same cpu
	 */
	if (DestinationCpu == XIH_PH_ATTRB_DEST_CPU_NONE)
	{
		DestinationCpu = FsblInstancePtr->ProcessorID;
	}


	/**
	 * Checksum Validation
	 */
	if (ChecksumType == XIH_PH_ATTRB_CHECKSUM_MD5)
	{
		/**
		 * Do the checksum validation
		 */
	}

#if defined(XFSBL_RSA) || defined(XFSBL_AES)
	if ((IsAuthenticationEnabled == TRUE) || (IsEncryptionEnabled == TRUE))
	{
		LoadAddress = PartitionHeader->DestinationLoadAddress;
		Length = PartitionHeader->TotalDataWordLength * 4U;
		Status = XFsbl_GetLoadAddress(DestinationCpu,
				&LoadAddress, Length);
		if (XFSBL_SUCCESS != Status)
		{
			goto END;
		}
	}
#endif

#ifdef XFSBL_BS
	if ((DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL) &&
			(LoadAddress == 0U))
	{
		LoadAddress = XFSBL_DDR_TEMP_ADDRESS;
	}
#endif

	/**
	 * Authentication Check
	 */
	if (IsAuthenticationEnabled == TRUE)
	{
		XFsbl_Printf(DEBUG_INFO,"Authentication Enabled\r\n");
#ifdef XFSBL_RSA
		/**
		 * Get the Sha type to be used from
		 * boot header attributes
		 */
		if ((FsblInstancePtr->BootHdrAttributes &
			XIH_BH_IMAGE_ATTRB_SHA2_MASK) ==
			XIH_BH_IMAGE_ATTRB_SHA2_MASK)
		{
			HashLen = XFSBL_HASH_TYPE_SHA2;
		} else {
			HashLen = XFSBL_HASH_TYPE_SHA3;
		}

		/**
		 * cache disbale can be removed
		 */
		Xil_DCacheDisable();

		/**
		 * Do the authentication validation
		 */
		Status = XFsbl_Authentication(FsblInstancePtr, LoadAddress, Length,
			(LoadAddress + Length) - XFSBL_AUTH_CERT_MIN_SIZE,
			HashLen);

		if (Status != XFSBL_SUCCESS)
                {
                        goto END;
                }
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_RSA_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_RSA_NOT_ENABLED;
		goto END;
#endif
	}

	/**
	 * Decrypt image through CSU DMA
	 */
	if (IsEncryptionEnabled == TRUE) {
		XFsbl_Printf(DEBUG_INFO, "Decryption Enabled\r\n");
#ifdef XFSBL_AES

		/* AES expects IV in big endian form */
		FsblIv[0] = Xil_Htonl(FsblIv[0]);
		FsblIv[1] = Xil_Htonl(FsblIv[1]);
		FsblIv[2] = Xil_Htonl(FsblIv[2]);

		/* Initialize the Aes Instance so that it's ready to use */
		XSecure_AesInitialize(&SecureAes, &CsuDma,
		 XSECURE_CSU_AES_KEY_SRC_DEV, FsblIv, NULL);

		XFsbl_Printf(DEBUG_INFO, " Aes initialized \r\n");

		UnencryptedLength = PartitionHeader->UnEncryptedDataWordLength * 4U;


		if (DestinationDevice != XIH_PH_ATTRB_DEST_DEVICE_PL) {
			Status = XSecure_AesDecrypt(&SecureAes, (u8 *) LoadAddress,
					(u8 *) LoadAddress, UnencryptedLength);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_DECRYPTION_FAIL;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_DECRYPTION_FAIL\r\n");
				goto END;
			} else {
				XFsbl_Printf(DEBUG_GENERAL, "Decryption Successful\r\n");
			}
		}
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_AES_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_AES_NOT_ENABLED;
		goto END;
#endif
	}

#ifdef XFSBL_BS
	/**
	 * for PL image use CSU DMA to route to PL
	 */
	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL)
	{
		/**
		 * Fsbl hook before bit stream download
		 */
		Status = XFsbl_HookBeforeBSDownload();
		if (Status != XFSBL_SUCCESS)
		{
			Status = XFSBL_ERROR_HOOK_BEFORE_BITSTREAM_DOWNLOAD;
			XFsbl_Printf(DEBUG_GENERAL,
			 "XFSBL_ERROR_HOOK_BEFORE_BITSTREAM_DOWNLOAD\r\n");
			goto END;
		}

		XFsbl_Printf(DEBUG_GENERAL, "Bitstream download to start now\r\n");

		Status = XFsbl_PcapInit();
		if (Status != XFSBL_SUCCESS) {
			goto END;
		}

		if (IsEncryptionEnabled == TRUE) {
#ifdef XFSBL_AES
			/*
			 * The secure bitstream would be sent through CSU DMA to AES
			 * and the decrypted bitstream is sent directly to PCAP
			 * by configuring SSS appropriately
			 */
			Status = XSecure_AesDecrypt(&SecureAes,
					(u8 *) XFSBL_DESTINATION_PCAP_ADDR,
					(u8 *) LoadAddress, UnencryptedLength);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_BITSTREAM_DECRYPTION_FAIL;
				XFsbl_Printf(DEBUG_GENERAL,
						"XFSBL_ERROR_BITSTREAM_DECRYPTION_FAIL\r\n");
				/* Reset PL */
				XFsbl_Out32(CSU_PCAP_PROG, 0x0);
				goto END;
			} else {
				XFsbl_Printf(DEBUG_GENERAL,
						"Bitstream decryption Successful\r\n");
			}
#endif
		}
		else {

			/* Use CSU DMA to load Bit stream to PL */
			BitstreamWordSize = PartitionHeader->UnEncryptedDataWordLength;

			Status = XFsbl_WriteToPcap(BitstreamWordSize, (u8 *) LoadAddress);
			if (Status != XFSBL_SUCCESS) {
				goto END;
			}
		}

		Status = XFsbl_PLWaitForDone();
		if (Status != XFSBL_SUCCESS) {
			goto END;
		}

		/**
		 * Fsbl hook after bit stream download
		 */
		Status = XFsbl_HookAfterBSDownload();
		if (Status != XFSBL_SUCCESS)
		{
			Status = XFSBL_ERROR_HOOK_AFTER_BITSTREAM_DOWNLOAD;
			XFsbl_Printf(DEBUG_GENERAL,
			 "XFSBL_ERROR_HOOK_AFTER_BITSTREAM_DOWNLOAD\r\n");
			goto END;
		}
	}
#endif

	/**
	 * Update the handoff details
	 */
	if ((DestinationDevice != XIH_PH_ATTRB_DEST_DEVICE_PL) &&
			(DestinationDevice != XIH_PH_ATTRB_DEST_DEVICE_PMU))
	{
		CpuNo = FsblInstancePtr->HandoffCpuNo;
		if (XFsbl_CheckHandoffCpu(FsblInstancePtr,
				DestinationCpu) == XFSBL_SUCCESS)
		{
			FsblInstancePtr->HandoffValues[CpuNo].CpuSettings =
					DestinationCpu | ExecState;
			FsblInstancePtr->HandoffValues[CpuNo].HandoffAddress =
					PartitionHeader->DestinationExecutionAddress;
			FsblInstancePtr->HandoffCpuNo += 1U;
		}
	}

END:
	return Status;
}
static u32 XFsbl_SetCpuPwrSettings (u32 CpuSettings, u32 Flags)
{
	u32 RegValue;
	u32 Status;
	u32 CpuId;
	u32 ExecState;
	u32 PwrStateMask;

	/**
	 * Reset the CPU
	 */
	if ((Flags & XFSBL_CPU_SWRST) != 0U)
	{
	CpuId = CpuSettings & XIH_PH_ATTRB_DEST_CPU_MASK;
		ExecState = CpuSettings & XIH_PH_ATTRB_A53_EXEC_ST_MASK;
		switch(CpuId)
		{

			case XIH_PH_ATTRB_DEST_CPU_A53_0:

			PwrStateMask = PMU_GLOBAL_PWR_STATE_ACPU0_MASK |
				PMU_GLOBAL_PWR_STATE_FP_MASK |
				PMU_GLOBAL_PWR_STATE_L2_BANK0_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_A53_0_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_A53_0_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Set to Aarch32 if enabled
			 */
			if (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)
			{
				RegValue = XFsbl_In32(APU_CONFIG_0);
				RegValue &= ~(APU_CONFIG_0_AA64N32_MASK_CPU0);
				XFsbl_Out32(APU_CONFIG_0, RegValue);
			}

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRF_APB_ACPU_CTRL);
			RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK |
			             CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK);
			XFsbl_Out32(CRF_APB_ACPU_CTRL, RegValue);

			/**
			 * Release reset
			 */
			RegValue = XFsbl_In32(CRF_APB_RST_FPD_APU);
			RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU0_RESET_MASK |
					CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK |
					CRF_APB_RST_FPD_APU_ACPU0_PWRON_RESET_MASK);
			XFsbl_Out32(CRF_APB_RST_FPD_APU, RegValue);

			break;

		case XIH_PH_ATTRB_DEST_CPU_A53_1:

			PwrStateMask = PMU_GLOBAL_PWR_STATE_ACPU1_MASK |
				PMU_GLOBAL_PWR_STATE_FP_MASK |
				PMU_GLOBAL_PWR_STATE_L2_BANK0_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_A53_1_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_A53_1_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Set to Aarch32 if enabled
			 */
			if (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)
			{
				RegValue = XFsbl_In32(APU_CONFIG_0);
				RegValue &= ~(APU_CONFIG_0_AA64N32_MASK_CPU1);
				XFsbl_Out32(APU_CONFIG_0, RegValue);
			}

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRF_APB_ACPU_CTRL);
			RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK |
			             CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK);
			XFsbl_Out32(CRF_APB_ACPU_CTRL, RegValue);

			/**
			 * Release reset
			 */
			RegValue = XFsbl_In32(CRF_APB_RST_FPD_APU);
			RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU1_RESET_MASK |
					CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK |
					CRF_APB_RST_FPD_APU_ACPU1_PWRON_RESET_MASK);
			XFsbl_Out32(CRF_APB_RST_FPD_APU, RegValue);

			break;

		case XIH_PH_ATTRB_DEST_CPU_A53_2:

			PwrStateMask = PMU_GLOBAL_PWR_STATE_ACPU2_MASK |
				PMU_GLOBAL_PWR_STATE_FP_MASK |
				PMU_GLOBAL_PWR_STATE_L2_BANK0_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_A53_2_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_A53_2_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Set to Aarch32 if enabled
			 */
			if (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)
			{
				RegValue = XFsbl_In32(APU_CONFIG_0);
				RegValue &= ~(APU_CONFIG_0_AA64N32_MASK_CPU2);
				XFsbl_Out32(APU_CONFIG_0, RegValue);
			}

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRF_APB_ACPU_CTRL);
			RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK |
			             CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK);
			XFsbl_Out32(CRF_APB_ACPU_CTRL, RegValue);

			/**
			 * Release reset
			 */
			RegValue = XFsbl_In32(CRF_APB_RST_FPD_APU);
			RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU2_RESET_MASK |
					CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK |
					CRF_APB_RST_FPD_APU_ACPU2_PWRON_RESET_MASK);

			XFsbl_Out32(CRF_APB_RST_FPD_APU, RegValue);

			break;

		case XIH_PH_ATTRB_DEST_CPU_A53_3:

			PwrStateMask = PMU_GLOBAL_PWR_STATE_ACPU3_MASK |
				PMU_GLOBAL_PWR_STATE_FP_MASK |
				PMU_GLOBAL_PWR_STATE_L2_BANK0_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_A53_3_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_A53_3_POWER_UP\r\n");
				goto END;
			}


			/**
			 * Set to Aarch32 if enabled
			 */
			if (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)
			{
				RegValue = XFsbl_In32(APU_CONFIG_0);
				RegValue &= ~(APU_CONFIG_0_AA64N32_MASK_CPU3);
				XFsbl_Out32(APU_CONFIG_0, RegValue);
			}

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRF_APB_ACPU_CTRL);
			RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK |
			             CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK);
			XFsbl_Out32(CRF_APB_ACPU_CTRL, RegValue);

			/**
			 * Release reset
			 */
			RegValue = XFsbl_In32(CRF_APB_RST_FPD_APU);
			RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU3_RESET_MASK |
					CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK |
					CRF_APB_RST_FPD_APU_ACPU3_PWRON_RESET_MASK);

			XFsbl_Out32(CRF_APB_RST_FPD_APU, RegValue);

			break;

		case XIH_PH_ATTRB_DEST_CPU_R5_0:

			Status = XFsbl_PowerUpIsland(PMU_GLOBAL_PWR_STATE_R5_0_MASK);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_R5_0_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_R5_0_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Place R5, TCM's in split mode
			 */
			RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
			RegValue |= (RPU_RPU_GLBL_CNTL_SLSPLIT_MASK);
			RegValue &= ~(RPU_RPU_GLBL_CNTL_TCM_COMB_MASK);
			RegValue &= ~(RPU_RPU_GLBL_CNTL_SLCLAMP_MASK);
			XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue);

			/**
			 * Place R5-0 in HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_0_CFG);
			RegValue &= ~(RPU_RPU_0_CFG_NCPUHALT_MASK);
			XFsbl_Out32(RPU_RPU_0_CFG, RegValue);

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL);
			RegValue |= (CRL_APB_CPU_R5_CTRL_CLKACT_MASK);
			XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue);

			/**
			 * Provide some delay,
			 * so that clock propogates properly.
			 */
			(void)usleep(0x50U);


			/**
			 * Release reset to R5-0
			 */
			RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK);
			XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue);


			/**
			 * Take R5-0 out of HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_0_CFG);
			RegValue |= RPU_RPU_0_CFG_NCPUHALT_MASK;
			XFsbl_Out32(RPU_RPU_0_CFG, RegValue);
			break;

		case XIH_PH_ATTRB_DEST_CPU_R5_1:

			Status = XFsbl_PowerUpIsland(PMU_GLOBAL_PWR_STATE_R5_1_MASK);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_R5_1_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_R5_1_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Place R5, TCM's in split mode
			 */
			RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
			RegValue |= RPU_RPU_GLBL_CNTL_SLSPLIT_MASK;
			RegValue &= ~(RPU_RPU_GLBL_CNTL_TCM_COMB_MASK);
			RegValue &= ~(RPU_RPU_GLBL_CNTL_SLCLAMP_MASK);
			XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue);

			/**
			 * Place R5-1 in HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_1_CFG);
			RegValue &= ~(RPU_RPU_1_CFG_NCPUHALT_MASK);
			XFsbl_Out32(RPU_RPU_1_CFG, RegValue);

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL);
			RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK;
			XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue);

			/**
			 * Provide some delay,
			 * so that clock propogates properly.
			 */
			(void)usleep(0x50U);

			/**
			 * Release reset to R5-1
			 */
			RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK);
			XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue);


			/**
			 * Take R5-1 out of HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_1_CFG);
			RegValue |= RPU_RPU_1_CFG_NCPUHALT_MASK;
			XFsbl_Out32(RPU_RPU_1_CFG, RegValue);
			break;
		case XIH_PH_ATTRB_DEST_CPU_R5_L:

			Status = XFsbl_PowerUpIsland(PMU_GLOBAL_PWR_STATE_R5_0_MASK);
			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_R5_L_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_R5_L_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Place R5, TCM's in safe mode
			 */
			RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
			RegValue &= ~(RPU_RPU_GLBL_CNTL_SLSPLIT_MASK);
			RegValue |= RPU_RPU_GLBL_CNTL_TCM_COMB_MASK;
			RegValue |= RPU_RPU_GLBL_CNTL_SLCLAMP_MASK;
			XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue);

			/**
			 * Place R5-0 in HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_0_CFG);
			RegValue &= ~(RPU_RPU_0_CFG_NCPUHALT_MASK);
			XFsbl_Out32(RPU_RPU_0_CFG, RegValue);

			/**
			 * Place R5-1 in HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_1_CFG);
			RegValue &= ~(RPU_RPU_1_CFG_NCPUHALT_MASK);
			XFsbl_Out32(RPU_RPU_1_CFG, RegValue);

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL);
			RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK;
			XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue);

			/**
			 * Provide some delay,
			 * so that clock propogates properly.
			 */
			(void )usleep(0x50U);

			/**
			 * Release reset to R5-0, R5-1
			 */
			RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK);
			XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue);


			/**
			 * Take R5-0 out of HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_0_CFG);
			RegValue |= RPU_RPU_0_CFG_NCPUHALT_MASK;
			XFsbl_Out32(RPU_RPU_0_CFG, RegValue);

			/**
			 * Take R5-1 out of HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_1_CFG);
			RegValue |= RPU_RPU_1_CFG_NCPUHALT_MASK;
			XFsbl_Out32(RPU_RPU_1_CFG, RegValue);
			break;

		default:
			XFsbl_Printf(DEBUG_GENERAL,
			    "XFSBL_ERROR_HANDOFF_CPUID\n\r");
			Status = XFSBL_ERROR_HANDOFF_CPUID;
			break;
		}

	}
	else
	{
		Status = XFSBL_SUCCESS;
	}
END:
	return Status;
}
u32 XFsbl_GetLoadAddress(u32 DestinationCpu, PTRSIZE * LoadAddressPtr, u32 Length)
{
	u32 Status = XFSBL_SUCCESS;
	PTRSIZE Address=0U;

	Address = *LoadAddressPtr;

	/**
	 * Update for R50 TCM address
	 */
	if ((DestinationCpu == XIH_PH_ATTRB_DEST_CPU_R5_0) &&
			(Address <= XFSBL_R5_TCM_END_ADDRESS))
	{
		/**
		 * Check if fits to TCM or not
		 */
		if ((Address + Length) > XFSBL_R5_TCM_END_ADDRESS)
		{
			Status = XFSBL_ERROR_LOAD_ADDRESS;
			XFsbl_Printf(DEBUG_GENERAL,
				"XFSBL_ERROR_LOAD_ADDRESS\r\n");
			goto END;
		}

		/**
		 * Update Address to the higher TCM address
		 */
		Address = XFSBL_R50_HIGH_TCM_START_ADDRESS + Address;

	} else
	/**
	 * Update for R5-1 TCM address
	 */
	if ((DestinationCpu == XIH_PH_ATTRB_DEST_CPU_R5_1) &&
			(Address <= XFSBL_R5_TCM_END_ADDRESS))
	{
		/**
		 * Check if fits to TCM or not
		 */
		if ((Address + Length) > XFSBL_R5_TCM_END_ADDRESS)
		{
			Status = XFSBL_ERROR_LOAD_ADDRESS;
			XFsbl_Printf(DEBUG_GENERAL,
				"XFSBL_ERROR_LOAD_ADDRESS\r\n");
			goto END;
		}
		/**
		 * Update Address to the higher TCM address
		 */
		Address = XFSBL_R51_HIGH_TCM_START_ADDRESS + Address;
	} else
	/**
	 * Update for the R5-L TCM address
	 */
	if ((DestinationCpu == XIH_PH_ATTRB_DEST_CPU_R5_L) &&
			(Address <= XFSBL_R5L_TCM_END_ADDRESS))
	{
		/**
		 * Check if fits to TCM or not
		 */
		if ((Address + Length) > XFSBL_R5L_TCM_END_ADDRESS)
		{
			Status = XFSBL_ERROR_LOAD_ADDRESS;
			XFsbl_Printf(DEBUG_GENERAL,
				"XFSBL_ERROR_LOAD_ADDRESS\r\n");
			goto END;
		}
		/**
		 * Update Address to the higher TCM address
		 */
		Address = XFSBL_R50_HIGH_TCM_START_ADDRESS + Address;
	} else
	{
		/**
		 * For MISRA complaince
		 */
	}

	/**
	 * Update the LoadAddress
	 */
	*LoadAddressPtr = Address;

END:
	return Status;
}
/**
 * This function copies the partition to specified destination
 *
 * @param	FsblInstancePtr is pointer to the XFsbl Instance
 *
 * @param	PartitionNum is the partition number in the image to be loaded
 *
 * @return	returns the error codes described in xfsbl_error.h on any error
 * 			returns XFSBL_SUCCESS on success
 *****************************************************************************/
static u32 XFsbl_PartitionCopy(XFsblPs * FsblInstancePtr, u32 PartitionNum)
{
	u32 Status=XFSBL_SUCCESS;
	u32 DestinationCpu=0U;
	u32 CpuNo=0U;
	u32 DestinationDevice=0U;
	u32 ExecState=0U;
	XFsblPs_PartitionHeader * PartitionHeader;
	u32 SrcAddress=0U;
	PTRSIZE LoadAddress=0U;
	u32 Length=0U;
	u32 RunningCpu=0U;

	/**
	 * Assign the partition header to local variable
	 */
	PartitionHeader =
		&FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum];

	RunningCpu = FsblInstancePtr->ProcessorID;

	/**
	 * Check for XIP image
	 * No need to copy for XIP image
	 */
	DestinationCpu = XFsbl_GetDestinationCpu(PartitionHeader);

	/**
	 * Get the execution state
	 */
	ExecState = XFsbl_GetA53ExecState(PartitionHeader);

	/**
	 * if destination cpu is not present, it means it is for same cpu
	 */
	if (DestinationCpu == XIH_PH_ATTRB_DEST_CPU_NONE)
	{
		DestinationCpu = FsblInstancePtr->ProcessorID;
	}

	if (PartitionHeader->UnEncryptedDataWordLength == 0U)
	{
		/**
		 * Update the Handoff address only for the first application
		 * of that cpu
		 * This is for XIP image. For other partitions it handoff
		 * address is updated after partition validation
		 */
		CpuNo = FsblInstancePtr->HandoffCpuNo;
		if (XFsbl_CheckHandoffCpu(FsblInstancePtr,
				DestinationCpu) == XFSBL_SUCCESS)
		{
			FsblInstancePtr->HandoffValues[CpuNo].CpuSettings =
			        DestinationCpu | ExecState;
			FsblInstancePtr->HandoffValues[CpuNo].HandoffAddress =
				PartitionHeader->DestinationExecutionAddress;
			FsblInstancePtr->HandoffCpuNo += 1U;
		} else {
			/**
			 *
			 * if two partitions has same destination cpu, error can
			 * be triggered here
			 */
		}
		Status = XFSBL_SUCCESS;
		goto END;
	}

	/**
	 * Copy the PL to temporary DDR Address
	 * Copy the PS to Load Address
	 * Copy the PMU firmware to PMU RAM
	 */
	DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader);
	LoadAddress = PartitionHeader->DestinationLoadAddress;

	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL)
	{
#ifdef XFSBL_BS

		if (LoadAddress == XFSBL_DUMMY_PL_ADDR)
		{
			LoadAddress = XFSBL_DDR_TEMP_ADDRESS;
		}
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_PL_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_PL_NOT_ENABLED;
		goto END;
#endif
	}

	/**
	 * Get the source(flash offset) address where it needs to copy
	 */
	SrcAddress = FsblInstancePtr->ImageOffsetAddress +
				((PartitionHeader->DataWordOffset) *
					XIH_PARTITION_WORD_LENGTH);

	/**
	 * Length of the partition to be copied
	 */
	Length  = (PartitionHeader->TotalDataWordLength) *
					XIH_PARTITION_WORD_LENGTH;


	/**
	 * When destination device is R5-0/R5-1/R5-L and load address is in TCM
	 * copy to high address of TCM address map
	 * Update the LoadAddress
	 */
	Status = XFsbl_GetLoadAddress(DestinationCpu, &LoadAddress, Length);
	if (XFSBL_SUCCESS != Status)
	{
		goto END;
	}

	/**
	 * Configure the memory
	 */
	XFsbl_ConfigureMemory(RunningCpu, DestinationCpu,
						LoadAddress, Length);

	/**
	 *
	 * Do not copy the IVT if FSBL is running in R5-0/R5-L at 0x0 TCM
	 * Update the SrcAddress, LoadAddress and Len based on the
	 * above condition
	 */
#if 1
	if (((FsblInstancePtr->ProcessorID ==
			XIH_PH_ATTRB_DEST_CPU_R5_0) ||
		(FsblInstancePtr->ProcessorID ==
				XIH_PH_ATTRB_DEST_CPU_R5_L)) &&
		((LoadAddress > XFSBL_R50_HIGH_TCM_START_ADDRESS) &&
		(LoadAddress <
			XFSBL_R50_HIGH_TCM_START_ADDRESS + XFSBL_IVT_LENGTH)))
	{

		/**
		 * Get the length of the IVT area to be
		 * skipped from Load Address
		 */
		TcmSkipAddress = LoadAddress/XFSBL_IVT_LENGTH;
		TcmSkipLength = XFSBL_IVT_LENGTH - TcmSkipAddress;

		/**
		 * Check if Length is less than SkipLength
		 */
		if (TcmSkipLength > Length)
		{
			TcmSkipLength = Length;
		}

		/**
		 * Copy the Skip length to a local array
		 */
		Status = FsblInstancePtr->DeviceOps.DeviceCopy(SrcAddress,
				(PTRSIZE )TcmVectorArray, TcmSkipLength);
		if (XFSBL_SUCCESS != Status)
		{
			goto END;
		}

		SrcAddress += TcmSkipLength;
		LoadAddress +=  TcmSkipLength;
		Length -= TcmSkipLength;
	}
#endif

	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PMU)
	{
		/* Enable PMU_0 IPI */
		XFsbl_Out32(IPI_PMU_0_IER, IPI_PMU_0_IER_PMU_0_MASK);

		/* Trigger PMU0 IPI in PMU IPI TRIG Reg */
		XFsbl_Out32(IPI_PMU_0_TRIG, IPI_PMU_0_TRIG_PMU_0_MASK);

		/**
		 * Wait until PMU Microblaze goes to sleep state,
		 * before starting firmware download to PMU RAM
		 */
		while((XFsbl_In32(PMU_GLOBAL_GLOBAL_CNTRL) &
				PMU_GLOBAL_GLOBAL_CNTRL_MB_SLEEP_MASK) !=
						PMU_GLOBAL_GLOBAL_CNTRL_MB_SLEEP_MASK ) {;}
	}

	/**
	 * Copy the partition to PS_DDR/PL_DDR/TCM
	 */
	Status = FsblInstancePtr->DeviceOps.DeviceCopy(SrcAddress,
					LoadAddress, Length);
	if (XFSBL_SUCCESS != Status)
	{
		goto END;
	}

END:
	return Status;
}
/**
 * This function checks the power state and reset for the memory type
 * and release the reset if required
 *
 * @param	MemoryType is the memory to be checked
 * 			- XFSBL_R5_0_TCM
 * 			- XFSBL_R5_1_TCM
 *				(to be added)
 *			- XFSBL_R5_0_TCMA
 *			- XFSBL_R5_0_TCMB
 *			- XFSBL_PS_DDR
 *			- XFSBL_PL_DDR
 *
 * @return	none
 *****************************************************************************/
static u32 XFsbl_PowerUpMemory(u32 MemoryType)
{
	u32 RegValue;
	u32 Status = XFSBL_SUCCESS;
	u32 PwrStateMask;

	/**
	 * Check the power status of the memory
	 * Power up if required
	 *
	 * Release the reset of the memory if present
	 */
	switch (MemoryType)
	{
		case XFSBL_R5_0_TCM:
		{

			PwrStateMask = PMU_GLOBAL_PWR_STATE_R5_0_MASK |
					PMU_GLOBAL_PWR_STATE_TCM0A_MASK |
					PMU_GLOBAL_PWR_STATE_TCM0B_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_R5_0_TCM_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_R5_0_TCM_POWER_UP\r\n");
				goto END;
			}

			/**
			 * To access TCM,
			 * 	Release reset to R5 and enable the clk
			 * 	R5 is under halt state
			 *
			 * 	If R5 are out of reset and clk is enabled so doing
			 * 	again is no issue. R5 might be under running state
			 */

			/**
			 * Place R5, TCM in split mode
			 */
			RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
			RegValue |= RPU_RPU_GLBL_CNTL_SLSPLIT_MASK;
			RegValue &= ~(RPU_RPU_GLBL_CNTL_TCM_COMB_MASK);
			RegValue &= ~(RPU_RPU_GLBL_CNTL_SLCLAMP_MASK);
			XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue);

			/**
			 * Place R5-0 in HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_0_CFG);
			RegValue &= ~(RPU_RPU_0_CFG_NCPUHALT_MASK);
			XFsbl_Out32(RPU_RPU_0_CFG, RegValue);

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL);
			RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK;
			XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue);

			/**
			 * Provide some delay,
			 * so that clock propogates properly.
			 */
			(void)usleep(0x50U);

			/**
			 * Release reset to R5-0
			 */
			RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK);
			XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue);
		} break;

		case XFSBL_R5_1_TCM:
		{

			PwrStateMask = PMU_GLOBAL_PWR_STATE_R5_1_MASK |
					PMU_GLOBAL_PWR_STATE_TCM1A_MASK |
					PMU_GLOBAL_PWR_STATE_TCM1B_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_R5_1_TCM_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_R5_1_TCM_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Place R5 in split mode
			 */
			RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
			RegValue |= RPU_RPU_GLBL_CNTL_SLSPLIT_MASK;
			RegValue &= ~(RPU_RPU_GLBL_CNTL_TCM_COMB_MASK);
			RegValue &= ~(RPU_RPU_GLBL_CNTL_SLCLAMP_MASK);
			XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue);

			/**
			 * Place R5-1 in HALT state
			 */
			RegValue = XFsbl_In32(RPU_RPU_1_CFG);
			RegValue &= ~(RPU_RPU_1_CFG_NCPUHALT_MASK);
			XFsbl_Out32(RPU_RPU_1_CFG, RegValue);

			/**
			 *  Enable the clock
			 */
			RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL);
			RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK;
			XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue);

			/**
			 * Provide some delay,
			 * so that clock propogates properly.
			 */
			(void )usleep(0x50U);

			/**
			 * Release reset to R5-1
			 */
			RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK);
			RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK);
			XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue);
		} break;

		case XFSBL_R5_L_TCM:
		{


			PwrStateMask = PMU_GLOBAL_PWR_STATE_R5_0_MASK |
					PMU_GLOBAL_PWR_STATE_TCM0A_MASK |
					PMU_GLOBAL_PWR_STATE_TCM0B_MASK |
					PMU_GLOBAL_PWR_STATE_TCM1A_MASK |
					PMU_GLOBAL_PWR_STATE_TCM1B_MASK;

			Status = XFsbl_PowerUpIsland(PwrStateMask);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_R5_L_TCM_POWER_UP;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_R5_L_TCM_POWER_UP\r\n");
				goto END;
			}

			/**
			 * Place R5 in lock step mode
			 * Combine TCM's
			 */
			RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL);
			RegValue |= RPU_RPU_GLBL_CNTL_SLCLAMP_MASK;
			RegValue &= ~(RPU_RPU_GLBL_CNTL_SLSPLIT_MASK);
			RegValue |= RPU_RPU_GLBL_CNTL_TCM_COMB_MASK;
			XFsbl_Out32(RPU_RPU_GLBL_CNTL, RegValue);

			/**
                         * Place R5-0 in HALT state
                         */
                        RegValue = XFsbl_In32(RPU_RPU_0_CFG);
                        RegValue &= ~(RPU_RPU_0_CFG_NCPUHALT_MASK);
                        XFsbl_Out32(RPU_RPU_0_CFG, RegValue);

			/**
                         * Place R5-1 in HALT state
                         */
                        RegValue = XFsbl_In32(RPU_RPU_1_CFG);
                        RegValue &= ~(RPU_RPU_1_CFG_NCPUHALT_MASK);
                        XFsbl_Out32(RPU_RPU_1_CFG, RegValue);

                        /**
                         *  Enable the clock
                         */
                        RegValue = XFsbl_In32(CRL_APB_CPU_R5_CTRL);
                        RegValue |= CRL_APB_CPU_R5_CTRL_CLKACT_MASK;
                        XFsbl_Out32(CRL_APB_CPU_R5_CTRL, RegValue);

                        /**
                         * Provide some delay,
                         * so that clock propogates properly.
                         */
                        (void )usleep(0x50U);

                        /**
                         * Release reset to R5-0,R5-1
                         */
                        RegValue = XFsbl_In32(CRL_APB_RST_LPD_TOP);
                        RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK);
                        RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK);
                        RegValue &= ~(CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK);
                        XFsbl_Out32(CRL_APB_RST_LPD_TOP, RegValue);
		} break;

		default:
			/* nothing to do */
			break;
	}

END:
	return Status;
}
예제 #19
0
/**
 * This function initializes the system using the psu_init()
 *
 * @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_SystemInit(XFsblPs * FsblInstancePtr)
{
	u32 Status =  XFSBL_SUCCESS;
#if defined (XPAR_PSU_DDR_0_S_AXI_BASEADDR) && !defined (ARMR5)
	u32 BlockNum;
#endif

	/**
	 * MIO33 can be used to control power to PL through PMU.
	 * For 1.0 and 2.0 Silicon, a workaround is needed to Powerup PL
	 * before MIO33 is configured. Hence, before MIO configuration,
	 * Powerup PL (but restore isolation).
	 */
	if (XGetPSVersion_Info() <= XPS_VERSION_2) {
		Status = XFsbl_PowerUpIsland(PMU_GLOBAL_PWR_STATE_PL_MASK);

		if (Status != XFSBL_SUCCESS) {
			Status = XFSBL_ERROR_PL_POWER_UP;
			XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_PL_POWER_UP\r\n");
			goto END;
		}

		/* For PS only reset, make sure FSBL exits with isolation removed */
		if (FsblInstancePtr->ResetReason != PS_ONLY_RESET) {
		XFsbl_IsolationRestore(PMU_GLOBAL_REQ_ISO_INT_EN_PL_NONPCAP_MASK);
		}
	}

	/**
	 * psu initialization
	 */
	Status = (u32)psu_init();
	if (XFSBL_SUCCESS != Status) {
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_PSU_INIT_FAILED\n\r");
		/**
		 * Need to check a way to communicate both FSBL code
		 * and PSU init error code
		 */
		Status = XFSBL_PSU_INIT_FAILED + Status;
		goto END;
	}

#ifdef XFSBL_PERF
	XTime_GetTime(&(FsblInstancePtr->PerfTime.tFsblStart));
#endif

#if defined (XPAR_PSU_DDR_0_S_AXI_BASEADDR) && !defined (ARMR5)
	/* For A53, mark DDR region as "Memory" as DDR initialization is done */

#ifdef ARMA53_64
	/* For A53 64bit*/
	for(BlockNum = 0; BlockNum < NUM_BLOCKS_A53_64; BlockNum++)
	{
		XFsbl_SetTlbAttributes(BlockNum * BLOCK_SIZE_A53_64, ATTRIB_MEMORY_A53_64);
	}
	Xil_DCacheFlush();
#else
	/* For A53 32bit*/
	for(BlockNum = 0; BlockNum < NUM_BLOCKS_A53_32; BlockNum++)
	{
		XFsbl_SetTlbAttributes(BlockNum * BLOCK_SIZE_A53_32, ATTRIB_MEMORY_A53_32);
	}
	Xil_DCacheFlush();
#endif
#endif


	/**
	 * Forcing the SD card detection signal to bypass the debouncing logic.
	 * This will ensure that SD controller doesn't end up waiting for long,
	 * fixed durations for card to be stable.
	 */
	XFsbl_Out32(IOU_SLCR_SD_CDN_CTRL,
			(IOU_SLCR_SD_CDN_CTRL_SD1_CDN_CTRL_MASK |
					IOU_SLCR_SD_CDN_CTRL_SD0_CDN_CTRL_MASK));

	/**
	 * DDR Check if present
	 */


	/**
	 * Poweroff the unused blocks as per PSU
	 */

END:
	return Status;
}
예제 #20
0
/**
 * This function does ECC Initialization of DDR memory
 *
 * @param none
 *
 * @return
 * 		- XFSBL_SUCCESS for successful ECC Initialization
 * 		-               or ECC is not enabled for DDR
 * 		- errors as mentioned in xfsbl_error.h
 *
 *****************************************************************************/
u32 XFsbl_DdrEccInit(void)
{
	u32 Status =  XFSBL_SUCCESS;
#if XPAR_PSU_DDRC_0_HAS_ECC
	u32 LengthBytes = XFSBL_PS_DDR_END_ADDRESS - XFSBL_PS_DDR_INIT_START_ADDRESS;
	u32 Length = 0;
	u32 DestAddr = XFSBL_PS_DDR_INIT_START_ADDRESS;
	u32 RegVal;

	XFsbl_Printf(DEBUG_GENERAL,"\n\rInitializing DDR ECC\n\r");

	Xil_DCacheDisable();

	while (LengthBytes > 0) {
		if (LengthBytes > GDMA_TRANSFER_MAX_LEN) {
			Length = GDMA_TRANSFER_MAX_LEN;
		} else {
			Length = LengthBytes;
		}

		/* Wait until the DMA is in idle state */
		do {
			RegVal = XFsbl_In32(GDMA_CH0_ZDMA_CH_STATUS);
			RegVal &= GDMA_CH0_ZDMA_CH_STATUS_STATE_MASK;
		} while ((RegVal != GDMA_CH0_ZDMA_CH_STATUS_STATE_DONE) &&
				(RegVal != GDMA_CH0_ZDMA_CH_STATUS_STATE_ERR));

		/* Enable Simple (Write Only) Mode */
		RegVal = XFsbl_In32(GDMA_CH0_ZDMA_CH_CTRL0);
		RegVal &= (GDMA_CH0_ZDMA_CH_CTRL0_POINT_TYPE_MASK |
				GDMA_CH0_ZDMA_CH_CTRL0_MODE_MASK);
		RegVal |= (GDMA_CH0_ZDMA_CH_CTRL0_POINT_TYPE_NORMAL |
				GDMA_CH0_ZDMA_CH_CTRL0_MODE_WR_ONLY);
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_CTRL0, RegVal);

		/* Fill in the data to be written */
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_WR_ONLY_WORD0, XFSBL_ECC_INIT_VAL_WORD);
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_WR_ONLY_WORD1, XFSBL_ECC_INIT_VAL_WORD);
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_WR_ONLY_WORD2, XFSBL_ECC_INIT_VAL_WORD);
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_WR_ONLY_WORD3, XFSBL_ECC_INIT_VAL_WORD);

		/* Write Destination Address */
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_DST_DSCR_WORD0, DestAddr);

		/* Size to be Transferred (for write-only mode, only dest is needed)*/
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_DST_DSCR_WORD2, Length);

		/* DMA Enable */
		RegVal = XFsbl_In32(GDMA_CH0_ZDMA_CH_CTRL2);
		RegVal |= GDMA_CH0_ZDMA_CH_CTRL2_EN_MASK;
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_CTRL2, RegVal);

		/* Check the status of the transfer by polling on DMA Done */
		do {
			RegVal = XFsbl_In32(GDMA_CH0_ZDMA_CH_ISR);
			RegVal &= GDMA_CH0_ZDMA_CH_ISR_DMA_DONE_MASK;
		} while (RegVal != GDMA_CH0_ZDMA_CH_ISR_DMA_DONE_MASK);

		/* Clear DMA status */
		RegVal = XFsbl_In32(GDMA_CH0_ZDMA_CH_ISR);
		RegVal |= GDMA_CH0_ZDMA_CH_ISR_DMA_DONE_MASK;
		XFsbl_Out32(GDMA_CH0_ZDMA_CH_ISR, GDMA_CH0_ZDMA_CH_ISR_DMA_DONE_MASK);

		/* Read the channel status for errors */
		RegVal = XFsbl_In32(GDMA_CH0_ZDMA_CH_STATUS);
		if (RegVal == GDMA_CH0_ZDMA_CH_STATUS_STATE_ERR) {
			Status = XFSBL_ERROR_DDR_ECC_INIT;
			XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_DDR_ECC_INIT\n\r");
			Xil_DCacheEnable();
			goto END;
		}

		LengthBytes -= Length;
		DestAddr += Length;
	}

	Xil_DCacheEnable();

END:
#endif
	return Status;
}
/**
*
* @param
*
* @return
*
* @note
*
*
*****************************************************************************/
static void XFsbl_FiqHandler (void)
{
	XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_FIQ_EXCEPTION\n\r");
	XFsbl_ErrorLockDown(XFSBL_ERROR_FIQ_EXCEPTION);
}
/**
 * This function initializes the primary boot device
 *
 * @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_PrimaryBootDeviceInit(XFsblPs * FsblInstancePtr)
{
	u32 Status =  XFSBL_SUCCESS;
	u32 BootMode=0U;

	/**
	 * Read Boot Mode register and update the value
	 */
	BootMode = XFsbl_In32(CRL_APB_BOOT_MODE_USER) &
			CRL_APB_BOOT_MODE_USER_BOOT_MODE_MASK;

	FsblInstancePtr->PrimaryBootDevice = BootMode;

	/**
	 * Enable drivers only if they are device boot modes
	 * Not required for JTAG modes
	 */
	if ( (BootMode == XFSBL_QSPI24_BOOT_MODE) ||
			(BootMode == XFSBL_QSPI32_BOOT_MODE) ||
			(BootMode == XFSBL_NAND_BOOT_MODE) ||
			(BootMode == XFSBL_SD0_BOOT_MODE) ||
			(BootMode == XFSBL_EMMC_BOOT_MODE) ||
			(BootMode == XFSBL_SD1_BOOT_MODE) ||
			(BootMode == XFSBL_SD1_LS_BOOT_MODE)) {
		/**
		 * Initialize the WDT and CSU drivers
		 */
#ifdef XFSBL_WDT_PRESENT
		Status = XFsbl_InitWdt();
		if (XFSBL_SUCCESS != Status) {
			XFsbl_Printf(DEBUG_GENERAL,"WDT initialization failed \n\r");
			goto END;
		}
#endif

		/* Initialize CSUDMA driver */
		Status = XFsbl_CsuDmaInit();
		if (XFSBL_SUCCESS != Status) {
			goto END;
		}
	}

	switch(BootMode)
	{
		/**
		 * For JTAG boot mode, it will be in while loop
		 */
		case XFSBL_JTAG_BOOT_MODE:
		{
			XFsbl_Printf(DEBUG_GENERAL,"In JTAG Boot Mode \n\r");
			Status = XFSBL_STATUS_JTAG;
		}
		break;

		case XFSBL_QSPI24_BOOT_MODE:
		{
			XFsbl_Printf(DEBUG_GENERAL,"QSPI 24bit Boot Mode \n\r");
#ifdef XFSBL_QSPI
			/**
			 * Update the deviceops structure with necessary values
			 */
			FsblInstancePtr->DeviceOps.DeviceInit = XFsbl_Qspi24Init;
			FsblInstancePtr->DeviceOps.DeviceCopy = XFsbl_Qspi24Copy;
			FsblInstancePtr->DeviceOps.DeviceRelease = XFsbl_Qspi24Release;
#else
			/**
			 * This bootmode is not supported in this release
			 */
			XFsbl_Printf(DEBUG_GENERAL,
				"XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r");
			Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE;
#endif
		}
		break;

		case XFSBL_QSPI32_BOOT_MODE:
		{
			XFsbl_Printf(DEBUG_GENERAL,"QSPI 32 bit Boot Mode \n\r");
#ifdef XFSBL_QSPI
			/**
			 * Update the deviceops structure with necessary values
			 *
			 */
            FsblInstancePtr->DeviceOps.DeviceInit = XFsbl_Qspi32Init;
			FsblInstancePtr->DeviceOps.DeviceCopy = XFsbl_Qspi32Copy;
			FsblInstancePtr->DeviceOps.DeviceRelease = XFsbl_Qspi32Release;
#else
			/**
			 * This bootmode is not supported in this release
			 */
			XFsbl_Printf(DEBUG_GENERAL,
					"XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r");
			Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE;
#endif
        }
        break;

		case XFSBL_NAND_BOOT_MODE:
		{
			XFsbl_Printf(DEBUG_GENERAL,"NAND Boot Mode \n\r");
#ifdef XFSBL_NAND
			/**
			 * Update the deviceops structure with necessary values
			 *
			 */
			FsblInstancePtr->DeviceOps.DeviceInit = XFsbl_NandInit;
			FsblInstancePtr->DeviceOps.DeviceCopy = XFsbl_NandCopy;
			FsblInstancePtr->DeviceOps.DeviceRelease =
							XFsbl_NandRelease;
#else
			/**
			 * This bootmode is not supported in this release
			 */
			XFsbl_Printf(DEBUG_GENERAL,
				"XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r");
			Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE;
#endif
		} break;

		case XFSBL_SD0_BOOT_MODE:
		case XFSBL_EMMC_BOOT_MODE:
		{
			if (BootMode == XFSBL_SD0_BOOT_MODE) {
				XFsbl_Printf(DEBUG_GENERAL,"SD0 Boot Mode \n\r");
			}
			else {
				XFsbl_Printf(DEBUG_GENERAL,"eMMC Boot Mode \n\r");
			}
#ifdef XFSBL_SD_0
			/**
			 * Update the deviceops structure with necessary values
			 */
			FsblInstancePtr->DeviceOps.DeviceInit = XFsbl_SdInit;
			FsblInstancePtr->DeviceOps.DeviceCopy = XFsbl_SdCopy;
			FsblInstancePtr->DeviceOps.DeviceRelease = XFsbl_SdRelease;
#else
			/**
			 * This bootmode is not supported in this release
			 */
			XFsbl_Printf(DEBUG_GENERAL,
				"XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r");
			Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE;
#endif
		} break;

		case XFSBL_SD1_BOOT_MODE:
		case XFSBL_SD1_LS_BOOT_MODE:
		{
			if (BootMode == XFSBL_SD1_BOOT_MODE) {
				XFsbl_Printf(DEBUG_GENERAL, "SD1 Boot Mode \n\r");
			}
			else {
				XFsbl_Printf(DEBUG_GENERAL,
						"SD1 with level shifter Boot Mode \n\r");
			}
#ifdef XFSBL_SD_1
			/**
			 * Update the deviceops structure with necessary values
			 */
			FsblInstancePtr->DeviceOps.DeviceInit = XFsbl_SdInit;
			FsblInstancePtr->DeviceOps.DeviceCopy = XFsbl_SdCopy;
			FsblInstancePtr->DeviceOps.DeviceRelease = XFsbl_SdRelease;
#else
			/**
			 * This bootmode is not supported in this release
			 */
			XFsbl_Printf(DEBUG_GENERAL,
				"XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r");
			Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE;
#endif
		} break;

		default:
		{
			XFsbl_Printf(DEBUG_GENERAL,
					"XFSBL_ERROR_UNSUPPORTED_BOOT_MODE\n\r");
			Status = XFSBL_ERROR_UNSUPPORTED_BOOT_MODE;
		} break;

	}

	/**
	 * In case of error or Jtag boot, goto end
	 */
	if (XFSBL_SUCCESS != Status) {
		goto END;
	}

	/**
	 * Initialize the Device Driver
	 */
	Status = FsblInstancePtr->DeviceOps.DeviceInit(BootMode);
	if (XFSBL_SUCCESS != Status) {
		goto END;
	}

END:
	return Status;
}
/**
 * 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 XFSBL_A53
	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 (XFSBL_PLATFORM == XFSBL_PLATFORM_QEMU) {
		/**
		 * 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, 0U);
			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();

END:
	return Status;
}
예제 #24
0
/** This is the FSBL main function and is implemented stage wise.
 *
 * @param	None
 *
 * @return	None
 *
 *****************************************************************************/
int main(void )
{
	/**
	 * Local variables
	 */
	u32 FsblStatus = XFSBL_SUCCESS;
	u32 FsblStage = XFSBL_STAGE1;
	u32 PartitionNum=0U;
	u32 EarlyHandoff = FALSE;

	/**
	 * Initialize globals.
	 */
	FsblInstancePtr.ErrorCode = FsblStatus;

	while (1) {

		switch (FsblStage)
		{

		case XFSBL_STAGE1:
			{
				/**
				 * Initialize the system
				 */
				XFsbl_CfgInitialize(&FsblInstancePtr);

				FsblStatus = XFsbl_Initialize(&FsblInstancePtr);
				if (XFSBL_SUCCESS != FsblStatus)
				{
					FsblStatus += XFSBL_ERROR_STAGE_1;
					FsblStage = XFSBL_STAGE_ERR;
				} else {

					/**
					 *
					 * Include the code for FSBL time measurements
					 * Initialize the global timer and get the value
					 */

					FsblStage = XFSBL_STAGE2;
				}
			}break;

		case XFSBL_STAGE2:
			{

				XFsbl_Printf(DEBUG_INFO,
						"================= In Stage 2 ============ \n\r");

				/**
				 * 	Primary Device
				 *  Secondary boot device
				 *  DeviceOps
				 *  image header
				 *  partition header
				 */
				FsblStatus = XFsbl_BootDeviceInitAndValidate(&FsblInstancePtr);
				if ( (XFSBL_SUCCESS != FsblStatus) &&
						(XFSBL_STATUS_JTAG != FsblStatus) )
				{
					XFsbl_Printf(DEBUG_GENERAL,"Boot Device "
							"Initialization failed 0x%0lx\n\r", FsblStatus);
					FsblStatus += XFSBL_ERROR_STAGE_2;
					FsblStage = XFSBL_STAGE_ERR;
				} else if (XFSBL_STATUS_JTAG == FsblStatus) {
					/**
					 * This is JTAG boot mode, go to the handoff stage
					 */
					FsblStage = XFSBL_STAGE4;
				} else {
					XFsbl_Printf(DEBUG_INFO,"Initialization Success \n\r");

					/**
					 * Start the partition loading from 1
					 * 0th partition will be FSBL
					 */
					PartitionNum = 0x1U;

					FsblStage = XFSBL_STAGE3;
				}
			} break;

		case XFSBL_STAGE3:
			{

				XFsbl_Printf(DEBUG_INFO,
					"======= In Stage 3, Partition No:%d ======= \n\r",
					PartitionNum);

				/**
				 * Load the partitions
				 *  image header
				 *  partition header
				 *  partition parameters
				 */
				FsblStatus = XFsbl_PartitionLoad(&FsblInstancePtr,
								  PartitionNum);
				if (XFSBL_SUCCESS != FsblStatus)
				{
					/**
					 * Error
					 */
					XFsbl_Printf(DEBUG_GENERAL,"Partition %d Load Failed, 0x%0lx\n\r",
							PartitionNum, FsblStatus);
					FsblStatus += XFSBL_ERROR_STAGE_3;
					FsblStage = XFSBL_STAGE_ERR;
				} else {
					XFsbl_Printf(DEBUG_INFO,"Partition %d Load Success \n\r",
									PartitionNum);
					/**
					 * Check loading all partitions is completed
					 */

					FsblStatus = XFsbl_CheckEarlyHandoff(&FsblInstancePtr, PartitionNum);

					if (PartitionNum <
						(FsblInstancePtr.ImageHeader.ImageHeaderTable.NoOfPartitions-1U))
					{
						if (TRUE == FsblStatus) {
							EarlyHandoff = TRUE;
							FsblStage = XFSBL_STAGE4;
						}
						else {
							/**
							 * No need to change the Fsbl Stage
							 * Load the next partition
							 */
							PartitionNum++;
						}
					} else {
						/**
						 * No more partitions present, go to handoff stage
						 */
						XFsbl_Printf(DEBUG_INFO,"All Partitions Loaded \n\r");
						FsblStage = XFSBL_STAGE4;
						EarlyHandoff = FsblStatus;

					}
				} /* End of else loop for Load Success */
			} break;

		case XFSBL_STAGE4:
			{

				XFsbl_Printf(DEBUG_INFO,
						"================= In Stage 4 ============ \n\r");

				/**
				 * Handoff to the applications
				 * Handoff address
				 * xip
				 * ps7 post config
				 */
				FsblStatus = XFsbl_Handoff(&FsblInstancePtr, PartitionNum, EarlyHandoff);

				if (XFSBL_STATUS_CONTINUE_PARTITION_LOAD == FsblStatus) {
					XFsbl_Printf(DEBUG_INFO,"Early handoff to a application complete \n\r");
					XFsbl_Printf(DEBUG_INFO,"Continuing to load remaining partitions \n\r");

					PartitionNum++;
					FsblStage = XFSBL_STAGE3;
				}
				else if (XFSBL_STATUS_CONTINUE_OTHER_HANDOFF == FsblStatus) {
					XFsbl_Printf(DEBUG_INFO,"Early handoff to a application complete \n\r");
					XFsbl_Printf(DEBUG_INFO,"Continuing handoff to other applications, if present \n\r");
					EarlyHandoff = FALSE;
				}
				else if (XFSBL_SUCCESS != FsblStatus) {
					/**
					 * Error
					 */
					XFsbl_Printf(DEBUG_GENERAL,"Handoff Failed 0x%0lx\n\r", FsblStatus);
					FsblStatus += XFSBL_ERROR_STAGE_4;
					FsblStage = XFSBL_STAGE_ERR;
				} else {
					/**
					 * we should never be here
					 */
					FsblStage = XFSBL_STAGE_DEFAULT;
				}
			} break;

		case XFSBL_STAGE_ERR:
			{
				XFsbl_Printf(DEBUG_INFO,
						"================= In Stage Err ============ \n\r");

				XFsbl_ErrorLockDown(FsblStatus);
				/**
				 * we should never be here
				 */
				FsblStage = XFSBL_STAGE_DEFAULT;
			}break;

		case XFSBL_STAGE_DEFAULT:
		default:
			{
				/**
				 * we should never be here
				 */
				XFsbl_Printf(DEBUG_GENERAL,"In default stage: "
						"We should never be here \n\r");

				/**
				 * Exit FSBL
				 */
				XFsbl_HandoffExit(0U, XFSBL_NO_HANDOFFEXIT);

			}break;

		} /* End of switch(FsblStage) */

	} /* End of while(1)  */

	/**
	 * We should never be here
	 */
	XFsbl_Printf(DEBUG_GENERAL,"In default stage: "
				"We should never be here \n\r");
	/**
	 * Exit FSBL
	 */
	XFsbl_HandoffExit(0U, XFSBL_NO_HANDOFFEXIT);

	return 0;
}
예제 #25
0
/**
 * Configure the RSA and SHA for the SPK
 * Signature verification.
 * If SPK Signature verification fails
 * then return unique error code saying
 * XFSBL_STAGE3_SPK_SIGN_VERIF_ERROR.
 *
 * @param
 *
 * @return
 *
 ******************************************************************************/
u32 XFsbl_SpkVer(XFsblPs *FsblInstancePtr , u64 AcOffset, u32 HashLen,
			u32 PartitionNum)
{
	u8 SpkHash[XFSBL_HASH_TYPE_SHA3] __attribute__ ((aligned (4)));
	u8 * PpkModular = (u8 *)NULL;
	u8 * PpkModularEx = (u8 *)NULL;
	u32 PpkExp = 0;
	u8 * AcPtr = (u8*) (PTRSIZE) AcOffset;
	u32 Status = XFSBL_SUCCESS;
	void * ShaCtx = (void * )NULL;
	u8 XFsbl_RsaSha3Array[512];

#ifdef XFSBL_SHA2
	sha2_context ShaCtxObj;
	ShaCtx = &ShaCtxObj;
#endif

#ifndef XFSBL_PS_DDR
	XFsblPs_PartitionHeader * PartitionHeader;
	u32 DestinationDevice = 0U;
	PartitionHeader =
		&FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum];
	DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader);

	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL)
	{
		/*
		 * If it is DDR less system, bitstream chunk containing
		 * Authentication Certificate has to be read from boot device
		 */
		if(XFSBL_SUCCESS != FsblInstancePtr->DeviceOps.DeviceCopy(
					(INTPTR)AcPtr, (PTRSIZE)ReadBuffer,
					XFSBL_AUTH_CERT_MIN_SIZE)) {
			XFsbl_Printf(DEBUG_GENERAL,
			"XFsbl_SpkVer: Device to OCM copy of certificate failed \r\n");
			Status = XFSBL_ERROR_SPK_RSA_DECRYPT;
			goto END;
		}

		/* Repoint Auth. cert. pointer to OCM buffer beginning*/
		AcPtr = ReadBuffer;
	}
#endif

	/* Re-initialize CSU DMA. This is a workaround and need to be removed */
	Status = XFsbl_CsuDmaInit();
	if (XST_SUCCESS != Status) {
		goto END;
	}

	(void)XFsbl_ShaStart(ShaCtx, HashLen);

	/* Hash the PPK + SPK choice */
	XFsbl_ShaUpdate(ShaCtx, AcPtr, 8, HashLen);

	/* Set PPK pointer */
	AcPtr += XFSBL_RSA_AC_ALIGN;
	PpkModular = (u8 *)AcPtr;
	AcPtr += XFSBL_PPK_MOD_SIZE;
	PpkModularEx = (u8 *)AcPtr;
	AcPtr += XFSBL_PPK_MOD_EXT_SIZE;
	PpkExp = *((u32 *)AcPtr);
	AcPtr += XFSBL_RSA_AC_ALIGN;

	XFsbl_Printf(DEBUG_DETAILED,
		"XFsbl_SpkVer: Ppk Mod %0x, Ppk Mod Ex %0x, Ppk Exp %0x\r\n",
		PpkModular, PpkModularEx, PpkExp);

	/* Calculate SPK + Auth header Hash */
	XFsbl_ShaUpdate(ShaCtx, (u8 *)AcPtr, XFSBL_SPK_SIZE, HashLen);

	XFsbl_ShaFinish(ShaCtx, (u8 *)SpkHash, HashLen);

	/* Set SPK Signature pointer */
	AcPtr += XFSBL_SPK_SIZE;

	XSecure_RsaInitialize(&SecureRsa, PpkModular,
				PpkModularEx, (u8 *)&PpkExp);

	/* Decrypt SPK Signature */
	if(XFSBL_SUCCESS !=
		XSecure_RsaDecrypt(&SecureRsa, AcPtr, XFsbl_RsaSha3Array))
	{
		XFsbl_Printf(DEBUG_GENERAL,
			"XFsbl_SpkVer: XFSBL_ERROR_SPK_RSA_DECRYPT\r\n");
		Status = XFSBL_ERROR_SPK_RSA_DECRYPT;
		goto END;
	}

	/* Authenticate SPK Signature */
	if(XFSBL_SUCCESS != XSecure_RsaSignVerification(XFsbl_RsaSha3Array,
							SpkHash, HashLen))
	{
		XFsbl_PrintArray(DEBUG_INFO, SpkHash,
				HashLen, "Calculated SPK Hash");
		XFsbl_PrintArray(DEBUG_INFO, XFsbl_RsaSha3Array,
				512, "RSA decrypted Hash");
		XFsbl_Printf(DEBUG_GENERAL,
			"XFsbl_SpkVer: XFSBL_ERROR_SPK_SIGNATURE\r\n");
		Status = XFSBL_ERROR_SPK_SIGNATURE;
	}

END:
	return Status;
}
예제 #26
0
/**
 * Configure the RSA and SHA for the
 * Boot Header Signature verification.
 * If Boot Header Signature verification
 * fails then return unique error code saying
 * XFSBL_STAGE3_BOOT_HDR_SIGN_VERIF_ERROR.
 *
 * @param
 *
 * @return
 *
 ******************************************************************************/
u32 XFsbl_PartitionSignVer(XFsblPs *FsblInstancePtr, u64 PartitionOffset,
				u32 PartitionLen, u64 AcOffset, u32 HashLen,
				u32 PartitionNum)
{

	u8 PartitionHash[XFSBL_HASH_TYPE_SHA3] __attribute__ ((aligned (4)));
	u8 * SpkModular = (u8 *)NULL;
	u8 * SpkModularEx = (u8 *)NULL;
	u32 SpkExp = 0;
	u8 * AcPtr = (u8*)(PTRSIZE) AcOffset;
	u32 Status = XFSBL_SUCCESS;
	u32 HashDataLen=0U;
#ifndef XFSBL_PS_DDR
	void * ShaCtx = (void * )NULL;
#endif
	u8 XFsbl_RsaSha3Array[512];

#ifdef XFSBL_SHA2
	sha2_context ShaCtxObj;
	ShaCtx = &ShaCtxObj;
#endif

	XFsbl_Printf(DEBUG_INFO, "Doing Partition Sign verification\r\n");

	/**
	 * hash to be calculated will be total length with AC minus
	 * signature size
	 */
	HashDataLen = PartitionLen - XFSBL_FSBL_SIG_SIZE;

	/* Calculate Partition Hash */
#ifndef XFSBL_PS_DDR
	XFsblPs_PartitionHeader * PartitionHeader;
	u32 DestinationDevice = 0U;
	PartitionHeader =
		&FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum];
	DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader);

	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL)
	{
		/**
		 * bitstream partion in DDR less system, Chunk by chunk copy
		 * into OCM and update SHA module
		 */
		u32 NumChunks = 0U;
		u32 RemainingBytes = 0U;
		u32 Index = 0U;
		u32 StartAddrByte = PartitionOffset;

		NumChunks = HashDataLen / READ_BUFFER_SIZE;
		RemainingBytes = (HashDataLen % READ_BUFFER_SIZE);

		/* Start the SHA engine */
		(void)XFsbl_ShaStart(ShaCtx, HashLen);

		XFsbl_Printf(DEBUG_INFO,
			"XFsbl_PartitionVer: NumChunks :%0d, RemainingBytes : %0d \r\n",
			NumChunks, RemainingBytes);

		for(Index = 0; Index < NumChunks; Index++)
		{
			if(XFSBL_SUCCESS !=FsblInstancePtr->DeviceOps.DeviceCopy(
					StartAddrByte, (PTRSIZE)ReadBuffer,
					READ_BUFFER_SIZE))
			{
				XFsbl_Printf(DEBUG_GENERAL,
					"XFsblPartitionVer: Device "
					"to OCM copy of partition failed \r\n");
				XFsbl_Printf(DEBUG_GENERAL,
				"XFsbl_PartitionVer: XFSBL_ERROR_PART_RSA_DECRYPT\r\n");
				Status = XFSBL_ERROR_PART_RSA_DECRYPT;
				goto END;
			}

			XFsbl_ShaUpdate(ShaCtx, (u8 *)ReadBuffer,
						READ_BUFFER_SIZE, HashLen);

			StartAddrByte += READ_BUFFER_SIZE;
		}

		/* Send the residual bytes if Size is not buffer size multiple */
		if(RemainingBytes != 0)
		{
			if(XFSBL_SUCCESS!=FsblInstancePtr->DeviceOps.DeviceCopy(
						StartAddrByte, (PTRSIZE)ReadBuffer,
						RemainingBytes))
			{
				XFsbl_Printf(DEBUG_GENERAL,
				"XFsbl_PartitionVer: XFSBL_ERROR_PART_RSA_DECRYPT\r\n");

				Status = XFSBL_ERROR_PART_RSA_DECRYPT;
				goto END;
			}

			XFsbl_ShaUpdate(ShaCtx, (u8 *)ReadBuffer,
						RemainingBytes, HashLen);
		}

		XFsbl_ShaFinish(ShaCtx, PartitionHash, HashLen);

		/**
		 * Copy Auth. Certificate to OCM buffer location
		 * Assign AcPtr to OCM buffer location
		 */
		if(XFSBL_SUCCESS != FsblInstancePtr->DeviceOps.DeviceCopy(
					(u32)(INTPTR)AcPtr, (PTRSIZE)ReadBuffer,
					XFSBL_AUTH_CERT_MIN_SIZE)) {
			XFsbl_Printf(DEBUG_GENERAL,
			"XFsbl_PartitionVer: Flash to OCM copy failed \r\n");
			Status = XFSBL_ERROR_SPK_RSA_DECRYPT;
			goto END;
		}

		/* Repoint Auth. Certificate pointer to start of OCM buffer */
		AcPtr = ReadBuffer;
	}
	else
	{
		XFsbl_Printf(DEBUG_INFO, "partver: sha calc. "
					"for non bs DDR less part \r\n");
		/* SHA calculation for non-bitstream, DDR less partitions */
		XFsbl_ShaDigest((const u8 *)(PTRSIZE)PartitionOffset,
					HashDataLen, PartitionHash, HashLen);
	}
#else
	/* SHA calculation in DDRful systems */
	XFsbl_ShaDigest((const u8 *)(PTRSIZE)PartitionOffset,
			HashDataLen, PartitionHash, HashLen);
#endif

	/* Set SPK pointer */
	AcPtr += (XFSBL_RSA_AC_ALIGN + XFSBL_PPK_SIZE);
	SpkModular = (u8 *)AcPtr;
	AcPtr += XFSBL_SPK_MOD_SIZE;
	SpkModularEx = (u8 *)AcPtr;
	AcPtr += XFSBL_SPK_MOD_EXT_SIZE;
	SpkExp = *((u32 *)AcPtr);
	AcPtr += XFSBL_RSA_AC_ALIGN;

	/* Increment by  SPK Signature pointer */
	AcPtr += XFSBL_SPK_SIG_SIZE;
	/* Increment by  BHDR Signature pointer */
	AcPtr += XFSBL_BHDR_SIG_SIZE;

	XFsbl_Printf(DEBUG_DETAILED,
		"XFsbl_PartVer: Spk Mod %0x, Spk Mod Ex %0x, Spk Exp %0x\r\n",
		SpkModular, SpkModularEx, SpkExp);

	XFsbl_Printf(DEBUG_INFO,
			"Partition Verification done \r\n");

	XSecure_RsaInitialize(&SecureRsa, SpkModular,
				SpkModularEx, (u8 *)&SpkExp);
	/* Decrypt Partition Signature. */
	if(XFSBL_SUCCESS !=
		XSecure_RsaDecrypt(&SecureRsa, AcPtr, XFsbl_RsaSha3Array))
	{
		XFsbl_Printf(DEBUG_GENERAL,
			"XFsbl_SpkVer: XFSBL_ERROR_PART_RSA_DECRYPT\r\n");
		Status = XFSBL_ERROR_PART_RSA_DECRYPT;
		goto END;
	}

	/* Authenticate Partition Signature */
	if(XFSBL_SUCCESS != XSecure_RsaSignVerification(XFsbl_RsaSha3Array,
				PartitionHash, HashLen))
	{
		XFsbl_PrintArray(DEBUG_INFO, PartitionHash,
				HashLen, "Calculated Partition Hash");
		XFsbl_PrintArray(DEBUG_INFO, XFsbl_RsaSha3Array,
				512, "RSA decrypted Hash");
		XFsbl_Printf(DEBUG_GENERAL,
			"XFsbl_PartVer: XFSBL_ERROR_PART_SIGNATURE\r\n");
		Status = XFSBL_ERROR_PART_SIGNATURE;
		goto END;
	}

END:
	return Status;
}
/**
*
* @param
*
* @return
*
* @note
*
*****************************************************************************/
static void XFsbl_PreFetchAbortHandler (void)
{
	XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_PREFETCH_ABORT_EXCEPTION\n\r");
	XFsbl_ErrorLockDown(XFSBL_ERROR_PREFETCH_ABORT_EXCEPTION);
}
/**
*
* @param
*
* @return
*
* @note
*
*
*****************************************************************************/
static void XFsbl_DataAbortHandler (void)
{
	XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_DATA_ABORT_EXCEPTION\n\r");
	XFsbl_ErrorLockDown(XFSBL_ERROR_DATA_ABORT_EXCEPTION);
}
/**
 * This function validates the image header
 *
 * @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_ValidateHeader(XFsblPs * FsblInstancePtr)
{
	u32 Status =  XFSBL_SUCCESS;
	u32 MultiBootOffset=0U;
	u32 BootHdrAttrb=0U;
	u32 FlashImageOffsetAddress=0U;
	u32 EfuseCtrl=0U;

	/**
	 * Read the Multiboot Register
	 */
	MultiBootOffset = XFsbl_In32(CSU_CSU_MULTI_BOOT);
	XFsbl_Printf(DEBUG_INFO,"Multiboot Reg : 0x%0lx \n\r", MultiBootOffset);

	/**
	 *  Calculate the Flash Offset Address
	 *  For file system based devices, Flash Offset Address should be 0 always
	 */
	if ((FsblInstancePtr->PrimaryBootDevice == XFSBL_SD0_BOOT_MODE) ||
			(FsblInstancePtr->PrimaryBootDevice == XFSBL_EMMC_BOOT_MODE) ||
			(FsblInstancePtr->PrimaryBootDevice == XFSBL_SD1_BOOT_MODE) ||
			(FsblInstancePtr->PrimaryBootDevice == XFSBL_SD1_LS_BOOT_MODE))
	{
		FsblInstancePtr->ImageOffsetAddress = 0x0U;
	} else {
		FsblInstancePtr->ImageOffsetAddress =
				MultiBootOffset * XFSBL_IMAGE_SEARCH_OFFSET;
	}

	FlashImageOffsetAddress = FsblInstancePtr->ImageOffsetAddress;

	/**
	 * Read Boot Image attributes
	 */
	Status = FsblInstancePtr->DeviceOps.DeviceCopy(FlashImageOffsetAddress
                    + XIH_BH_IMAGE_ATTRB_OFFSET,
                   (PTRSIZE ) &BootHdrAttrb, XIH_FIELD_LEN);
        if (XFSBL_SUCCESS != Status) {
                XFsbl_Printf(DEBUG_GENERAL,"Device Copy Failed \n\r");
                goto END;
        }
	FsblInstancePtr->BootHdrAttributes = BootHdrAttrb;

	/**
	 * Read Image Header and validate Image Header Table
	 */
	Status = XFsbl_ReadImageHeader(&FsblInstancePtr->ImageHeader,
					&FsblInstancePtr->DeviceOps,
					FlashImageOffsetAddress,
					FsblInstancePtr->ProcessorID);
	if (XFSBL_SUCCESS != Status) {
		goto END;
	}


	/**
	 * Read Efuse bit and check Boot Header for Authentication
	 */
	EfuseCtrl = XFsbl_In32(EFUSE_SEC_CTRL);
	if (((EfuseCtrl & EFUSE_SEC_CTRL_RSA_EN_MASK) != 0) ||
	    ((BootHdrAttrb & XIH_BH_IMAGE_ATTRB_RSA_MASK)
		== XIH_BH_IMAGE_ATTRB_RSA_MASK)) {

		XFsbl_Printf(DEBUG_INFO,"Authentication Enabled\r\n");
#ifdef XFSBL_RSA
		/**
		 * Authenticate the image header
		 */

#else
                XFsbl_Printf(DEBUG_GENERAL,"Rsa code not Enabled\r\n");
                Status = XFSBL_ERROR_RSA_NOT_ENABLED;
                goto END;
#endif
	}
END:
	return Status;
}
예제 #30
0
/**
 * This function is used to copy the data from QSPI flash to destination
 * address
 *
 * @param SrcAddress is the address of the QSPI flash where copy should
 * start from
 *
 * @param DestAddress is the address of the destination where it
 * should copy to
 *
 * @param Length Length of the bytes to be copied
 *
 * @return
 * 		- XFSBL_SUCCESS for successful copy
 * 		- errors as mentioned in xfsbl_error.h
 *
 *****************************************************************************/
u32 XFsbl_Qspi32Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
{
	u32 Status = XFSBL_SUCCESS;
	u32 QspiAddr=0;
	u32 RemainingBytes=0;
	u32 TransferBytes=0;
	u32 DiscardByteCnt;

	XFsbl_Printf(DEBUG_INFO,"QSPI Reading Src 0x%0lx, Dest %0lx, Length %0lx\r\n",
			SrcAddress, DestAddress, Length);

	/**
	 * Check the read length with Qspi flash size
	 */
	if ((SrcAddress + Length) > QspiFlashSize)
	{
		Status = XFSBL_ERROR_QSPI_LENGTH;
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_LENGTH\r\n");
		goto END;
	}


	/**
	 * Update no of bytes to be copied
	 */
	RemainingBytes = Length;

	while(RemainingBytes > 0) {

		if (RemainingBytes > DMA_DATA_TRAN_SIZE)
		{
			TransferBytes = DMA_DATA_TRAN_SIZE;
		} else {
			TransferBytes = RemainingBytes;
		}

		/**
		 * Translate address based on type of connection
		 * If stacked assert the slave select based on address
		 */
		QspiAddr = XFsbl_GetQspiAddr((u32 )SrcAddress);

		XFsbl_Printf(DEBUG_INFO,".");
		XFsbl_Printf(DEBUG_DETAILED,
					"QSPI Read Src 0x%0lx, Dest %0lx, Length %0lx\r\n",
						QspiAddr, DestAddress, TransferBytes);

		/**
		 * Setup the read command with the specified address and data for the
		 * Flash
		 */

		WriteBuffer[COMMAND_OFFSET]   = ReadCommand;
		WriteBuffer[ADDRESS_1_OFFSET] = (u8)((QspiAddr & 0xFF000000) >> 24);
		WriteBuffer[ADDRESS_2_OFFSET] = (u8)((QspiAddr & 0xFF0000) >> 16);
		WriteBuffer[ADDRESS_3_OFFSET] = (u8)((QspiAddr & 0xFF00) >> 8);
		WriteBuffer[ADDRESS_4_OFFSET] = (u8)(QspiAddr & 0xFF);
		DiscardByteCnt = 5;

		FlashMsg[0].TxBfrPtr = WriteBuffer;
		FlashMsg[0].RxBfrPtr = NULL;
		FlashMsg[0].ByteCount = DiscardByteCnt;
		FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
		FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;

		/*
		 * It is recommended to have a separate entry for dummy
		 */
		if ((ReadCommand == FAST_READ_CMD_32BIT) ||
				(ReadCommand == DUAL_READ_CMD_32BIT) ||
				(ReadCommand == QUAD_READ_CMD_32BIT)) {

			/* Update Dummy cycles as per flash specs for QUAD IO */

			/*
			 * It is recommended that Bus width value during dummy
			 * phase should be same as data phase
			 */
			if (ReadCommand == FAST_READ_CMD_32BIT) {
				FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
			}

			if (ReadCommand == DUAL_READ_CMD_32BIT) {
				FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_DUALSPI;
			}

			if (ReadCommand == QUAD_READ_CMD_32BIT) {
				FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_QUADSPI;
			}

			FlashMsg[1].TxBfrPtr = NULL;
			FlashMsg[1].RxBfrPtr = NULL;
			FlashMsg[1].ByteCount = DUMMY_CLOCKS;
			FlashMsg[1].Flags = 0;
		}

		if (ReadCommand == FAST_READ_CMD_32BIT) {
			FlashMsg[2].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
		}

		if (ReadCommand == DUAL_READ_CMD_32BIT) {
			FlashMsg[2].BusWidth = XQSPIPSU_SELECT_MODE_DUALSPI;
		}

		if (ReadCommand == QUAD_READ_CMD_32BIT) {
			FlashMsg[2].BusWidth = XQSPIPSU_SELECT_MODE_QUADSPI;
		}

		FlashMsg[2].TxBfrPtr = NULL;
		FlashMsg[2].RxBfrPtr = (u8 *)DestAddress;
		FlashMsg[2].ByteCount = TransferBytes;
		FlashMsg[2].Flags = XQSPIPSU_MSG_FLAG_RX;

		if(QspiPsuInstancePtr->Config.ConnectionMode ==
				XQSPIPSU_CONNECTION_MODE_PARALLEL){
			FlashMsg[2].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
		}

		/**
		 * Send the read command to the Flash to read the specified number
		 * of bytes from the Flash, send the read command and address and
		 * receive the specified number of bytes of data in the data buffer
		 */
		Status = XQspiPsu_PolledTransfer(QspiPsuInstancePtr, FlashMsg, 3);
		if (Status != XST_SUCCESS) {
			Status = XFSBL_ERROR_QSPI_READ;
			XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_READ\r\n");
			goto END;
		}

		/**
		 * Update the variables
		 */
		RemainingBytes -= TransferBytes;
		DestAddress += TransferBytes;
		SrcAddress += TransferBytes;

	}

END:
	return Status;
}