blob: 1fa234d7976866cc777e21e4871d53ca9324a9db [file] [log] [blame]
Roberto Vargasa1c16b62017-08-03 09:16:43 +01001/*
Zelalem87675d42020-02-03 14:56:42 -06002 * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
Roberto Vargasa1c16b62017-08-03 09:16:43 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Roberto Vargasa1c16b62017-08-03 09:16:43 +01007#include <platform_def.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008
9#include <common/debug.h>
10#include <drivers/cfi/v2m_flash.h>
11#include <lib/psci/psci.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000012#include <lib/utils.h>
Antonio Nino Diazbd7b7402019-01-25 14:30:04 +000013#include <plat/arm/common/plat_arm.h>
Roberto Vargas550eb082018-01-05 16:00:05 +000014
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 */
Sandrine Bailleuxafa91db2019-01-31 15:01:32 +010023#define DRAM1_NS_IMAGE_LIMIT (PLAT_ARM_NS_IMAGE_BASE + (32 << TWO_MB_SHIFT))
Roberto Vargas550eb082018-01-05 16:00:05 +000024#define DRAM1_PROTECTED_SIZE (ARM_NS_DRAM1_END+1u - DRAM1_NS_IMAGE_LIMIT)
25
Roberto Vargas2ca18d92018-02-12 12:36:17 +000026static mem_region_t arm_ram_ranges[] = {
Roberto Vargas550eb082018-01-05 16:00:05 +000027 {DRAM1_NS_IMAGE_LIMIT, DRAM1_PROTECTED_SIZE},
Julius Werner8e0ef0f2019-07-09 14:02:43 -070028#ifdef __aarch64__
Roberto Vargas550eb082018-01-05 16:00:05 +000029 {ARM_DRAM2_BASE, 1u << ONE_GB_SHIFT},
Roberto Vargasf8fda102017-08-08 11:27:20 +010030#endif
Roberto Vargasa1c16b62017-08-03 09:16:43 +010031};
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 ******************************************************************************/
38int arm_psci_read_mem_protect(int *enabled)
39{
40 int tmp;
41
42 tmp = *(int *) PLAT_ARM_MEM_PROT_ADDR;
Roberto Vargas550eb082018-01-05 16:00:05 +000043 *enabled = (tmp == 1) ? 1 : 0;
Roberto Vargasa1c16b62017-08-03 09:16:43 +010044 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 ******************************************************************************/
51int arm_nor_psci_write_mem_protect(int val)
52{
Sathees Balya30952cc2018-09-27 14:41:02 +010053 unsigned long enable = (val != 0) ? 1UL : 0UL;
Roberto Vargasa1c16b62017-08-03 09:16:43 +010054
55 if (nor_unlock(PLAT_ARM_MEM_PROT_ADDR) != 0) {
56 ERROR("unlocking memory protect variable\n");
57 return -1;
58 }
59
Sathees Balya30952cc2018-09-27 14:41:02 +010060 if (enable == 1UL) {
Roberto Vargasa1c16b62017-08-03 09:16:43 +010061 /*
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 ******************************************************************************/
Roberto Vargas550eb082018-01-05 16:00:05 +000085/*
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)
95void arm_nor_psci_do_dyn_mem_protect(void)
Roberto Vargasa1c16b62017-08-03 09:16:43 +010096{
97 int enable;
98
99 arm_psci_read_mem_protect(&enable);
Roberto Vargas550eb082018-01-05 16:00:05 +0000100 if (enable == 0)
Roberto Vargasa1c16b62017-08-03 09:16:43 +0100101 return;
Roberto Vargas550eb082018-01-05 16:00:05 +0000102
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 ******************************************************************************/
115void arm_nor_psci_do_static_mem_protect(void)
116{
117 int enable;
118
Antonio Nino Diazfec756f2018-07-18 16:24:16 +0100119 (void) arm_psci_read_mem_protect(&enable);
Roberto Vargas550eb082018-01-05 16:00:05 +0000120 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));
Antonio Nino Diazfec756f2018-07-18 16:24:16 +0100126 (void) arm_nor_psci_write_mem_protect(0);
Roberto Vargasa1c16b62017-08-03 09:16:43 +0100127}
128
129/*******************************************************************************
130 * Function that checks if a region is protected by the memory protect
131 * mechanism
132 ******************************************************************************/
133int 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}