1 /* 2 * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <platform_def.h> 8 9 #include <common/debug.h> 10 #include <drivers/cfi/v2m_flash.h> 11 #include <lib/psci/psci.h> 12 #include <lib/utils.h> 13 #include <plat/arm/common/plat_arm.h> 14 15 /* 16 * DRAM1 is used also to load the NS boot loader. For this reason we 17 * cannot clear the full DRAM1, because in that case we would clear 18 * the NS images (especially for RESET_TO_BL31 and RESET_TO_SPMIN cases). 19 * For this reason we reserve 128 MB for the NS images and protect the RAM 20 * until the end of DRAM1. 21 * We limit the size of DRAM2 to 1 GB to avoid big delays while booting 22 */ 23 #define DRAM1_NS_IMAGE_LIMIT (PLAT_ARM_NS_IMAGE_BASE + SZ_128M) 24 #define DRAM1_PROTECTED_SIZE (ARM_NS_DRAM1_END+1u - DRAM1_NS_IMAGE_LIMIT) 25 26 static mem_region_t arm_ram_ranges[] = { 27 {DRAM1_NS_IMAGE_LIMIT, DRAM1_PROTECTED_SIZE}, 28 #ifdef __aarch64__ 29 {ARM_DRAM2_BASE, 1u << ONE_GB_SHIFT}, 30 #endif 31 }; 32 33 /******************************************************************************* 34 * Function that reads the content of the memory protect variable that 35 * enables clearing of non secure memory when system boots. This variable 36 * should be stored in a secure NVRAM. 37 ******************************************************************************/ 38 int arm_psci_read_mem_protect(int *enabled) 39 { 40 int tmp; 41 42 tmp = *(int *) PLAT_ARM_MEM_PROT_ADDR; 43 *enabled = (tmp == 1) ? 1 : 0; 44 return 0; 45 } 46 47 /******************************************************************************* 48 * Function that writes the content of the memory protect variable that 49 * enables overwritten of non secure memory when system boots. 50 ******************************************************************************/ 51 int arm_nor_psci_write_mem_protect(int val) 52 { 53 unsigned long enable = (val != 0) ? 1UL : 0UL; 54 55 if (nor_unlock(PLAT_ARM_MEM_PROT_ADDR) != 0) { 56 ERROR("unlocking memory protect variable\n"); 57 return -1; 58 } 59 60 if (enable == 1UL) { 61 /* 62 * If we want to write a value different than 0 63 * then we have to erase the full block because 64 * otherwise we cannot ensure that the value programmed 65 * into the flash is going to be the same than the value 66 * requested by the caller 67 */ 68 if (nor_erase(PLAT_ARM_MEM_PROT_ADDR) != 0) { 69 ERROR("erasing block containing memory protect variable\n"); 70 return -1; 71 } 72 } 73 74 if (nor_word_program(PLAT_ARM_MEM_PROT_ADDR, enable) != 0) { 75 ERROR("programming memory protection variable\n"); 76 return -1; 77 } 78 return 0; 79 } 80 81 /******************************************************************************* 82 * Function used for required psci operations performed when 83 * system boots 84 ******************************************************************************/ 85 /* 86 * PLAT_MEM_PROTECT_VA_FRAME is a address specifically 87 * selected in a way that is not needed an additional 88 * translation table for memprotect. It happens because 89 * we use a chunk of size 2MB and it means that it can 90 * be mapped in a level 2 table and the level 2 table 91 * for 0xc0000000 is already used and the entry for 92 * 0xc0000000 is not used. 93 */ 94 #if defined(PLAT_XLAT_TABLES_DYNAMIC) 95 void arm_nor_psci_do_dyn_mem_protect(void) 96 { 97 int enable; 98 99 arm_psci_read_mem_protect(&enable); 100 if (enable == 0) 101 return; 102 103 INFO("PSCI: Overwriting non secure memory\n"); 104 clear_map_dyn_mem_regions(arm_ram_ranges, 105 ARRAY_SIZE(arm_ram_ranges), 106 PLAT_ARM_MEM_PROTEC_VA_FRAME, 107 1 << TWO_MB_SHIFT); 108 } 109 #endif 110 111 /******************************************************************************* 112 * Function used for required psci operations performed when 113 * system boots and dynamic memory is not used. 114 ******************************************************************************/ 115 void arm_nor_psci_do_static_mem_protect(void) 116 { 117 int enable; 118 119 (void) arm_psci_read_mem_protect(&enable); 120 if (enable == 0) 121 return; 122 123 INFO("PSCI: Overwriting non secure memory\n"); 124 clear_mem_regions(arm_ram_ranges, 125 ARRAY_SIZE(arm_ram_ranges)); 126 (void) arm_nor_psci_write_mem_protect(0); 127 } 128 129 /******************************************************************************* 130 * Function that checks if a region is protected by the memory protect 131 * mechanism 132 ******************************************************************************/ 133 int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length) 134 { 135 return mem_region_in_array_chk(arm_ram_ranges, 136 ARRAY_SIZE(arm_ram_ranges), 137 base, length); 138 } 139