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