xref: /rk3399_ARM-atf/plat/arm/board/fvp/fvp_common.c (revision b62673c645752a78f649282cfa293e8da09e3bef)
1 /*
2  * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <string.h>
9 
10 #include <common/debug.h>
11 #include <drivers/arm/cci.h>
12 #include <drivers/arm/ccn.h>
13 #include <drivers/arm/gicv2.h>
14 #include <drivers/arm/sp804_delay_timer.h>
15 #include <drivers/generic_delay_timer.h>
16 #include <fconf_hw_config_getter.h>
17 #include <lib/mmio.h>
18 #include <lib/smccc.h>
19 #include <lib/xlat_tables/xlat_tables_compat.h>
20 #include <platform_def.h>
21 #include <services/arm_arch_svc.h>
22 #include <services/rmm_core_manifest.h>
23 #if SPM_MM
24 #include <services/spm_mm_partition.h>
25 #endif
26 
27 #include <plat/arm/common/arm_config.h>
28 #include <plat/arm/common/plat_arm.h>
29 #include <plat/common/platform.h>
30 
31 #include "fvp_private.h"
32 
33 /* Defines for GIC Driver build time selection */
34 #define FVP_GICV2		1
35 #define FVP_GICV3		2
36 
37 /* Defines for RMM Console */
38 #define FVP_RMM_CONSOLE_BASE		UL(0x1c0c0000)
39 #define FVP_RMM_CONSOLE_BAUD		UL(115200)
40 #define FVP_RMM_CONSOLE_CLK_IN_HZ	UL(14745600)
41 #define FVP_RMM_CONSOLE_NAME		"pl011"
42 #define FVP_RMM_CONSOLE_COUNT		UL(1)
43 
44 /*******************************************************************************
45  * arm_config holds the characteristics of the differences between the three FVP
46  * platforms (Base, A53_A57 & Foundation). It will be populated during cold boot
47  * at each boot stage by the primary before enabling the MMU (to allow
48  * interconnect configuration) & used thereafter. Each BL will have its own copy
49  * to allow independent operation.
50  ******************************************************************************/
51 arm_config_t arm_config;
52 
53 #define MAP_DEVICE0	MAP_REGION_FLAT(DEVICE0_BASE,			\
54 					DEVICE0_SIZE,			\
55 					MT_DEVICE | MT_RW | MT_SECURE)
56 
57 #define MAP_DEVICE1	MAP_REGION_FLAT(DEVICE1_BASE,			\
58 					DEVICE1_SIZE,			\
59 					MT_DEVICE | MT_RW | MT_SECURE)
60 
61 #if FVP_GICR_REGION_PROTECTION
62 #define MAP_GICD_MEM	MAP_REGION_FLAT(BASE_GICD_BASE,			\
63 					BASE_GICD_SIZE,			\
64 					MT_DEVICE | MT_RW | MT_SECURE)
65 
66 /* Map all core's redistributor memory as read-only. After boots up,
67  * per-core map its redistributor memory as read-write */
68 #define MAP_GICR_MEM	MAP_REGION_FLAT(BASE_GICR_BASE,			\
69 					(BASE_GICR_SIZE * PLATFORM_CORE_COUNT),\
70 					MT_DEVICE | MT_RO | MT_SECURE)
71 #endif /* FVP_GICR_REGION_PROTECTION */
72 
73 /*
74  * Need to be mapped with write permissions in order to set a new non-volatile
75  * counter value.
76  */
77 #define MAP_DEVICE2	MAP_REGION_FLAT(DEVICE2_BASE,			\
78 					DEVICE2_SIZE,			\
79 					MT_DEVICE | MT_RW | MT_SECURE)
80 
81 #if TRANSFER_LIST
82 #ifdef FW_NS_HANDOFF_BASE
83 #define MAP_FW_NS_HANDOFF                                             \
84 	MAP_REGION_FLAT(FW_NS_HANDOFF_BASE, PLAT_ARM_FW_HANDOFF_SIZE, \
85 			MT_MEMORY | MT_RW | MT_NS)
86 #endif
87 #ifdef PLAT_ARM_EL3_FW_HANDOFF_BASE
88 #define MAP_EL3_FW_HANDOFF                            \
89 	MAP_REGION_FLAT(PLAT_ARM_EL3_FW_HANDOFF_BASE, \
90 			PLAT_ARM_FW_HANDOFF_SIZE, MT_MEMORY | MT_RW | EL3_PAS)
91 #endif
92 #endif
93 
94 /*
95  * Table of memory regions for various BL stages to map using the MMU.
96  * This doesn't include Trusted SRAM as setup_page_tables() already takes care
97  * of mapping it.
98  */
99 #ifdef IMAGE_BL1
100 const mmap_region_t plat_arm_mmap[] = {
101 	ARM_MAP_SHARED_RAM,
102 	V2M_MAP_FLASH0_RO,
103 	V2M_MAP_IOFPGA,
104 	MAP_DEVICE0,
105 #if FVP_INTERCONNECT_DRIVER == FVP_CCN
106 	MAP_DEVICE1,
107 #endif
108 #if TRUSTED_BOARD_BOOT
109 	/* To access the Root of Trust Public Key registers. */
110 	MAP_DEVICE2,
111 	/* Map DRAM to authenticate NS_BL2U image. */
112 	ARM_MAP_NS_DRAM1,
113 #endif
114 	{0}
115 };
116 #endif
117 #ifdef IMAGE_BL2
118 const mmap_region_t plat_arm_mmap[] = {
119 	ARM_MAP_SHARED_RAM,
120 	V2M_MAP_FLASH0_RW,
121 	V2M_MAP_IOFPGA,
122 	MAP_DEVICE0,
123 #if FVP_INTERCONNECT_DRIVER == FVP_CCN
124 	MAP_DEVICE1,
125 #endif
126 	ARM_MAP_NS_DRAM1,
127 #ifdef __aarch64__
128 	ARM_MAP_DRAM2,
129 #endif
130 	/*
131 	 * Required to load HW_CONFIG, SPMC and SPs to trusted DRAM.
132 	 */
133 	ARM_MAP_TRUSTED_DRAM,
134 
135 	/*
136 	 * Required to load Event Log in TZC secured memory
137 	 */
138 #if MEASURED_BOOT && (defined(SPD_tspd) || defined(SPD_opteed) || \
139 defined(SPD_spmd))
140 	ARM_MAP_EVENT_LOG_DRAM1,
141 #endif /* MEASURED_BOOT && (SPD_tspd || SPD_opteed || SPD_spmd) */
142 
143 #if ENABLE_RME
144 	ARM_MAP_RMM_DRAM,
145 	ARM_MAP_GPT_L1_DRAM,
146 #endif /* ENABLE_RME */
147 #ifdef SPD_tspd
148 	ARM_MAP_TSP_SEC_MEM,
149 #endif
150 #if TRUSTED_BOARD_BOOT
151 	/* To access the Root of Trust Public Key registers. */
152 	MAP_DEVICE2,
153 #endif /* TRUSTED_BOARD_BOOT */
154 
155 #if CRYPTO_SUPPORT && !RESET_TO_BL2
156 	/*
157 	 * To access shared the Mbed TLS heap while booting the
158 	 * system with Crypto support
159 	 */
160 	ARM_MAP_BL1_RW,
161 #endif /* CRYPTO_SUPPORT && !RESET_TO_BL2 */
162 #if SPM_MM || SPMC_AT_EL3
163 	ARM_SP_IMAGE_MMAP,
164 #endif
165 #if ARM_BL31_IN_DRAM
166 	ARM_MAP_BL31_SEC_DRAM,
167 #endif
168 #ifdef SPD_opteed
169 	ARM_MAP_OPTEE_CORE_MEM,
170 	ARM_OPTEE_PAGEABLE_LOAD_MEM,
171 #endif
172 #ifdef MAP_EL3_FW_HANDOFF
173 	MAP_EL3_FW_HANDOFF,
174 #endif
175 	{ 0 }
176 };
177 #endif
178 #ifdef IMAGE_BL2U
179 const mmap_region_t plat_arm_mmap[] = {
180 	MAP_DEVICE0,
181 	V2M_MAP_IOFPGA,
182 	{0}
183 };
184 #endif
185 #ifdef IMAGE_BL31
186 const mmap_region_t plat_arm_mmap[] = {
187 	ARM_MAP_SHARED_RAM,
188 #if USE_DEBUGFS
189 	/* Required by devfip, can be removed if devfip is not used */
190 	V2M_MAP_FLASH0_RW,
191 #endif /* USE_DEBUGFS */
192 	ARM_MAP_EL3_TZC_DRAM,
193 	V2M_MAP_IOFPGA,
194 	MAP_DEVICE0,
195 #if FVP_GICR_REGION_PROTECTION
196 	MAP_GICD_MEM,
197 	MAP_GICR_MEM,
198 #else
199 	MAP_DEVICE1,
200 #endif /* FVP_GICR_REGION_PROTECTION */
201 	ARM_V2M_MAP_MEM_PROTECT,
202 #if SPM_MM
203 	ARM_SPM_BUF_EL3_MMAP,
204 #endif
205 #if ENABLE_RME
206 	ARM_MAP_GPT_L1_DRAM,
207 	ARM_MAP_EL3_RMM_SHARED_MEM,
208 #endif
209 #ifdef MAP_FW_NS_HANDOFF
210 	MAP_FW_NS_HANDOFF,
211 #endif
212 #if defined(MAP_EL3_FW_HANDOFF) && !RESET_TO_BL31
213 	MAP_EL3_FW_HANDOFF,
214 #endif
215 	{ 0 }
216 };
217 
218 #if defined(IMAGE_BL31) && SPM_MM
219 const mmap_region_t plat_arm_secure_partition_mmap[] = {
220 	V2M_MAP_IOFPGA_EL0, /* for the UART */
221 	V2M_MAP_SECURE_SYSTEMREG_EL0, /* for initializing flash */
222 #if PSA_FWU_SUPPORT
223 	V2M_MAP_FLASH0_RW_EL0, /* for firmware update service in standalone mm */
224 #endif
225 	V2M_MAP_FLASH1_RW_EL0, /* for secure variable service in standalone mm */
226 	MAP_REGION_FLAT(DEVICE0_BASE,
227 			DEVICE0_SIZE,
228 			MT_DEVICE | MT_RO | MT_SECURE | MT_USER),
229 	ARM_SP_IMAGE_MMAP,
230 	ARM_SP_IMAGE_NS_BUF_MMAP,
231 	ARM_SP_IMAGE_RW_MMAP,
232 	ARM_SPM_BUF_EL0_MMAP,
233 	{0}
234 };
235 #endif
236 #endif
237 #ifdef IMAGE_BL32
238 const mmap_region_t plat_arm_mmap[] = {
239 #ifndef __aarch64__
240 	ARM_MAP_SHARED_RAM,
241 	ARM_V2M_MAP_MEM_PROTECT,
242 #endif
243 	V2M_MAP_IOFPGA,
244 	MAP_DEVICE0,
245 	MAP_DEVICE1,
246 	{0}
247 };
248 #endif
249 
250 #ifdef IMAGE_RMM
251 const mmap_region_t plat_arm_mmap[] = {
252 	V2M_MAP_IOFPGA,
253 	MAP_DEVICE0,
254 	MAP_DEVICE1,
255 	{0}
256 };
257 #endif
258 
259 ARM_CASSERT_MMAP
260 
261 #if FVP_INTERCONNECT_DRIVER != FVP_CCN
262 static const int fvp_cci400_map[] = {
263 	PLAT_FVP_CCI400_CLUS0_SL_PORT,
264 	PLAT_FVP_CCI400_CLUS1_SL_PORT,
265 };
266 
267 static const int fvp_cci5xx_map[] = {
268 	PLAT_FVP_CCI5XX_CLUS0_SL_PORT,
269 	PLAT_FVP_CCI5XX_CLUS1_SL_PORT,
270 };
271 
272 static unsigned int get_interconnect_master(void)
273 {
274 	unsigned int master;
275 	u_register_t mpidr;
276 
277 	mpidr = read_mpidr_el1();
278 	master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ?
279 		MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr);
280 
281 	assert(master < FVP_CLUSTER_COUNT);
282 	return master;
283 }
284 #endif
285 
286 #if defined(IMAGE_BL31) && SPM_MM
287 /*
288  * Boot information passed to a secure partition during initialisation. Linear
289  * indices in MP information will be filled at runtime.
290  */
291 static spm_mm_mp_info_t sp_mp_info[] = {
292 	[0] = {0x80000000, 0},
293 	[1] = {0x80000001, 0},
294 	[2] = {0x80000002, 0},
295 	[3] = {0x80000003, 0},
296 	[4] = {0x80000100, 0},
297 	[5] = {0x80000101, 0},
298 	[6] = {0x80000102, 0},
299 	[7] = {0x80000103, 0},
300 };
301 
302 const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = {
303 	.h.type              = PARAM_SP_IMAGE_BOOT_INFO,
304 	.h.version           = VERSION_1,
305 	.h.size              = sizeof(spm_mm_boot_info_t),
306 	.h.attr              = 0,
307 	.sp_mem_base         = ARM_SP_IMAGE_BASE,
308 	.sp_mem_limit        = ARM_SP_IMAGE_LIMIT,
309 	.sp_image_base       = ARM_SP_IMAGE_BASE,
310 	.sp_stack_base       = PLAT_SP_IMAGE_STACK_BASE,
311 	.sp_heap_base        = ARM_SP_IMAGE_HEAP_BASE,
312 	.sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE,
313 	.sp_shared_buf_base  = PLAT_SPM_BUF_BASE,
314 	.sp_image_size       = ARM_SP_IMAGE_SIZE,
315 	.sp_pcpu_stack_size  = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
316 	.sp_heap_size        = ARM_SP_IMAGE_HEAP_SIZE,
317 	.sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE,
318 	.sp_shared_buf_size  = PLAT_SPM_BUF_SIZE,
319 	.num_sp_mem_regions  = ARM_SP_IMAGE_NUM_MEM_REGIONS,
320 	.num_cpus            = PLATFORM_CORE_COUNT,
321 	.mp_info             = &sp_mp_info[0],
322 };
323 
324 const struct mmap_region *plat_get_secure_partition_mmap(void *cookie)
325 {
326 	return plat_arm_secure_partition_mmap;
327 }
328 
329 const struct spm_mm_boot_info *plat_get_secure_partition_boot_info(
330 		void *cookie)
331 {
332 	return &plat_arm_secure_partition_boot_info;
333 }
334 #endif
335 
336 /*******************************************************************************
337  * A single boot loader stack is expected to work on both the Foundation FVP
338  * models and the two flavours of the Base FVP models (AEMv8 & Cortex). The
339  * SYS_ID register provides a mechanism for detecting the differences between
340  * these platforms. This information is stored in a per-BL array to allow the
341  * code to take the correct path.Per BL platform configuration.
342  ******************************************************************************/
343 void __init fvp_config_setup(void)
344 {
345 	unsigned int rev, hbi, bld, arch, sys_id;
346 
347 	sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID);
348 	rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK;
349 	hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK;
350 	bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK;
351 	arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK;
352 
353 	if (arch != ARCH_MODEL) {
354 		ERROR("This firmware is for FVP models\n");
355 		panic();
356 	}
357 
358 	/*
359 	 * The build field in the SYS_ID tells which variant of the GIC
360 	 * memory is implemented by the model.
361 	 */
362 	switch (bld) {
363 	case BLD_GIC_VE_MMAP:
364 		ERROR("Legacy Versatile Express memory map for GIC peripheral"
365 				" is not supported\n");
366 		panic();
367 		break;
368 	case BLD_GIC_A53A57_MMAP:
369 		break;
370 	default:
371 		ERROR("Unsupported board build %x\n", bld);
372 		panic();
373 	}
374 
375 	/*
376 	 * The hbi field in the SYS_ID is 0x020 for the Base FVP & 0x010
377 	 * for the Foundation FVP.
378 	 */
379 	switch (hbi) {
380 	case HBI_FOUNDATION_FVP:
381 		arm_config.flags = 0;
382 
383 		/*
384 		 * Check for supported revisions of Foundation FVP
385 		 * Allow future revisions to run but emit warning diagnostic
386 		 */
387 		switch (rev) {
388 		case REV_FOUNDATION_FVP_V2_0:
389 		case REV_FOUNDATION_FVP_V2_1:
390 		case REV_FOUNDATION_FVP_v9_1:
391 		case REV_FOUNDATION_FVP_v9_6:
392 			break;
393 		default:
394 			WARN("Unrecognized Foundation FVP revision %x\n", rev);
395 			break;
396 		}
397 		break;
398 	case HBI_BASE_FVP:
399 		arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC);
400 
401 		/*
402 		 * Check for supported revisions
403 		 * Allow future revisions to run but emit warning diagnostic
404 		 */
405 		switch (rev) {
406 		case REV_BASE_FVP_V0:
407 			arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400;
408 			break;
409 		case REV_BASE_FVP_REVC:
410 			arm_config.flags |= (ARM_CONFIG_FVP_HAS_SMMUV3 |
411 					ARM_CONFIG_FVP_HAS_CCI5XX);
412 			break;
413 		default:
414 			WARN("Unrecognized Base FVP revision %x\n", rev);
415 			break;
416 		}
417 		break;
418 	default:
419 		ERROR("Unsupported board HBI number 0x%x\n", hbi);
420 		panic();
421 	}
422 
423 	/*
424 	 * We assume that the presence of MT bit, and therefore shifted
425 	 * affinities, is uniform across the platform: either all CPUs, or no
426 	 * CPUs implement it.
427 	 */
428 	if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U)
429 		arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF;
430 }
431 
432 
433 void __init fvp_interconnect_init(void)
434 {
435 #if FVP_INTERCONNECT_DRIVER == FVP_CCN
436 	if (ccn_get_part0_id(PLAT_ARM_CCN_BASE) != CCN_502_PART0_ID) {
437 		ERROR("Unrecognized CCN variant detected. Only CCN-502 is supported");
438 		panic();
439 	}
440 
441 	plat_arm_interconnect_init();
442 #else
443 	uintptr_t cci_base = 0U;
444 	const int *cci_map = NULL;
445 	unsigned int map_size = 0U;
446 
447 	/* Initialize the right interconnect */
448 	if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) != 0U) {
449 		cci_base = PLAT_FVP_CCI5XX_BASE;
450 		cci_map = fvp_cci5xx_map;
451 		map_size = ARRAY_SIZE(fvp_cci5xx_map);
452 	} else if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) != 0U) {
453 		cci_base = PLAT_FVP_CCI400_BASE;
454 		cci_map = fvp_cci400_map;
455 		map_size = ARRAY_SIZE(fvp_cci400_map);
456 	} else {
457 		return;
458 	}
459 
460 	assert(cci_base != 0U);
461 	assert(cci_map != NULL);
462 	cci_init(cci_base, cci_map, map_size);
463 #endif
464 }
465 
466 void fvp_interconnect_enable(void)
467 {
468 #if FVP_INTERCONNECT_DRIVER == FVP_CCN
469 	plat_arm_interconnect_enter_coherency();
470 #else
471 	unsigned int master;
472 
473 	if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
474 				 ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
475 		master = get_interconnect_master();
476 		cci_enable_snoop_dvm_reqs(master);
477 	}
478 #endif
479 }
480 
481 void fvp_interconnect_disable(void)
482 {
483 #if FVP_INTERCONNECT_DRIVER == FVP_CCN
484 	plat_arm_interconnect_exit_coherency();
485 #else
486 	unsigned int master;
487 
488 	if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
489 				 ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
490 		master = get_interconnect_master();
491 		cci_disable_snoop_dvm_reqs(master);
492 	}
493 #endif
494 }
495 
496 #if CRYPTO_SUPPORT
497 int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
498 {
499 	assert(heap_addr != NULL);
500 	assert(heap_size != NULL);
501 
502 	return arm_get_mbedtls_heap(heap_addr, heap_size);
503 }
504 #endif /* CRYPTO_SUPPORT */
505 
506 void fvp_timer_init(void)
507 {
508 #if USE_SP804_TIMER
509 	/* Enable the clock override for SP804 timer 0, which means that no
510 	 * clock dividers are applied and the raw (35MHz) clock will be used.
511 	 */
512 	mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV);
513 
514 	/* Initialize delay timer driver using SP804 dual timer 0 */
515 	sp804_timer_init(V2M_SP804_TIMER0_BASE,
516 			SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV);
517 #else
518 	generic_delay_timer_init();
519 
520 	/* Enable System level generic timer */
521 	mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF,
522 			CNTCR_FCREQ(0U) | CNTCR_EN);
523 #endif /* USE_SP804_TIMER */
524 }
525 
526 /*****************************************************************************
527  * plat_is_smccc_feature_available() - This function checks whether SMCCC
528  *                                     feature is availabile for platform.
529  * @fid: SMCCC function id
530  *
531  * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
532  * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
533  *****************************************************************************/
534 int32_t plat_is_smccc_feature_available(u_register_t fid)
535 {
536 	switch (fid) {
537 	case SMCCC_ARCH_SOC_ID:
538 		return SMC_ARCH_CALL_SUCCESS;
539 	default:
540 		return SMC_ARCH_CALL_NOT_SUPPORTED;
541 	}
542 }
543 
544 /* Get SOC version */
545 int32_t plat_get_soc_version(void)
546 {
547 	return (int32_t)
548 		(SOC_ID_SET_JEP_106(ARM_SOC_CONTINUATION_CODE,
549 				    ARM_SOC_IDENTIFICATION_CODE) |
550 		 (FVP_SOC_ID & SOC_ID_IMPL_DEF_MASK));
551 }
552 
553 /* Get SOC revision */
554 int32_t plat_get_soc_revision(void)
555 {
556 	unsigned int sys_id;
557 
558 	sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID);
559 	return (int32_t)(((sys_id >> V2M_SYS_ID_REV_SHIFT) &
560 			  V2M_SYS_ID_REV_MASK) & SOC_ID_REV_MASK);
561 }
562 
563 #if ENABLE_RME
564 /*
565  * Get a pointer to the RMM-EL3 Shared buffer and return it
566  * through the pointer passed as parameter.
567  *
568  * This function returns the size of the shared buffer.
569  */
570 size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared)
571 {
572 	*shared = (uintptr_t)RMM_SHARED_BASE;
573 
574 	return (size_t)RMM_SHARED_SIZE;
575 }
576 
577 /*
578  * Calculate checksum of 64-bit words @buffer with @size length
579  */
580 static uint64_t checksum_calc(uint64_t *buffer, size_t size)
581 {
582 	uint64_t sum = 0UL;
583 
584 	assert(((uintptr_t)buffer & (sizeof(uint64_t) - 1UL)) == 0UL);
585 	assert((size & (sizeof(uint64_t) - 1UL)) == 0UL);
586 
587 	for (unsigned long i = 0UL; i < (size / sizeof(uint64_t)); i++) {
588 		sum += buffer[i];
589 	}
590 
591 	return sum;
592 }
593 /*
594  * Boot Manifest structure illustration, with two DRAM banks,
595  * a single console and one device memory with two PCIe device
596  * non-coherent address ranges.
597  *
598  * +--------------------------------------------------+
599  * | offset |        field       |      comment       |
600  * +--------+--------------------+--------------------+
601  * |   0    |       version      |     0x00000004     |
602  * +--------+--------------------+--------------------+
603  * |   4    |       padding      |     0x00000000     |
604  * +--------+--------------------+--------------------+
605  * |   8    |      plat_data     |       NULL         |
606  * +--------+--------------------+--------------------+
607  * |   16   |      num_banks     |                    |
608  * +--------+--------------------+                    |
609  * |   24   |       banks        |     plat_dram      +--+
610  * +--------+--------------------+                    |  |
611  * |   32   |      checksum      |                    |  |
612  * +--------+--------------------+--------------------+  |
613  * |   40   |    num_consoles    |                    |  |
614  * +--------+--------------------+                    |  |
615  * |   48   |      consoles      |    plat_console    +--|--+
616  * +--------+--------------------+                    |  |  |
617  * |   56   |      checksum      |                    |  |  |
618  * +--------+--------------------+--------------------+  |  |
619  * |   64   |      num_banks     |                    |  |  |
620  * +--------+--------------------+                    |  |  |
621  * |   72   |        banks       |  plat_ncoh_region  +--|--|--+
622  * +--------+--------------------+                    |  |  |  |
623  * |   80   |      checksum      |                    |  |  |  |
624  * +--------+--------------------+--------------------+  |  |  |
625  * |   88   |      num_banks     |                    |  |  |  |
626  * +--------+--------------------+                    |  |  |  |
627  * |   96   |       banks        |   plat_coh_region  |  |  |  |
628  * +--------+--------------------+                    |  |  |  |
629  * |   104  |      checksum      |                    |  |  |  |
630  * +--------+--------------------+--------------------+<-+  |  |
631  * |   112  |       base 0       |                    |     |  |
632  * +--------+--------------------+     mem_bank[0]    |     |  |
633  * |   120  |       size 0       |                    |     |  |
634  * +--------+--------------------+--------------------+     |  |
635  * |   128  |       base 1       |                    |     |  |
636  * +--------+--------------------+     mem_bank[1]    |     |  |
637  * |   136  |       size 1       |                    |     |  |
638  * +--------+--------------------+--------------------+<----+  |
639  * |   144  |       base         |                    |        |
640  * +--------+--------------------+                    |        |
641  * |   152  |      map_pages     |                    |        |
642  * +--------+--------------------+                    |        |
643  * |   160  |       name         |                    |        |
644  * +--------+--------------------+     consoles[0]    |        |
645  * |   168  |     clk_in_hz      |                    |        |
646  * +--------+--------------------+                    |        |
647  * |   176  |     baud_rate      |                    |        |
648  * +--------+--------------------+                    |        |
649  * |   184  |       flags        |                    |        |
650  * +--------+--------------------+--------------------+<-------+
651  * |   192  |       base 0       |                    |
652  * +--------+--------------------+   ncoh_region[0]   |
653  * |   200  |       size 0       |                    |
654  * +--------+--------------------+--------------------+
655  * |   208  |       base 1       |                    |
656  * +--------+--------------------+   ncoh_region[1]   |
657  * |   216  |       size 1       |                    |
658  * +--------+--------------------+--------------------+
659  */
660 int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
661 {
662 	uint64_t checksum, num_banks, num_consoles;
663 	uint64_t num_ncoh_regions, num_coh_regions;
664 	struct memory_bank *bank_ptr, *ncoh_region_ptr;
665 	struct console_info *console_ptr;
666 
667 	assert(manifest != NULL);
668 
669 	/* Get number of DRAM banks */
670 	num_banks = FCONF_GET_PROPERTY(hw_config, dram_layout, num_banks);
671 	assert(num_banks <= ARM_DRAM_NUM_BANKS);
672 
673 	/* Set number of consoles */
674 	num_consoles = FVP_RMM_CONSOLE_COUNT;
675 
676 	/* Set number of device non-coherent address ranges based on DT */
677 	num_ncoh_regions = FCONF_GET_PROPERTY(hw_config, pci_props, num_ncoh_regions);
678 
679 	manifest->version = RMMD_MANIFEST_VERSION;
680 	manifest->padding = 0U; /* RES0 */
681 	manifest->plat_data = 0UL;
682 	manifest->plat_dram.num_banks = num_banks;
683 	manifest->plat_console.num_consoles = num_consoles;
684 	manifest->plat_ncoh_region.num_banks = num_ncoh_regions;
685 
686 	/* FVP does not support device coherent address ranges */
687 	num_coh_regions = 0UL;
688 	manifest->plat_coh_region.num_banks = num_coh_regions;
689 	manifest->plat_coh_region.banks = NULL;
690 	manifest->plat_coh_region.checksum = 0UL;
691 
692 	bank_ptr = (struct memory_bank *)
693 			(((uintptr_t)manifest) + sizeof(struct rmm_manifest));
694 	console_ptr = (struct console_info *)
695 			((uintptr_t)bank_ptr + (num_banks *
696 						sizeof(struct memory_bank)));
697 	ncoh_region_ptr = (struct memory_bank *)
698 			((uintptr_t)console_ptr + (num_consoles *
699 						sizeof(struct console_info)));
700 	manifest->plat_dram.banks = bank_ptr;
701 	manifest->plat_console.consoles = console_ptr;
702 	manifest->plat_ncoh_region.banks = ncoh_region_ptr;
703 
704 	/* Ensure the manifest is not larger than the shared buffer */
705 	assert((sizeof(struct rmm_manifest) +
706 		(sizeof(struct memory_bank) *
707 			manifest->plat_dram.num_banks) +
708 		(sizeof(struct console_info) *
709 			manifest->plat_console.num_consoles) +
710 		(sizeof(struct memory_bank) *
711 			manifest->plat_ncoh_region.num_banks) +
712 		(sizeof(struct memory_bank) *
713 			manifest->plat_coh_region.num_banks))
714 		<= ARM_EL3_RMM_SHARED_SIZE);
715 
716 	/* Calculate checksum of plat_dram structure */
717 	checksum = num_banks + (uint64_t)bank_ptr;
718 
719 	/* Store FVP DRAM banks data in Boot Manifest */
720 	for (unsigned long i = 0UL; i < num_banks; i++) {
721 		bank_ptr[i].base = FCONF_GET_PROPERTY(hw_config, dram_layout, dram_bank[i].base);
722 		bank_ptr[i].size = FCONF_GET_PROPERTY(hw_config, dram_layout, dram_bank[i].size);
723 	}
724 
725 	/* Update checksum */
726 	checksum += checksum_calc((uint64_t *)bank_ptr, sizeof(struct memory_bank) * num_banks);
727 
728 	/* Checksum must be 0 */
729 	manifest->plat_dram.checksum = ~checksum + 1UL;
730 
731 	/* Calculate the checksum of plat_consoles structure */
732 	checksum = num_consoles + (uint64_t)console_ptr;
733 
734 	/* Zero out the console info struct */
735 	(void)memset((void *)console_ptr, '\0',
736 			sizeof(struct console_info) * num_consoles);
737 
738 	console_ptr[0].base = FVP_RMM_CONSOLE_BASE;
739 	console_ptr[0].map_pages = 1UL;
740 	console_ptr[0].clk_in_hz = FVP_RMM_CONSOLE_CLK_IN_HZ;
741 	console_ptr[0].baud_rate = FVP_RMM_CONSOLE_BAUD;
742 
743 	(void)strlcpy(console_ptr[0].name, FVP_RMM_CONSOLE_NAME,
744 						RMM_CONSOLE_MAX_NAME_LEN - 1UL);
745 
746 	/* Update checksum */
747 	checksum += checksum_calc((uint64_t *)console_ptr,
748 					sizeof(struct console_info) * num_consoles);
749 	/* Checksum must be 0 */
750 	manifest->plat_console.checksum = ~checksum + 1UL;
751 
752 	/*
753 	 * Calculate the checksum of device non-coherent address ranges
754 	 * info structure
755 	 */
756 	checksum = num_ncoh_regions + (uint64_t)ncoh_region_ptr;
757 
758 	/* Zero out the PCIe region info struct */
759 	(void)memset((void *)ncoh_region_ptr, 0,
760 			sizeof(struct memory_bank) * num_ncoh_regions);
761 
762 	for (unsigned long i = 0UL; i < num_ncoh_regions; i++) {
763 		ncoh_region_ptr[i].base =
764 			FCONF_GET_PROPERTY(hw_config, pci_props, ncoh_regions[i].base);
765 		ncoh_region_ptr[i].size =
766 			FCONF_GET_PROPERTY(hw_config, pci_props, ncoh_regions[i].size);
767 	}
768 
769 	/* Update checksum */
770 	checksum += checksum_calc((uint64_t *)ncoh_region_ptr,
771 			sizeof(struct memory_bank) * num_ncoh_regions);
772 
773 	/* Checksum must be 0 */
774 	manifest->plat_ncoh_region.checksum = ~checksum + 1UL;
775 
776 	return 0;
777 }
778 #endif	/* ENABLE_RME */
779