• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2017-2020, 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 64 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 + (32 << TWO_MB_SHIFT))
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  ******************************************************************************/
arm_psci_read_mem_protect(int * enabled)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  ******************************************************************************/
arm_nor_psci_write_mem_protect(int val)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)
arm_nor_psci_do_dyn_mem_protect(void)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  ******************************************************************************/
arm_nor_psci_do_static_mem_protect(void)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  ******************************************************************************/
arm_psci_mem_protect_chk(uintptr_t base,u_register_t length)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