diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c index e8acc360..6ce28976 100644 --- a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c @@ -657,6 +657,9 @@ u32 XFsbl_Handoff (XFsblPs * FsblInstancePtr) u64 RunningCpuHandoffAddress=0U; u32 RunningCpuExecState=0U; s32 RunningCpuHandoffAddressPresent=FALSE; + u32 NoOfPartitions; + u32 PartitionIndex; + u32 PartitionAttributes; /** * if JTAG bootmode, be in while loop as of now @@ -714,6 +717,29 @@ u32 XFsbl_Handoff (XFsblPs * FsblInstancePtr) goto END; } + /* If PMU FW is present then handoff it to PMU MicroBlaze */ + NoOfPartitions = + FsblInstancePtr->ImageHeader.ImageHeaderTable.NoOfPartitions; + for (PartitionIndex = 0; + PartitionIndex < NoOfPartitions; PartitionIndex++) + { + PartitionAttributes = FsblInstancePtr->ImageHeader. + PartitionHeader[PartitionIndex].PartitionAttributes; + if ((PartitionAttributes & XIH_PH_ATTRB_DEST_DEVICE_MASK) + == XIH_PH_ATTRB_DEST_DEVICE_PMU) + { + /* Wakeup the processor */ + XFsbl_Out32(PMU_GLOBAL_GLOBAL_CNTRL, + XFsbl_In32(PMU_GLOBAL_GLOBAL_CNTRL) | 0x1); + + /* wait until done waking up */ + while((XFsbl_In32(PMU_GLOBAL_GLOBAL_CNTRL) & + PMU_GLOBAL_GLOBAL_CNTRL_MB_SLEEP_MASK) == + PMU_GLOBAL_GLOBAL_CNTRL_MB_SLEEP_MASK ) {;} + } + + } + /** * Flush the L1 data cache and L2 cache */ diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_hw.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_hw.h index dacddf4f..b79bde85 100644 --- a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_hw.h +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_hw.h @@ -277,6 +277,9 @@ extern "C" { */ #define PMU_GLOBAL_BASEADDR 0XFFD80000U +#define PMU_GLOBAL_GLOBAL_CNTRL ( ( PMU_GLOBAL_BASEADDR ) + 0X00000000U ) +#define PMU_GLOBAL_GLOBAL_CNTRL_MB_SLEEP_MASK 0X00010000U + /* rpu */ /** @@ -371,6 +374,21 @@ extern "C" { */ #define RSA_CORE_CTRL ( ( RSA_CORE_BASEADDR ) + 0X00000010U ) +/* LPD_SLCR Base Address */ +#define LPD_SLCR_BASEADDR 0XFF410000U + +/* Register: LPD_SLCR_PERSISTENT4 */ +#define LPD_SLCR_PERSISTENT4 ( ( LPD_SLCR_BASEADDR ) + 0X00000030U ) + +/* Register: LPD_SLCR_PERSISTENT5 */ +#define LPD_SLCR_PERSISTENT5 ( ( LPD_SLCR_BASEADDR ) + 0X00000034U ) + +/* IPI Base Address */ +#define IPI_BASEADDR 0XFF300000U + +/* Register: IPI_PMU_0_TRIG */ +#define IPI_PMU_0_TRIG ( ( IPI_BASEADDR ) + 0X00030000U ) +#define IPI_APU_TRIG_PMU_0_SHIFT 16U /**************************** Type Definitions *******************************/ @@ -382,7 +400,11 @@ extern "C" { * For error reporting PMU_GLOBAL_PERS_GLOB_GEN_STORAGE1 is used */ #define XFSBL_ERROR_STATUS_REGISTER_OFFSET (PMU_GLOBAL_PERS_GLOB_GEN_STORAGE1) -#define XFSBL_PMU_RAM_ADDRESS (0xFFDC0000U) + + +/* PMU RAM address for PMU FW */ +#define XFSBL_PMU_RAM_START_ADDRESS (0xFFDC0000U) +#define XFSBL_PMU_RAM_END_ADDRESS (0xFFDDFFFFU) /** * ARM Processor defines diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.c index 507f12e7..16a063c9 100644 --- a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.c +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.c @@ -115,9 +115,12 @@ __inline u32 XFsbl_GetA53ExecState( /************************** Function Prototypes ******************************/ static u32 XFsbl_ValidateImageHeaderTable( XFsblPs_ImageHeaderTable * ImageHeaderTable); -static u32 XFsbl_CheckValidMemoryAddress(u64 Address, u32 CpuId); +static u32 XFsbl_CheckValidMemoryAddress(u64 Address, u32 CpuId, u32 DevId); +static void XFsbl_SetATFHandoffParameters( + XFsblPs_PartitionHeader *PartitionHeader, u32 EntryCount); /************************** Variable Definitions *****************************/ +XFsblPs_ATFHandoffParams ATFHandoffParams; /****************************************************************************/ /** @@ -289,6 +292,9 @@ u32 XFsbl_ReadImageHeader(XFsblPs_ImageHeader * ImageHeader, u32 ImageHeaderTableAddressOffset=0U; u32 PartitionHeaderAddress=0U; u32 PartitionIndex=0U; + XFsblPs_PartitionHeader *CurrPartitionHdr; + u32 EntryCount = 0; + u32 DestnCPU; /** * Read the Image Header Table offset from @@ -377,6 +383,33 @@ u32 XFsbl_ReadImageHeader(XFsblPs_ImageHeader * ImageHeader, } #endif + /** + * Assumption: Next partition corresponds to ATF + * The first partition of an application will have a non zero + * execution address. All the remaining partitions of that + * application will have 0 as execution address. Hence look for + * the non zero execution address for partition which is not + * the first one and ensure the CPU is A53 + */ + + CurrPartitionHdr = &ImageHeader->PartitionHeader[PartitionIndex]; + + DestnCPU = XFsbl_GetDestinationCpu(CurrPartitionHdr); + + if ((PartitionIndex > 1) && (EntryCount < XFSBL_MAX_ENTRIES_FOR_ATF) && + (CurrPartitionHdr->DestinationExecutionAddress != 0U) && + (((DestnCPU >= XIH_PH_ATTRB_DEST_CPU_A53_0) && + (DestnCPU <= XIH_PH_ATTRB_DEST_CPU_A53_3)))) + { + /** + * Populate handoff parameters to ATF + * These correspond to the partition of application + * which ATF will be loading + */ + XFsbl_SetATFHandoffParameters(CurrPartitionHdr, EntryCount); + EntryCount++; + } + /** * Update the next partition present address */ @@ -385,15 +418,33 @@ u32 XFsbl_ReadImageHeader(XFsblPs_ImageHeader * ImageHeader, * XIH_PARTITION_WORD_LENGTH; } + /** + * After setting handoff parameters of all partitions to ATF, + * Store lower address of the structure at Persistent register 4 + * and higher address at Persistent register 5 + */ + XFsbl_Out32(LPD_SLCR_PERSISTENT4,(u32)(((PTRSIZE)(&ATFHandoffParams)) & 0xFFFFFFFF)); + XFsbl_Out32(LPD_SLCR_PERSISTENT5, (u32)(((PTRSIZE)(&ATFHandoffParams)) >> 32)); + END: return Status; } -static u32 XFsbl_CheckValidMemoryAddress(u64 Address, u32 CpuId) +static u32 XFsbl_CheckValidMemoryAddress(u64 Address, u32 CpuId, u32 DevId) { u32 Status = XFSBL_SUCCESS; + /* Check if Address is in the range of PMU RAM for PMU FW */ + if (DevId == XIH_PH_ATTRB_DEST_DEVICE_PMU) + { + if ((Address >= XFSBL_PMU_RAM_START_ADDRESS) && + (Address < XFSBL_PMU_RAM_END_ADDRESS) ) + { + goto END; + } + } + /** * Check if Address is in the range of TCM for R5 */ @@ -471,7 +522,7 @@ u32 XFsbl_ValidatePartitionHeader( { u32 Status = XFSBL_SUCCESS; u32 DestinationCpu=0U; - /* u32 RpuGlobalCntl=0; */ + u32 DestinationDevice=0; s32 IsEncrypted=FALSE, IsAuthenticated=FALSE; @@ -492,7 +543,7 @@ u32 XFsbl_ValidatePartitionHeader( DestinationCpu = XFsbl_GetDestinationCpu(PartitionHeader); - + DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader); /** * Partition fields Validation */ @@ -604,7 +655,7 @@ u32 XFsbl_ValidatePartitionHeader( */ Status = XFsbl_CheckValidMemoryAddress( PartitionHeader->DestinationLoadAddress, - DestinationCpu); + DestinationCpu, DestinationDevice); if (Status != XFSBL_SUCCESS) { goto END; @@ -693,23 +744,6 @@ u32 XFsbl_ValidatePartitionHeader( goto END; } - /** - * Check for PMU address not in PMU RAM - */ - if (XFsbl_GetDestinationDevice(PartitionHeader) == - XIH_PH_ATTRB_DEST_DEVICE_PMU) - { - if (PartitionHeader->DestinationLoadAddress != - XFSBL_PMU_RAM_ADDRESS) - { - Status = XFSBL_ERROR_INVALID_LOAD_ADDRESS; - XFsbl_Printf(DEBUG_GENERAL, - "XFSBL_ERROR_INVALID_LOAD_ADDRESS\n\r"); - goto END; - } - } - - /** * Print Partition Header Details */ @@ -731,3 +765,54 @@ u32 XFsbl_ValidatePartitionHeader( END: return Status; } + +/****************************************************************************/ +/** +* This function sets the handoff parameters to the ARM Trusted Firmware (ATF) +* Some of the inputs for this are taken from FSBL partition header +* A pointer to the structure containing these parameters is stored in +* persistent register 5, which ATF reads +* +* @param PartitionHeader is pointer to the XFsblPs_PartitionHeader structure +* +* @return None +* +* @note +* +*****************************************************************************/ +static void XFsbl_SetATFHandoffParameters( + XFsblPs_PartitionHeader *PartitionHeader, u32 EntryCount) +{ + u32 PartitionAttributes; + u64 PartitionFlags; + + PartitionAttributes = PartitionHeader->PartitionAttributes; + + PartitionFlags = + (((PartitionAttributes & XIH_PH_ATTRB_A53_EXEC_ST_MASK) + >> XIH_ATTRB_A53_EXEC_ST_SHIFT_DIFF) | + ((PartitionAttributes & XIH_PH_ATTRB_ENDIAN_MASK) + >> XIH_ATTRB_ENDIAN_SHIFT_DIFF) | + ((PartitionAttributes & XIH_PH_ATTRB_TR_SECURE_MASK) + << XIH_ATTRB_TR_SECURE_SHIFT_DIFF) | + ((PartitionAttributes & XIH_PH_ATTRB_TARGET_EL_MASK) + << XIH_ATTRB_TARGET_EL_SHIFT_DIFF) | + ((PartitionAttributes & XIH_PH_ATTRB_DEST_CPU_A53_MASK) + >> XIH_ATTRB_DEST_CPU_A53_SHIFT_DIFF)); + + /* Insert magic string */ + if (EntryCount == 0) + { + ATFHandoffParams.MagicValue[0] = 'X'; + ATFHandoffParams.MagicValue[1] = 'L'; + ATFHandoffParams.MagicValue[2] = 'N'; + ATFHandoffParams.MagicValue[3] = 'X'; + } + + ATFHandoffParams.NumEntries = EntryCount + 1; + + ATFHandoffParams.Entry[EntryCount].EntryPoint = + PartitionHeader->DestinationExecutionAddress; + ATFHandoffParams.Entry[EntryCount].PartitionFlags = PartitionFlags; + +} diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.h index d263eff0..5b52f5a0 100644 --- a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.h +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.h @@ -71,6 +71,7 @@ extern "C" { * Boot header field offset */ #define XIH_BH_IH_OFFSET (0x3CU) +#define XIH_BH_TOTAL_PFW_LENGTH_OFFSET (0x38U) #define XIH_BH_IMAGE_ATTRB_OFFSET (0x44U) #define XIH_BH_IH_TABLE_OFFSET (0x98U) #define XIH_BH_PH_TABLE_OFFSET (0x9CU) @@ -82,6 +83,7 @@ extern "C" { * Defines for length of the headers */ #define XIH_FIELD_LEN (4U) +#define XIH_PFW_LEN_FIELD_LEN (4U) #define XIH_IHT_LEN (64U) #define XIH_PH_LEN (64U) @@ -127,6 +129,7 @@ extern "C" { /** * Partition Attribute fields */ +#define XIH_PH_ATTRB_ENDIAN_MASK (0x40000U) #define XIH_PH_ATTRB_PART_OWNER_MASK (0x30000U) #define XIH_PH_ATTRB_RSA_SIGNATURE_MASK (0x8000U) #define XIH_PH_ATTRB_CHECKSUM_MASK (0x7000U) @@ -134,7 +137,9 @@ extern "C" { #define XIH_PH_ATTRB_ENCRYPTION_MASK (0x0080U) #define XIH_PH_ATTRB_DEST_DEVICE_MASK (0x0070U) #define XIH_PH_ATTRB_A53_EXEC_ST_MASK (0x0008U) - +#define XIH_PH_ATTRB_TARGET_EL_MASK (0x0006U) +#define XIH_PH_ATTRB_TR_SECURE_MASK (0x0001U) +#define XIH_PH_ATTRB_DEST_CPU_A53_MASK (0x0600U) /** * Partition Attribute Values @@ -164,6 +169,30 @@ extern "C" { #define XIH_PH_ATTRB_A53_EXEC_ST_AA32 (0x0008U) #define XIH_PH_ATTRB_A53_EXEC_ST_AA64 (0x0000U) +/** + * Below is the bit mapping of fields in the ATF Handoff parameters + * with that of Partition header. The number of bits shifted is + * is based on the difference between these two offsets + * + * ATFHandoffParams PartitionHeader Shift + * Parameter PartitionFlags PartitionAttributes difference + * ---------------------------------------------------------------------- + * Exec State 0 3 3 right + * ENDIAN 1 18 17 right + * SECURE 2 0 2 left + * EL 3:4 1:2 2 left + * CPU_A53 5:6 9:10 4 right + */ +#define XIH_ATTRB_A53_EXEC_ST_SHIFT_DIFF (3U) +#define XIH_ATTRB_ENDIAN_SHIFT_DIFF (17U) +#define XIH_ATTRB_TR_SECURE_SHIFT_DIFF (2U) +#define XIH_ATTRB_TARGET_EL_SHIFT_DIFF (2U) +#define XIH_ATTRB_DEST_CPU_A53_SHIFT_DIFF (4U) + + +/* Number of entries possible in ATF: 4 cores * 2 (secure, nonsecure) */ +#define XFSBL_MAX_ENTRIES_FOR_ATF 8 + /**************************** Type Definitions *******************************/ /** @@ -218,6 +247,24 @@ typedef struct { /**< Partition header */ } XFsblPs_ImageHeader; +/* Structure corresponding to each partition entry */ +typedef struct { + u64 EntryPoint; + /**< Entry point */ + u64 PartitionFlags; + /**< Attributes of partition */ +} XFsblPs_PartitionEntry; + +/* Structure for handoff parameters to ARM Trusted Firmware (ATF) */ +typedef struct { + char8 MagicValue[4]; + /**< 32 bit magic string */ + u32 NumEntries; + /**< Number of Entries */ + XFsblPs_PartitionEntry Entry[XFSBL_MAX_ENTRIES_FOR_ATF]; + /**< Structure corresponding to each entry */ +} XFsblPs_ATFHandoffParams; + /***************** Macros (Inline Functions) Definitions *********************/ __inline u32 XFsbl_GetPartitionOwner( XFsblPs_PartitionHeader * PartitionHeader); diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_partition_load.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_partition_load.c index f90715bd..e866c688 100644 --- a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_partition_load.c +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_partition_load.c @@ -737,9 +737,6 @@ static u32 XFsbl_PartitionCopy(XFsblPs * FsblInstancePtr, u32 PartitionNum) * Copy the PL to temporary DDR Address * Copy the PS to Load Address * Copy the PMU firmware to PMU RAM - * (It may be good if we copy to DDR instead of PMU RAM - * And finish the PMU RAM copy at handoff so that PMU is - * not in waiting state - Need to check the exact working of PMU) */ DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader); LoadAddress = PartitionHeader->DestinationLoadAddress; @@ -834,6 +831,20 @@ static u32 XFsbl_PartitionCopy(XFsblPs * FsblInstancePtr, u32 PartitionNum) } #endif + if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PMU) + { + /* Trigger PMU0 IPI in PMU IPI TRIG Reg */ + XFsbl_Out32(IPI_PMU_0_TRIG, IPI_APU_TRIG_PMU_0_SHIFT); + + /** + * 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 */