1 /*
2  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3  *
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 
15 mem_region_t arm_ram_ranges[] = {
16 	{ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_SIZE},
17 #ifdef AARCH64
18 	{ARM_DRAM2_BASE, ARM_DRAM2_SIZE},
19 #endif
20 };
21 
22 /*******************************************************************************
23  * Function that reads the content of the memory protect variable that
24  * enables clearing of non secure memory when system boots. This variable
25  * should be stored in a secure NVRAM.
26  ******************************************************************************/
arm_psci_read_mem_protect(int * enabled)27 int arm_psci_read_mem_protect(int *enabled)
28 {
29 	int tmp;
30 
31 	tmp = *(int *) PLAT_ARM_MEM_PROT_ADDR;
32 	*enabled = (tmp == 1);
33 	return 0;
34 }
35 
36 /*******************************************************************************
37  * Function that writes the content of the memory protect variable that
38  * enables overwritten of non secure memory when system boots.
39  ******************************************************************************/
arm_nor_psci_write_mem_protect(int val)40 int arm_nor_psci_write_mem_protect(int val)
41 {
42 	int enable = (val != 0);
43 
44 	if (nor_unlock(PLAT_ARM_MEM_PROT_ADDR) != 0) {
45 		ERROR("unlocking memory protect variable\n");
46 		return -1;
47 	}
48 
49 	if (enable) {
50 		/*
51 		 * If we want to write a value different than 0
52 		 * then we have to erase the full block because
53 		 * otherwise we cannot ensure that the value programmed
54 		 * into the flash is going to be the same than the value
55 		 * requested by the caller
56 		 */
57 		if (nor_erase(PLAT_ARM_MEM_PROT_ADDR) != 0) {
58 			ERROR("erasing block containing memory protect variable\n");
59 			return -1;
60 		}
61 	}
62 
63 	if (nor_word_program(PLAT_ARM_MEM_PROT_ADDR, enable) != 0) {
64 		ERROR("programming memory protection variable\n");
65 		return -1;
66 	}
67 	return 0;
68 }
69 
70 /*******************************************************************************
71  * Function used for required psci operations performed when
72  * system boots
73  ******************************************************************************/
arm_nor_psci_do_mem_protect(void)74 void arm_nor_psci_do_mem_protect(void)
75 {
76 	int enable;
77 
78 	arm_psci_read_mem_protect(&enable);
79 	if (!enable)
80 		return;
81 	INFO("PSCI: Overwritting non secure memory\n");
82 	clear_mem_regions(arm_ram_ranges, ARRAY_SIZE(arm_ram_ranges));
83 	arm_nor_psci_write_mem_protect(0);
84 }
85 
86 /*******************************************************************************
87  * Function that checks if a region is protected by the memory protect
88  * mechanism
89  ******************************************************************************/
arm_psci_mem_protect_chk(uintptr_t base,u_register_t length)90 int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length)
91 {
92 	return mem_region_in_array_chk(arm_ram_ranges,
93 				       ARRAY_SIZE(arm_ram_ranges),
94 				       base, length);
95 }
96