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 | EL3_PAS) 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