blob: c01e4ed5c2c61397ea238914ea2033b789cda324 [file] [log] [blame]
Roberto Vargasa1c16b62017-08-03 09:16:43 +01001/*
Roberto Vargas2ca18d92018-02-12 12:36:17 +00002 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
Roberto Vargasa1c16b62017-08-03 09:16:43 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <debug.h>
8#include <mmio.h>
9#include <norflash.h>
10#include <plat_arm.h>
11#include <platform_def.h>
12#include <psci.h>
13#include <utils.h>
14
Roberto Vargas550eb082018-01-05 16:00:05 +000015
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_OFFSET + (32 << TWO_MB_SHIFT))
25#define DRAM1_PROTECTED_SIZE (ARM_NS_DRAM1_END+1u - DRAM1_NS_IMAGE_LIMIT)
26
Roberto Vargas2ca18d92018-02-12 12:36:17 +000027static mem_region_t arm_ram_ranges[] = {
Roberto Vargas550eb082018-01-05 16:00:05 +000028 {DRAM1_NS_IMAGE_LIMIT, DRAM1_PROTECTED_SIZE},
Roberto Vargasf8fda102017-08-08 11:27:20 +010029#ifdef AARCH64
Roberto Vargas550eb082018-01-05 16:00:05 +000030 {ARM_DRAM2_BASE, 1u << ONE_GB_SHIFT},
Roberto Vargasf8fda102017-08-08 11:27:20 +010031#endif
Roberto Vargasa1c16b62017-08-03 09:16:43 +010032};
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 ******************************************************************************/
39int arm_psci_read_mem_protect(int *enabled)
40{
41 int tmp;
42
43 tmp = *(int *) PLAT_ARM_MEM_PROT_ADDR;
Roberto Vargas550eb082018-01-05 16:00:05 +000044 *enabled = (tmp == 1) ? 1 : 0;
Roberto Vargasa1c16b62017-08-03 09:16:43 +010045 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 ******************************************************************************/
52int arm_nor_psci_write_mem_protect(int val)
53{
54 int enable = (val != 0);
55
56 if (nor_unlock(PLAT_ARM_MEM_PROT_ADDR) != 0) {
57 ERROR("unlocking memory protect variable\n");
58 return -1;
59 }
60
Roberto Vargas550eb082018-01-05 16:00:05 +000061 if (enable != 0) {
Roberto Vargasa1c16b62017-08-03 09:16:43 +010062 /*
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 ******************************************************************************/
Roberto Vargas550eb082018-01-05 16:00:05 +000086/*
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)
96void arm_nor_psci_do_dyn_mem_protect(void)
Roberto Vargasa1c16b62017-08-03 09:16:43 +010097{
98 int enable;
99
100 arm_psci_read_mem_protect(&enable);
Roberto Vargas550eb082018-01-05 16:00:05 +0000101 if (enable == 0)
Roberto Vargasa1c16b62017-08-03 09:16:43 +0100102 return;
Roberto Vargas550eb082018-01-05 16:00:05 +0000103
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 ******************************************************************************/
116void arm_nor_psci_do_static_mem_protect(void)
117{
118 int enable;
119
120 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));
Roberto Vargasa1c16b62017-08-03 09:16:43 +0100127 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 ******************************************************************************/
134int 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}