1 /* 2 * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 10 #include <arch_helpers.h> 11 #include <bl31/bl31.h> 12 #include <bl31/ehf.h> 13 #include <common/debug.h> 14 #include <common/fdt_wrappers.h> 15 #include <common/runtime_svc.h> 16 #include <lib/el3_runtime/context_mgmt.h> 17 #include <lib/smccc.h> 18 #include <lib/utils.h> 19 #include <lib/xlat_tables/xlat_tables_v2.h> 20 #include <libfdt.h> 21 #include <plat/common/platform.h> 22 #include <services/ffa_svc.h> 23 #include <services/spmc_svc.h> 24 #include <services/spmd_svc.h> 25 #include "spmc.h" 26 27 #include <platform_def.h> 28 29 /* 30 * Allocate a secure partition descriptor to describe each SP in the system that 31 * does not reside at EL3. 32 */ 33 static struct secure_partition_desc sp_desc[SECURE_PARTITION_COUNT]; 34 35 /* 36 * Allocate an NS endpoint descriptor to describe each VM and the Hypervisor in 37 * the system that interacts with a SP. It is used to track the Hypervisor 38 * buffer pair, version and ID for now. It could be extended to track VM 39 * properties when the SPMC supports indirect messaging. 40 */ 41 static struct ns_endpoint_desc ns_ep_desc[NS_PARTITION_COUNT]; 42 43 /* 44 * Helper function to obtain the descriptor of the last SP to whom control was 45 * handed to on this physical cpu. Currently, we assume there is only one SP. 46 * TODO: Expand to track multiple partitions when required. 47 */ 48 struct secure_partition_desc *spmc_get_current_sp_ctx(void) 49 { 50 return &(sp_desc[ACTIVE_SP_DESC_INDEX]); 51 } 52 53 /* 54 * Helper function to obtain the execution context of an SP on the 55 * current physical cpu. 56 */ 57 struct sp_exec_ctx *spmc_get_sp_ec(struct secure_partition_desc *sp) 58 { 59 return &(sp->ec[get_ec_index(sp)]); 60 } 61 62 /* Helper function to get pointer to SP context from its ID. */ 63 struct secure_partition_desc *spmc_get_sp_ctx(uint16_t id) 64 { 65 /* Check for SWd Partitions. */ 66 for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) { 67 if (sp_desc[i].sp_id == id) { 68 return &(sp_desc[i]); 69 } 70 } 71 return NULL; 72 } 73 74 /****************************************************************************** 75 * This function returns to the place where spmc_sp_synchronous_entry() was 76 * called originally. 77 ******************************************************************************/ 78 __dead2 void spmc_sp_synchronous_exit(struct sp_exec_ctx *ec, uint64_t rc) 79 { 80 /* 81 * The SPM must have initiated the original request through a 82 * synchronous entry into the secure partition. Jump back to the 83 * original C runtime context with the value of rc in x0; 84 */ 85 spm_secure_partition_exit(ec->c_rt_ctx, rc); 86 87 panic(); 88 } 89 90 /******************************************************************************* 91 * Return FFA_ERROR with specified error code. 92 ******************************************************************************/ 93 uint64_t spmc_ffa_error_return(void *handle, int error_code) 94 { 95 SMC_RET8(handle, FFA_ERROR, 96 FFA_TARGET_INFO_MBZ, error_code, 97 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, 98 FFA_PARAM_MBZ, FFA_PARAM_MBZ); 99 } 100 101 /****************************************************************************** 102 * Helper function to validate a secure partition ID to ensure it does not 103 * conflict with any other FF-A component and follows the convention to 104 * indicate it resides within the secure world. 105 ******************************************************************************/ 106 bool is_ffa_secure_id_valid(uint16_t partition_id) 107 { 108 /* Ensure the ID is not the invalid partition ID. */ 109 if (partition_id == INV_SP_ID) { 110 return false; 111 } 112 113 /* Ensure the ID is not the SPMD ID. */ 114 if (partition_id == SPMD_DIRECT_MSG_ENDPOINT_ID) { 115 return false; 116 } 117 118 /* 119 * Ensure the ID follows the convention to indicate it resides 120 * in the secure world. 121 */ 122 if (!ffa_is_secure_world_id(partition_id)) { 123 return false; 124 } 125 126 /* Ensure we don't conflict with the SPMC partition ID. */ 127 if (partition_id == FFA_SPMC_ID) { 128 return false; 129 } 130 131 /* Ensure we do not already have an SP context with this ID. */ 132 if (spmc_get_sp_ctx(partition_id)) { 133 return false; 134 } 135 136 return true; 137 } 138 139 /******************************************************************************* 140 * This function either forwards the request to the other world or returns 141 * with an ERET depending on the source of the call. 142 ******************************************************************************/ 143 static uint64_t spmc_smc_return(uint32_t smc_fid, 144 bool secure_origin, 145 uint64_t x1, 146 uint64_t x2, 147 uint64_t x3, 148 uint64_t x4, 149 void *handle, 150 void *cookie, 151 uint64_t flags, 152 uint16_t dst_id) 153 { 154 /* If the destination is in the normal world always go via the SPMD. */ 155 if (ffa_is_normal_world_id(dst_id)) { 156 return spmd_smc_handler(smc_fid, x1, x2, x3, x4, 157 cookie, handle, flags); 158 } 159 /* 160 * If the caller is secure and we want to return to the secure world, 161 * ERET directly. 162 */ 163 else if (secure_origin && ffa_is_secure_world_id(dst_id)) { 164 SMC_RET5(handle, smc_fid, x1, x2, x3, x4); 165 } 166 /* If we originated in the normal world then switch contexts. */ 167 else if (!secure_origin && ffa_is_secure_world_id(dst_id)) { 168 return spmd_smc_switch_state(smc_fid, secure_origin, x1, x2, 169 x3, x4, handle); 170 } else { 171 /* Unknown State. */ 172 panic(); 173 } 174 175 /* Shouldn't be Reached. */ 176 return 0; 177 } 178 179 /******************************************************************************* 180 * FF-A ABI Handlers. 181 ******************************************************************************/ 182 183 /******************************************************************************* 184 * Helper function to validate arg2 as part of a direct message. 185 ******************************************************************************/ 186 static inline bool direct_msg_validate_arg2(uint64_t x2) 187 { 188 /* 189 * We currently only support partition messages, therefore ensure x2 is 190 * not set. 191 */ 192 if (x2 != (uint64_t) 0) { 193 VERBOSE("Arg2 MBZ for partition messages (0x%lx).\n", x2); 194 return false; 195 } 196 return true; 197 } 198 199 /******************************************************************************* 200 * Handle direct request messages and route to the appropriate destination. 201 ******************************************************************************/ 202 static uint64_t direct_req_smc_handler(uint32_t smc_fid, 203 bool secure_origin, 204 uint64_t x1, 205 uint64_t x2, 206 uint64_t x3, 207 uint64_t x4, 208 void *cookie, 209 void *handle, 210 uint64_t flags) 211 { 212 uint16_t dst_id = ffa_endpoint_destination(x1); 213 struct secure_partition_desc *sp; 214 unsigned int idx; 215 216 /* Check if arg2 has been populated correctly based on message type. */ 217 if (!direct_msg_validate_arg2(x2)) { 218 return spmc_ffa_error_return(handle, 219 FFA_ERROR_INVALID_PARAMETER); 220 } 221 222 /* 223 * If called by the secure world it is an invalid call since a 224 * SP cannot call into the Normal world and there is no other SP to call 225 * into. If there are other SPs in future then the partition runtime 226 * model would need to be validated as well. 227 */ 228 if (secure_origin) { 229 VERBOSE("Direct request not supported to the Normal World.\n"); 230 return spmc_ffa_error_return(handle, 231 FFA_ERROR_INVALID_PARAMETER); 232 } 233 234 /* Check if the SP ID is valid. */ 235 sp = spmc_get_sp_ctx(dst_id); 236 if (sp == NULL) { 237 VERBOSE("Direct request to unknown partition ID (0x%x).\n", 238 dst_id); 239 return spmc_ffa_error_return(handle, 240 FFA_ERROR_INVALID_PARAMETER); 241 } 242 243 /* 244 * Check that the target execution context is in a waiting state before 245 * forwarding the direct request to it. 246 */ 247 idx = get_ec_index(sp); 248 if (sp->ec[idx].rt_state != RT_STATE_WAITING) { 249 VERBOSE("SP context on core%u is not waiting (%u).\n", 250 idx, sp->ec[idx].rt_model); 251 return spmc_ffa_error_return(handle, FFA_ERROR_BUSY); 252 } 253 254 /* 255 * Everything checks out so forward the request to the SP after updating 256 * its state and runtime model. 257 */ 258 sp->ec[idx].rt_state = RT_STATE_RUNNING; 259 sp->ec[idx].rt_model = RT_MODEL_DIR_REQ; 260 return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4, 261 handle, cookie, flags, dst_id); 262 } 263 264 /******************************************************************************* 265 * Handle direct response messages and route to the appropriate destination. 266 ******************************************************************************/ 267 static uint64_t direct_resp_smc_handler(uint32_t smc_fid, 268 bool secure_origin, 269 uint64_t x1, 270 uint64_t x2, 271 uint64_t x3, 272 uint64_t x4, 273 void *cookie, 274 void *handle, 275 uint64_t flags) 276 { 277 uint16_t dst_id = ffa_endpoint_destination(x1); 278 struct secure_partition_desc *sp; 279 unsigned int idx; 280 281 /* Check if arg2 has been populated correctly based on message type. */ 282 if (!direct_msg_validate_arg2(x2)) { 283 return spmc_ffa_error_return(handle, 284 FFA_ERROR_INVALID_PARAMETER); 285 } 286 287 /* Check that the response did not originate from the Normal world. */ 288 if (!secure_origin) { 289 VERBOSE("Direct Response not supported from Normal World.\n"); 290 return spmc_ffa_error_return(handle, 291 FFA_ERROR_INVALID_PARAMETER); 292 } 293 294 /* 295 * Check that the response is either targeted to the Normal world or the 296 * SPMC e.g. a PM response. 297 */ 298 if ((dst_id != FFA_SPMC_ID) && ffa_is_secure_world_id(dst_id)) { 299 VERBOSE("Direct response to invalid partition ID (0x%x).\n", 300 dst_id); 301 return spmc_ffa_error_return(handle, 302 FFA_ERROR_INVALID_PARAMETER); 303 } 304 305 /* Obtain the SP descriptor and update its runtime state. */ 306 sp = spmc_get_sp_ctx(ffa_endpoint_source(x1)); 307 if (sp == NULL) { 308 VERBOSE("Direct response to unknown partition ID (0x%x).\n", 309 dst_id); 310 return spmc_ffa_error_return(handle, 311 FFA_ERROR_INVALID_PARAMETER); 312 } 313 314 /* Sanity check state is being tracked correctly in the SPMC. */ 315 idx = get_ec_index(sp); 316 assert(sp->ec[idx].rt_state == RT_STATE_RUNNING); 317 318 /* Ensure SP execution context was in the right runtime model. */ 319 if (sp->ec[idx].rt_model != RT_MODEL_DIR_REQ) { 320 VERBOSE("SP context on core%u not handling direct req (%u).\n", 321 idx, sp->ec[idx].rt_model); 322 return spmc_ffa_error_return(handle, FFA_ERROR_DENIED); 323 } 324 325 /* Update the state of the SP execution context. */ 326 sp->ec[idx].rt_state = RT_STATE_WAITING; 327 328 /* 329 * If the receiver is not the SPMC then forward the response to the 330 * Normal world. 331 */ 332 if (dst_id == FFA_SPMC_ID) { 333 spmc_sp_synchronous_exit(&sp->ec[idx], x4); 334 /* Should not get here. */ 335 panic(); 336 } 337 338 return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4, 339 handle, cookie, flags, dst_id); 340 } 341 342 /******************************************************************************* 343 * This function handles the FFA_MSG_WAIT SMC to allow an SP to relinquish its 344 * cycles. 345 ******************************************************************************/ 346 static uint64_t msg_wait_handler(uint32_t smc_fid, 347 bool secure_origin, 348 uint64_t x1, 349 uint64_t x2, 350 uint64_t x3, 351 uint64_t x4, 352 void *cookie, 353 void *handle, 354 uint64_t flags) 355 { 356 struct secure_partition_desc *sp; 357 unsigned int idx; 358 359 /* 360 * Check that the response did not originate from the Normal world as 361 * only the secure world can call this ABI. 362 */ 363 if (!secure_origin) { 364 VERBOSE("Normal world cannot call FFA_MSG_WAIT.\n"); 365 return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 366 } 367 368 /* Get the descriptor of the SP that invoked FFA_MSG_WAIT. */ 369 sp = spmc_get_current_sp_ctx(); 370 if (sp == NULL) { 371 return spmc_ffa_error_return(handle, 372 FFA_ERROR_INVALID_PARAMETER); 373 } 374 375 /* 376 * Get the execution context of the SP that invoked FFA_MSG_WAIT. 377 */ 378 idx = get_ec_index(sp); 379 380 /* Ensure SP execution context was in the right runtime model. */ 381 if (sp->ec[idx].rt_model == RT_MODEL_DIR_REQ) { 382 return spmc_ffa_error_return(handle, FFA_ERROR_DENIED); 383 } 384 385 /* Sanity check the state is being tracked correctly in the SPMC. */ 386 assert(sp->ec[idx].rt_state == RT_STATE_RUNNING); 387 388 /* 389 * Perform a synchronous exit if the partition was initialising. The 390 * state is updated after the exit. 391 */ 392 if (sp->ec[idx].rt_model == RT_MODEL_INIT) { 393 spmc_sp_synchronous_exit(&sp->ec[idx], x4); 394 /* Should not get here */ 395 panic(); 396 } 397 398 /* Update the state of the SP execution context. */ 399 sp->ec[idx].rt_state = RT_STATE_WAITING; 400 401 /* Resume normal world if a secure interrupt was handled. */ 402 if (sp->ec[idx].rt_model == RT_MODEL_INTR) { 403 /* FFA_MSG_WAIT can only be called from the secure world. */ 404 unsigned int secure_state_in = SECURE; 405 unsigned int secure_state_out = NON_SECURE; 406 407 cm_el1_sysregs_context_save(secure_state_in); 408 cm_el1_sysregs_context_restore(secure_state_out); 409 cm_set_next_eret_context(secure_state_out); 410 SMC_RET0(cm_get_context(secure_state_out)); 411 } 412 413 /* Forward the response to the Normal world. */ 414 return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4, 415 handle, cookie, flags, FFA_NWD_ID); 416 } 417 418 static uint64_t ffa_error_handler(uint32_t smc_fid, 419 bool secure_origin, 420 uint64_t x1, 421 uint64_t x2, 422 uint64_t x3, 423 uint64_t x4, 424 void *cookie, 425 void *handle, 426 uint64_t flags) 427 { 428 struct secure_partition_desc *sp; 429 unsigned int idx; 430 431 /* Check that the response did not originate from the Normal world. */ 432 if (!secure_origin) { 433 return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 434 } 435 436 /* Get the descriptor of the SP that invoked FFA_ERROR. */ 437 sp = spmc_get_current_sp_ctx(); 438 if (sp == NULL) { 439 return spmc_ffa_error_return(handle, 440 FFA_ERROR_INVALID_PARAMETER); 441 } 442 443 /* Get the execution context of the SP that invoked FFA_ERROR. */ 444 idx = get_ec_index(sp); 445 446 /* 447 * We only expect FFA_ERROR to be received during SP initialisation 448 * otherwise this is an invalid call. 449 */ 450 if (sp->ec[idx].rt_model == RT_MODEL_INIT) { 451 ERROR("SP 0x%x failed to initialize.\n", sp->sp_id); 452 spmc_sp_synchronous_exit(&sp->ec[idx], x2); 453 /* Should not get here. */ 454 panic(); 455 } 456 457 return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 458 } 459 460 /******************************************************************************* 461 * This function will parse the Secure Partition Manifest. From manifest, it 462 * will fetch details for preparing Secure partition image context and secure 463 * partition image boot arguments if any. 464 ******************************************************************************/ 465 static int sp_manifest_parse(void *sp_manifest, int offset, 466 struct secure_partition_desc *sp, 467 entry_point_info_t *ep_info) 468 { 469 int32_t ret, node; 470 uint32_t config_32; 471 472 /* 473 * Look for the mandatory fields that are expected to be present in 474 * the SP manifests. 475 */ 476 node = fdt_path_offset(sp_manifest, "/"); 477 if (node < 0) { 478 ERROR("Did not find root node.\n"); 479 return node; 480 } 481 482 ret = fdt_read_uint32(sp_manifest, node, "exception-level", &config_32); 483 if (ret != 0) { 484 ERROR("Missing SP Exception Level information.\n"); 485 return ret; 486 } 487 488 sp->runtime_el = config_32; 489 490 ret = fdt_read_uint32(sp_manifest, node, "ffa-version", &config_32); 491 if (ret != 0) { 492 ERROR("Missing Secure Partition FF-A Version.\n"); 493 return ret; 494 } 495 496 sp->ffa_version = config_32; 497 498 ret = fdt_read_uint32(sp_manifest, node, "execution-state", &config_32); 499 if (ret != 0) { 500 ERROR("Missing Secure Partition Execution State.\n"); 501 return ret; 502 } 503 504 sp->execution_state = config_32; 505 506 /* 507 * Look for the optional fields that are expected to be present in 508 * an SP manifest. 509 */ 510 ret = fdt_read_uint32(sp_manifest, node, "id", &config_32); 511 if (ret != 0) { 512 WARN("Missing Secure Partition ID.\n"); 513 } else { 514 if (!is_ffa_secure_id_valid(config_32)) { 515 ERROR("Invalid Secure Partition ID (0x%x).\n", 516 config_32); 517 return -EINVAL; 518 } 519 sp->sp_id = config_32; 520 } 521 522 return 0; 523 } 524 525 /******************************************************************************* 526 * This function gets the Secure Partition Manifest base and maps the manifest 527 * region. 528 * Currently only one Secure Partition manifest is considered which is used to 529 * prepare the context for the single Secure Partition. 530 ******************************************************************************/ 531 static int find_and_prepare_sp_context(void) 532 { 533 void *sp_manifest; 534 uintptr_t manifest_base; 535 uintptr_t manifest_base_align; 536 entry_point_info_t *next_image_ep_info; 537 int32_t ret; 538 struct secure_partition_desc *sp; 539 540 next_image_ep_info = bl31_plat_get_next_image_ep_info(SECURE); 541 if (next_image_ep_info == NULL) { 542 WARN("No Secure Partition image provided by BL2.\n"); 543 return -ENOENT; 544 } 545 546 sp_manifest = (void *)next_image_ep_info->args.arg0; 547 if (sp_manifest == NULL) { 548 WARN("Secure Partition manifest absent.\n"); 549 return -ENOENT; 550 } 551 552 manifest_base = (uintptr_t)sp_manifest; 553 manifest_base_align = page_align(manifest_base, DOWN); 554 555 /* 556 * Map the secure partition manifest region in the EL3 translation 557 * regime. 558 * Map an area equal to (2 * PAGE_SIZE) for now. During manifest base 559 * alignment the region of 1 PAGE_SIZE from manifest align base may 560 * not completely accommodate the secure partition manifest region. 561 */ 562 ret = mmap_add_dynamic_region((unsigned long long)manifest_base_align, 563 manifest_base_align, 564 PAGE_SIZE * 2, 565 MT_RO_DATA); 566 if (ret != 0) { 567 ERROR("Error while mapping SP manifest (%d).\n", ret); 568 return ret; 569 } 570 571 ret = fdt_node_offset_by_compatible(sp_manifest, -1, 572 "arm,ffa-manifest-1.0"); 573 if (ret < 0) { 574 ERROR("Error happened in SP manifest reading.\n"); 575 return -EINVAL; 576 } 577 578 /* 579 * Store the size of the manifest so that it can be used later to pass 580 * the manifest as boot information later. 581 */ 582 next_image_ep_info->args.arg1 = fdt_totalsize(sp_manifest); 583 INFO("Manifest size = %lu bytes.\n", next_image_ep_info->args.arg1); 584 585 /* 586 * Select an SP descriptor for initialising the partition's execution 587 * context on the primary CPU. 588 */ 589 sp = spmc_get_current_sp_ctx(); 590 591 /* Initialize entry point information for the SP */ 592 SET_PARAM_HEAD(next_image_ep_info, PARAM_EP, VERSION_1, 593 SECURE | EP_ST_ENABLE); 594 595 /* Parse the SP manifest. */ 596 ret = sp_manifest_parse(sp_manifest, ret, sp, next_image_ep_info); 597 if (ret != 0) { 598 ERROR("Error in Secure Partition manifest parsing.\n"); 599 return ret; 600 } 601 602 /* Check that the runtime EL in the manifest was correct. */ 603 if (sp->runtime_el != S_EL1) { 604 ERROR("Unexpected runtime EL: %d\n", sp->runtime_el); 605 return -EINVAL; 606 } 607 608 /* Perform any common initialisation. */ 609 spmc_sp_common_setup(sp, next_image_ep_info); 610 611 /* Perform any initialisation specific to S-EL1 SPs. */ 612 spmc_el1_sp_setup(sp, next_image_ep_info); 613 614 /* Initialize the SP context with the required ep info. */ 615 spmc_sp_common_ep_commit(sp, next_image_ep_info); 616 617 return 0; 618 } 619 620 /******************************************************************************* 621 * This function takes an SP context pointer and performs a synchronous entry 622 * into it. 623 ******************************************************************************/ 624 uint64_t spmc_sp_synchronous_entry(struct sp_exec_ctx *ec) 625 { 626 uint64_t rc; 627 628 assert(ec != NULL); 629 630 /* Assign the context of the SP to this CPU */ 631 cm_set_context(&(ec->cpu_ctx), SECURE); 632 633 /* Restore the context assigned above */ 634 cm_el1_sysregs_context_restore(SECURE); 635 cm_set_next_eret_context(SECURE); 636 637 /* Invalidate TLBs at EL1. */ 638 tlbivmalle1(); 639 dsbish(); 640 641 /* Enter Secure Partition */ 642 rc = spm_secure_partition_enter(&ec->c_rt_ctx); 643 644 /* Save secure state */ 645 cm_el1_sysregs_context_save(SECURE); 646 647 return rc; 648 } 649 650 /******************************************************************************* 651 * SPMC Helper Functions. 652 ******************************************************************************/ 653 static int32_t sp_init(void) 654 { 655 uint64_t rc; 656 struct secure_partition_desc *sp; 657 struct sp_exec_ctx *ec; 658 659 sp = spmc_get_current_sp_ctx(); 660 ec = spmc_get_sp_ec(sp); 661 ec->rt_model = RT_MODEL_INIT; 662 ec->rt_state = RT_STATE_RUNNING; 663 664 INFO("Secure Partition (0x%x) init start.\n", sp->sp_id); 665 666 rc = spmc_sp_synchronous_entry(ec); 667 if (rc != 0) { 668 /* Indicate SP init was not successful. */ 669 ERROR("SP (0x%x) failed to initialize (%lu).\n", 670 sp->sp_id, rc); 671 return 0; 672 } 673 674 ec->rt_state = RT_STATE_WAITING; 675 INFO("Secure Partition initialized.\n"); 676 677 return 1; 678 } 679 680 static void initalize_sp_descs(void) 681 { 682 struct secure_partition_desc *sp; 683 684 for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) { 685 sp = &sp_desc[i]; 686 sp->sp_id = INV_SP_ID; 687 sp->secondary_ep = 0; 688 } 689 } 690 691 static void initalize_ns_ep_descs(void) 692 { 693 struct ns_endpoint_desc *ns_ep; 694 695 for (unsigned int i = 0U; i < NS_PARTITION_COUNT; i++) { 696 ns_ep = &ns_ep_desc[i]; 697 /* 698 * Clashes with the Hypervisor ID but will not be a 699 * problem in practice. 700 */ 701 ns_ep->ns_ep_id = 0; 702 ns_ep->ffa_version = 0; 703 } 704 } 705 706 /******************************************************************************* 707 * Initialize SPMC attributes for the SPMD. 708 ******************************************************************************/ 709 void spmc_populate_attrs(spmc_manifest_attribute_t *spmc_attrs) 710 { 711 spmc_attrs->major_version = FFA_VERSION_MAJOR; 712 spmc_attrs->minor_version = FFA_VERSION_MINOR; 713 spmc_attrs->exec_state = MODE_RW_64; 714 spmc_attrs->spmc_id = FFA_SPMC_ID; 715 } 716 717 /******************************************************************************* 718 * Initialize contexts of all Secure Partitions. 719 ******************************************************************************/ 720 int32_t spmc_setup(void) 721 { 722 int32_t ret; 723 724 /* Initialize endpoint descriptors */ 725 initalize_sp_descs(); 726 initalize_ns_ep_descs(); 727 728 /* Perform physical SP setup. */ 729 730 /* Disable MMU at EL1 (initialized by BL2) */ 731 disable_mmu_icache_el1(); 732 733 /* Initialize context of the SP */ 734 INFO("Secure Partition context setup start.\n"); 735 736 ret = find_and_prepare_sp_context(); 737 if (ret != 0) { 738 ERROR("Error in SP finding and context preparation.\n"); 739 return ret; 740 } 741 742 /* Register init function for deferred init. */ 743 bl31_register_bl32_init(&sp_init); 744 745 INFO("Secure Partition setup done.\n"); 746 747 return 0; 748 } 749 750 /******************************************************************************* 751 * Secure Partition Manager SMC handler. 752 ******************************************************************************/ 753 uint64_t spmc_smc_handler(uint32_t smc_fid, 754 bool secure_origin, 755 uint64_t x1, 756 uint64_t x2, 757 uint64_t x3, 758 uint64_t x4, 759 void *cookie, 760 void *handle, 761 uint64_t flags) 762 { 763 switch (smc_fid) { 764 765 case FFA_MSG_SEND_DIRECT_REQ_SMC32: 766 case FFA_MSG_SEND_DIRECT_REQ_SMC64: 767 return direct_req_smc_handler(smc_fid, secure_origin, x1, x2, 768 x3, x4, cookie, handle, flags); 769 770 case FFA_MSG_SEND_DIRECT_RESP_SMC32: 771 case FFA_MSG_SEND_DIRECT_RESP_SMC64: 772 return direct_resp_smc_handler(smc_fid, secure_origin, x1, x2, 773 x3, x4, cookie, handle, flags); 774 775 case FFA_MSG_WAIT: 776 return msg_wait_handler(smc_fid, secure_origin, x1, x2, x3, x4, 777 cookie, handle, flags); 778 779 case FFA_ERROR: 780 return ffa_error_handler(smc_fid, secure_origin, x1, x2, x3, x4, 781 cookie, handle, flags); 782 783 default: 784 WARN("Unsupported FF-A call 0x%08x.\n", smc_fid); 785 break; 786 } 787 return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 788 } 789