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