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