System/Security: Memprot API unified (ESP32C3)

Unified Memory protection API for all PMS-aware chips (ESP32C3)

Closes JIRA IDF-3849
This commit is contained in:
Martin Vychodil 2021-09-06 10:22:40 +02:00
parent 7c7fbb1fd0
commit dd938eb952
41 changed files with 3443 additions and 3090 deletions

View File

@ -33,7 +33,8 @@ set(optional_reqs ulp
esp_netif
soc
esp-tls
esp_https_ota)
esp_https_ota
esp_hw_support)
idf_build_get_property(build_components BUILD_COMPONENTS)
foreach(req ${optional_reqs})

View File

@ -1,16 +1,9 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <stdint.h>
@ -46,6 +39,7 @@ typedef int esp_err_t;
#define ESP_ERR_MESH_BASE 0x4000 /*!< Starting number of MESH error codes */
#define ESP_ERR_FLASH_BASE 0x6000 /*!< Starting number of flash error codes */
#define ESP_ERR_HW_CRYPTO_BASE 0xc000 /*!< Starting number of HW cryptography module error codes */
#define ESP_ERR_MEMPROT_BASE 0xd000 /*!< Starting number of Memory Protection API error codes */
/**
* @brief Returns string for esp_err_t error codes

View File

@ -23,6 +23,9 @@
#if __has_include("esp_image_format.h")
#include "esp_image_format.h"
#endif
#if __has_include("esp_memprot_err.h")
#include "esp_memprot_err.h"
#endif
#if __has_include("esp_mesh.h")
#include "esp_mesh.h"
#endif
@ -758,6 +761,33 @@ static const esp_err_msg_t esp_err_msg_table[] = {
# endif
# ifdef ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING
ERR_TBL_IT(ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING), /* 49157 0xc005 */
# endif
// components/esp_common/include/esp_err.h
# ifdef ESP_ERR_MEMPROT_BASE
ERR_TBL_IT(ESP_ERR_MEMPROT_BASE), /* 53248 0xd000 Starting number of Memory Protection API
error codes */
# endif
// components/esp_hw_support/include/esp_memprot_err.h
# ifdef ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID
ERR_TBL_IT(ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID), /* 53249 0xd001 */
# endif
# ifdef ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID
ERR_TBL_IT(ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID), /* 53250 0xd002 */
# endif
# ifdef ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE
ERR_TBL_IT(ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE), /* 53251 0xd003 */
# endif
# ifdef ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED
ERR_TBL_IT(ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED), /* 53252 0xd004 */
# endif
# ifdef ESP_ERR_MEMPROT_UNIMGMT_BLOCK_INVALID
ERR_TBL_IT(ESP_ERR_MEMPROT_UNIMGMT_BLOCK_INVALID), /* 53253 0xd005 */
# endif
# ifdef ESP_ERR_MEMPROT_WORLD_INVALID
ERR_TBL_IT(ESP_ERR_MEMPROT_WORLD_INVALID), /* 53254 0xd006 */
# endif
# ifdef ESP_ERR_MEMPROT_AREA_INVALID
ERR_TBL_IT(ESP_ERR_MEMPROT_AREA_INVALID), /* 53255 0xd007 */
# endif
};
#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP

View File

@ -0,0 +1,194 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/////////////////////////////////////////////////////////////////////////////////////////
// ESP Memory Protection API (PMS)
// - allows configuration and violation-interrupt handling of the PMS module operations
// - not intended for public use.
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "esp_err.h"
#include "esp_memprot_err.h"
#include "soc_memprot_types.h"
#include "esp_memprot_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ESP_MEMPROT_ERR_CHECK(retval, fnc) if ((retval=fnc) != ESP_OK) { return retval; }
/**
* @brief Basic PMS interrupt source info
*/
typedef struct {
esp_mprot_mem_t mem_type; /*!< Memory type containing the faulting address */
int core; /*!< CPU/Core ID running the faulting instruction */
} esp_memp_intr_source_t;
/**
* @brief Clears current interrupt ON flag for given Memory type and CPU/Core ID
*
* This operation is non-atomic for some chips by PMS module design
* In such a case the interrupt clearing happens in two steps:
* 1. Interrupt CLR flag is set (clears interrupt-ON status and inhibits linked interrupt processing)
* 2. Interrupt CLR flag is reset (resumes the interrupt monitoring)
*
* @param mem_type Memory type (see esp_mprot_mem_t enum)
* @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG on passing invalid pointer
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
*/
esp_err_t esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core);
/**
* @brief Checks whether any of the PMS settings is locked
*
* @param[out] locked Any lock on? (true/false)
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG on invalid locked ptr
* Other failures: error code of any failing esp_mprot_get_*_lock() routine (called internally)
*/
esp_err_t esp_mprot_is_conf_locked_any(bool *locked);
/**
* @brief Checks whether any PMS violation-interrupt monitoring is enabled
*
* @param[out] locked Any PMS violation interrupt monitor is enabled (true/false)
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG on invalid enabled ptr
* Other failures: error code of esp_mprot_get_monitor_en() routine (called internally for all Memory types)
*/
esp_err_t esp_mprot_is_intr_ena_any(bool *enabled);
/**
* @brief Returns active PMS violation-interrupt Memory type if any (MEMPROT_TYPE_NONE when none detected)
* and the CPU/CoreID which was running the faulty code (-1 when no interrupt available)
*
* If there are more interrupts indicated on (shouldn't happen), the order of precedence is given by 'esp_mprot_mem_t' enum definition (low->high)
*
* @param[out] mem_type Out-pointer for Memory type given by the faulting address (see esp_mprot_mem_t enum)
* @param[out] core Out-pointer for CPU/Core ID (see *_CPU_NUM defs in soc.h)
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG on passing invalid pointer(s)
*/
esp_err_t esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr);
/**
* @brief Returns the address which caused the violation interrupt for given Memory type and CPU/Core ID.
* This function is to be called after a basic resolving of (current) interrupt's parameters (ie corresponding
* Memory type and CPU ID see esp_mprot_get_active_intr()). This is to minimize processing time of actual exception
* as this API is typicaly used in a panic-handling code.
* If there is no active interrupt available for the Memory type/CPU ID required, fault_addr is set to NULL.
*
* @param mem_type memory type
* @param[out] fault_addr Address of the operation which caused the PMS violation interrupt
* @param core Faulting instruction CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
*
* @return ESP_OK on success
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
* ESP_ERR_INVALID_ARG on invalid fault_addr pointer
*/
esp_err_t esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core);
/**
* @brief Returns PMS World identifier of the code causing the violation interrupt
*
* The value is read from appropriate PMS violation status register and thus might be 0 if the interrupt is not currently active.
*
* @param mem_type Memory type
* @param[out] world PMS World type (see esp_mprot_pms_world_t)
* @param core Faulting instruction CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
*
* @return ESP_OK on success
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
* ESP_ERR_INVALID_ARG on passing invalid pointer(s)
* ESP_ERR_MEMPROT_WORLD_INVALID on invalid World identifier fetched from the register
*/
esp_err_t esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core);
/**
* @brief Returns an operation type which caused the violation interrupt
*
* The operation resolving is processed over various PMS status register flags, according to given Memory type argument.
* If the interrupt is not active the result returned is irrelevant (likely evaluated to MEMPROT_OP_READ).
*
* @param mem_type Memory type
* @param[out] oper Operation type (see MEMPROT_OP_* defines)
* @param core Faulting instruction CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
*
* @return ESP_OK on success
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
* ESP_ERR_INVALID_ARG on invalid oper pointer
*/
esp_err_t esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core);
/**
* @brief Checks whether given memory type supports byte-enables info
*
* Byte-enables status is available only for DMA/DRAM operations
*
* @param mem_type memory type
*
* @return byte-enables info available true/false
*/
bool esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type);
/**
* @brief Returns byte-enables for the address which caused the violation interrupt
*
* The value is taken from appropriate PMS violation status register, based on given Memory type
*
* @param mem_type Memory type (MEMPROT_TYPE_DRAM0_SRAM)
* @param[out] byte_en Byte-enables bits
* @param core Faulting instruction CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
*
* @return ESP_OK on success
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
* ESP_ERR_INVALID_ARGUMENT on invalid byte_en pointer
*/
esp_err_t esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core);
/**
* @brief Convenient routine for setting the PMS defaults
*
* Called on system startup, depending on ESP_SYSTEM_MEMPROT_FEATURE Kconfig value
*
* @param memp_config pointer to Memprot configuration structure (esp_memp_config_t). The structure si chip-specific,
* for details and defaults see appropriate [target-chip]/soc_memprot_types.h
*
* @return ESP_OK on success
* Other failures: error code of the failing routine called internally. No specific error processing provided in such a case
* due to large number of embedded calls (ie no global unique error table is provided and thus one error code can have different meanings,
* depending on the routine issuing the error)
*/
esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config);
/**
* @brief Generates PMS configuration string of actual device (diagnostics)
*
* The functions generates a string from current configuration, control and status registers of the PMS (or similar) module of actual device.
* The values are fetched using HAL LL calls to help finding possible errors in the Memprot API implementation
*
* @param[out] dump_info_string configuration string buffer pointer. The string is allocated by the callee and must be freed by the caller.
*
* @return ESP_OK on success
* ESP_ERR_NO_MEM on buffer allocation failure
* ESP_ERR_INVALID_ARGUMENT on invalid dump_info_string pointer
*/
esp_err_t esp_mprot_dump_configuration(char **dump_info_string);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief ESP Memprot API error code definition
*/
#define ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID (ESP_ERR_MEMPROT_BASE + 1) /**< Memory type invalid in given context */
#define ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID (ESP_ERR_MEMPROT_BASE + 2) /**< Splitting address invalid in given context */
#define ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE (ESP_ERR_MEMPROT_BASE + 3) /**< Splitting address out of range */
#define ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED (ESP_ERR_MEMPROT_BASE + 4) /**< Splitting address not aligned to required boundaries */
#define ESP_ERR_MEMPROT_UNIMGMT_BLOCK_INVALID (ESP_ERR_MEMPROT_BASE + 5) /**< Required unified-management block is not valid */
#define ESP_ERR_MEMPROT_WORLD_INVALID (ESP_ERR_MEMPROT_BASE + 6) /**< Required World identifier is not valid */
#define ESP_ERR_MEMPROT_AREA_INVALID (ESP_ERR_MEMPROT_BASE + 7) /**< Required Area identifier is not valid */
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,36 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief PMS World type (attribute per PMS area, similar to x86 Ring scheme)
*/
typedef enum {
MEMPROT_PMS_WORLD_NONE = 0x00000000,
MEMPROT_PMS_WORLD_0 = 0x00000001,
MEMPROT_PMS_WORLD_1 = 0x00000002,
MEMPROT_PMS_WORLD_2 = 0x00000004,
MEMPROT_PMS_WORLD_ALL = 0x7FFFFFFF,
MEMPROT_PMS_WORLD_INVALID = 0x80000000
} esp_mprot_pms_world_t;
/**
* @brief Memory operation/permission type recognized by PMS
*/
#define MEMPROT_OP_NONE 0x00000000
#define MEMPROT_OP_READ 0x00000001
#define MEMPROT_OP_WRITE 0x00000002
#define MEMPROT_OP_EXEC 0x00000004
#define MEMPROT_OP_INVALID 0x80000000
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,194 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "esp_err.h"
#include "esp_memprot_err.h"
#include "hal/memprot_types.h"
#include "soc_memprot_types.h"
#include "esp_memprot_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Convert Memprot low level errors to esp_err_t
*/
esp_err_t esp_mprot_ll_err_to_esp_err(const memprot_ll_err_t err);
/**
* @brief Convert Memprot low level PMS World IDs to esp_mprot_pms_world_t
*/
esp_mprot_pms_world_t esp_mprot_ll_world_to_hl_world(const memprot_ll_world_t world);
/**
* @brief Converts operation type to string, no combination of operations allowed
*
* @param oper_type PMS operation type
*/
const char *esp_mprot_oper_type_to_str(const uint32_t oper_type);
/**
* @brief Converts PMS World type to string
*
* @param area_type PMS World type
*/
const char *esp_mprot_pms_world_to_str(const esp_mprot_pms_world_t world_type);
/**
* @brief Sets splitting address for given line type in the target Memory type
*
* @param mem_type memory type
* @param line_type split address type
* @param line_addr target address from a memory range relevant to given line_addr
*
* @return ESP_OK on success
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
* ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID on invalid line_type
* ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE on splitting line out of given memory-type range
* ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED on splitting line not aligned to PMS-required boundaries
*/
esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr);
/**
* @brief Gets PMS splitting address for given split_addr type
*
* The value is read from the PMS configuration registers
*
* @param mem_type memory type
* @param line_type Split line type (see esp_mprot_split_addr_t enum)
* @param[out] line_addr Split line address from the configuration register
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG on line_addr is pointer
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
* ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID on invalid line_type
*/
esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr);
/**
* @brief Returns default main I/D splitting address for given Memory type
*
* @param mem_type memory type
* @param[out] def_split_addr Main I/D splitting address of required mem_type
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARG on invalid def_split_addr pointer
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
*/
esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, void **def_split_addr);
/**
* @brief Sets a lock for the main IRAM/DRAM splitting addresses
* Locks can be unlocked only by digital system reset
*
* @param mem_type memory type
*
* @return ESP_OK on success
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
*/
esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type);
/**
* @brief Gets a lock status for the splitting address configuration of given Memory type
*
* @param mem_type memory type
* @param[out] locked mem_type related lock status
*
* @return ESP_OK on success
* ESP_ERR_INVALID_ARGUMENT on invalid locked pointer
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
*/
esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked);
/**
* @brief Sets a lock for PMS Area settings of required Memory type
* Locks can be unlocked only by digital system reset
*
* @param mem_type memory type
*
* @return ESP_OK on success
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
*/
esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type);
/**
* @brief Gets a lock status for PMS Area settings of required Memory type
*
* @param mem_type memory type
* @param[out] locked mem_type related lock status
*
* @return ESP_OK on success
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
* ESP_ERR_INVALID_ARGUMENT on invalid locked pointer
*/
esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked);
/**
* @brief Sets permissions for given PMS Area
*
* @param area_type PMS area type
* @param flags combination of MEMPROT_OP_* defines
*
* @return ESP_OK on success
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
*/
esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags);
/**
* @brief Gets current permissions for given PMS Area
*
* @param area_type PMS area type
* @param[out] flags combination of MEMPROT_OP_* defines
*
* @return ESP_OK on success
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
* ESP_ERR_INVALID_ARG on invalid flags pointer
*/
esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags);
/**
* @brief Sets a lock for PMS interrupt monitor settings of required Memory type
*
* Locks can be unlocked only by digital system reset
*
* @param mem_type memory type (see esp_mprot_mem_t enum)
*
* @return ESP_OK on success
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
*/
esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type);
/**
* @brief Gets a lock status for PMS interrupt monitor settings of required Memory type
*
* @param mem_type memory type
* @param[out] locked mem_type related lock status
*
* @return ESP_OK on success
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
* ESP_ERR_INVALID_ARG on invalid locked pointer
*/
esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked);
/**
* @brief Enable PMS violation interrupt monitoring of required Memory type
*
* @param mem_type memory type
* @param enable enable/disable violation interrupt monitoring
*
* @return ESP_OK on success
* ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
*/
esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable);
#ifdef __cplusplus
}
#endif

View File

@ -1,449 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* INTERNAL API
* generic interface to PMS memory protection features
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef IRAM_SRAM_START
#define IRAM_SRAM_START 0x4037C000
#endif
#ifndef DRAM_SRAM_START
#define DRAM_SRAM_START 0x3FC7C000
#endif
#ifndef MAP_DRAM_TO_IRAM
#define MAP_DRAM_TO_IRAM(addr) (addr - DRAM_SRAM_START + IRAM_SRAM_START)
#endif
#ifndef MAP_IRAM_TO_DRAM
#define MAP_IRAM_TO_DRAM(addr) (addr - IRAM_SRAM_START + DRAM_SRAM_START)
#endif
typedef enum {
MEMPROT_NONE = 0x00000000,
MEMPROT_IRAM0_SRAM = 0x00000001,
MEMPROT_DRAM0_SRAM = 0x00000002,
MEMPROT_ALL = 0xFFFFFFFF
} mem_type_prot_t;
typedef enum {
MEMPROT_SPLITLINE_NONE = 0,
MEMPROT_IRAM0_DRAM0_SPLITLINE,
MEMPROT_IRAM0_LINE_0_SPLITLINE,
MEMPROT_IRAM0_LINE_1_SPLITLINE,
MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE,
MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE
} split_line_t;
typedef enum {
MEMPROT_PMS_AREA_NONE = 0,
MEMPROT_IRAM0_PMS_AREA_0,
MEMPROT_IRAM0_PMS_AREA_1,
MEMPROT_IRAM0_PMS_AREA_2,
MEMPROT_IRAM0_PMS_AREA_3,
MEMPROT_DRAM0_PMS_AREA_0,
MEMPROT_DRAM0_PMS_AREA_1,
MEMPROT_DRAM0_PMS_AREA_2,
MEMPROT_DRAM0_PMS_AREA_3
} pms_area_t;
typedef enum
{
MEMPROT_PMS_WORLD_0 = 0,
MEMPROT_PMS_WORLD_1,
MEMPROT_PMS_WORLD_2,
MEMPROT_PMS_WORLD_INVALID = 0xFFFFFFFF
} pms_world_t;
typedef enum
{
MEMPROT_PMS_OP_READ = 0,
MEMPROT_PMS_OP_WRITE,
MEMPROT_PMS_OP_FETCH,
MEMPROT_PMS_OP_INVALID = 0xFFFFFFFF
} pms_operation_type_t;
/**
* @brief Converts Memory protection type to string
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type);
/**
* @brief Converts Split line type to string
*
* @param line_type Split line type (see split_line_t enum)
*/
const char *esp_memprot_split_line_to_str(split_line_t line_type);
/**
* @brief Converts PMS Area type to string
*
* @param area_type PMS Area type (see pms_area_t enum)
*/
const char *esp_memprot_pms_to_str(pms_area_t area_type);
/**
* @brief Returns PMS splitting address for given Split line type
*
* The value is taken from PMS configuration registers (IRam0 range)
* For details on split lines see 'esp_memprot_set_prot_int' function description
*
* @param line_type Split line type (see split_line_t enum)
*
* @return appropriate split line address
*/
uint32_t *esp_memprot_get_split_addr(split_line_t line_type);
/**
* @brief Returns default main IRAM/DRAM splitting address
*
* The address value is given by _iram_text_end global (IRam0 range)
* @return Main I/D split line (IRam0_DRam0_Split_Addr)
*/
void *esp_memprot_get_default_main_split_addr(void);
/**
* @brief Sets a lock for the main IRAM/DRAM splitting address
*
* Locks can be unlocked only by digital system reset
*/
void esp_memprot_set_split_line_lock(void);
/**
* @brief Gets a lock status for the main IRAM/DRAM splitting address
*
* @return true/false (locked/unlocked)
*/
bool esp_memprot_get_split_line_lock(void);
/**
* @brief Sets required split line address
*
* @param line_type Split line type (see split_line_t enum)
* @param line_addr target address from a memory range relevant to given line_type (IRAM/DRAM)
*/
void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr);
/**
* @brief Sets a lock for PMS Area settings of required Memory type
*
* Locks can be unlocked only by digital system reset
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type);
/**
* @brief Gets a lock status for PMS Area settings of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (locked/unlocked)
*/
bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type);
/**
* @brief Sets permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
*
* @param area_type IRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag
* @param w Write permission flag
* @param x Execute permission flag
*/
void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x);
/**
* @brief Gets current permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
*
* @param area_type IRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag holder
* @param w Write permission flag holder
* @param x Execute permission flag holder
*/
void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x);
/**
* @brief Sets permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
*
* @param area_type DRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag
* @param w Write permission flag
*/
void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w);
/**
* @brief Gets current permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
*
* @param area_type DRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag holder
* @param w Write permission flag holder
*/
void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w);
/**
* @brief Sets a lock for PMS interrupt monitor settings of required Memory type
*
* Locks can be unlocked only by digital system reset
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type);
/**
* @brief Gets a lock status for PMS interrupt monitor settings of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (locked/unlocked)
*/
bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type);
/**
* @brief Enable PMS violation interrupt monitoring of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
* @param enable/disable
*/
void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable);
/**
* @brief Gets enable/disable status for PMS interrupt monitor settings of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (enabled/disabled)
*/
bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type);
/**
* @brief Gets CPU ID for currently active PMS violation interrupt
*
* @return CPU ID (CPU_PRO for ESP32C3)
*/
int IRAM_ATTR esp_memprot_intr_get_cpuid(void);
/**
* @brief Clears current interrupt ON flag for given Memory type
*
* Interrupt clearing happens in two steps:
* 1. Interrupt CLR flag is set (to clear the interrupt ON status)
* 2. Interrupt CLR flag is reset (to allow further monitoring)
* This operation is non-atomic by PMS module design
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void IRAM_ATTR esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type);
/**
* @brief Returns active PMS violation interrupt (if any)
*
* This function iterates through supported Memory type status registers
* and returns the first interrupt-on flag. If none is found active,
* MEMPROT_NONE is returned.
* Order of checking (in current version):
* 1. MEMPROT_IRAM0_SRAM
* 2. MEMPROT_DRAM0_SRAM
*
* @return mem_type Memory protection type related to active interrupt found (see mem_type_prot_t enum)
*/
mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void);
/**
* @brief Checks whether any violation interrupt is active
*
* @return true/false (yes/no)
*/
bool IRAM_ATTR esp_memprot_is_locked_any(void);
/**
* @brief Checks whether any violation interrupt is enabled
*
* @return true/false (yes/no)
*/
bool IRAM_ATTR esp_memprot_is_intr_ena_any(void);
/**
* @brief Checks whether any violation interrupt is enabled
*
* @return true/false (yes/no)
*/
bool IRAM_ATTR esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type);
/**
* @brief Returns the address which caused the violation interrupt (if any)
*
* The address is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return faulting address
*/
uint32_t IRAM_ATTR esp_memprot_get_violate_addr(mem_type_prot_t mem_type);
/**
* @brief Returns the World identifier of the code causing the violation interrupt (if any)
*
* The value is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return World identifier (see pms_world_t enum)
*/
pms_world_t IRAM_ATTR esp_memprot_get_violate_world(mem_type_prot_t mem_type);
/**
* @brief Returns Read or Write operation type which caused the violation interrupt (if any)
*
* The value (bit) is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return PMS operation type relevant to mem_type parameter (se pms_operation_type_t)
*/
pms_operation_type_t IRAM_ATTR esp_memprot_get_violate_wr(mem_type_prot_t mem_type);
/**
* @brief Returns LoadStore flag of the operation type which caused the violation interrupt (if any)
*
* The value (bit) is taken from appropriate PMS violation status register, based given Memory type
* Effective only on IRam0 access
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (LoadStore bit on/off)
*/
bool IRAM_ATTR esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type);
/**
* @brief Returns byte-enables for the address which caused the violation interrupt (if any)
*
* The value is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return byte-enables
*/
uint32_t IRAM_ATTR esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type);
/**
* @brief Returns raw contents of DRam0 status register 1
*
* @return 32-bit register value
*/
uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_1(void);
/**
* @brief Returns raw contents of DRam0 status register 2
*
* @return 32-bit register value
*/
uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_2(void);
/**
* @brief Returns raw contents of IRam0 status register
*
* @return 32-bit register value
*/
uint32_t IRAM_ATTR esp_memprot_get_iram_status_reg(void);
/**
* @brief Register PMS violation interrupt in global interrupt matrix for given Memory type
*
* Memory protection components uses specific interrupt number, see ETS_MEMPROT_ERR_INUM
* The registration makes the panic-handler routine being called when the interrupt appears
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type);
/**
* @brief Convenient routine for setting the PMS defaults
*
* Called on application startup, depending on CONFIG_ESP_SYSTEM_MEMPROT_FEATURE Kconfig settings
* For implementation details see 'esp_memprot_set_prot_int' description
*
* @param invoke_panic_handler register all interrupts for panic handling (true/false)
* @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
* @param mem_type_mask 32-bit field of specific PMS parts to configure (see 'esp_memprot_set_prot_int')
*/
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask);
/**
* @brief Internal routine for setting the PMS defaults
*
* Called on application startup from within 'esp_memprot_set_prot'. Allows setting a specific splitting address
* (main I/D split line) - see the parameter 'split_addr'. If the 'split_addr' equals to NULL, default I/D split line
* is used (&_iram_text_end) and all the remaining lines share the same address.
* The function sets all the split lines and PMS areas to the same space,
* ie there is a single instruction space and single data space at the end.
* The PMS split lines and permission areas scheme described below:
*
* DRam0/DMA IRam0
* -----------------------------------------------
* ... | IRam0_PMS_0 |
* DRam0_PMS_0 ----------------------------------------------- IRam0_line1_Split_addr
* ... | IRam0_PMS_1 |
* ... ----------------------------------------------- IRam0_line0_Split_addr
* | IRam0_PMS_2 |
* =============================================== IRam0_DRam0_Split_addr (main I/D)
* | DRam0_PMS_1 |
* DRam0_DMA_line0_Split_addr ----------------------------------------------- ...
* | DRam0_PMS_2 | ...
* DRam0_DMA_line1_Split_addr ----------------------------------------------- IRam0_PMS_3
* | DRam0_PMS_3 | ...
* -----------------------------------------------
*
* Default settings provided by 'esp_memprot_set_prot_int' are as follows:
*
* DRam0/DMA IRam0
* -----------------------------------------------
* | IRam0_PMS_0 = IRam0_PMS_1 = IRam0_PMS_2 |
* | DRam0_PMS_0 | IRam0_line1_Split_addr
* DRam0_DMA_line0_Split_addr | | =
* = =============================================== IRam0_line0_Split_addr
* DRam0_DMA_line1_Split_addr | | =
* | DRam0_PMS_1 = DRam0_PMS_2 = DRam0_PMS_3 | IRam0_DRam0_Split_addr (main I/D)
* | IRam0_PMS_3 |
* -----------------------------------------------
*
* Once the memprot feature is locked, it can be unlocked only by digital system reset
*
* @param invoke_panic_handler register all the violation interrupts for panic handling (true/false)
* @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
* @param split_addr specific main I/D adrees or NULL to use default ($_iram_text_end)
* @param mem_type_mask 32-bit field of specific PMS parts to configure (members of mem_type_prot_t)
*/
void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask);
/**
* @brief Returns raw contents of PMS interrupt monitor register for given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return 32-bit register value
*/
uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,175 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
//////////////////////////////////////////////////////////
// ESP32-C3 PMS memory protection types
//
#pragma once
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Memory types recognized by PMS
*/
typedef enum {
MEMPROT_TYPE_NONE = 0x00000000,
MEMPROT_TYPE_IRAM0_SRAM = 0x00000001,
MEMPROT_TYPE_DRAM0_SRAM = 0x00000002,
MEMPROT_TYPE_IRAM0_RTCFAST = 0x00000004,
MEMPROT_TYPE_ALL = 0x7FFFFFFF,
MEMPROT_TYPE_INVALID = 0x80000000,
MEMPROT_TYPE_IRAM0_ANY = MEMPROT_TYPE_IRAM0_SRAM | MEMPROT_TYPE_IRAM0_RTCFAST
} esp_mprot_mem_t;
/**
* @brief Splitting address (line) type
*/
typedef enum {
MEMPROT_SPLIT_ADDR_NONE = 0x00000000,
MEMPROT_SPLIT_ADDR_IRAM0_DRAM0 = 0x00000001,
MEMPROT_SPLIT_ADDR_IRAM0_LINE_0 = 0x00000002,
MEMPROT_SPLIT_ADDR_IRAM0_LINE_1 = 0x00000004,
MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0 = 0x00000008,
MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1 = 0x00000010,
MEMPROT_SPLIT_ADDR_ALL = 0x7FFFFFFF,
MEMPROT_SPLIT_ADDR_INVALID = 0x80000000,
MEMPROT_SPLIT_ADDR_MAIN = MEMPROT_SPLIT_ADDR_IRAM0_DRAM0
} esp_mprot_split_addr_t;
/**
* @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address)
*/
typedef enum {
MEMPROT_PMS_AREA_NONE = 0x00000000,
MEMPROT_PMS_AREA_IRAM0_0 = 0x00000001,
MEMPROT_PMS_AREA_IRAM0_1 = 0x00000002,
MEMPROT_PMS_AREA_IRAM0_2 = 0x00000004,
MEMPROT_PMS_AREA_IRAM0_3 = 0x00000008,
MEMPROT_PMS_AREA_DRAM0_0 = 0x00000010,
MEMPROT_PMS_AREA_DRAM0_1 = 0x00000020,
MEMPROT_PMS_AREA_DRAM0_2 = 0x00000040,
MEMPROT_PMS_AREA_DRAM0_3 = 0x00000080,
MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO = 0x00000100,
MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI = 0x00000200,
MEMPROT_PMS_AREA_ALL = 0x7FFFFFFF,
MEMPROT_PMS_AREA_INVALID = 0x80000000
} esp_mprot_pms_area_t;
/**
* @brief Memory protection configuration
*/
typedef struct {
bool invoke_panic_handler; /*!< Register PMS violation interrupt for panic-handling */
bool lock_feature; /*!< Lock all PMS settings */
void *split_addr; /*!< Main I/D splitting address */
uint32_t mem_type_mask; /*!< Memory types required to protect. See esp_mprot_mem_t enum */
} esp_memp_config_t;
#define ESP_MEMPROT_DEFAULT_CONFIG() { \
.invoke_panic_handler = true, \
.lock_feature = true, \
.split_addr = NULL, \
.mem_type_mask = MEMPROT_TYPE_ALL \
}
/**
* @brief Converts Memory protection type to string
*
* @param mem_type Memory protection type
*/
static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type)
{
switch (mem_type) {
case MEMPROT_TYPE_NONE:
return "NONE";
case MEMPROT_TYPE_IRAM0_SRAM:
return "IRAM0_SRAM";
case MEMPROT_TYPE_DRAM0_SRAM:
return "DRAM0_SRAM";
case MEMPROT_TYPE_IRAM0_RTCFAST:
return "IRAM0_RTCFAST";
case MEMPROT_TYPE_IRAM0_ANY:
return "IRAM0_ANY";
case MEMPROT_TYPE_ALL:
return "ALL";
default:
return "INVALID";
}
}
/**
* @brief Converts Splitting address type to string
*
* @param line_type Split line type
*/
static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type)
{
switch (line_type) {
case MEMPROT_SPLIT_ADDR_NONE:
return "SPLIT_ADDR_NONE";
case MEMPROT_SPLIT_ADDR_IRAM0_DRAM0:
return "SPLIT_ADDR_IRAM0_DRAM0";
case MEMPROT_SPLIT_ADDR_IRAM0_LINE_0:
return "SPLIT_ADDR_IRAM0_LINE_0";
case MEMPROT_SPLIT_ADDR_IRAM0_LINE_1:
return "SPLIT_ADDR_IRAM0_LINE_1";
case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0:
return "SPLIT_ADDR_DRAM0_DMA_LINE_0";
case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1:
return "SPLIT_ADDR_DRAM0_DMA_LINE_1";
case MEMPROT_SPLIT_ADDR_ALL:
return "SPLIT_ADDR_ALL";
default:
return "SPLIT_ADDR_INVALID";
}
}
/**
* @brief Converts PMS Area type to string
*
* @param area_type PMS Area type
*/
static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type)
{
switch (area_type) {
case MEMPROT_PMS_AREA_NONE:
return "PMS_AREA_NONE";
case MEMPROT_PMS_AREA_IRAM0_0:
return "PMS_AREA_IRAM0_0";
case MEMPROT_PMS_AREA_IRAM0_1:
return "PMS_AREA_IRAM0_1";
case MEMPROT_PMS_AREA_IRAM0_2:
return "PMS_AREA_IRAM0_2";
case MEMPROT_PMS_AREA_IRAM0_3:
return "PMS_AREA_IRAM0_3";
case MEMPROT_PMS_AREA_DRAM0_0:
return "PMS_AREA_DRAM0_0";
case MEMPROT_PMS_AREA_DRAM0_1:
return "PMS_AREA_DRAM0_1";
case MEMPROT_PMS_AREA_DRAM0_2:
return "PMS_AREA_DRAM0_2";
case MEMPROT_PMS_AREA_DRAM0_3:
return "PMS_AREA_DRAM0_3";
case MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO:
return "PMS_AREA_IRAM0_RTCFAST_LO";
case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI:
return "PMS_AREA_IRAM0_RTCFAST_HI";
case MEMPROT_PMS_AREA_ALL:
return "PMS_AREA_ALL";
default:
return "PMS_AREA_INVALID";
}
}
#ifdef __cplusplus
}
#endif

View File

@ -1,448 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* INTERNAL API
* generic interface to PMS memory protection features
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef IRAM_SRAM_START
#define IRAM_SRAM_START 0x4037C000
#endif
#ifndef DRAM_SRAM_START
#define DRAM_SRAM_START 0x3FC7C000
#endif
#ifndef MAP_DRAM_TO_IRAM
#define MAP_DRAM_TO_IRAM(addr) (addr - DRAM_SRAM_START + IRAM_SRAM_START)
#endif
#ifndef MAP_IRAM_TO_DRAM
#define MAP_IRAM_TO_DRAM(addr) (addr - IRAM_SRAM_START + DRAM_SRAM_START)
#endif
typedef enum {
MEMPROT_NONE = 0x00000000,
MEMPROT_IRAM0_SRAM = 0x00000001,
MEMPROT_DRAM0_SRAM = 0x00000002,
MEMPROT_ALL = 0xFFFFFFFF
} mem_type_prot_t;
typedef enum {
MEMPROT_SPLITLINE_NONE = 0,
MEMPROT_IRAM0_DRAM0_SPLITLINE,
MEMPROT_IRAM0_LINE_0_SPLITLINE,
MEMPROT_IRAM0_LINE_1_SPLITLINE,
MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE,
MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE
} split_line_t;
typedef enum {
MEMPROT_PMS_AREA_NONE = 0,
MEMPROT_IRAM0_PMS_AREA_0,
MEMPROT_IRAM0_PMS_AREA_1,
MEMPROT_IRAM0_PMS_AREA_2,
MEMPROT_IRAM0_PMS_AREA_3,
MEMPROT_DRAM0_PMS_AREA_0,
MEMPROT_DRAM0_PMS_AREA_1,
MEMPROT_DRAM0_PMS_AREA_2,
MEMPROT_DRAM0_PMS_AREA_3
} pms_area_t;
typedef enum
{
MEMPROT_PMS_WORLD_0 = 0,
MEMPROT_PMS_WORLD_1,
MEMPROT_PMS_WORLD_2,
MEMPROT_PMS_WORLD_INVALID = 0xFFFFFFFF
} pms_world_t;
typedef enum
{
MEMPROT_PMS_OP_READ = 0,
MEMPROT_PMS_OP_WRITE,
MEMPROT_PMS_OP_FETCH,
MEMPROT_PMS_OP_INVALID = 0xFFFFFFFF
} pms_operation_type_t;
/**
* @brief Converts Memory protection type to string
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type);
/**
* @brief Converts Split line type to string
*
* @param line_type Split line type (see split_line_t enum)
*/
const char *esp_memprot_split_line_to_str(split_line_t line_type);
/**
* @brief Converts PMS Area type to string
*
* @param area_type PMS Area type (see pms_area_t enum)
*/
const char *esp_memprot_pms_to_str(pms_area_t area_type);
/**
* @brief Returns PMS splitting address for given Split line type
*
* The value is taken from PMS configuration registers (IRam0 range)
* For details on split lines see 'esp_memprot_set_prot_int' function description
*
* @param line_type Split line type (see split_line_t enum)
*
* @return appropriate split line address
*/
uint32_t *esp_memprot_get_split_addr(split_line_t line_type);
/**
* @brief Returns default main IRAM/DRAM splitting address
*
* The address value is given by _iram_text_end global (IRam0 range)
* @return Main I/D split line (IRam0_DRam0_Split_Addr)
*/
void *esp_memprot_get_default_main_split_addr(void);
/**
* @brief Sets a lock for the main IRAM/DRAM splitting address
*
* Locks can be unlocked only by digital system reset
*/
void esp_memprot_set_split_line_lock(void);
/**
* @brief Gets a lock status for the main IRAM/DRAM splitting address
*
* @return true/false (locked/unlocked)
*/
bool esp_memprot_get_split_line_lock(void);
/**
* @brief Sets required split line address
*
* @param line_type Split line type (see split_line_t enum)
* @param line_addr target address from a memory range relevant to given line_type (IRAM/DRAM)
*/
void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr);
/**
* @brief Sets a lock for PMS Area settings of required Memory type
*
* Locks can be unlocked only by digital system reset
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type);
/**
* @brief Gets a lock status for PMS Area settings of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (locked/unlocked)
*/
bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type);
/**
* @brief Sets permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
*
* @param area_type IRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag
* @param w Write permission flag
* @param x Execute permission flag
*/
void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x);
/**
* @brief Gets current permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
*
* @param area_type IRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag holder
* @param w Write permission flag holder
* @param x Execute permission flag holder
*/
void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x);
/**
* @brief Sets permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
*
* @param area_type DRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag
* @param w Write permission flag
*/
void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w);
/**
* @brief Gets current permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
*
* @param area_type DRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag holder
* @param w Write permission flag holder
*/
void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w);
/**
* @brief Sets a lock for PMS interrupt monitor settings of required Memory type
*
* Locks can be unlocked only by digital system reset
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type);
/**
* @brief Gets a lock status for PMS interrupt monitor settings of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (locked/unlocked)
*/
bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type);
/**
* @brief Enable PMS violation interrupt monitoring of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
* @param enable/disable
*/
void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable);
/**
* @brief Gets enable/disable status for PMS interrupt monitor settings of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (enabled/disabled)
*/
bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type);
/**
* @brief Gets CPU ID for currently active PMS violation interrupt
*
* @return CPU ID (CPU_PRO for ESP32H2)
*/
int IRAM_ATTR esp_memprot_intr_get_cpuid(void);
/**
* @brief Clears current interrupt ON flag for given Memory type
*
* Interrupt clearing happens in two steps:
* 1. Interrupt CLR flag is set (to clear the interrupt ON status)
* 2. Interrupt CLR flag is reset (to allow further monitoring)
* This operation is non-atomic by PMS module design
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void IRAM_ATTR esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type);
/**
* @brief Returns active PMS violation interrupt (if any)
*
* This function iterates through supported Memory type status registers
* and returns the first interrupt-on flag. If none is found active,
* MEMPROT_NONE is returned.
* Order of checking (in current version):
* 1. MEMPROT_IRAM0_SRAM
* 2. MEMPROT_DRAM0_SRAM
*
* @return mem_type Memory protection type related to active interrupt found (see mem_type_prot_t enum)
*/
mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void);
/**
* @brief Checks whether any violation interrupt is active
*
* @return true/false (yes/no)
*/
bool IRAM_ATTR esp_memprot_is_locked_any(void);
/**
* @brief Checks whether any violation interrupt is enabled
*
* @return true/false (yes/no)
*/
bool IRAM_ATTR esp_memprot_is_intr_ena_any(void);
/**
* @brief Checks whether any violation interrupt is enabled
*
* @return true/false (yes/no)
*/
bool IRAM_ATTR esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type);
/**
* @brief Returns the address which caused the violation interrupt (if any)
*
* The address is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return faulting address
*/
uint32_t IRAM_ATTR esp_memprot_get_violate_addr(mem_type_prot_t mem_type);
/**
* @brief Returns the World identifier of the code causing the violation interrupt (if any)
*
* The value is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return World identifier (see pms_world_t enum)
*/
pms_world_t IRAM_ATTR esp_memprot_get_violate_world(mem_type_prot_t mem_type);
/**
* @brief Returns Read or Write operation type which caused the violation interrupt (if any)
*
* The value (bit) is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return PMS operation type relevant to mem_type parameter (se pms_operation_type_t)
*/
pms_operation_type_t IRAM_ATTR esp_memprot_get_violate_wr(mem_type_prot_t mem_type);
/**
* @brief Returns LoadStore flag of the operation type which caused the violation interrupt (if any)
*
* The value (bit) is taken from appropriate PMS violation status register, based given Memory type
* Effective only on IRam0 access
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (LoadStore bit on/off)
*/
bool IRAM_ATTR esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type);
/**
* @brief Returns byte-enables for the address which caused the violation interrupt (if any)
*
* The value is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return byte-enables
*/
uint32_t IRAM_ATTR esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type);
/**
* @brief Returns raw contents of DRam0 status register 1
*
* @return 32-bit register value
*/
uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_1(void);
/**
* @brief Returns raw contents of DRam0 status register 2
*
* @return 32-bit register value
*/
uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_2(void);
/**
* @brief Returns raw contents of IRam0 status register
*
* @return 32-bit register value
*/
uint32_t IRAM_ATTR esp_memprot_get_iram_status_reg(void);
/**
* @brief Register PMS violation interrupt in global interrupt matrix for given Memory type
*
* Memory protection components uses specific interrupt number, see ETS_MEMPROT_ERR_INUM
* The registration makes the panic-handler routine being called when the interrupt appears
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type);
/**
* @brief Convenient routine for setting the PMS defaults
*
* Called on application startup, depending on CONFIG_ESP_SYSTEM_MEMPROT_FEATURE Kconfig settings
* For implementation details see 'esp_memprot_set_prot_int' description
*
* @param invoke_panic_handler register all interrupts for panic handling (true/false)
* @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
* @param mem_type_mask 32-bit field of specific PMS parts to configure (see 'esp_memprot_set_prot_int')
*/
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask);
/**
* @brief Internal routine for setting the PMS defaults
*
* Called on application startup from within 'esp_memprot_set_prot'. Allows setting a specific splitting address
* (main I/D split line) - see the parameter 'split_addr'. If the 'split_addr' equals to NULL, default I/D split line
* is used (&_iram_text_end) and all the remaining lines share the same address.
* The function sets all the split lines and PMS areas to the same space,
* ie there is a single instruction space and single data space at the end.
* The PMS split lines and permission areas scheme described below:
*
* DRam0/DMA IRam0
* -----------------------------------------------
* ... | IRam0_PMS_0 |
* DRam0_PMS_0 ----------------------------------------------- IRam0_line1_Split_addr
* ... | IRam0_PMS_1 |
* ... ----------------------------------------------- IRam0_line0_Split_addr
* | IRam0_PMS_2 |
* =============================================== IRam0_DRam0_Split_addr (main I/D)
* | DRam0_PMS_1 |
* DRam0_DMA_line0_Split_addr ----------------------------------------------- ...
* | DRam0_PMS_2 | ...
* DRam0_DMA_line1_Split_addr ----------------------------------------------- IRam0_PMS_3
* | DRam0_PMS_3 | ...
* -----------------------------------------------
*
* Default settings provided by 'esp_memprot_set_prot_int' are as follows:
*
* DRam0/DMA IRam0
* -----------------------------------------------
* | IRam0_PMS_0 = IRam0_PMS_1 = IRam0_PMS_2 |
* | DRam0_PMS_0 | IRam0_line1_Split_addr
* DRam0_DMA_line0_Split_addr | | =
* = =============================================== IRam0_line0_Split_addr
* DRam0_DMA_line1_Split_addr | | =
* | DRam0_PMS_1 = DRam0_PMS_2 = DRam0_PMS_3 | IRam0_DRam0_Split_addr (main I/D)
* | IRam0_PMS_3 |
* -----------------------------------------------
*
* Once the memprot feature is locked, it can be unlocked only by digital system reset
*
* @param invoke_panic_handler register all the violation interrupts for panic handling (true/false)
* @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
* @param split_addr specific main I/D adrees or NULL to use default ($_iram_text_end)
* @param mem_type_mask 32-bit field of specific PMS parts to configure (members of mem_type_prot_t)
*/
void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask);
/**
* @brief Returns raw contents of PMS interrupt monitor register for given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return 32-bit register value
*/
uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,117 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
//////////////////////////////////////////////////////////
// ESP32-H2 PMS memory protection types
//
#pragma once
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Memory types recognized by PMS
*/
typedef enum {
MEMPROT_TYPE_NONE = 0x00000000,
MEMPROT_TYPE_ALL = 0x7FFFFFFF,
MEMPROT_TYPE_INVALID = 0x80000000
} esp_mprot_mem_t;
/**
* @brief Splitting address (line) type
*/
typedef enum {
MEMPROT_SPLIT_ADDR_NONE = 0x00000000,
MEMPROT_SPLIT_ADDR_ALL = 0x7FFFFFFF,
MEMPROT_SPLIT_ADDR_INVALID = 0x80000000
} esp_mprot_split_addr_t;
/**
* @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address)
*/
typedef enum {
MEMPROT_PMS_AREA_NONE = 0x00000000,
MEMPROT_PMS_AREA_ALL = 0x7FFFFFFF,
MEMPROT_PMS_AREA_INVALID = 0x80000000
} esp_mprot_pms_area_t;
/**
* @brief Memory protection configuration
*/
typedef struct {
bool invoke_panic_handler; /*!< Register PMS violation interrupt for panic-handling */
bool lock_feature; /*!< Lock all PMS settings */
void *split_addr; /*!< Main I/D splitting address */
uint32_t mem_type_mask; /*!< Memory types required to protect. See esp_mprot_mem_t enum */
} esp_memp_config_t;
#define ESP_MEMPROT_DEFAULT_CONFIG() {\
.invoke_panic_handler = true, \
.lock_feature = true, \
.split_addr = NULL, \
.mem_type_mask = MEMPROT_TYPE_ALL \
}
/**
* @brief Converts Memory protection type to string
*
* @param mem_type Memory protection type
*/
static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type)
{
switch (mem_type) {
case MEMPROT_TYPE_NONE:
return "MEMPROT_TYPE_NONE";
case MEMPROT_TYPE_ALL:
return "MEMPROT_TYPE_ALL";
default:
return "MEMPROT_TYPE_INVALID";
}
}
/**
* @brief Converts Splitting address type to string
*
* @param line_type Split line type
*/
static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type)
{
switch (line_type) {
case MEMPROT_SPLIT_ADDR_NONE:
return "MEMPROT_SPLIT_ADDR_NONE";
case MEMPROT_SPLIT_ADDR_ALL:
return "MEMPROT_SPLIT_ADDR_ALL";
default:
return "MEMPROT_SPLIT_ADDR_INVALID";
}
}
/**
* @brief Converts PMS Area type to string
*
* @param area_type PMS Area type
*/
static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type)
{
switch (area_type) {
case MEMPROT_PMS_AREA_NONE:
return "MEMPROT_PMS_AREA_NONE";
case MEMPROT_PMS_AREA_ALL:
return "MEMPROT_PMS_AREA_ALL";
default:
return "MEMPROT_PMS_AREA_INVALID";
}
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,117 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
//////////////////////////////////////////////////////////
// ESP32-S2 PMS memory protection types
//
#pragma once
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Memory types recognized by PMS
*/
typedef enum {
MEMPROT_TYPE_NONE = 0x00000000,
MEMPROT_TYPE_ALL = 0x7FFFFFFF,
MEMPROT_TYPE_INVALID = 0x80000000
} esp_mprot_mem_t;
/**
* @brief Splitting address (line) type
*/
typedef enum {
MEMPROT_SPLIT_ADDR_NONE = 0x00000000,
MEMPROT_SPLIT_ADDR_ALL = 0x7FFFFFFF,
MEMPROT_SPLIT_ADDR_INVALID = 0x80000000
} esp_mprot_split_addr_t;
/**
* @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address)
*/
typedef enum {
MEMPROT_PMS_AREA_NONE = 0x00000000,
MEMPROT_PMS_AREA_ALL = 0x7FFFFFFF,
MEMPROT_PMS_AREA_INVALID = 0x80000000
} esp_mprot_pms_area_t;
/**
* @brief Memory protection configuration
*/
typedef struct {
bool invoke_panic_handler; /*!< Register PMS violation interrupt for panic-handling */
bool lock_feature; /*!< Lock all PMS settings */
void *split_addr; /*!< Main I/D splitting address */
uint32_t mem_type_mask; /*!< Memory types required to protect. See esp_mprot_mem_t enum */
} esp_memp_config_t;
#define ESP_MEMPROT_DEFAULT_CONFIG() { \
.invoke_panic_handler = true, \
.lock_feature = true, \
.split_addr = NULL, \
.mem_type_mask = MEMPROT_TYPE_ALL \
}
/**
* @brief Converts Memory protection type to string
*
* @param mem_type Memory protection type
*/
static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type)
{
switch (mem_type) {
case MEMPROT_TYPE_NONE:
return "MEMPROT_TYPE_NONE";
case MEMPROT_TYPE_ALL:
return "MEMPROT_TYPE_ALL";
default:
return "MEMPROT_TYPE_INVALID";
}
}
/**
* @brief Converts Splitting address type to string
*
* @param line_type Split line type
*/
static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type)
{
switch (line_type) {
case MEMPROT_SPLIT_ADDR_NONE:
return "MEMPROT_SPLIT_ADDR_NONE";
case MEMPROT_SPLIT_ADDR_ALL:
return "MEMPROT_SPLIT_ADDR_ALL";
default:
return "MEMPROT_SPLIT_ADDR_INVALID";
}
}
/**
* @brief Converts PMS Area type to string
*
* @param area_type PMS Area type
*/
static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type)
{
switch (area_type) {
case MEMPROT_PMS_AREA_NONE:
return "MEMPROT_PMS_AREA_NONE";
case MEMPROT_PMS_AREA_ALL:
return "MEMPROT_PMS_AREA_ALL";
default:
return "MEMPROT_PMS_AREA_INVALID";
}
}
#ifdef __cplusplus
}
#endif

View File

@ -1,484 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* INTERNAL API
* generic interface to MMU memory protection features
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
MEMPROT_NONE = 0x00000000,
MEMPROT_IRAM0_SRAM = 0x00000001,
MEMPROT_DRAM0_SRAM = 0x00000002,
MEMPROT_IRAM0_RTCFAST = 0x00000004,
MEMPROT_DRAM0_RTCFAST = 0x00000008,
MEMPROT_PERI1_RTCSLOW = 0x00000010,
MEMPROT_PERI2_RTCSLOW_0 = 0x00000020,
MEMPROT_PERI2_RTCSLOW_1 = 0x00000040,
MEMPROT_ALL = 0xFFFFFFFF
} mem_type_prot_t;
/**
* @brief Returns splitting address for required memory region
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*
* @return Splitting address for the memory region required.
* The address is given by region-specific global symbol exported from linker script,
* it is not read out from related configuration register.
*/
uint32_t *IRAM_ATTR esp_memprot_get_split_addr(mem_type_prot_t mem_type);
/**
* @brief Initializes illegal memory access control (MMU) for required memory section.
*
* All memory access interrupts share ETS_MEMACCESS_ERR_INUM input channel, it is caller's
* responsibility to properly detect actual intr. source as well as possible prioritization in case
* of multiple source reported during one intr.handling routine run
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*/
void esp_memprot_intr_init(mem_type_prot_t mem_type);
/**
* @brief Enable/disable the memory protection interrupt
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param enable enable/disable
*/
void esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable);
/**
* @brief Sets a request for clearing interrupt-on flag for specified memory region (register write)
*
* @note When called without actual interrupt-on flag set, subsequent occurrence of related interrupt is ignored.
* Should be used only after the real interrupt appears, typically as the last step in interrupt handler's routine.
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*/
void esp_memprot_clear_intr(mem_type_prot_t mem_type);
/**
* @brief Detects which memory protection interrupt is active
*
* @note Check order
* MEMPROT_IRAM0_SRAM
* MEMPROT_IRAM0_RTCFAST
* MEMPROT_DRAM0_SRAM
* MEMPROT_DRAM0_RTCFAST
*
* @return Memory protection area type (see mem_type_prot_t enum)
*/
mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void);
/**
* @brief Gets interrupt status register contents for specified memory region
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*
* @return Contents of status register
*/
uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type);
/**
* @brief Get details of given interrupt status
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param faulting_address Faulting address causing the interrupt [out]
* @param op_type Operation being processed at the faulting address [out]
* IRAM0: 0 - read, 1 - write
* DRAM0: 0 - read, 1 - write
* @param op_subtype Additional info for op_type [out]
* IRAM0: 0 - instruction segment access, 1 - data segment access
* DRAM0: 0 - non-atomic operation, 1 - atomic operation
*/
void IRAM_ATTR esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype);
/**
* @brief Gets string representation of required memory region identifier
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*
* @return mem_type as string
*/
const char *IRAM_ATTR esp_memprot_type_to_str(mem_type_prot_t mem_type);
/**
* @brief Detects whether any of the interrupt locks is active (requires digital system reset to unlock)
*
* @return true/false
*/
bool esp_memprot_is_locked_any(void);
/**
* @brief Sets lock for specified memory region.
*
* Locks can be unlocked only by digital system reset
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*/
void esp_memprot_set_lock(mem_type_prot_t mem_type);
/**
* @brief Gets lock status for required memory region
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*
* @return true/false (locked/unlocked)
*/
bool esp_memprot_get_lock(mem_type_prot_t mem_type);
/**
* @brief Gets permission control configuration register contents for required memory region
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*
* @return Permission control register contents
*/
uint32_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type);
/**
* @brief Gets interrupt permission settings for unified management block
*
* Gets interrupt permission settings register contents for required memory region, returns settings for unified management blocks
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*
* @return Permission settings register contents
*/
uint32_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type);
/**
* @brief Gets interrupt permission settings for split management block
*
* Gets interrupt permission settings register contents for required memory region, returns settings for split management blocks
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*
* @return Permission settings register contents
*/
uint32_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type);
/**
* @brief Detects whether any of the memory protection interrupts is enabled
*
* @return true/false
*/
bool esp_memprot_is_intr_ena_any(void);
/**
* @brief Gets interrupt-enabled flag for given memory region
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*
* @return Interrupt-enabled value
*/
uint32_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type);
/**
* @brief Gets interrupt-active flag for given memory region
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*
* @return Interrupt-active value
*/
uint32_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type);
/**
* @brief Gets interrupt-clear request flag for given memory region
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*
* @return Interrupt-clear request value
*/
uint32_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type);
/**
* @brief Gets read permission value for specified block and memory region
*
* Returns read permission bit value for required unified-management block (0-3) in given memory region.
* Applicable to all memory types.
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param block Memory block identifier (0-3)
*
* @return Read permission value for required block
*/
uint32_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block);
/**
* @brief Gets write permission value for specified block and memory region
*
* Returns write permission bit value for required unified-management block (0-3) in given memory region.
* Applicable to all memory types.
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param block Memory block identifier (0-3)
*
* @return Write permission value for required block
*/
uint32_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block);
/**
* @brief Gets execute permission value for specified block and memory region
*
* Returns execute permission bit value for required unified-management block (0-3) in given memory region.
* Applicable only to IRAM memory types
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param block Memory block identifier (0-3)
*
* @return Execute permission value for required block
*/
uint32_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block);
/**
* @brief Sets permissions for specified block in DRAM region
*
* Sets Read and Write permission for specified unified-management block (0-3) in given memory region.
* Applicable only to DRAM memory types
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param block Memory block identifier (0-3)
* @param write_perm Write permission flag
* @param read_perm Read permission flag
*/
void esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm);
/**
* @brief Sets permissions for high and low memory segment in DRAM region
*
* Sets Read and Write permission for both low and high memory segments given by splitting address.
* The splitting address must be equal to or higher then beginning of block 5
* Applicable only to DRAM memory types
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param split_addr Address to split the memory region to lower and higher segment
* @param lw Low segment Write permission flag
* @param lr Low segment Read permission flag
* @param hw High segment Write permission flag
* @param hr High segment Read permission flag
*/
void esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr);
/**
* @brief Sets permissions for specified block in IRAM region
*
* Sets Read, Write and Execute permission for specified unified-management block (0-3) in given memory region.
* Applicable only to IRAM memory types
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param block Memory block identifier (0-3)
* @param write_perm Write permission flag
* @param exec_perm Execute permission flag
*/
void esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm);
/**
* @brief Sets permissions for high and low memory segment in IRAM region
*
* Sets Read, Write and Execute permission for both low and high memory segments given by splitting address.
* The splitting address must be equal to or higher then beginning of block 5
* Applicable only to IRAM memory types
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param split_addr Address to split the memory region to lower and higher segment
* @param lw Low segment Write permission flag
* @param lr Low segment Read permission flag
* @param lx Low segment Execute permission flag
* @param hw High segment Write permission flag
* @param hr High segment Read permission flag
* @param hx High segment Execute permission flag
*/
void esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx);
/**
* @brief Activates memory protection for all supported memory region types
*
* @note The feature is disabled when JTAG interface is connected
*
* @param invoke_panic_handler map mem.prot interrupt to ETS_MEMACCESS_ERR_INUM and thus invokes panic handler when fired ('true' not suitable for testing)
* @param lock_feature sets LOCK bit, see esp_memprot_set_lock() ('true' not suitable for testing)
* @param mem_type_mask holds a set of required memory protection types (bitmask built of mem_type_prot_t). NULL means default (MEMPROT_ALL in this version)
*/
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask);
/**
* @brief Get permission settings bits for IRAM0 split mgmt. Only IRAM0 memory types allowed
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param lw Low segment Write permission flag
* @param lr Low segment Read permission flag
* @param lx Low segment Execute permission flag
* @param hw High segment Write permission flag
* @param hr High segment Read permission flag
* @param hx High segment Execute permission flag
*/
void esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx);
/**
* @brief Get permission settings bits for DRAM0 split mgmt. Only DRAM0 memory types allowed
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param lw Low segment Write permission flag
* @param lr Low segment Read permission flag
* @param hw High segment Write permission flag
* @param hr High segment Read permission flag
*/
void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr);
/**
* @brief Sets permissions for high and low memory segment in PERIBUS1 region
*
* Sets Read and Write permission for both low and high memory segments given by splitting address.
* Applicable only to PERIBUS1 memory types
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param split_addr Address to split the memory region to lower and higher segment
* @param lw Low segment Write permission flag
* @param lr Low segment Read permission flag
* @param hw High segment Write permission flag
* @param hr High segment Read permission flag
*/
void esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr);
/**
* @brief Get permission settings bits for PERIBUS1 split mgmt. Only PERIBUS1 memory types allowed
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param lw Low segment Write permission flag
* @param lr Low segment Read permission flag
* @param hw High segment Write permission flag
* @param hr High segment Read permission flag
*/
void esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr);
/**
* @brief Get permission settings bits for PERIBUS2 split mgmt. Only PERIBUS2 memory types allowed
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param lw Low segment Write permission flag
* @param lr Low segment Read permission flag
* @param lx Low segment Execute permission flag
* @param hw High segment Write permission flag
* @param hr High segment Read permission flag
* @param hx High segment Execute permission flag
*/
void esp_memprot_get_perm_split_bits_peri2(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx);
/**
* @brief Sets permissions for high and low memory segment in PERIBUS2 region
*
* Sets Read Write permission for both low and high memory segments given by splitting address.
* Applicable only to PERIBUS2 memory types
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param split_addr Address to split the memory region to lower and higher segment
* @param lw Low segment Write permission flag
* @param lr Low segment Read permission flag
* @param lx Low segment Execute permission flag
* @param hw High segment Write permission flag
* @param hr High segment Read permission flag
* @param hx High segment Execute permission flag
*/
void esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx);
/**
* @brief Get permissions for specified memory type. Irrelevant bits are ignored
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param lw Low segment Write permission flag
* @param lr Low segment Read permission flag
* @param lx Low segment Execute permission flag
* @param hw High segment Write permission flag
* @param hr High segment Read permission flag
* @param hx High segment Execute permission flag
*/
void esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx);
/**
* @brief Get Read permission settings for low and high regions of given memory type
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param lr Low segment Read permission flag
* @param hr High segment Read permission flag
*/
void esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr);
/**
* @brief Get Write permission settings for low and high regions of given memory type
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param lr Low segment Write permission flag
* @param hr High segment Write permission flag
*/
void esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw);
/**
* @brief Get Execute permission settings for low and high regions of given memory type
* Applicable only to IBUS-compatible memory types
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param lr Low segment Exec permission flag
* @param hr High segment Exec permission flag
*/
void esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx);
/**
* @brief Returns the lowest address in required memory region
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*/
uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type);
/**
* @brief Returns the highest address in required memory region
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
*/
uint32_t esp_memprot_get_high_limit(mem_type_prot_t mem_type);
/**
* @brief Sets READ permission bit for required memory region
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param lr Low segment Read permission flag
* @param hr High segment Read permission flag
*/
void esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr);
/**
* @brief Sets WRITE permission bit for required memory region
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param lr Low segment Write permission flag
* @param hr High segment Write permission flag
*/
void esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw);
/**
* @brief Sets EXECUTE permission bit for required memory region
*
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
* @param lr Low segment Exec permission flag
* @param hr High segment Exec permission flag
*/
void esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,119 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
//////////////////////////////////////////////////////////
// ESP32-S3 PMS memory protection types
//
#pragma once
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Memory types recognized by PMS
*/
typedef enum {
MEMPROT_TYPE_NONE = 0x00000000,
MEMPROT_TYPE_ALL = 0x7FFFFFFF,
MEMPROT_TYPE_INVALID = 0x80000000
} esp_mprot_mem_t;
/**
* @brief Splitting address (line) type
*/
typedef enum {
MEMPROT_SPLIT_ADDR_NONE = 0x00000000,
MEMPROT_SPLIT_ADDR_ALL = 0x7FFFFFFF,
MEMPROT_SPLIT_ADDR_INVALID = 0x80000000
} esp_mprot_split_addr_t;
/**
* @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address)
*/
typedef enum {
MEMPROT_PMS_AREA_NONE = 0x00000000,
MEMPROT_PMS_AREA_ALL = 0x7FFFFFFF,
MEMPROT_PMS_AREA_INVALID = 0x80000000
} esp_mprot_pms_area_t;
/**
* @brief Memory protection configuration
*/
typedef struct {
bool invoke_panic_handler; /*!< Register PMS violation interrupt for panic-handling */
bool lock_feature; /*!< Lock all PMS settings */
void *split_addr; /*!< Main I/D splitting address */
uint32_t mem_type_mask; /*!< Memory types required to protect. See esp_mprot_mem_t enum */
int target_cpu[]; /*!< Array of CPU/core IDs required to receive given PMS protection */
} esp_memp_config_t;
#define ESP_MEMPROT_DEFAULT_CONFIG() { \
.invoke_panic_handler = true, \
.lock_feature = true, \
.split_addr = NULL, \
.mem_type_mask = MEMPROT_TYPE_ALL,\
.target_cpu[] = {PRO_CPU_NUM, APP_CPU_NUM} \
}
/**
* @brief Converts Memory protection type to string
*
* @param mem_type Memory protection type
*/
static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type)
{
switch (mem_type) {
case MEMPROT_TYPE_NONE:
return "MEMPROT_TYPE_NONE";
case MEMPROT_TYPE_ALL:
return "MEMPROT_TYPE_ALL";
default:
return "MEMPROT_TYPE_INVALID";
}
}
/**
* @brief Converts Splitting address type to string
*
* @param line_type Split line type
*/
static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type)
{
switch (line_type) {
case MEMPROT_SPLIT_ADDR_NONE:
return "MEMPROT_SPLIT_ADDR_NONE";
case MEMPROT_SPLIT_ADDR_ALL:
return "MEMPROT_SPLIT_ADDR_ALL";
default:
return "MEMPROT_SPLIT_ADDR_INVALID";
}
}
/**
* @brief Converts PMS Area type to string
*
* @param area_type PMS Area type
*/
static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type)
{
switch (area_type) {
case MEMPROT_PMS_AREA_NONE:
return "MEMPROT_PMS_AREA_NONE";
case MEMPROT_PMS_AREA_ALL:
return "MEMPROT_PMS_AREA_ALL";
default:
return "MEMPROT_PMS_AREA_INVALID";
}
}
#ifdef __cplusplus
}
#endif

View File

@ -10,11 +10,12 @@ set(srcs "cpu_util_esp32c3.c"
if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "../async_memcpy_impl_gdma.c"
"memprot.c"
"esp_hmac.c"
"esp_crypto_lock.c"
"esp_ds.c"
"dport_access.c")
"dport_access.c"
"esp_memprot.c"
"../esp_memprot_conv.c")
endif()
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")

View File

@ -0,0 +1,869 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "sdkconfig.h"
#include "soc/periph_defs.h"
#include "esp_intr_alloc.h"
#include "hal/memprot_ll.h"
#include "riscv/interrupt.h"
#include "esp32c3/rom/ets_sys.h"
#include "esp_cpu.h"
#include "esp_fault.h"
#include "esp_attr.h"
#include "hal/memprot_types.h"
#include "esp_private/esp_memprot_internal.h"
#include "esp_memprot.h"
extern int _iram_text_end;
extern int _rtc_text_end;
static void *esp_memprot_iram0_get_def_split_addr(void)
{
return &_iram_text_end;
}
static void *esp_memprot_dram0_get_def_split_addr(void)
{
return MAP_IRAM_TO_DRAM(&_iram_text_end);
}
static void *esp_memprot_rtcfast_get_min_split_addr(void)
{
return &_rtc_text_end;
}
esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr)
{
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
switch (line_type) {
case MEMPROT_SPLIT_ADDR_IRAM0_DRAM0:
return esp_mprot_ll_err_to_esp_err(memprot_ll_set_iram0_split_line_main_I_D(line_addr));
case MEMPROT_SPLIT_ADDR_IRAM0_LINE_0:
return esp_mprot_ll_err_to_esp_err(memprot_ll_set_iram0_split_line_I_0(line_addr));
case MEMPROT_SPLIT_ADDR_IRAM0_LINE_1:
return esp_mprot_ll_err_to_esp_err(memprot_ll_set_iram0_split_line_I_1(line_addr));
default:
return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
} break;
case MEMPROT_TYPE_DRAM0_SRAM:
switch (line_type) {
case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0:
return esp_mprot_ll_err_to_esp_err(memprot_ll_set_dram0_split_line_D_0(line_addr));
case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1:
return esp_mprot_ll_err_to_esp_err(memprot_ll_set_dram0_split_line_D_1(line_addr));
default:
return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
} break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
if (line_type == MEMPROT_SPLIT_ADDR_MAIN) {
/* so far only WORLD_0 is supported */
return esp_mprot_ll_err_to_esp_err(memprot_ll_set_rtcfast_split_line(line_addr, MEMP_LL_WORLD_0));
} else {
return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
}
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
}
esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr)
{
if (line_addr == NULL) {
return ESP_ERR_INVALID_ARG;
}
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
switch (line_type) {
case MEMPROT_SPLIT_ADDR_IRAM0_DRAM0:
*line_addr = memprot_ll_get_iram0_split_line_main_I_D();
break;
case MEMPROT_SPLIT_ADDR_IRAM0_LINE_0:
*line_addr = memprot_ll_get_iram0_split_line_I_0();
break;
case MEMPROT_SPLIT_ADDR_IRAM0_LINE_1:
*line_addr = memprot_ll_get_iram0_split_line_I_1();
break;
default:
return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
} break;
case MEMPROT_TYPE_DRAM0_SRAM:
switch (line_type) {
case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0:
*line_addr = memprot_ll_get_dram0_split_line_D_0();
break;
case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1:
*line_addr = memprot_ll_get_dram0_split_line_D_1();
break;
default:
return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
} break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
if (line_type == MEMPROT_SPLIT_ADDR_MAIN) {
/* so far only WORLD_0 is supported */
return esp_mprot_ll_err_to_esp_err(memprot_ll_get_rtcfast_split_line(MEMP_LL_WORLD_0, line_addr));
} else {
return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
}
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
return ESP_OK;
}
esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, void **def_split_addr)
{
if (def_split_addr == NULL) {
return ESP_ERR_INVALID_ARG;
}
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
*def_split_addr = esp_memprot_iram0_get_def_split_addr();
break;
case MEMPROT_TYPE_DRAM0_SRAM:
*def_split_addr = esp_memprot_dram0_get_def_split_addr();
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
*def_split_addr = esp_memprot_rtcfast_get_min_split_addr();
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
return ESP_OK;
}
esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type)
{
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
case MEMPROT_TYPE_DRAM0_SRAM:
memprot_ll_set_iram0_dram0_split_line_lock();
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
//caution: RTCFAST shares the lock with other PIF PMS constraints!
memprot_ll_set_pif_constraint_lock();
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
return ESP_OK;
}
esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked)
{
if (locked == NULL) {
return ESP_ERR_INVALID_ARG;
}
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
case MEMPROT_TYPE_DRAM0_SRAM:
*locked = memprot_ll_get_iram0_dram0_split_line_lock();
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
*locked = memprot_ll_get_pif_constraint_lock();
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
return ESP_OK;
}
esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type)
{
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
memprot_ll_iram0_set_pms_lock();
break;
case MEMPROT_TYPE_DRAM0_SRAM:
memprot_ll_dram0_set_pms_lock();
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
//caution: RTCFAST shares the lock with other PIF PMS constraints!
memprot_ll_set_pif_constraint_lock();
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
return ESP_OK;
}
esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked)
{
if (locked == NULL) {
return ESP_ERR_INVALID_ARG;
}
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
*locked = memprot_ll_iram0_get_pms_lock();
break;
case MEMPROT_TYPE_DRAM0_SRAM:
*locked = memprot_ll_dram0_get_pms_lock();
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
*locked = memprot_ll_get_pif_constraint_lock();
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
return ESP_OK;
}
esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags)
{
bool r = flags & MEMPROT_OP_READ;
bool w = flags & MEMPROT_OP_WRITE;
bool x = flags & MEMPROT_OP_EXEC;
switch (area_type) {
case MEMPROT_PMS_AREA_IRAM0_0:
memprot_ll_iram0_set_pms_area_0(r, w, x);
break;
case MEMPROT_PMS_AREA_IRAM0_1:
memprot_ll_iram0_set_pms_area_1(r, w, x);
break;
case MEMPROT_PMS_AREA_IRAM0_2:
memprot_ll_iram0_set_pms_area_2(r, w, x);
break;
case MEMPROT_PMS_AREA_IRAM0_3:
memprot_ll_iram0_set_pms_area_3(r, w, x);
break;
case MEMPROT_PMS_AREA_DRAM0_0:
memprot_ll_dram0_set_pms_area_0(r, w);
break;
case MEMPROT_PMS_AREA_DRAM0_1:
memprot_ll_dram0_set_pms_area_1(r, w);
break;
case MEMPROT_PMS_AREA_DRAM0_2:
memprot_ll_dram0_set_pms_area_2(r, w);
break;
case MEMPROT_PMS_AREA_DRAM0_3:
memprot_ll_dram0_set_pms_area_3(r, w);
break;
case MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO:
memprot_ll_rtcfast_set_pms_area(r, w, x, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW);
break;
case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI:
memprot_ll_rtcfast_set_pms_area(r, w, x, MEMP_LL_WORLD_0, MEMP_LL_AREA_HIGH);
break;
default:
return ESP_ERR_NOT_SUPPORTED;
}
return ESP_OK;
}
esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags)
{
if (flags == NULL) {
return ESP_ERR_INVALID_ARG;
}
bool r = false;
bool w = false;
bool x = false;
switch (area_type) {
case MEMPROT_PMS_AREA_IRAM0_0:
memprot_ll_iram0_get_pms_area_0(&r, &w, &x);
break;
case MEMPROT_PMS_AREA_IRAM0_1:
memprot_ll_iram0_get_pms_area_1(&r, &w, &x);
break;
case MEMPROT_PMS_AREA_IRAM0_2:
memprot_ll_iram0_get_pms_area_2(&r, &w, &x);
break;
case MEMPROT_PMS_AREA_IRAM0_3:
memprot_ll_iram0_get_pms_area_3(&r, &w, &x);
break;
case MEMPROT_PMS_AREA_DRAM0_0:
memprot_ll_dram0_get_pms_area_0(&r, &w);
break;
case MEMPROT_PMS_AREA_DRAM0_1:
memprot_ll_dram0_get_pms_area_1(&r, &w);
break;
case MEMPROT_PMS_AREA_DRAM0_2:
memprot_ll_dram0_get_pms_area_2(&r, &w);
break;
case MEMPROT_PMS_AREA_DRAM0_3:
memprot_ll_dram0_get_pms_area_3(&r, &w);
break;
case MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO:
memprot_ll_rtcfast_get_pms_area(&r, &w, &x, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW);
break;
case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI:
memprot_ll_rtcfast_get_pms_area(&r, &w, &x, MEMP_LL_WORLD_0, MEMP_LL_AREA_HIGH);
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
*flags = 0;
if (r) {
*flags |= MEMPROT_OP_READ;
}
if (w) {
*flags |= MEMPROT_OP_WRITE;
}
if (x) {
*flags |= MEMPROT_OP_EXEC;
}
return ESP_OK;
}
esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type)
{
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
memprot_ll_iram0_set_monitor_lock();
break;
case MEMPROT_TYPE_DRAM0_SRAM:
memprot_ll_dram0_set_monitor_lock();
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
memprot_ll_rtcfast_set_monitor_lock();
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
return ESP_OK;
}
esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked)
{
if (locked == NULL) {
return ESP_ERR_INVALID_ARG;
}
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
*locked = memprot_ll_iram0_get_monitor_lock();
break;
case MEMPROT_TYPE_DRAM0_SRAM:
*locked = memprot_ll_dram0_get_monitor_lock();
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
*locked = memprot_ll_rtcfast_get_monitor_lock();
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
return ESP_OK;
}
esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable)
{
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
memprot_ll_iram0_set_monitor_en(enable);
break;
case MEMPROT_TYPE_DRAM0_SRAM:
memprot_ll_dram0_set_monitor_en(enable);
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
memprot_ll_rtcfast_set_monitor_en(enable);
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
return ESP_OK;
}
esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled)
{
if (enabled == NULL) {
return ESP_ERR_INVALID_ARG;
}
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
*enabled = memprot_ll_iram0_get_monitor_en();
break;
case MEMPROT_TYPE_DRAM0_SRAM:
*enabled = memprot_ll_dram0_get_monitor_en();
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
*enabled = memprot_ll_rtcfast_get_monitor_en();
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core __attribute__((unused)))
{
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
memprot_ll_iram0_set_monitor_intrclr();
memprot_ll_iram0_reset_monitor_intrclr();
break;
case MEMPROT_TYPE_DRAM0_SRAM:
memprot_ll_dram0_set_monitor_intrclr();
memprot_ll_dram0_reset_monitor_intrclr();
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
memprot_ll_rtcfast_set_monitor_intrclr();
memprot_ll_rtcfast_reset_monitor_intrclr();
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr)
{
if (active_memp_intr == NULL) {
return ESP_ERR_INVALID_ARG;
}
active_memp_intr->core = PRO_CPU_NUM;
if (memprot_ll_iram0_get_monitor_status_intr() > 0) {
active_memp_intr->mem_type = MEMPROT_TYPE_IRAM0_SRAM;
} else if (memprot_ll_dram0_get_monitor_status_intr() > 0) {
active_memp_intr->mem_type = MEMPROT_TYPE_DRAM0_SRAM;
} else if (memprot_ll_rtcfast_get_monitor_status_intr() > 0) {
active_memp_intr->mem_type = MEMPROT_TYPE_IRAM0_RTCFAST;
} else {
active_memp_intr->mem_type = MEMPROT_TYPE_NONE;
}
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_is_conf_locked_any(bool *locked)
{
if (locked == NULL) {
return ESP_ERR_INVALID_ARG;
}
bool lock_on = false;
esp_err_t res;
ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_split_addr_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on))
*locked |= lock_on;
ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on))
*locked |= lock_on;
ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_pms_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on))
*locked |= lock_on;
ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_pms_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on))
*locked |= lock_on;
ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on))
*locked |= lock_on;
ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on));
*locked |= lock_on;
ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST, &lock_on));
*locked |= lock_on;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_is_intr_ena_any(bool *enabled)
{
if (enabled == NULL) {
return ESP_ERR_INVALID_ARG;
}
bool ena_on = false;
esp_err_t res;
ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, &ena_on))
*enabled |= ena_on;
ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, &ena_on))
*enabled |= ena_on;
ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, &ena_on))
*enabled |= ena_on;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core __attribute__((unused)))
{
if (fault_addr == NULL) {
return ESP_ERR_INVALID_ARG;
}
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
*fault_addr = (void *)memprot_ll_iram0_get_monitor_status_fault_addr();
break;
case MEMPROT_TYPE_DRAM0_SRAM:
*fault_addr = (void *)memprot_ll_dram0_get_monitor_status_fault_addr();
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
*fault_addr = (void *)memprot_ll_rtcfast_get_monitor_status_fault_addr();
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core __attribute__((unused)))
{
if (world == NULL) {
return ESP_ERR_INVALID_ARG;
}
esp_mprot_pms_world_t res;
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
res = esp_mprot_ll_world_to_hl_world(memprot_ll_iram0_get_monitor_status_fault_world());
break;
case MEMPROT_TYPE_DRAM0_SRAM:
res = esp_mprot_ll_world_to_hl_world(memprot_ll_dram0_get_monitor_status_fault_world());
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
res = esp_mprot_ll_world_to_hl_world(memprot_ll_rtcfast_get_monitor_status_fault_world());
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
if (res == MEMPROT_PMS_WORLD_INVALID) {
return ESP_ERR_MEMPROT_WORLD_INVALID;
}
*world = res;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core __attribute__((unused)))
{
if (oper == NULL) {
return ESP_ERR_INVALID_ARG;
}
uint32_t operation = MEMPROT_OP_NONE;
if ((mem_type == MEMPROT_TYPE_IRAM0_SRAM && memprot_ll_iram0_get_monitor_status_fault_loadstore() == 0) ||
(mem_type == MEMPROT_TYPE_IRAM0_RTCFAST && memprot_ll_rtcfast_get_monitor_status_fault_loadstore() == 0)) {
operation = MEMPROT_OP_EXEC;
}
if (operation == MEMPROT_OP_NONE) {
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
operation = memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_OP_WRITE : MEMPROT_OP_READ;
break;
case MEMPROT_TYPE_DRAM0_SRAM:
operation = memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_OP_WRITE : MEMPROT_OP_READ;
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
operation = memprot_ll_rtcfast_get_monitor_status_fault_wr() == 1 ? MEMPROT_OP_WRITE : MEMPROT_OP_READ;
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
}
*oper = operation;
return ESP_OK;
}
bool IRAM_ATTR esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type)
{
return mem_type == MEMPROT_TYPE_DRAM0_SRAM;
}
esp_err_t IRAM_ATTR esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core __attribute__((unused)))
{
if (byte_en == NULL) {
return ESP_ERR_INVALID_ARG;
}
switch (mem_type) {
case MEMPROT_TYPE_DRAM0_SRAM:
*byte_en = memprot_ll_dram0_get_monitor_status_fault_byte_en();
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
return ESP_OK;
}
/* internal */
static esp_err_t esp_mprot_set_intr_matrix(const esp_mprot_mem_t mem_type)
{
ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM);
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
intr_matrix_set(PRO_CPU_NUM, memprot_ll_iram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
break;
case MEMPROT_TYPE_DRAM0_SRAM:
intr_matrix_set(PRO_CPU_NUM, memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
intr_matrix_set(PRO_CPU_NUM, memprot_ll_rtcfast_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
break;
default:
return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
}
/* Set the type and priority to cache error interrupts. */
esprv_intc_int_set_type(BIT(ETS_MEMPROT_ERR_INUM), INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM);
return ESP_OK;
}
esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config)
{
if (memp_config == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (memp_config->mem_type_mask == MEMPROT_TYPE_NONE) {
return ESP_ERR_NO_MEM;
}
//debugger connected:
// 1.check the signal repeatedly to avoid possible glitching attempt
// 2.leave the Memprot unset to allow debug operations
if (esp_cpu_in_ocd_debug_mode()) {
ESP_FAULT_ASSERT(!esp_cpu_in_ocd_debug_mode());
return ESP_OK;
}
bool use_iram0 = memp_config->mem_type_mask & MEMPROT_TYPE_IRAM0_SRAM;
bool use_dram0 = memp_config->mem_type_mask & MEMPROT_TYPE_DRAM0_SRAM;
bool use_rtcfast = memp_config->mem_type_mask & MEMPROT_TYPE_IRAM0_RTCFAST;
esp_err_t ret = ESP_OK;
//disable protection (must be unlocked)
if (use_iram0) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, false))
}
if (use_dram0) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, false))
}
if (use_rtcfast) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, false))
}
//panic handling
if (memp_config->invoke_panic_handler) {
if (use_iram0) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_IRAM0_SRAM))
}
if (use_dram0) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_DRAM0_SRAM))
}
if (use_rtcfast) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_IRAM0_RTCFAST))
}
}
//set split lines (must-have for all mem_types). This version sets only the main I/D which is then shared for all PMS regions
void *line_addr = memp_config->split_addr;
if (line_addr == NULL) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_default_main_split_addr(MEMPROT_TYPE_IRAM0_SRAM, &line_addr))
}
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_LINE_1, line_addr))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_LINE_0, line_addr))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_DRAM0, line_addr))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_DRAM0_SRAM, MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr))))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_DRAM0_SRAM, MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr))))
//set permissions
if (use_iram0) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_0, MEMPROT_OP_READ | MEMPROT_OP_EXEC))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_1, MEMPROT_OP_READ | MEMPROT_OP_EXEC))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_2, MEMPROT_OP_READ | MEMPROT_OP_EXEC))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_3, MEMPROT_OP_NONE))
}
if (use_dram0) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_0, MEMPROT_OP_NONE ))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_1, MEMPROT_OP_READ | MEMPROT_OP_WRITE))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_2, MEMPROT_OP_READ | MEMPROT_OP_WRITE))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_3, MEMPROT_OP_READ | MEMPROT_OP_WRITE))
}
if (use_rtcfast) {
//RTCFAST split-line cannot be set manually - always use default
void *rtc_fast_line;
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_default_main_split_addr(MEMPROT_TYPE_IRAM0_RTCFAST, &rtc_fast_line));
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_RTCFAST, MEMPROT_SPLIT_ADDR_MAIN, rtc_fast_line))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO, MEMPROT_OP_READ | MEMPROT_OP_EXEC))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI, MEMPROT_OP_READ | MEMPROT_OP_WRITE))
}
//reenable the protection
if (use_iram0) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM, NULL))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, true))
}
if (use_dram0) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_DRAM0_SRAM, NULL))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, true))
}
if (use_rtcfast) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_RTCFAST, NULL))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, true))
}
//lock if required
if (memp_config->lock_feature) {
if (use_iram0) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_IRAM0_SRAM))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_IRAM0_SRAM))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM))
}
if (use_dram0) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_DRAM0_SRAM))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM))
}
if (use_rtcfast) {
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_IRAM0_RTCFAST))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_IRAM0_RTCFAST))
ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST))
}
}
return ret;
}
esp_err_t esp_mprot_dump_configuration(char **dump_info_string)
{
if (dump_info_string == NULL) {
return ESP_ERR_INVALID_ARG;;
}
*dump_info_string = calloc(1024, 1);
if (*dump_info_string == NULL) {
return ESP_ERR_NO_MEM;
}
bool line_lock = memprot_ll_get_iram0_dram0_split_line_lock();
uint32_t line_ID = (uint32_t)memprot_ll_get_iram0_split_line_main_I_D();
uint32_t line_I0 = (uint32_t)memprot_ll_get_iram0_split_line_I_0();
uint32_t line_I1 = (uint32_t)memprot_ll_get_iram0_split_line_I_1();
uint32_t line_D0 = (uint32_t)memprot_ll_get_dram0_split_line_D_0();
uint32_t line_D1 = (uint32_t)memprot_ll_get_dram0_split_line_D_1();
uint32_t line_ID_cat = (uint32_t)memprot_ll_get_iram0_split_line_main_I_D_cat();
uint32_t line_I0_cat = (uint32_t)memprot_ll_get_iram0_split_line_I_0_cat();
uint32_t line_I1_cat = (uint32_t)memprot_ll_get_iram0_split_line_I_1_cat();
uint32_t line_D0_cat = (uint32_t)memprot_ll_get_dram0_split_line_D_0_cat();
uint32_t line_D1_cat = (uint32_t)memprot_ll_get_dram0_split_line_D_1_cat();
sprintf(*dump_info_string,
"Split line settings (lock=%u):\n"
" IRAM0:\n line ID (main): 0x%08X (cat=0x%08X)\n line I0: 0x%08X (cat=0x%08X)\n line I1: 0x%08X (cat=0x%08X)\n"
" DRAM0:\n line D0: 0x%08X (cat=0x%08X)\n line D1: 0x%08X (cat=0x%08X)\n",
line_lock, line_ID, line_ID_cat, line_I0, line_I0_cat, line_I1, line_I1_cat, line_D0, line_D0_cat, line_D1, line_D1_cat);
uint32_t offset = strlen(*dump_info_string);
void *line_RTC = NULL;
esp_err_t err = esp_mprot_ll_err_to_esp_err(memprot_ll_get_rtcfast_split_line(MEMP_LL_WORLD_0, &line_RTC));
if (err != ESP_OK) {
sprintf((*dump_info_string + offset), " RTCFAST:\n line main: N/A (world=0) - %s\n", esp_err_to_name(err));
} else {
sprintf((*dump_info_string + offset), " RTCFAST:\n line main: 0x%08X (world=0)\n", (uint32_t)line_RTC);
}
offset = strlen(*dump_info_string);
bool ar0i, ar1i, ar2i, ar3i;
bool aw0i, aw1i, aw2i, aw3i;
bool ax0i, ax1i, ax2i, ax3i;
bool ar0d, ar1d, ar2d, ar3d;
bool aw0d, aw1d, aw2d, aw3d;
bool pms_lock_i = memprot_ll_iram0_get_pms_lock();
memprot_ll_iram0_get_pms_area_0(&ar0i, &aw0i, &ax0i);
memprot_ll_iram0_get_pms_area_1(&ar1i, &aw1i, &ax1i);
memprot_ll_iram0_get_pms_area_2(&ar2i, &aw2i, &ax2i);
memprot_ll_iram0_get_pms_area_3(&ar3i, &aw3i, &ax3i);
bool pms_lock_d = memprot_ll_dram0_get_pms_lock();
memprot_ll_dram0_get_pms_area_0(&ar0d, &aw0d);
memprot_ll_dram0_get_pms_area_1(&ar1d, &aw1d);
memprot_ll_dram0_get_pms_area_2(&ar2d, &aw2d);
memprot_ll_dram0_get_pms_area_3(&ar3d, &aw3d);
bool rtc_line_lock = memprot_ll_get_pif_constraint_lock();
sprintf((*dump_info_string + offset),
"PMS area settings:\n"
" IRAM0 (lock=%u):\n area 0: r=%u,w=%u,x=%u\n area 1: r=%u,w=%u,x=%u\n area 2: r=%u,w=%u,x=%u\n area 3: r=%u,w=%u,x=%u\n"
" DRAM0 (lock=%u):\n area 0: r=%u,w=%u\n area 1: r=%u,w=%u\n area 2: r=%u,w=%u\n area 3: r=%u,w=%u\n"
" RTCFAST (lock=%u):\n",
pms_lock_i, ar0i, aw0i, ax0i, ar1i, aw1i, ax1i, ar2i, aw2i, ax2i, ar3i, aw3i, ax3i,
pms_lock_d, ar0d, aw0d, ar1d, aw1d, ar2d, aw2d, ar3d, aw3d, rtc_line_lock);
offset = strlen(*dump_info_string);
bool arl0rtc, awl0rtc, axl0rtc;
bool arh0rtc, awh0rtc, axh0rtc;
err = esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_pms_area(&arl0rtc, &awl0rtc, &axl0rtc, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW));
if (err != ESP_OK) {
sprintf((*dump_info_string + offset), " area low: N/A - %s\n", esp_err_to_name(err));
} else {
sprintf((*dump_info_string + offset), " area low: r=%u,w=%u,x=%u\n", arl0rtc, awl0rtc, axl0rtc);
}
offset = strlen(*dump_info_string);
err = esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_pms_area(&arh0rtc, &awh0rtc, &axh0rtc, MEMP_LL_WORLD_0, MEMP_LL_AREA_HIGH));
if (err != ESP_OK) {
sprintf((*dump_info_string + offset), " area high: N/A - %s\n", esp_err_to_name(err));
} else {
sprintf((*dump_info_string + offset), " area high: r=%u,w=%u,x=%u\n", arh0rtc, awh0rtc, axh0rtc);
}
offset = strlen(*dump_info_string);
bool monitor_lock_i = memprot_ll_iram0_get_monitor_lock();
bool monitor_en_i = memprot_ll_iram0_get_monitor_en();
bool monitor_clr_i = memprot_ll_iram0_get_monitor_intrclr();
bool monitor_lock_d = memprot_ll_dram0_get_monitor_lock();
bool monitor_en_d = memprot_ll_dram0_get_monitor_en();
bool monitor_clr_d = memprot_ll_dram0_get_monitor_intrclr();
bool monitor_lock_rtc = memprot_ll_rtcfast_get_monitor_lock();
bool monitor_en_rtc = memprot_ll_rtcfast_get_monitor_en();
bool monitor_clr_rtc = memprot_ll_rtcfast_get_monitor_intrclr();
sprintf((*dump_info_string + offset),
"Monitor settings:\n"
" IRAM0 (lock=%u):\n enabled=%u\n intr_clr=%u\n"
" DRAM0 (lock=%u):\n enabled=%u\n intr_clr=%u\n"
" RTCFAST (lock=%u):\n enabled=%u\n intr_clr=%u\n",
monitor_lock_i, monitor_en_i, monitor_clr_i,
monitor_lock_d, monitor_en_d, monitor_clr_d,
monitor_lock_rtc, monitor_en_rtc, monitor_clr_rtc);
return ESP_OK;
}

View File

@ -1,617 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* INTERNAL API
* implementation of PMS memory protection features
*/
#include <stdio.h>
#include "sdkconfig.h"
#include "soc/sensitive_reg.h"
#include "soc/dport_access.h"
#include "soc/periph_defs.h"
#include "esp_intr_alloc.h"
#include "hal/memprot_ll.h"
#include "esp32c3/memprot.h"
#include "riscv/interrupt.h"
#include "esp32c3/rom/ets_sys.h"
#include "esp_log.h"
#include "esp_fault.h"
#include "soc/cpu.h"
extern int _iram_text_end;
static const char *TAG = "memprot";
const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type)
{
switch (mem_type) {
case MEMPROT_NONE:
return "NONE";
case MEMPROT_IRAM0_SRAM:
return "IRAM0_SRAM";
case MEMPROT_DRAM0_SRAM:
return "DRAM0_SRAM";
case MEMPROT_ALL:
return "ALL";
default:
return "UNKNOWN";
}
}
const char *esp_memprot_split_line_to_str(split_line_t line_type)
{
switch (line_type) {
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
return "MEMPROT_IRAM0_DRAM0_SPLITLINE";
case MEMPROT_IRAM0_LINE_0_SPLITLINE:
return "MEMPROT_IRAM0_LINE_0_SPLITLINE";
case MEMPROT_IRAM0_LINE_1_SPLITLINE:
return "MEMPROT_IRAM0_LINE_1_SPLITLINE";
case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
return "MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE";
case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
return "MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE";
default:
return "UNKNOWN";
}
}
const char *esp_memprot_pms_to_str(pms_area_t area_type)
{
switch (area_type) {
case MEMPROT_IRAM0_PMS_AREA_0:
return "MEMPROT_IRAM0_PMS_AREA_0";
case MEMPROT_IRAM0_PMS_AREA_1:
return "MEMPROT_IRAM0_PMS_AREA_1";
case MEMPROT_IRAM0_PMS_AREA_2:
return "MEMPROT_IRAM0_PMS_AREA_2";
case MEMPROT_IRAM0_PMS_AREA_3:
return "MEMPROT_IRAM0_PMS_AREA_3";
case MEMPROT_DRAM0_PMS_AREA_0:
return "MEMPROT_DRAM0_PMS_AREA_0";
case MEMPROT_DRAM0_PMS_AREA_1:
return "MEMPROT_DRAM0_PMS_AREA_1";
case MEMPROT_DRAM0_PMS_AREA_2:
return "MEMPROT_DRAM0_PMS_AREA_2";
case MEMPROT_DRAM0_PMS_AREA_3:
return "MEMPROT_DRAM0_PMS_AREA_3";
default:
return "UNKNOWN";
}
}
/* split lines */
void *esp_memprot_get_default_main_split_addr()
{
return &_iram_text_end;
}
uint32_t *esp_memprot_get_split_addr(split_line_t line_type)
{
switch ( line_type ) {
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
return memprot_ll_get_iram0_split_line_main_I_D();
case MEMPROT_IRAM0_LINE_0_SPLITLINE:
return memprot_ll_get_iram0_split_line_I_0();
case MEMPROT_IRAM0_LINE_1_SPLITLINE:
return memprot_ll_get_iram0_split_line_I_1();
case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
return memprot_ll_get_dram0_split_line_D_0();
case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
return memprot_ll_get_dram0_split_line_D_1();
default:
abort();
}
}
void esp_memprot_set_split_line_lock()
{
memprot_ll_set_iram0_dram0_split_line_lock();
}
bool esp_memprot_get_split_line_lock()
{
return memprot_ll_get_iram0_dram0_split_line_lock();
}
void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr)
{
ESP_EARLY_LOGD(TAG, "Setting split line %s, addr: 0x%08X", esp_memprot_split_line_to_str(line_type), (uint32_t)line_addr);
//split-line must be divisible by 512 (PMS module restriction)
assert( ((uint32_t)line_addr) % 0x200 == 0 );
switch ( line_type ) {
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
memprot_ll_set_iram0_split_line_main_I_D(line_addr);
break;
case MEMPROT_IRAM0_LINE_0_SPLITLINE:
memprot_ll_set_iram0_split_line_I_0(line_addr);
break;
case MEMPROT_IRAM0_LINE_1_SPLITLINE:
memprot_ll_set_iram0_split_line_I_1(line_addr);
break;
case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
memprot_ll_set_dram0_split_line_D_0(line_addr);
break;
case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
memprot_ll_set_dram0_split_line_D_1(line_addr);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid split line type, aborting: 0x%08X", (uint32_t)line_addr);
abort();
}
}
/* PMS */
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_set_pms_lock();
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_set_pms_lock();
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_get_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_pms_lock();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_pms_lock();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_iram_set_pms_area(area:%s r:%u w:%u, x:%u)", esp_memprot_pms_to_str(area_type), r, w, x);
switch ( area_type ) {
case MEMPROT_IRAM0_PMS_AREA_0:
memprot_ll_iram0_set_pms_area_0(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_1:
memprot_ll_iram0_set_pms_area_1(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_2:
memprot_ll_iram0_set_pms_area_2(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_3:
memprot_ll_iram0_set_pms_area_3(r, w, x);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
abort();
}
}
void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_iram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
switch ( area_type ) {
case MEMPROT_IRAM0_PMS_AREA_0:
memprot_ll_iram0_get_pms_area_0(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_1:
memprot_ll_iram0_get_pms_area_1(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_2:
memprot_ll_iram0_get_pms_area_2(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_3:
memprot_ll_iram0_get_pms_area_3(r, w, x);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
abort();
}
}
void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_dram_set_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
switch ( area_type ) {
case MEMPROT_DRAM0_PMS_AREA_0:
memprot_ll_dram0_set_pms_area_0(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_1:
memprot_ll_dram0_set_pms_area_1(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_2:
memprot_ll_dram0_set_pms_area_2(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_3:
memprot_ll_dram0_set_pms_area_3(r, w);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
abort();
}
}
void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_dram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
switch ( area_type ) {
case MEMPROT_DRAM0_PMS_AREA_0:
memprot_ll_dram0_get_pms_area_0(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_1:
memprot_ll_dram0_get_pms_area_1(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_2:
memprot_ll_dram0_get_pms_area_2(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_3:
memprot_ll_dram0_get_pms_area_3(r, w);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
abort();
}
}
/* monitor */
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_set_monitor_lock();
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_set_monitor_lock();
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_get_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_lock();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_lock();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_set_monitor_en(enable);
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_set_monitor_en(enable);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_en();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_en();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_is_intr_ena_any()
{
return esp_memprot_get_monitor_en(MEMPROT_IRAM0_SRAM) || esp_memprot_get_monitor_en(MEMPROT_DRAM0_SRAM);
}
void esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_monitor_clear_intr(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_clear_monitor_intr();
memprot_ll_iram0_reset_clear_monitor_intr();
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_clear_monitor_intr();
memprot_ll_dram0_reset_clear_monitor_intr();
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
mem_type_prot_t esp_memprot_get_active_intr_memtype()
{
if ( memprot_ll_iram0_get_monitor_status_intr() > 0 ) {
return MEMPROT_IRAM0_SRAM;
} else if ( memprot_ll_dram0_get_monitor_status_intr() ) {
return MEMPROT_DRAM0_SRAM;
}
return MEMPROT_NONE;
}
bool esp_memprot_is_locked_any()
{
return
esp_memprot_get_split_line_lock() ||
esp_memprot_get_pms_lock(MEMPROT_IRAM0_SRAM) ||
esp_memprot_get_pms_lock(MEMPROT_DRAM0_SRAM) ||
esp_memprot_get_monitor_lock(MEMPROT_IRAM0_SRAM) ||
esp_memprot_get_monitor_lock(MEMPROT_DRAM0_SRAM);
}
bool esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_intr() == 1;
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_intr() == 1;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
uint32_t esp_memprot_get_violate_addr(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_fault_addr();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_addr();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
pms_world_t esp_memprot_get_violate_world(mem_type_prot_t mem_type)
{
uint32_t world = 0;
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
world = memprot_ll_iram0_get_monitor_status_fault_world();
break;
case MEMPROT_DRAM0_SRAM:
world = memprot_ll_dram0_get_monitor_status_fault_world();
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
switch ( world ) {
case 0x01: return MEMPROT_PMS_WORLD_0;
case 0x10: return MEMPROT_PMS_WORLD_1;
default: return MEMPROT_PMS_WORLD_INVALID;
}
}
pms_operation_type_t esp_memprot_get_violate_wr(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_fault_loadstore() == 1;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
uint32_t esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_byte_en();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
int esp_memprot_intr_get_cpuid()
{
return PRO_CPU_NUM;
}
void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_intr_matrix(%s)", esp_memprot_mem_type_to_str(mem_type));
ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM);
switch (mem_type) {
case MEMPROT_IRAM0_SRAM:
intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_iram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
break;
case MEMPROT_DRAM0_SRAM:
intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
/* Set the type and priority to cache error interrupts. */
esprv_intc_int_set_type(BIT(ETS_MEMPROT_ERR_INUM), INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM);
}
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask)
{
esp_memprot_set_prot_int(invoke_panic_handler, lock_feature, NULL, mem_type_mask);
}
void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_prot(panic_handler: %u, lock: %u, split.addr: 0x%08X, mem.types: 0x%08X", invoke_panic_handler, lock_feature, (uint32_t)split_addr, (uint32_t)mem_type_mask);
uint32_t required_mem_prot = mem_type_mask == NULL ? (uint32_t)MEMPROT_ALL : *mem_type_mask;
bool use_iram0 = required_mem_prot & MEMPROT_IRAM0_SRAM;
bool use_dram0 = required_mem_prot & MEMPROT_DRAM0_SRAM;
if (required_mem_prot == MEMPROT_NONE) {
return;
}
//disable protection
if (use_iram0) {
esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, false);
}
if (use_dram0) {
esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, false);
}
//if being debugged check we are not glitched and dont enable Memprot
if (esp_cpu_in_ocd_debug_mode()) {
ESP_FAULT_ASSERT(esp_cpu_in_ocd_debug_mode());
} else {
if (invoke_panic_handler) {
if (use_iram0) {
esp_memprot_set_intr_matrix(MEMPROT_IRAM0_SRAM);
}
if (use_dram0) {
esp_memprot_set_intr_matrix(MEMPROT_DRAM0_SRAM);
}
}
//set split lines (must-have for all mem_types)
const void *line_addr = split_addr == NULL ? esp_memprot_get_default_main_split_addr() : split_addr;
esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_1_SPLITLINE, line_addr);
esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_0_SPLITLINE, line_addr);
esp_memprot_set_split_line(MEMPROT_IRAM0_DRAM0_SPLITLINE, line_addr);
esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE,
(void *) (MAP_IRAM_TO_DRAM((uint32_t) line_addr)));
esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE,
(void *) (MAP_IRAM_TO_DRAM((uint32_t) line_addr)));
//set permissions
if (required_mem_prot & MEMPROT_IRAM0_SRAM) {
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_0, true, false, true);
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_1, true, false, true);
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_2, true, false, true);
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_3, true, true, false);
}
if (required_mem_prot & MEMPROT_DRAM0_SRAM) {
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_0, true, false);
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_1, true, true);
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_2, true, true);
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_3, true, true);
}
//reenable the protection
if (use_iram0) {
esp_memprot_monitor_clear_intr(MEMPROT_IRAM0_SRAM);
esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, true);
}
if (use_dram0) {
esp_memprot_monitor_clear_intr(MEMPROT_DRAM0_SRAM);
esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, true);
}
//lock if required
if (lock_feature) {
esp_memprot_set_split_line_lock();
if (use_iram0) {
esp_memprot_set_pms_lock(MEMPROT_IRAM0_SRAM);
esp_memprot_set_monitor_lock(MEMPROT_IRAM0_SRAM);
}
if (use_dram0) {
esp_memprot_set_pms_lock(MEMPROT_DRAM0_SRAM);
esp_memprot_set_monitor_lock(MEMPROT_DRAM0_SRAM);
}
}
}
}
uint32_t esp_memprot_get_dram_status_reg_1()
{
return memprot_ll_dram0_get_monitor_status_register_1();
}
uint32_t esp_memprot_get_dram_status_reg_2()
{
return memprot_ll_dram0_get_monitor_status_register_2();
}
uint32_t esp_memprot_get_iram_status_reg()
{
return memprot_ll_iram0_get_monitor_status_register();
}
uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type)
{
switch (mem_type) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_enable_register();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_enable_register();
default:
abort();
}
}

View File

@ -10,11 +10,12 @@ set(srcs "cpu_util_esp32h2.c"
if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "../async_memcpy_impl_gdma.c"
"memprot.c"
"esp_hmac.c"
"esp_crypto_lock.c"
"esp_ds.c"
"dport_access.c")
"dport_access.c"
"esp_memprot.c"
"../esp_memprot_conv.c")
endif()
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")

View File

@ -0,0 +1,215 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "soc/periph_defs.h"
#include "esp_intr_alloc.h"
#include "esp_fault.h"
#include "esp_attr.h"
#include "esp_memprot_err.h"
#include "hal/memprot_types.h"
#include "esp_private/esp_memprot_internal.h"
#include "esp_memprot.h"
esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr)
{
return ESP_OK;
}
esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr)
{
if (line_addr == NULL) {
return ESP_ERR_INVALID_ARG;
}
*line_addr = NULL;
return ESP_OK;
}
esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, void **def_split_addr)
{
if (def_split_addr == NULL) {
return ESP_ERR_INVALID_ARG;
}
*def_split_addr = NULL;
return ESP_OK;
}
esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type)
{
return ESP_OK;
}
esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked)
{
if (locked == NULL) {
return ESP_ERR_INVALID_ARG;
}
*locked = false;
return ESP_OK;
}
esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type)
{
return ESP_OK;
}
esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked)
{
if (locked == NULL) {
return ESP_ERR_INVALID_ARG;
}
*locked = false;
return ESP_OK;
}
esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags)
{
return ESP_OK;
}
esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags)
{
if (flags == NULL) {
return ESP_ERR_INVALID_ARG;
}
*flags = MEMPROT_OP_NONE;
return ESP_OK;
}
esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type)
{
return ESP_OK;
}
esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked)
{
if (locked == NULL) {
return ESP_ERR_INVALID_ARG;
}
*locked = false;
return ESP_OK;
}
esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable)
{
return ESP_OK;
}
esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled)
{
if (enabled == NULL) {
return ESP_ERR_INVALID_ARG;
}
*enabled = false;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core __attribute__((unused)))
{
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr)
{
if (active_memp_intr == NULL) {
return ESP_ERR_INVALID_ARG;
}
active_memp_intr->mem_type = MEMPROT_TYPE_NONE;
active_memp_intr->core = -1;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_is_conf_locked_any(bool *locked)
{
if (locked == NULL) {
return ESP_ERR_INVALID_ARG;
}
*locked = false;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_is_intr_ena_any(bool *enabled)
{
if (enabled == NULL) {
return ESP_ERR_INVALID_ARG;
}
*enabled = false;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core __attribute__((unused)))
{
if (fault_addr == NULL) {
return ESP_ERR_INVALID_ARG;
}
*fault_addr = NULL;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core __attribute__((unused)))
{
if (world == NULL) {
return ESP_ERR_INVALID_ARG;
}
*world = MEMPROT_PMS_WORLD_NONE;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core __attribute__((unused)))
{
if (oper == NULL) {
return ESP_ERR_INVALID_ARG;
}
*oper = MEMPROT_OP_NONE;
return ESP_OK;
}
bool IRAM_ATTR esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type)
{
return false;
}
esp_err_t IRAM_ATTR esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core __attribute__((unused)))
{
if (byte_en == NULL) {
return ESP_ERR_INVALID_ARG;
}
*byte_en = 0;
return ESP_OK;
}
esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config)
{
return ESP_OK;
}

View File

@ -1,608 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* INTERNAL API
* implementation of PMS memory protection features
*/
#include <stdio.h>
#include "sdkconfig.h"
#include "soc/sensitive_reg.h"
#include "soc/dport_access.h"
#include "soc/periph_defs.h"
#include "esp_intr_alloc.h"
#include "hal/memprot_ll.h"
#include "esp32h2/memprot.h"
#include "riscv/interrupt.h"
#include "esp32h2/rom/ets_sys.h"
#include "esp_log.h"
extern int _iram_text_end;
static const char *TAG = "memprot";
const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type)
{
switch (mem_type) {
case MEMPROT_NONE:
return "NONE";
case MEMPROT_IRAM0_SRAM:
return "IRAM0_SRAM";
case MEMPROT_DRAM0_SRAM:
return "DRAM0_SRAM";
case MEMPROT_ALL:
return "ALL";
default:
return "UNKNOWN";
}
}
const char *esp_memprot_split_line_to_str(split_line_t line_type)
{
switch (line_type) {
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
return "MEMPROT_IRAM0_DRAM0_SPLITLINE";
case MEMPROT_IRAM0_LINE_0_SPLITLINE:
return "MEMPROT_IRAM0_LINE_0_SPLITLINE";
case MEMPROT_IRAM0_LINE_1_SPLITLINE:
return "MEMPROT_IRAM0_LINE_1_SPLITLINE";
case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
return "MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE";
case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
return "MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE";
default:
return "UNKNOWN";
}
}
const char *esp_memprot_pms_to_str(pms_area_t area_type)
{
switch (area_type) {
case MEMPROT_IRAM0_PMS_AREA_0:
return "MEMPROT_IRAM0_PMS_AREA_0";
case MEMPROT_IRAM0_PMS_AREA_1:
return "MEMPROT_IRAM0_PMS_AREA_1";
case MEMPROT_IRAM0_PMS_AREA_2:
return "MEMPROT_IRAM0_PMS_AREA_2";
case MEMPROT_IRAM0_PMS_AREA_3:
return "MEMPROT_IRAM0_PMS_AREA_3";
case MEMPROT_DRAM0_PMS_AREA_0:
return "MEMPROT_DRAM0_PMS_AREA_0";
case MEMPROT_DRAM0_PMS_AREA_1:
return "MEMPROT_DRAM0_PMS_AREA_1";
case MEMPROT_DRAM0_PMS_AREA_2:
return "MEMPROT_DRAM0_PMS_AREA_2";
case MEMPROT_DRAM0_PMS_AREA_3:
return "MEMPROT_DRAM0_PMS_AREA_3";
default:
return "UNKNOWN";
}
}
/* split lines */
void *esp_memprot_get_default_main_split_addr()
{
return &_iram_text_end;
}
uint32_t *esp_memprot_get_split_addr(split_line_t line_type)
{
switch ( line_type ) {
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
return memprot_ll_get_iram0_split_line_main_I_D();
case MEMPROT_IRAM0_LINE_0_SPLITLINE:
return memprot_ll_get_iram0_split_line_I_0();
case MEMPROT_IRAM0_LINE_1_SPLITLINE:
return memprot_ll_get_iram0_split_line_I_1();
case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
return memprot_ll_get_dram0_split_line_D_0();
case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
return memprot_ll_get_dram0_split_line_D_1();
default:
abort();
}
}
void esp_memprot_set_split_line_lock()
{
memprot_ll_set_iram0_dram0_split_line_lock();
}
bool esp_memprot_get_split_line_lock()
{
return memprot_ll_get_iram0_dram0_split_line_lock();
}
void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr)
{
ESP_EARLY_LOGD(TAG, "Setting split line %s, addr: 0x%08X", esp_memprot_split_line_to_str(line_type), (uint32_t)line_addr);
//split-line must be divisible by 512 (PMS module restriction)
assert( ((uint32_t)line_addr) % 0x200 == 0 );
switch ( line_type ) {
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
memprot_ll_set_iram0_split_line_main_I_D(line_addr);
break;
case MEMPROT_IRAM0_LINE_0_SPLITLINE:
memprot_ll_set_iram0_split_line_I_0(line_addr);
break;
case MEMPROT_IRAM0_LINE_1_SPLITLINE:
memprot_ll_set_iram0_split_line_I_1(line_addr);
break;
case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
memprot_ll_set_dram0_split_line_D_0(line_addr);
break;
case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
memprot_ll_set_dram0_split_line_D_1(line_addr);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid split line type, aborting: 0x%08X", (uint32_t)line_addr);
abort();
}
}
/* PMS */
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_set_pms_lock();
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_set_pms_lock();
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_get_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_pms_lock();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_pms_lock();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_iram_set_pms_area(area:%s r:%u w:%u, x:%u)", esp_memprot_pms_to_str(area_type), r, w, x);
switch ( area_type ) {
case MEMPROT_IRAM0_PMS_AREA_0:
memprot_ll_iram0_set_pms_area_0(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_1:
memprot_ll_iram0_set_pms_area_1(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_2:
memprot_ll_iram0_set_pms_area_2(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_3:
memprot_ll_iram0_set_pms_area_3(r, w, x);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
abort();
}
}
void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_iram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
switch ( area_type ) {
case MEMPROT_IRAM0_PMS_AREA_0:
memprot_ll_iram0_get_pms_area_0(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_1:
memprot_ll_iram0_get_pms_area_1(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_2:
memprot_ll_iram0_get_pms_area_2(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_3:
memprot_ll_iram0_get_pms_area_3(r, w, x);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
abort();
}
}
void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_dram_set_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
switch ( area_type ) {
case MEMPROT_DRAM0_PMS_AREA_0:
memprot_ll_dram0_set_pms_area_0(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_1:
memprot_ll_dram0_set_pms_area_1(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_2:
memprot_ll_dram0_set_pms_area_2(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_3:
memprot_ll_dram0_set_pms_area_3(r, w);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
abort();
}
}
void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_dram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
switch ( area_type ) {
case MEMPROT_DRAM0_PMS_AREA_0:
memprot_ll_dram0_get_pms_area_0(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_1:
memprot_ll_dram0_get_pms_area_1(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_2:
memprot_ll_dram0_get_pms_area_2(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_3:
memprot_ll_dram0_get_pms_area_3(r, w);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
abort();
}
}
/* monitor */
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_set_monitor_lock();
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_set_monitor_lock();
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_get_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_lock();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_lock();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_set_monitor_en(enable);
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_set_monitor_en(enable);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_en();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_en();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_is_intr_ena_any()
{
return esp_memprot_get_monitor_en(MEMPROT_IRAM0_SRAM) || esp_memprot_get_monitor_en(MEMPROT_DRAM0_SRAM);
}
void esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_monitor_clear_intr(%s)", esp_memprot_mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_clear_monitor_intr();
memprot_ll_iram0_reset_clear_monitor_intr();
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_clear_monitor_intr();
memprot_ll_dram0_reset_clear_monitor_intr();
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
mem_type_prot_t esp_memprot_get_active_intr_memtype()
{
if ( memprot_ll_iram0_get_monitor_status_intr() > 0 ) {
return MEMPROT_IRAM0_SRAM;
} else if ( memprot_ll_dram0_get_monitor_status_intr() ) {
return MEMPROT_DRAM0_SRAM;
}
return MEMPROT_NONE;
}
bool esp_memprot_is_locked_any()
{
return
esp_memprot_get_split_line_lock() ||
esp_memprot_get_pms_lock(MEMPROT_IRAM0_SRAM) ||
esp_memprot_get_pms_lock(MEMPROT_DRAM0_SRAM) ||
esp_memprot_get_monitor_lock(MEMPROT_IRAM0_SRAM) ||
esp_memprot_get_monitor_lock(MEMPROT_DRAM0_SRAM);
}
bool esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_intr() == 1;
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_intr() == 1;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
uint32_t esp_memprot_get_violate_addr(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_fault_addr();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_addr();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
pms_world_t esp_memprot_get_violate_world(mem_type_prot_t mem_type)
{
uint32_t world = 0;
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
world = memprot_ll_iram0_get_monitor_status_fault_world();
break;
case MEMPROT_DRAM0_SRAM:
world = memprot_ll_dram0_get_monitor_status_fault_world();
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
switch ( world ) {
case 0x01: return MEMPROT_PMS_WORLD_0;
case 0x10: return MEMPROT_PMS_WORLD_1;
default: return MEMPROT_PMS_WORLD_INVALID;
}
}
pms_operation_type_t esp_memprot_get_violate_wr(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_fault_loadstore() == 1;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
uint32_t esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_byte_en();
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
}
int esp_memprot_intr_get_cpuid()
{
return PRO_CPU_NUM;
}
void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_intr_matrix(%s)", esp_memprot_mem_type_to_str(mem_type));
ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM);
switch (mem_type) {
case MEMPROT_IRAM0_SRAM:
intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_iram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
break;
case MEMPROT_DRAM0_SRAM:
intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
break;
default:
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
abort();
}
/* Set the type and priority to cache error interrupts. */
esprv_intc_int_set_type(BIT(ETS_MEMPROT_ERR_INUM), INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM);
}
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask)
{
esp_memprot_set_prot_int(invoke_panic_handler, lock_feature, NULL, mem_type_mask);
}
void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask)
{
ESP_EARLY_LOGD(TAG, "esp_memprot_set_prot(panic_handler: %u, lock: %u, split.addr: 0x%08X, mem.types: 0x%08X", invoke_panic_handler, lock_feature, (uint32_t)split_addr, (uint32_t)mem_type_mask);
uint32_t required_mem_prot = mem_type_mask == NULL ? (uint32_t)MEMPROT_ALL : *mem_type_mask;
bool use_iram0 = required_mem_prot & MEMPROT_IRAM0_SRAM;
bool use_dram0 = required_mem_prot & MEMPROT_DRAM0_SRAM;
if (required_mem_prot == MEMPROT_NONE) {
return;
}
//disable protection
if (use_iram0) {
esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, false);
}
if (use_dram0) {
esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, false);
}
//panic handling
if (invoke_panic_handler) {
if (use_iram0) {
esp_memprot_set_intr_matrix(MEMPROT_IRAM0_SRAM);
}
if (use_dram0) {
esp_memprot_set_intr_matrix(MEMPROT_DRAM0_SRAM);
}
}
//set split lines (must-have for all mem_types)
const void *line_addr = split_addr == NULL ? esp_memprot_get_default_main_split_addr() : split_addr;
esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_1_SPLITLINE, line_addr);
esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_0_SPLITLINE, line_addr);
esp_memprot_set_split_line(MEMPROT_IRAM0_DRAM0_SPLITLINE, line_addr);
esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)));
esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)));
//set permissions
if (required_mem_prot & MEMPROT_IRAM0_SRAM) {
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_0, true, false, true);
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_1, true, false, true);
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_2, true, false, true);
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_3, true, true, false);
}
if (required_mem_prot & MEMPROT_DRAM0_SRAM) {
esp_memprot_dram_set_pms_area( MEMPROT_DRAM0_PMS_AREA_0, true, false );
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_1, true, true);
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_2, true, true);
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_3, true, true);
}
//reenable protection
if (use_iram0) {
esp_memprot_monitor_clear_intr(MEMPROT_IRAM0_SRAM);
esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, true);
}
if (use_dram0) {
esp_memprot_monitor_clear_intr(MEMPROT_DRAM0_SRAM);
esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, true);
}
//lock if required
if (lock_feature) {
esp_memprot_set_split_line_lock();
if (use_iram0) {
esp_memprot_set_pms_lock(MEMPROT_IRAM0_SRAM);
esp_memprot_set_monitor_lock(MEMPROT_IRAM0_SRAM);
}
if (use_dram0) {
esp_memprot_set_pms_lock(MEMPROT_DRAM0_SRAM);
esp_memprot_set_monitor_lock(MEMPROT_DRAM0_SRAM);
}
}
}
uint32_t esp_memprot_get_dram_status_reg_1()
{
return memprot_ll_dram0_get_monitor_status_register_1();
}
uint32_t esp_memprot_get_dram_status_reg_2()
{
return memprot_ll_dram0_get_monitor_status_register_2();
}
uint32_t esp_memprot_get_iram_status_reg()
{
return memprot_ll_iram0_get_monitor_status_register();
}
uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type)
{
switch (mem_type) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_enable_register();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_enable_register();
default:
abort();
}
}

View File

@ -18,7 +18,6 @@ if(NOT BOOTLOADER_BUILD)
"esp_hmac.c"
"esp_ds.c"
"esp_crypto_lock.c"
"memprot.c"
"spiram.c")
if(CONFIG_SPIRAM_MODE_QUAD)

View File

@ -0,0 +1,215 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "soc/periph_defs.h"
#include "esp_intr_alloc.h"
#include "esp_fault.h"
#include "esp_attr.h"
#include "esp_memprot_err.h"
#include "hal/memprot_types.h"
#include "esp_private/esp_memprot_internal.h"
#include "esp_memprot.h"
esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr)
{
return ESP_OK;
}
esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr)
{
if (line_addr == NULL) {
return ESP_ERR_INVALID_ARG;
}
*line_addr = NULL;
return ESP_OK;
}
esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, void **def_split_addr)
{
if (def_split_addr == NULL) {
return ESP_ERR_INVALID_ARG;
}
*def_split_addr = NULL;
return ESP_OK;
}
esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type)
{
return ESP_OK;
}
esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked)
{
if (locked == NULL) {
return ESP_ERR_INVALID_ARG;
}
*locked = false;
return ESP_OK;
}
esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type)
{
return ESP_OK;
}
esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked)
{
if (locked == NULL) {
return ESP_ERR_INVALID_ARG;
}
*locked = false;
return ESP_OK;
}
esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags)
{
return ESP_OK;
}
esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags)
{
if (flags == NULL) {
return ESP_ERR_INVALID_ARG;
}
*flags = MEMPROT_OP_NONE;
return ESP_OK;
}
esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type)
{
return ESP_OK;
}
esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked)
{
if (locked == NULL) {
return ESP_ERR_INVALID_ARG;
}
*locked = false;
return ESP_OK;
}
esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable)
{
return ESP_OK;
}
esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled)
{
if (enabled == NULL) {
return ESP_ERR_INVALID_ARG;
}
*enabled = false;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core __attribute__((unused)))
{
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr)
{
if (active_memp_intr == NULL) {
return ESP_ERR_INVALID_ARG;
}
active_memp_intr->mem_type = MEMPROT_TYPE_NONE;
active_memp_intr->core = -1;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_is_conf_locked_any(bool *locked)
{
if (locked == NULL) {
return ESP_ERR_INVALID_ARG;
}
*locked = false;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_is_intr_ena_any(bool *enabled)
{
if (enabled == NULL) {
return ESP_ERR_INVALID_ARG;
}
*enabled = false;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core __attribute__((unused)))
{
if (fault_addr == NULL) {
return ESP_ERR_INVALID_ARG;
}
*fault_addr = NULL;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core __attribute__((unused)))
{
if (world == NULL) {
return ESP_ERR_INVALID_ARG;
}
*world = MEMPROT_PMS_WORLD_NONE;
return ESP_OK;
}
esp_err_t IRAM_ATTR esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core __attribute__((unused)))
{
if (oper == NULL) {
return ESP_ERR_INVALID_ARG;
}
*oper = MEMPROT_OP_NONE;
return ESP_OK;
}
bool IRAM_ATTR esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type)
{
return false;
}
esp_err_t IRAM_ATTR esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core __attribute__((unused)))
{
if (byte_en == NULL) {
return ESP_ERR_INVALID_ARG;
}
*byte_en = 0;
return ESP_OK;
}
esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config)
{
return ESP_OK;
}

View File

@ -1,17 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* INTERNAL API
* implementation of generic interface to MMU memory protection features
*/
#include <stdbool.h>
#include "esp32s3/memprot.h"
mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void)
{
return MEMPROT_NONE;
}

View File

@ -0,0 +1,63 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_memprot_err.h"
#include "hal/memprot_types.h"
#include "esp_memprot_types.h"
esp_err_t esp_mprot_ll_err_to_esp_err(const memprot_ll_err_t err)
{
switch (err) {
case MEMP_LL_OK: return ESP_OK;
case MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE: return ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE;
case MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED: return ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED;
case MEMP_LL_ERR_UNI_BLOCK_INVALID: return ESP_ERR_MEMPROT_UNIMGMT_BLOCK_INVALID;
case MEMP_LL_ERR_WORLD_INVALID: return ESP_ERR_MEMPROT_WORLD_INVALID;
case MEMP_LL_ERR_AREA_INVALID: return ESP_ERR_MEMPROT_AREA_INVALID;
default:
return ESP_FAIL;
}
}
esp_mprot_pms_world_t esp_mprot_ll_world_to_hl_world(const memprot_ll_world_t world)
{
switch (world) {
case MEMP_LL_WORLD_NONE: return MEMPROT_PMS_WORLD_NONE;
case MEMP_LL_WORLD_0: return MEMPROT_PMS_WORLD_0;
case MEMP_LL_WORLD_1: return MEMPROT_PMS_WORLD_1;
default:
return MEMPROT_PMS_WORLD_INVALID;
}
}
const char *esp_mprot_oper_type_to_str(const uint32_t oper_type)
{
switch (oper_type) {
case MEMPROT_OP_NONE: return "NONE";
case MEMPROT_OP_READ: return "READ";
case MEMPROT_OP_WRITE: return "WRITE";
case MEMPROT_OP_EXEC: return "EXEC";
default: return "INVALID";
}
}
const char *esp_mprot_pms_world_to_str(const esp_mprot_pms_world_t world_type)
{
switch (world_type) {
case MEMPROT_PMS_WORLD_NONE:
return "PMS_WORLD_NONE";
case MEMPROT_PMS_WORLD_0:
return "PMS_WORLD_0";
case MEMPROT_PMS_WORLD_1:
return "PMS_WORLD_1";
case MEMPROT_PMS_WORLD_2:
return "PMS_WORLD_2";
case MEMPROT_PMS_WORLD_ALL:
return "PMS_WORLD_ALL";
default:
return "PMS_WORLD_INVALID";
}
}

View File

@ -14,16 +14,14 @@
#include "soc/rtc_cntl_reg.h"
#include "esp_private/panic_internal.h"
#include "esp_rom_uart.h"
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/memprot.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/memprot.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/memprot.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/memprot.h"
#elif CONFIG_IDF_TARGET_ESP8684
#include "esp8684/memprot.h"
#else
#include "esp_memprot.h"
#endif
#endif
#define SHUTDOWN_HANDLERS_NO 5
@ -88,9 +86,18 @@ void IRAM_ATTR esp_restart(void)
bool digital_reset_needed = false;
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#if CONFIG_IDF_TARGET_ESP32S2
if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) {
digital_reset_needed = true;
}
#else
bool is_on = false;
if (esp_mprot_is_intr_ena_any(&is_on) != ESP_OK || is_on) {
digital_reset_needed = true;
} else if (esp_mprot_is_conf_locked_any(&is_on) != ESP_OK || is_on) {
digital_reset_needed = true;
}
#endif
#endif
if (digital_reset_needed) {
esp_restart_noos_dig();

View File

@ -20,6 +20,7 @@ SECTIONS
mapping[rtc_text]
*rtc_wake_stub*.*(.literal .text .literal.* .text.*)
*(.rtc_text_end_test)
_rtc_text_end = ABSOLUTE(.);
} > rtc_iram_seg
@ -377,7 +378,7 @@ SECTIONS
/* ESP32-C3 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */
. += _esp_memprot_prefetch_pad_size;
. = ALIGN(_esp_memprot_align_size);
/* iram_end_test section exists for use by memprot unit tests only */
/* iram_end_test section exists for use by Memprot unit tests only */
*(.iram_end_test)
_iram_text_end = ABSOLUTE(.);
} > iram0_0_seg

View File

@ -15,12 +15,11 @@
#include "esp_private/cache_err_int.h"
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#if CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/memprot.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/memprot.h"
#elif CONFIG_IDF_TARGET_ESP8684
#if CONFIG_IDF_TARGET_ESP8684
#include "esp8684/memprot.h"
#else
#include "esp_private/esp_memprot_internal.h"
#include "esp_memprot.h"
#endif
#endif
@ -156,35 +155,62 @@ static inline void print_cache_err_details(const void *frame)
* explanation of why the panic occured.
*/
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
static esp_memp_intr_source_t s_memp_intr = {MEMPROT_TYPE_INVALID, -1};
#define PRINT_MEMPROT_ERROR(err) \
panic_print_str("N/A (error "); \
panic_print_str(esp_err_to_name(err)); \
panic_print_str(")");
static inline void print_memprot_err_details(const void *frame __attribute__((unused)))
{
if (s_memp_intr.mem_type == MEMPROT_TYPE_INVALID && s_memp_intr.core == -1) {
panic_print_str(" - no details available -\r\n");
return;
}
//common memprot fault info
mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype();
panic_print_str( " memory type: ");
panic_print_str( esp_memprot_mem_type_to_str(mem_type) );
panic_print_str( "\r\n faulting address: 0x");
panic_print_hex( esp_memprot_get_violate_addr(mem_type) );
panic_print_str( "\r\n world:");
panic_print_dec( esp_memprot_get_violate_world(mem_type) );
panic_print_str(" memory type: ");
panic_print_str(esp_mprot_mem_type_to_str(s_memp_intr.mem_type));
char operation = 0;
// IRAM fault: check instruction-fetch flag
if ( mem_type == MEMPROT_IRAM0_SRAM ) {
if ( esp_memprot_get_violate_loadstore(mem_type) ) {
operation = 'X';
}
panic_print_str("\r\n faulting address: ");
void *faulting_addr;
esp_err_t res = esp_mprot_get_violate_addr(s_memp_intr.mem_type, &faulting_addr, &s_memp_intr.core);
if (res == ESP_OK) {
panic_print_str("0x");
panic_print_hex((int)faulting_addr);
} else {
PRINT_MEMPROT_ERROR(res)
}
// W/R - common
if ( operation == 0 ) {
operation = esp_memprot_get_violate_wr(mem_type) == MEMPROT_PMS_OP_WRITE ? 'W' : 'R';
panic_print_str( "\r\n world: ");
esp_mprot_pms_world_t world;
res = esp_mprot_get_violate_world(s_memp_intr.mem_type, &world, &s_memp_intr.core);
if (res == ESP_OK) {
panic_print_str(esp_mprot_pms_world_to_str(world));
} else {
PRINT_MEMPROT_ERROR(res)
}
panic_print_str( "\r\n operation type: ");
panic_print_char( operation );
uint32_t operation;
res = esp_mprot_get_violate_operation(s_memp_intr.mem_type, &operation, &s_memp_intr.core);
if (res == ESP_OK) {
panic_print_str(esp_mprot_oper_type_to_str(operation));
} else {
PRINT_MEMPROT_ERROR(res)
}
// DRAM/DMA fault: check byte-enables
if ( mem_type == MEMPROT_DRAM0_SRAM ) {
if (esp_mprot_has_byte_enables(s_memp_intr.mem_type)) {
panic_print_str("\r\n byte-enables: " );
panic_print_hex(esp_memprot_get_violate_byte_en(mem_type));
uint32_t byte_enables;
res = esp_mprot_get_violate_byte_enables(s_memp_intr.mem_type, &byte_enables, &s_memp_intr.core);
if (res == ESP_OK) {
panic_print_hex(byte_enables);
} else {
PRINT_MEMPROT_ERROR(res)
}
}
panic_print_str("\r\n");
@ -273,11 +299,10 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
info->reason = pseudo_reason[PANIC_RSN_INTWDT_CPU0 + core];
}
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
else if ( frame->mcause == ETS_MEMPROT_ERR_INUM ) {
info->core = esp_memprot_intr_get_cpuid();
else if (frame->mcause == ETS_MEMPROT_ERR_INUM) {
info->reason = pseudo_reason[PANIC_RSN_MEMPROT];
info->details = print_memprot_err_details;
info->core = esp_mprot_get_active_intr(&s_memp_intr) == ESP_OK ? s_memp_intr.core : -1;
}
#endif
}
@ -320,7 +345,8 @@ void panic_arch_fill_info(void *frame, panic_info_t *info)
info->frame = &regs;
}
static void panic_print_basic_backtrace(const void *frame, int core) {
static void panic_print_basic_backtrace(const void *frame, int core)
{
// Basic backtrace
panic_print_str("\r\nStack memory:\r\n");
uint32_t sp = (uint32_t)((RvExcFrame *)frame)->sp;

View File

@ -22,13 +22,11 @@
#include "soc/extmem_reg.h"
#include "soc/cache_memory.h"
#include "soc/rtc_cntl_reg.h"
#if CONFIG_IDF_TARGET_ESP32S2
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#ifdef CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/memprot.h"
#endif
#elif CONFIG_IDF_TARGET_ESP32S3
#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#include "esp32s3/memprot.h"
#else
#include "esp_memprot.h"
#endif
#endif
#endif // CONFIG_IDF_TARGET_ESP32
@ -268,13 +266,9 @@ static inline void print_memprot_err_details(const void *f)
mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype();
if (mem_type != MEMPROT_NONE) {
#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged
if (esp_memprot_get_fault_status(mem_type, &fault_addr, &op_type, &op_subtype) != ESP_OK) {
op_type = MEMPROT_OP_INVALID;
}
#else
esp_memprot_get_fault_status(mem_type, &fault_addr, &op_type, &op_subtype);
#endif
}
if (op_type == MEMPROT_OP_INVALID) {
@ -437,9 +431,11 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
info->exception = PANIC_EXCEPTION_DEBUG;
}
//MV note: ESP32S3 PMS handling?
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
if (frame->exccause == PANIC_RSN_CACHEERR) {
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE && CONFIG_IDF_TARGET_ESP32S2
if ( esp_memprot_is_intr_ena_any() ) {
info->details = print_memprot_err_details;
info->reason = "Memory protection fault";

View File

@ -39,7 +39,7 @@
#include "esp32s3/rom/cache.h"
#include "esp32s3/spiram.h"
#include "esp32s3/dport_access.h"
#include "esp32s3/memprot.h"
#include "esp_memprot.h"
#include "soc/assist_debug_reg.h"
#include "soc/cache_memory.h"
#include "soc/system_reg.h"
@ -48,12 +48,12 @@
#include "esp32c3/rtc.h"
#include "esp32c3/rom/cache.h"
#include "soc/cache_memory.h"
#include "esp32c3/memprot.h"
#include "esp_memprot.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rtc.h"
#include "esp32h2/rom/cache.h"
#include "soc/cache_memory.h"
#include "esp32h2/memprot.h"
#include "esp_memprot.h"
#elif CONFIG_IDF_TARGET_ESP8684
#include "esp8684/rtc.h"
#include "esp8684/rom/cache.h"
@ -368,7 +368,7 @@ void IRAM_ATTR call_start_cpu0(void)
#if CONFIG_IDF_TARGET_ESP32S3
extern int _rodata_reserved_end;
uint32_t cache_mmu_drom_size = (((uint32_t)&_rodata_reserved_end - rodata_reserved_start_align + MMU_PAGE_SIZE - 1)/MMU_PAGE_SIZE)*sizeof(uint32_t);
uint32_t cache_mmu_drom_size = (((uint32_t)&_rodata_reserved_end - rodata_reserved_start_align + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE) * sizeof(uint32_t);
#endif
Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size);
@ -485,12 +485,12 @@ void IRAM_ATTR call_start_cpu0(void)
#endif
extern void Cache_Set_IDROM_MMU_Info(uint32_t instr_page_num, uint32_t rodata_page_num, uint32_t rodata_start, uint32_t rodata_end, int i_off, int ro_off);
Cache_Set_IDROM_MMU_Info(cache_mmu_irom_size/sizeof(uint32_t), \
cache_mmu_drom_size/sizeof(uint32_t), \
(uint32_t)&_rodata_reserved_start, \
(uint32_t)&_rodata_reserved_end, \
s_instr_flash2spiram_off, \
s_rodata_flash2spiram_off);
Cache_Set_IDROM_MMU_Info(cache_mmu_irom_size / sizeof(uint32_t), \
cache_mmu_drom_size / sizeof(uint32_t), \
(uint32_t)&_rodata_reserved_start, \
(uint32_t)&_rodata_reserved_end, \
s_instr_flash2spiram_off, \
s_rodata_flash2spiram_off);
#endif
#if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S2_DATA_CACHE_WRAP || \
@ -566,32 +566,41 @@ void IRAM_ATTR call_start_cpu0(void)
esp_cache_err_int_init();
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE && !CONFIG_ESP_SYSTEM_MEMPROT_TEST
// Memprot cannot be locked during OS startup as the lock-on prevents any PMS changes until a next reboot
// If such a situation appears, it is likely an malicious attempt to bypass the system safety setup -> print error & reset
#if CONFIG_IDF_TARGET_ESP32S2
if (esp_memprot_is_locked_any()) {
#else
bool is_locked = false;
if (esp_mprot_is_conf_locked_any(&is_locked) != ESP_OK || is_locked) {
#endif
ESP_EARLY_LOGE(TAG, "Memprot feature locked after the system reset! Potential safety corruption, rebooting.");
esp_restart_noos_dig();
}
//default configuration of PMS Memprot
esp_err_t memp_err = ESP_OK;
#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK
#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged
memp_err = esp_memprot_set_prot(true, true, NULL);
memp_err = esp_memprot_set_prot(PANIC_HNDL_ON, MEMPROT_LOCK, NULL);
#else
esp_memprot_set_prot(true, true, NULL);
#endif
#else
#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged
memp_err = esp_memprot_set_prot(true, false, NULL);
#else
esp_memprot_set_prot(true, false, NULL);
memp_err = esp_memprot_set_prot(PANIC_HNDL_ON, MEMPROT_UNLOCK, NULL);
#endif
#else //CONFIG_IDF_TARGET_ESP32S2 specific end
esp_memp_config_t memp_cfg = ESP_MEMPROT_DEFAULT_CONFIG();
#if !CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK
memp_cfg.lock_feature = false;
#endif
memp_err = esp_mprot_set_prot(&memp_cfg);
#endif //other IDF_TARGETS end
if (memp_err != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to set Memprot feature (error 0x%08X), rebooting.", memp_err);
ESP_EARLY_LOGE(TAG, "Failed to set Memprot feature (0x%08X: %s), rebooting.", memp_err, esp_err_to_name(memp_err));
esp_restart_noos_dig();
}
#endif
#endif //CONFIG_ESP_SYSTEM_MEMPROT_FEATURE && !CONFIG_ESP_SYSTEM_MEMPROT_TEST
// Read the application binary image header. This will also decrypt the header if the image is encrypted.
__attribute__((unused)) esp_image_header_t fhdr = {0};

View File

@ -3,6 +3,7 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include "esp_spi_flash.h"
@ -24,16 +25,16 @@
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/dport_access.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#endif
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#ifdef CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/memprot.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/memprot.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/memprot.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/memprot.h"
#elif CONFIG_IDF_TARGET_ESP8684
#include "esp8684/memprot.h"
#else
#include "esp_memprot.h"
#endif
#endif
#include "esp_private/panic_internal.h"
@ -230,9 +231,18 @@ void __attribute__((noreturn)) panic_restart(void)
}
#endif
#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
#if CONFIG_IDF_TARGET_ESP32S2
if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) {
digital_reset_needed = true;
}
#else
bool is_on = false;
if (esp_mprot_is_intr_ena_any(&is_on) != ESP_OK || is_on) {
digital_reset_needed = true;
} else if (esp_mprot_is_conf_locked_any(&is_on) != ESP_OK || is_on) {
digital_reset_needed = true;
}
#endif
#endif
if (digital_reset_needed) {
esp_restart_noos_dig();

View File

@ -1,59 +1,22 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/sensitive_reg.h"
#include "soc/cache_memory.h"
#include "hal/assert.h"
#include "soc/memprot_defs.h"
#include "hal/memprot_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ******************************************************************************************************
* *** GLOBALS ***
* NOTE: in this version, all the configurations apply only to WORLD_0
*/
#define IRAM_SRAM_START 0x4037C000
#define DRAM_SRAM_START 0x3FC7C000
/* ICache size is fixed to 16KB on ESP32-C3 */
#ifndef ICACHE_SIZE
#define ICACHE_SIZE 0x4000
#endif
#ifndef I_D_SRAM_SEGMENT_SIZE
#define I_D_SRAM_SEGMENT_SIZE 0x20000
#endif
#define I_D_SPLIT_LINE_SHIFT 0x9
#define I_D_FAULT_ADDR_SHIFT 0x2
typedef union {
struct {
uint32_t cat0 : 2;
uint32_t cat1 : 2;
uint32_t cat2 : 2;
uint32_t res0 : 8;
uint32_t splitaddr : 8;
uint32_t res1 : 10;
};
uint32_t val;
} constrain_reg_fields_t;
* *** COMMON ***
* ******************************************************************************************************/
static inline void memprot_ll_set_iram0_dram0_split_line_lock(void)
{
REG_WRITE(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_0_REG, 1);
@ -64,7 +27,7 @@ static inline bool memprot_ll_get_iram0_dram0_split_line_lock(void)
return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_0_REG) == 1;
}
static inline void* memprot_ll_get_split_addr_from_reg(uint32_t regval, uint32_t base)
static inline void *memprot_ll_get_split_addr_from_reg(uint32_t regval, uint32_t base)
{
constrain_reg_fields_t reg_val;
reg_val.val = regval;
@ -85,43 +48,30 @@ static inline void* memprot_ll_get_split_addr_from_reg(uint32_t regval, uint32_t
/* ******************************************************************************************************
* *** IRAM0 ***
*/
//16kB (CACHE)
#define IRAM0_SRAM_LEVEL_0_LOW IRAM_SRAM_START //0x40370000
#define IRAM0_SRAM_LEVEL_0_HIGH (IRAM0_SRAM_LEVEL_0_LOW + ICACHE_SIZE - 0x1) //0x4037FFFF
//128kB (LEVEL 1)
#define IRAM0_SRAM_LEVEL_1_LOW (IRAM0_SRAM_LEVEL_0_HIGH + 0x1) //0x40380000
#define IRAM0_SRAM_LEVEL_1_HIGH (IRAM0_SRAM_LEVEL_1_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x4039FFFF
//128kB (LEVEL 2)
#define IRAM0_SRAM_LEVEL_2_LOW (IRAM0_SRAM_LEVEL_1_HIGH + 0x1) //0x403A0000
#define IRAM0_SRAM_LEVEL_2_HIGH (IRAM0_SRAM_LEVEL_2_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x403BFFFF
//128kB (LEVEL 3)
#define IRAM0_SRAM_LEVEL_3_LOW (IRAM0_SRAM_LEVEL_2_HIGH + 0x1) //0x403C0000
#define IRAM0_SRAM_LEVEL_3_HIGH (IRAM0_SRAM_LEVEL_3_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x403DFFFF
//permission bits
#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R 0x1
#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W 0x2
#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_F 0x4
* ******************************************************************************************************/
static inline uint32_t memprot_ll_iram0_get_intr_source_num(void)
{
return ETS_CORE0_IRAM0_PMS_INTR_SOURCE;
}
///////////////////////////////////
// IRAM0 - SPLIT LINES
///////////////////////////////////
static inline void memprot_ll_set_iram0_split_line(const void *line_addr, uint32_t sensitive_reg)
/* ********************************
* IRAM0 - SPLIT LINES
*
* NOTES:
* 1. IRAM0/DRAM0 split-lines must be aligned to 512B boundaries (PMS module restriction)
* 2. split address must fall into appropriate IRAM0/DRAM0 region
*/
static inline memprot_ll_err_t memprot_ll_set_iram0_split_line(const void *line_addr, uint32_t sensitive_reg)
{
uint32_t addr = (uint32_t)line_addr;
HAL_ASSERT(addr >= IRAM0_SRAM_LEVEL_1_LOW && addr <= IRAM0_SRAM_LEVEL_3_HIGH);
if (addr < IRAM0_SRAM_LEVEL_1_LOW || addr > IRAM0_SRAM_LEVEL_3_HIGH) {
return MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE;
}
if (addr % 0x200 != 0) {
return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED;
}
uint32_t category[3] = {0};
if (addr <= IRAM0_SRAM_LEVEL_1_HIGH) {
@ -141,47 +91,61 @@ static inline void memprot_ll_set_iram0_split_line(const void *line_addr, uint32
(category[2] << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_2_S);
uint32_t conf_addr = ((addr >> I_D_SPLIT_LINE_SHIFT) & SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_V) << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_S;
uint32_t reg_cfg = conf_addr | category_bits;
REG_WRITE(sensitive_reg, reg_cfg);
return MEMP_LL_OK;
}
/* can be both IRAM0/DRAM0 address */
static inline void memprot_ll_set_iram0_split_line_main_I_D(const void *line_addr)
static inline memprot_ll_err_t memprot_ll_set_iram0_split_line_main_I_D(const void *line_addr)
{
memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG);
return memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG);
}
static inline void memprot_ll_set_iram0_split_line_I_0(const void *line_addr)
static inline memprot_ll_err_t memprot_ll_set_iram0_split_line_I_0(const void *line_addr)
{
memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG);
return memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG);
}
static inline void memprot_ll_set_iram0_split_line_I_1(const void *line_addr)
static inline memprot_ll_err_t memprot_ll_set_iram0_split_line_I_1(const void *line_addr)
{
memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG);
return memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG);
}
static inline void* memprot_ll_get_iram0_split_line_main_I_D(void)
static inline uint32_t memprot_ll_get_iram0_split_line_main_I_D_cat(void)
{
return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG) & 0x3F;
}
static inline uint32_t memprot_ll_get_iram0_split_line_I_0_cat(void)
{
return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG) & 0x3F;
}
static inline uint32_t memprot_ll_get_iram0_split_line_I_1_cat(void)
{
return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG) & 0x3F;
}
static inline void *memprot_ll_get_iram0_split_line_main_I_D(void)
{
return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG), SOC_DIRAM_IRAM_LOW);
}
static inline void* memprot_ll_get_iram0_split_line_I_0(void)
static inline void *memprot_ll_get_iram0_split_line_I_0(void)
{
return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG), SOC_DIRAM_IRAM_LOW);
}
static inline void* memprot_ll_get_iram0_split_line_I_1(void)
static inline void *memprot_ll_get_iram0_split_line_I_1(void)
{
return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG), SOC_DIRAM_IRAM_LOW);
}
///////////////////////////////////
// IRAM0 - PMS CONFIGURATION
///////////////////////////////////
// lock
static inline void memprot_ll_iram0_set_pms_lock(void)
@ -198,14 +162,14 @@ static inline bool memprot_ll_iram0_get_pms_lock(void)
static inline uint32_t memprot_ll_iram0_set_permissions(bool r, bool w, bool x)
{
uint32_t permissions = 0;
if ( r ) {
permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R;
if (r) {
permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R;
}
if ( w ) {
permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W;
if (w) {
permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W;
}
if ( x ) {
permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_F;
if (x) {
permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_F;
}
return permissions;
@ -233,39 +197,38 @@ static inline void memprot_ll_iram0_set_pms_area_3(bool r, bool w, bool x)
static inline void memprot_ll_iram0_get_permissions(uint32_t perms, bool *r, bool *w, bool *x)
{
*r = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R;
*w = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W;
*x = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_F;
*r = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R;
*w = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W;
*x = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_F;
}
static inline void memprot_ll_iram0_get_pms_area_0(bool *r, bool *w, bool *x)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0);
memprot_ll_iram0_get_permissions( permissions, r, w, x);
memprot_ll_iram0_get_permissions(permissions, r, w, x);
}
static inline void memprot_ll_iram0_get_pms_area_1(bool *r, bool *w, bool *x)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1);
memprot_ll_iram0_get_permissions( permissions, r, w, x);
memprot_ll_iram0_get_permissions(permissions, r, w, x);
}
static inline void memprot_ll_iram0_get_pms_area_2(bool *r, bool *w, bool *x)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2);
memprot_ll_iram0_get_permissions( permissions, r, w, x);
memprot_ll_iram0_get_permissions(permissions, r, w, x);
}
static inline void memprot_ll_iram0_get_pms_area_3(bool *r, bool *w, bool *x)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3);
memprot_ll_iram0_get_permissions( permissions, r, w, x);
memprot_ll_iram0_get_permissions(permissions, r, w, x);
}
///////////////////////////////////
// IRAM0 - MONITOR
///////////////////////////////////
// lock
static inline void memprot_ll_iram0_set_monitor_lock(void)
@ -281,26 +244,31 @@ static inline bool memprot_ll_iram0_get_monitor_lock(void)
// interrupt enable/clear
static inline void memprot_ll_iram0_set_monitor_en(bool enable)
{
if ( enable ) {
REG_SET_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN );
if (enable) {
REG_SET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN);
} else {
REG_CLR_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN );
REG_CLR_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN);
}
}
static inline bool memprot_ll_iram0_get_monitor_intrclr(void)
{
return REG_GET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR) > 0;
}
static inline bool memprot_ll_iram0_get_monitor_en(void)
{
return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN ) == 1;
return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN) == 1;
}
static inline void memprot_ll_iram0_clear_monitor_intr(void)
static inline void memprot_ll_iram0_set_monitor_intrclr(void)
{
REG_SET_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR );
REG_SET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR);
}
static inline void memprot_ll_iram0_reset_clear_monitor_intr(void)
static inline void memprot_ll_iram0_reset_monitor_intrclr(void)
{
REG_CLR_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR );
REG_CLR_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR);
}
static inline uint32_t memprot_ll_iram0_get_monitor_enable_register(void)
@ -308,31 +276,31 @@ static inline uint32_t memprot_ll_iram0_get_monitor_enable_register(void)
return REG_READ(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG);
}
// // permission violation status
// permission violation status
static inline uint32_t memprot_ll_iram0_get_monitor_status_intr(void)
{
return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_INTR );
return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_INTR);
}
static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_wr(void)
{
return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WR );
return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WR);
}
static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_loadstore(void)
{
return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_LOADSTORE );
return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_LOADSTORE);
}
static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_world(void)
{
return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD );
return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD);
}
static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_addr(void)
static inline intptr_t memprot_ll_iram0_get_monitor_status_fault_addr(void)
{
uint32_t addr = REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR );
return addr > 0 ? (addr << I_D_FAULT_ADDR_SHIFT) + IRAM0_ADDRESS_LOW : 0;
uint32_t addr = REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR);
return (intptr_t)(addr > 0 ? (addr << I_D_FAULT_ADDR_SHIFT) + IRAM0_ADDRESS_LOW : 0);
}
static inline uint32_t memprot_ll_iram0_get_monitor_status_register(void)
@ -342,43 +310,309 @@ static inline uint32_t memprot_ll_iram0_get_monitor_status_register(void)
/* ******************************************************************************************************
* *** DRAM0 ***
* *** RTC_FAST ***
*/
//cache not available from DRAM (!)
#define DRAM0_SRAM_LEVEL_0_LOW DRAM_SRAM_START //0x3FC7C000
#define DRAM0_SRAM_LEVEL_0_HIGH (DRAM0_SRAM_LEVEL_0_LOW + ICACHE_SIZE - 0x1) //0x3FC7FFFF
static inline uint32_t memprot_ll_rtcfast_get_intr_source_num(void)
{
return ETS_CORE0_PIF_PMS_INTR_SOURCE;
}
//128kB
#define DRAM0_SRAM_LEVEL_1_LOW (DRAM0_SRAM_LEVEL_0_HIGH + 0x1) //0x3FC80000
#define DRAM0_SRAM_LEVEL_1_HIGH (DRAM0_SRAM_LEVEL_1_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FC9FFFF
//shared PIF PMS lock
//!!!: use after ALL the constraints have been set
static inline void memprot_ll_set_pif_constraint_lock(void)
{
REG_WRITE(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_0_REG, 1);
}
//128kB
#define DRAM0_SRAM_LEVEL_2_LOW (DRAM0_SRAM_LEVEL_1_HIGH + 0x1) //0x3FCA0000
#define DRAM0_SRAM_LEVEL_2_HIGH (DRAM0_SRAM_LEVEL_2_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FCBFFFF
static inline bool memprot_ll_get_pif_constraint_lock(void)
{
return REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_0_REG) == 1;
}
//128kB
#define DRAM0_SRAM_LEVEL_3_LOW (DRAM0_SRAM_LEVEL_2_HIGH + 0x1) //0x3FCC0000
#define DRAM0_SRAM_LEVEL_3_HIGH (DRAM0_SRAM_LEVEL_3_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FCDFFFF
static inline uint32_t memprot_ll_rtcfast_get_splitaddr_register(void)
{
return REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG);
}
#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W 0x2
#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R 0x1
/* ********************************
* IRAM0 RTCFAST - SPLIT LINES
*
* NOTES:
* 1. there is only 1 split line for RTCFAST/WORLD
* 2. RTCFAST split-line must be aligned to 4B boundaries (PMS stores 11 bits of 13-bit offset in 8kB RTCFAST region)
* 3. RTCFAST has weird section structure (text -> dummy (!) -> force -> data) - .dummy section seems to have wrong mapping (it doesn't fall inline with .rtctext)
*/
static inline memprot_ll_err_t memprot_ll_set_rtcfast_split_line(const void *line_addr, memprot_ll_world_t world)
{
uint32_t addr = (uint32_t)line_addr;
uint32_t mask;
if (addr < SOC_RTC_IRAM_LOW || addr >= SOC_RTC_IRAM_HIGH) {
return MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE;
}
if (addr % 0x4 != 0) {
return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED;
}
switch (world) {
case MEMP_LL_WORLD_0:
mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_M;
break;
case MEMP_LL_WORLD_1:
mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_M;
break;
default:
return MEMP_LL_ERR_WORLD_INVALID;
}
//offset bits to store are the same width for both worlds -> using SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_V
CLEAR_PERI_REG_MASK(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG, mask);
REG_SET_BITS(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG, mask, (addr >> 2) & SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_V);
return MEMP_LL_OK;
}
static inline memprot_ll_err_t memprot_ll_get_rtcfast_split_line(memprot_ll_world_t world, void **line_addr)
{
uint32_t reg_addr = REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG);
uint32_t mask = 0;
uint32_t shift = 0;
switch (world) {
case MEMP_LL_WORLD_0:
mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_M;
shift = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_S;
break;
case MEMP_LL_WORLD_1:
mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_M;
shift = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_S;
break;
default:
return MEMP_LL_ERR_WORLD_INVALID;
}
*line_addr = (void *)((((reg_addr & mask) >> shift) << 2) + SOC_RTC_IRAM_LOW);
return MEMP_LL_OK;
}
///////////////////////////////////
// RTC_FAST - PMS CONFIGURATION
// permission settings
static inline uint32_t memprot_ll_rtcfast_set_permissions(bool r, bool w, bool x)
{
uint32_t permissions = 0;
if (r) {
permissions |= SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_R;
}
if (w) {
permissions |= SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_W;
}
if (x) {
permissions |= SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_F;
}
return permissions;
}
static inline memprot_ll_err_t memprot_ll_rtcfast_set_pms_area(bool r, bool w, bool x, memprot_ll_world_t world, memprot_ll_area_t area)
{
uint32_t bits = 0;
uint32_t mask = 0;
switch (world) {
case MEMP_LL_WORLD_0: {
switch (area) {
case MEMP_LL_AREA_LOW:
bits = memprot_ll_rtcfast_set_permissions(r, w, x) << SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L_S;
mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L_M;
break;
case MEMP_LL_AREA_HIGH:
bits = memprot_ll_rtcfast_set_permissions(r, w, x) << SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H_S;
mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H_M;
break;
default:
return MEMP_LL_ERR_AREA_INVALID;
}
} break;
case MEMP_LL_WORLD_1: {
switch (area) {
case MEMP_LL_AREA_LOW:
bits = memprot_ll_rtcfast_set_permissions(r, w, x) << SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L_S;
mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L_M;
break;
case MEMP_LL_AREA_HIGH:
bits = memprot_ll_rtcfast_set_permissions(r, w, x) << SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H_S;
mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H_M;
break;
default:
return MEMP_LL_ERR_AREA_INVALID;
}
} break;
default:
return MEMP_LL_ERR_WORLD_INVALID;
}
CLEAR_PERI_REG_MASK(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, mask);
REG_SET_BITS(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, bits, mask);
return MEMP_LL_OK;
}
static inline void memprot_ll_rtcfast_get_permissions(uint32_t perms, bool *r, bool *w, bool *x)
{
*r = perms & SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_R;
*w = perms & SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_W;
*x = perms & SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_F;
}
static inline memprot_ll_err_t memprot_ll_rtcfast_get_pms_area(bool *r, bool *w, bool *x, memprot_ll_world_t world, memprot_ll_area_t area)
{
uint32_t permissions = 0;
switch (world) {
case MEMP_LL_WORLD_0: {
switch (area) {
case MEMP_LL_AREA_LOW:
permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L);
break;
case MEMP_LL_AREA_HIGH:
permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H);
break;
default:
return MEMP_LL_ERR_AREA_INVALID;
}
} break;
case MEMP_LL_WORLD_1: {
switch (area) {
case MEMP_LL_AREA_LOW:
permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L);
break;
case MEMP_LL_AREA_HIGH:
permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H);
break;
default:
return MEMP_LL_ERR_AREA_INVALID;
}
} break;
default:
return MEMP_LL_ERR_WORLD_INVALID;
}
memprot_ll_rtcfast_get_permissions(permissions, r, w, x);
return MEMP_LL_OK;
}
static inline uint32_t memprot_ll_rtcfast_get_permission_register(void)
{
return REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG);
}
///////////////////////////////////
// RTC_FAST - MONITOR
// lock
static inline void memprot_ll_rtcfast_set_monitor_lock(void)
{
REG_WRITE(SENSITIVE_CORE_0_PIF_PMS_MONITOR_0_REG, 1);
}
static inline bool memprot_ll_rtcfast_get_monitor_lock(void)
{
return REG_READ(SENSITIVE_CORE_0_PIF_PMS_MONITOR_0_REG) == 1;
}
// interrupt enable/clear
static inline void memprot_ll_rtcfast_set_monitor_en(bool enable)
{
if (enable) {
REG_SET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN);
} else {
REG_CLR_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN);
}
}
static inline bool memprot_ll_rtcfast_get_monitor_en(void)
{
return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN) > 0;
}
static inline bool memprot_ll_rtcfast_get_monitor_intrclr(void)
{
return REG_GET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR) > 0;
}
static inline void memprot_ll_rtcfast_set_monitor_intrclr(void)
{
REG_SET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR);
}
static inline void memprot_ll_rtcfast_reset_monitor_intrclr(void)
{
REG_CLR_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR);
}
static inline uint32_t memprot_ll_rtcfast_get_monitor_register(void)
{
return REG_READ(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG);
}
// permission violation status
static inline uint32_t memprot_ll_rtcfast_get_monitor_status_intr(void)
{
return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_INTR);
}
static inline intptr_t memprot_ll_rtcfast_get_monitor_status_fault_addr(void)
{
//full address SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HADDR
return (intptr_t)REG_READ(SENSITIVE_CORE_0_PIF_PMS_MONITOR_3_REG);
}
static inline uint32_t memprot_ll_rtcfast_get_monitor_status_fault_world(void)
{
return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HWORLD);
}
static inline uint32_t memprot_ll_rtcfast_get_monitor_status_fault_loadstore(void)
{
return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HPORT_0);
}
static inline uint32_t memprot_ll_rtcfast_get_monitor_status_fault_wr(void)
{
return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HWRITE);
}
/* ******************************************************************************************************
* *** DRAM0 ***
* ******************************************************************************************************/
static inline uint32_t memprot_ll_dram0_get_intr_source_num(void)
{
return ETS_CORE0_DRAM0_PMS_INTR_SOURCE;
}
///////////////////////////////////
// DRAM0 - SPLIT LINES
///////////////////////////////////
static inline void memprot_ll_set_dram0_split_line(const void *line_addr, uint32_t sensitive_reg)
static inline memprot_ll_err_t memprot_ll_set_dram0_split_line(const void *line_addr, uint32_t sensitive_reg)
{
uint32_t addr = (uint32_t)line_addr;
HAL_ASSERT(addr >= DRAM0_SRAM_LEVEL_1_LOW && addr <= DRAM0_SRAM_LEVEL_3_HIGH);
//sanity check: split address required above unified mgmt region & 32bit aligned
if (addr < DRAM0_SRAM_LEVEL_1_LOW || addr > DRAM0_SRAM_LEVEL_3_HIGH) {
return MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE;
}
//split-line must be divisible by 512 (PMS module restriction)
if (addr % 0x200 != 0) {
return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED;
}
uint32_t category[3] = {0};
if (addr <= DRAM0_SRAM_LEVEL_1_HIGH) {
@ -398,36 +632,45 @@ static inline void memprot_ll_set_dram0_split_line(const void *line_addr, uint32
(category[2] << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_2_S);
uint32_t conf_addr = ((addr >> I_D_SPLIT_LINE_SHIFT) & SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_V) << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_S;
uint32_t reg_cfg = conf_addr | category_bits;
REG_WRITE(sensitive_reg, reg_cfg);
return MEMP_LL_OK;
}
static inline void memprot_ll_set_dram0_split_line_D_0(const void *line_addr)
static inline memprot_ll_err_t memprot_ll_set_dram0_split_line_D_0(const void *line_addr)
{
memprot_ll_set_dram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG);
return memprot_ll_set_dram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG);
}
static inline void memprot_ll_set_dram0_split_line_D_1(const void *line_addr)
static inline memprot_ll_err_t memprot_ll_set_dram0_split_line_D_1(const void *line_addr)
{
memprot_ll_set_dram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5_REG);
return memprot_ll_set_dram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5_REG);
}
static inline void* memprot_ll_get_dram0_split_line_D_0(void)
static inline void *memprot_ll_get_dram0_split_line_D_0(void)
{
return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG), SOC_DIRAM_DRAM_LOW);
}
static inline void* memprot_ll_get_dram0_split_line_D_1(void)
static inline void *memprot_ll_get_dram0_split_line_D_1(void)
{
return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5_REG), SOC_DIRAM_DRAM_LOW);
}
static inline uint32_t memprot_ll_get_dram0_split_line_D_0_cat(void)
{
return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG) & 0x3F;
}
static inline uint32_t memprot_ll_get_dram0_split_line_D_1_cat(void)
{
return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5_REG) & 0x3F;
}
///////////////////////////////////
// DRAM0 - PMS CONFIGURATION
///////////////////////////////////
// lock
static inline void memprot_ll_dram0_set_pms_lock(void)
@ -444,11 +687,11 @@ static inline bool memprot_ll_dram0_get_pms_lock(void)
static inline uint32_t memprot_ll_dram0_set_permissions(bool r, bool w)
{
uint32_t permissions = 0;
if ( r ) {
permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R;
if (r) {
permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R;
}
if ( w ) {
permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W;
if (w) {
permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W;
}
return permissions;
@ -476,37 +719,36 @@ static inline void memprot_ll_dram0_set_pms_area_3(bool r, bool w)
static inline void memprot_ll_dram0_get_permissions(uint32_t perms, bool *r, bool *w )
{
*r = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R;
*w = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W;
*r = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R;
*w = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W;
}
static inline void memprot_ll_dram0_get_pms_area_0(bool *r, bool *w)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0);
memprot_ll_dram0_get_permissions( permissions, r, w);
memprot_ll_dram0_get_permissions(permissions, r, w);
}
static inline void memprot_ll_dram0_get_pms_area_1(bool *r, bool *w)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1);
memprot_ll_dram0_get_permissions( permissions, r, w);
memprot_ll_dram0_get_permissions(permissions, r, w);
}
static inline void memprot_ll_dram0_get_pms_area_2(bool *r, bool *w)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2);
memprot_ll_dram0_get_permissions( permissions, r, w);
memprot_ll_dram0_get_permissions(permissions, r, w);
}
static inline void memprot_ll_dram0_get_pms_area_3(bool *r, bool *w)
{
uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3);
memprot_ll_dram0_get_permissions( permissions, r, w);
memprot_ll_dram0_get_permissions(permissions, r, w);
}
///////////////////////////////////
// DRAM0 - MONITOR
///////////////////////////////////
// lock
static inline void memprot_ll_dram0_set_monitor_lock(void)
@ -522,26 +764,31 @@ static inline bool memprot_ll_dram0_get_monitor_lock(void)
// interrupt enable/clear
static inline void memprot_ll_dram0_set_monitor_en(bool enable)
{
if ( enable ) {
REG_SET_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN );
if (enable) {
REG_SET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN);
} else {
REG_CLR_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN );
REG_CLR_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN);
}
}
static inline bool memprot_ll_dram0_get_monitor_en(void)
{
return REG_GET_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN ) == 1;
return REG_GET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN) > 0;
}
static inline void memprot_ll_dram0_clear_monitor_intr(void)
static inline void memprot_ll_dram0_set_monitor_intrclr(void)
{
REG_SET_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR );
REG_SET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR);
}
static inline void memprot_ll_dram0_reset_clear_monitor_intr(void)
static inline void memprot_ll_dram0_reset_monitor_intrclr(void)
{
REG_CLR_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR );
REG_CLR_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR);
}
static inline bool memprot_ll_dram0_get_monitor_intrclr(void)
{
return REG_GET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR) > 0;
}
static inline uint32_t memprot_ll_dram0_get_monitor_enable_register(void)
@ -552,33 +799,33 @@ static inline uint32_t memprot_ll_dram0_get_monitor_enable_register(void)
// permission violation status
static inline uint32_t memprot_ll_dram0_get_monitor_status_intr(void)
{
return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_INTR );
return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_INTR);
}
static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_lock(void)
{
return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_LOCK );
return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_LOCK);
}
static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_world(void)
{
return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD );
return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD);
}
static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_addr(void)
{
uint32_t addr = REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR );
uint32_t addr = REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR);
return addr > 0 ? (addr << I_D_FAULT_ADDR_SHIFT) + DRAM0_ADDRESS_LOW : 0;
}
static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_wr(void)
{
return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_3_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WR );
return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_3_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WR);
}
static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_byte_en(void)
{
return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_BYTEEN );
return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_BYTEEN);
}
static inline uint32_t memprot_ll_dram0_get_monitor_status_register_1(void)

View File

@ -1,16 +1,8 @@
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
@ -25,11 +17,34 @@ extern "C" {
typedef enum {
MEMP_LL_OK = 0,
MEMP_LL_FAIL = 1,
MEMP_LL_ERR_SPLIT_ADDR_INVALID = 2,
MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE = 2,
MEMP_LL_ERR_SPLIT_ADDR_INVALID = 2, /* temporary duplicate for S2 builds */
MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED = 3,
MEMP_LL_ERR_UNI_BLOCK_INVALID = 4
MEMP_LL_ERR_UNI_BLOCK_INVALID = 4,
MEMP_LL_ERR_AREA_INVALID = 5,
MEMP_LL_ERR_WORLD_INVALID = 6
} memprot_ll_err_t;
/**
* @brief Memprot LL PMS World IDs
*
*/
typedef enum {
MEMP_LL_WORLD_NONE = 0x00,
MEMP_LL_WORLD_0 = 0x01,
MEMP_LL_WORLD_1 = 0x10
} memprot_ll_world_t;
/**
* @brief Memprot LL PMS Area IDs
*
*/
typedef enum {
MEMP_LL_AREA_NONE = 0,
MEMP_LL_AREA_LOW = 1,
MEMP_LL_AREA_HIGH = 2
} memprot_ll_area_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,100 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/soc.h"
#include "soc/sensitive_reg.h"
#include "esp32c3/rom/cache.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef union {
struct {
uint32_t cat0 : 2;
uint32_t cat1 : 2;
uint32_t cat2 : 2;
uint32_t res0 : 8;
uint32_t splitaddr : 8;
uint32_t res1 : 10;
};
uint32_t val;
} constrain_reg_fields_t;
#ifndef I_D_SRAM_SEGMENT_SIZE
#define I_D_SRAM_SEGMENT_SIZE 0x20000
#endif
#define I_D_SPLIT_LINE_SHIFT 0x9
#define I_D_FAULT_ADDR_SHIFT 0x2
#define DRAM_SRAM_START 0x3FC7C000
#ifndef MAP_DRAM_TO_IRAM
#define MAP_DRAM_TO_IRAM(addr) (addr - DRAM_SRAM_START + SOC_IRAM_LOW)
#endif
#ifndef MAP_IRAM_TO_DRAM
#define MAP_IRAM_TO_DRAM(addr) (addr - SOC_IRAM_LOW + DRAM_SRAM_START)
#endif
//IRAM0
//16kB (ICACHE)
#define IRAM0_SRAM_LEVEL_0_LOW SOC_IRAM_LOW //0x40370000
#define IRAM0_SRAM_LEVEL_0_HIGH (IRAM0_SRAM_LEVEL_0_LOW + CACHE_MEMORY_IBANK_SIZE - 0x1) //0x4037FFFF
//128kB (LEVEL 1)
#define IRAM0_SRAM_LEVEL_1_LOW (IRAM0_SRAM_LEVEL_0_HIGH + 0x1) //0x40380000
#define IRAM0_SRAM_LEVEL_1_HIGH (IRAM0_SRAM_LEVEL_1_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x4039FFFF
//128kB (LEVEL 2)
#define IRAM0_SRAM_LEVEL_2_LOW (IRAM0_SRAM_LEVEL_1_HIGH + 0x1) //0x403A0000
#define IRAM0_SRAM_LEVEL_2_HIGH (IRAM0_SRAM_LEVEL_2_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x403BFFFF
//128kB (LEVEL 3)
#define IRAM0_SRAM_LEVEL_3_LOW (IRAM0_SRAM_LEVEL_2_HIGH + 0x1) //0x403C0000
#define IRAM0_SRAM_LEVEL_3_HIGH (IRAM0_SRAM_LEVEL_3_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x403DFFFF
//permission bits
#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R 0x1
#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W 0x2
#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_F 0x4
//DRAM0
//16kB ICACHE not available from DRAM0
//128kB (LEVEL 1)
#define DRAM0_SRAM_LEVEL_1_LOW SOC_DRAM_LOW //0x3FC80000
#define DRAM0_SRAM_LEVEL_1_HIGH (DRAM0_SRAM_LEVEL_1_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FC9FFFF
//128kB (LEVEL 2)
#define DRAM0_SRAM_LEVEL_2_LOW (DRAM0_SRAM_LEVEL_1_HIGH + 0x1) //0x3FCA0000
#define DRAM0_SRAM_LEVEL_2_HIGH (DRAM0_SRAM_LEVEL_2_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FCBFFFF
//128kB (LEVEL 3)
#define DRAM0_SRAM_LEVEL_3_LOW (DRAM0_SRAM_LEVEL_2_HIGH + 0x1) //0x3FCC0000
#define DRAM0_SRAM_LEVEL_3_HIGH (DRAM0_SRAM_LEVEL_3_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FCDFFFF
#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R 0x1
#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W 0x2
//RTC FAST
//permission bits
#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_W 0x1
#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_R 0x2
#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_F 0x4
#define AREA_LOW 0
#define AREA_HIGH 1
#ifdef __cplusplus
}
#endif

View File

@ -452,7 +452,6 @@ components/esp_common/include/esp_assert.h
components/esp_common/include/esp_bit_defs.h
components/esp_common/include/esp_check.h
components/esp_common/include/esp_compiler.h
components/esp_common/include/esp_err.h
components/esp_common/include/esp_types.h
components/esp_common/src/esp_err_to_name.c
components/esp_common/test/test_attr.c
@ -1016,7 +1015,6 @@ components/hal/esp32c3/include/hal/hmac_hal.h
components/hal/esp32c3/include/hal/hmac_ll.h
components/hal/esp32c3/include/hal/i2c_ll.h
components/hal/esp32c3/include/hal/interrupt_controller_ll.h
components/hal/esp32c3/include/hal/memprot_ll.h
components/hal/esp32c3/include/hal/mpu_ll.h
components/hal/esp32c3/include/hal/rtc_cntl_ll.h
components/hal/esp32c3/include/hal/rwdt_ll.h
@ -1143,7 +1141,6 @@ components/hal/include/hal/interrupt_controller_types.h
components/hal/include/hal/ledc_hal.h
components/hal/include/hal/mcpwm_hal.h
components/hal/include/hal/mcpwm_types.h
components/hal/include/hal/memprot_types.h
components/hal/include/hal/mpu_hal.h
components/hal/include/hal/mpu_types.h
components/hal/include/hal/pcnt_hal.h
@ -3234,7 +3231,6 @@ tools/test_apps/system/gdb_loadable_elf/main/hello_world_main.c
tools/test_apps/system/longjmp_test/app_test.py
tools/test_apps/system/longjmp_test/main/hello_world_main.c
tools/test_apps/system/memprot/app_test.py
tools/test_apps/system/memprot/main/esp32c3/test_memprot_main.c
tools/test_apps/system/memprot/main/esp32c3/test_panic.c
tools/test_apps/system/memprot/main/esp32s2/test_memprot_main.c
tools/test_apps/system/memprot/main/esp32s2/test_panic.c

View File

@ -89,6 +89,9 @@ components/app_trace/include/esp_sysview_trace.h
components/esp_gdbstub/include/esp_gdbstub.h
components/openssl/include/platform/ssl_pm.h
components/esp_hw_support/include/esp_memprot.h
components/esp_hw_support/include/esp_private/esp_memprot_internal.h
### Here are the files that use CONFIG_XXX values but don't include sdkconfig.h
#
components/heap/include/esp_heap_task_info.h

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32-S2 | ESP32-C3 |
| Supported Targets | ESP32-C3 | ESP32-S2 |
| ----------------- | -------- | -------- |

View File

@ -15,7 +15,8 @@ MEM_TEST_S2 = [
MEM_TEST_C3 = [
['IRAM0_SRAM', 'WRX'],
['DRAM0_SRAM', 'WR']
['DRAM0_SRAM', 'WR'],
['IRAM0_RTCFAST', 'WRX'],
]

View File

@ -1,4 +1,3 @@
config ESP_SYSTEM_MEMPROT_IRAM_TESTBUF
config ESP_SYSTEM_MEMPROT_TEST
bool
default y if IDF_TARGET_ESP32C3
default n if !IDF_TARGET_ESP32C3
default y

View File

@ -1,9 +1,17 @@
/* MEMPROT (PMS) testing code */
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "sdkconfig.h"
#include "esp32c3/memprot.h"
#include "esp_rom_sys.h"
#include <string.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "hal/memprot_types.h"
#include "soc/memprot_defs.h"
#include "esp_private/esp_memprot_internal.h"
#include "esp_memprot.h"
#include "esp_rom_sys.h"
/**
* ESP32C3 MEMORY PROTECTION MODULE TEST
@ -11,11 +19,13 @@
*
* In order to safely test all the memprot features, this test application uses memprot default settings
* plus proprietary testing buffers:
* - iram_test_buffer (.iram_end_test, 1kB) - all low region operations
* - dram_test_buffer (.dram0.data, 1kB) - all high region operations
* - s_iram_test_buffer (.iram_end_test, 1kB) - all IRAM/DRAM low region operations, test-only section
* - s_dram_test_buffer (.dram0.data, 1kB) - all IRAM/DRAM high region operations, standard section
* - s_rtc_text_test_buffer (.rtc_text_end_test, 1kB) - all RTCFAST low region operations, test-only section
* - s_rtc_data_test_buffer (.rtc.data, 1kB) - all RTCFAST high region operations, standard section
* Testing addresses are set to the middle of the testing buffers:
* - test_ptr_low = iram_test_buffer + 0x200
* - test_ptr_high = dram_test_buffer + 0x200
* - test_ptr_low = (s_iram_test_buffer | s_rtc_text_test_buffer) + 0x200
* - test_ptr_high = (s_dram_test_buffer | s_rtc_data_test_buffer) + 0x200
* Each operation is tested at both low & high region addresses.
* Each test result checked against expected status of PMS violation interrupt status and
* against expected value stored in the memory tested (where applicable)
@ -28,19 +38,31 @@
* | DRam0_PMS_0 |
* | |
* | |
* | - - - - - - - iram_test_buffer - - - - - - -| IRam0_line1_Split_addr
* | - - - - - - - s_iram_test_buffer - - - - - -| IRam0_line1_Split_addr
* DRam0_DMA_line0_Split_addr | -- test_ptr_low -- | =
* = =============================================== IRam0_line0_Split_addr
* DRam0_DMA_line1_Split_addr | | =
* | - - - - - - - dram_test_buffer - - - - - - -| IRam0_DRam0_Split_addr (main I/D)
* | - - - - - - - s_dram_test_buffer - - - - - --| IRam0_DRam0_Split_addr (main I/D)
* | -- test_ptr_high -- |
* | - - - - - - - - - - - - - - - - - - - - - - |
* | |
* | DRam0_PMS_1 = DRam0_PMS_2 = DRam0_PMS_3 |
* | IRam0_PMS_3 |
* | |
* | ... |
* | |
* =============================================== SOC_RTC_IRAM_LOW (0x50000000)
* | -- test_ptr_low -- |
* | - - - - - - s_rtc_text_test_buffer - - - - -| RtcFast_Split_addr (_rtc_text_end)
* | -- .rtc.dummy -- | (UNUSED - PADDING)
* 8 kB | - - - - - - - - - - - - - - - - - - - - - - | [_rtc_dummy_end = _rtc_force_fast_start]
* | -- .rtc.force_fast -- | (NOT USED IN THIS TEST)
* | - - - - - - s_rtc_data_test_buffer - - - - -| [_rtc_force_fast_end = _rtc_data_start]
* | -- test_ptr_high -- |
* | - - - - - - - - - - - - - - - - - - - - - - |
* =============================================== SOC_RTC_IRAM_HIGH (0x50001FFF)
* | |
* -----------------------------------------------
*
* For more details on PMS memprot settings see 'esp_memprot_set_prot_int' function in esp32c3/memprot.h
*/
@ -48,345 +70,519 @@
slli a0,a0,0x1
ret
*/
static uint8_t fnc_buff[] = { 0x06, 0x05, 0x82, 0x80 };
static uint8_t s_fnc_buff[] = { 0x06, 0x05, 0x82, 0x80 };
typedef int (*fnc_ptr)(int);
#define SRAM_TEST_BUFFER_SIZE 0x400
#define SRAM_TEST_OFFSET 0x200
static uint8_t __attribute__((section(".iram_end_test"))) iram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
static uint8_t dram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
static uint8_t __attribute__((section(".iram_end_test"))) s_iram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
static uint8_t __attribute__((section(".rtc_text_end_test"))) s_rtc_text_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
static uint8_t RTC_DATA_ATTR s_rtc_data_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
static uint8_t s_dram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
extern volatile bool g_override_illegal_instruction;
static void *test_memprot_addr_low(mem_type_prot_t mem_type)
static void *test_mprot_addr_low(esp_mprot_mem_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return (void*)((uint32_t)iram_test_buffer + SRAM_TEST_OFFSET);
case MEMPROT_DRAM0_SRAM:
return (void*)MAP_IRAM_TO_DRAM((uint32_t)iram_test_buffer + SRAM_TEST_OFFSET);
default:
abort();
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
return (void *)((uint32_t)s_iram_test_buffer + SRAM_TEST_OFFSET);
case MEMPROT_TYPE_DRAM0_SRAM:
return (void *)MAP_IRAM_TO_DRAM((uint32_t)s_iram_test_buffer + SRAM_TEST_OFFSET);
case MEMPROT_TYPE_IRAM0_RTCFAST:
return (void *)((uint32_t)s_rtc_text_test_buffer + SRAM_TEST_OFFSET);
default:
abort();
}
}
static void *test_memprot_addr_high(mem_type_prot_t mem_type)
static void *test_mprot_addr_high(esp_mprot_mem_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return (void*)MAP_DRAM_TO_IRAM((uint32_t)dram_test_buffer + SRAM_TEST_OFFSET);
case MEMPROT_DRAM0_SRAM:
return (void*)((uint32_t)dram_test_buffer + SRAM_TEST_OFFSET);
default:
abort();
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
return (void *)MAP_DRAM_TO_IRAM((uint32_t)s_dram_test_buffer + SRAM_TEST_OFFSET);
case MEMPROT_TYPE_DRAM0_SRAM:
return (void *)((uint32_t)s_dram_test_buffer + SRAM_TEST_OFFSET);
case MEMPROT_TYPE_IRAM0_RTCFAST:
return (void *)((uint32_t)s_rtc_data_test_buffer + SRAM_TEST_OFFSET);
default:
abort();
}
}
static void __attribute__((unused)) dump_status_register(mem_type_prot_t mem_type)
static void __attribute__((unused)) test_mprot_dump_status_register(esp_mprot_mem_t mem_type)
{
char operation = 0;
esp_rom_printf("FAULT [");
// IRAM fault: check instruction-fetch flag
if ( mem_type == MEMPROT_IRAM0_SRAM ) {
if ( esp_memprot_get_violate_loadstore(mem_type) ) {
operation = 'X';
}
void *addr;
esp_err_t err = esp_mprot_get_violate_addr(mem_type, &addr, NULL);
if (err == ESP_OK) {
esp_rom_printf("fault addr: 0x%08X,", (uint32_t)addr);
} else {
esp_rom_printf("fault addr: N/A (%s),", esp_err_to_name(err));
}
// W/R - common
if ( operation == 0 ) {
operation = esp_memprot_get_violate_wr(mem_type) == MEMPROT_PMS_OP_WRITE ? 'W' : 'R';
esp_mprot_pms_world_t world;
err = esp_mprot_get_violate_world(mem_type, &world, NULL);
if (err == ESP_OK) {
esp_rom_printf(" world: %s,", esp_mprot_pms_world_to_str(world));
} else {
esp_rom_printf(" world: N/A (%s),", esp_err_to_name(err));
}
esp_rom_printf(
" FAULT [ world: %u, fault addr: 0x%08X, operation: %c",
esp_memprot_get_violate_world(mem_type),
esp_memprot_get_violate_addr(mem_type),
operation
);
uint32_t oper;
err = esp_mprot_get_violate_operation(mem_type, &oper, NULL);
if (err == ESP_OK) {
esp_rom_printf(" operation: %s", esp_mprot_oper_type_to_str(oper));
} else {
esp_rom_printf(" operation: N/A (%s)", esp_err_to_name(err));
}
// DRAM/DMA fault: check byte-enables
if ( mem_type == MEMPROT_DRAM0_SRAM ) {
esp_rom_printf( ", byte en: 0x%08X", esp_memprot_get_violate_byte_en(mem_type) );
if (mem_type == MEMPROT_TYPE_DRAM0_SRAM) {
uint32_t byteen;
err = esp_mprot_get_violate_byte_enables(mem_type, &byteen, NULL);
if (err == ESP_OK) {
esp_rom_printf(", byte en: 0x%08X", byteen);
} else {
esp_rom_printf(", byte en: N/A (%s)", esp_err_to_name(err));
}
}
esp_rom_printf( " ]\n" );
esp_rom_printf( "]\n" );
}
static void check_test_result(mem_type_prot_t mem_type, bool expected_status)
static void test_mprot_check_test_result(esp_mprot_mem_t mem_type, bool expected_status)
{
bool test_result =
expected_status ?
!esp_memprot_get_violate_intr_on(mem_type) :
esp_memprot_get_violate_intr_on(mem_type);
esp_memp_intr_source_t memp_intr;
esp_err_t err = esp_mprot_get_active_intr(&memp_intr);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_get_active_intr() failed (%s) - test_mprot_check_test_result\n", esp_err_to_name(err));
return;
}
if ( test_result ) {
bool intr_on = memp_intr.mem_type == mem_type && memp_intr.core > -1;
bool test_result = expected_status ? !intr_on : intr_on;
if (test_result) {
esp_rom_printf("OK\n");
} else {
dump_status_register(mem_type);
test_mprot_dump_status_register(mem_type);
}
}
static void test_memprot_get_permissions(bool low, mem_type_prot_t mem_type, bool *read, bool *write, bool *exec )
static void test_mprot_clear_all_interrupts(void)
{
bool _r, _w, _x;
pms_area_t area = MEMPROT_PMS_AREA_NONE;
esp_err_t err = esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM, NULL);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM) failed (%s) - test_mprot_clear_all_interrupts\n", esp_err_to_name(err));
}
err = esp_mprot_monitor_clear_intr(MEMPROT_TYPE_DRAM0_SRAM, NULL);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_monitor_clear_intr(MEMPROT_TYPE_DRAM0_SRAM) failed (%s) - test_mprot_clear_all_interrupts\n", esp_err_to_name(err));
}
err = esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_RTCFAST, NULL);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_RTCFAST) failed (%s) - test_mprot_clear_all_interrupts\n", esp_err_to_name(err));
}
}
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
area = low ? MEMPROT_IRAM0_PMS_AREA_2 : MEMPROT_IRAM0_PMS_AREA_3;
esp_memprot_iram_get_pms_area(area, &_r, &_w, &_x);
static void test_mprot_get_permissions(bool low, esp_mprot_mem_t mem_type, bool *read, bool *write, bool *exec )
{
esp_mprot_pms_area_t area;
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM:
area = low ? MEMPROT_PMS_AREA_IRAM0_2 : MEMPROT_PMS_AREA_IRAM0_3;
break;
case MEMPROT_DRAM0_SRAM:
area = low ? MEMPROT_DRAM0_PMS_AREA_0 : MEMPROT_DRAM0_PMS_AREA_1;
esp_memprot_dram_get_pms_area(area, &_r, &_w);
case MEMPROT_TYPE_DRAM0_SRAM:
area = low ? MEMPROT_PMS_AREA_DRAM0_0 : MEMPROT_PMS_AREA_DRAM0_1;
break;
case MEMPROT_TYPE_IRAM0_RTCFAST:
area = low ? MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO : MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI;
break;
default:
abort();
}
if ( read ) {
*read = _r;
uint32_t flags;
esp_err_t err = esp_mprot_get_pms_area(area, &flags);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_get_pms_area() failed (%s) - test_mprot_get_permissions\n", esp_err_to_name(err));
return;
}
if ( write ) {
*write = _w;
if (read) {
*read = flags & MEMPROT_OP_READ;
}
if ( exec ) {
*exec = _x;
if (write) {
*write = flags & MEMPROT_OP_WRITE;
}
if (exec) {
*exec = flags & MEMPROT_OP_EXEC;
}
}
static void test_memprot_set_permissions(bool low, mem_type_prot_t mem_type, bool read, bool write, bool *exec)
static void test_mprot_set_permissions(bool low, esp_mprot_mem_t mem_type, bool read, bool write, bool *exec)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM: {
bool _ex;
if (!exec) {
test_memprot_get_permissions( low, mem_type, NULL, NULL, &_ex);
exec = &_ex;
}
esp_err_t err;
uint32_t flags = 0;
if (read) {
flags |= MEMPROT_OP_READ;
}
if (write) {
flags |= MEMPROT_OP_WRITE;
}
if (exec && *exec) {
flags |= MEMPROT_OP_EXEC;
}
switch (mem_type) {
case MEMPROT_TYPE_IRAM0_SRAM: {
if (low) {
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_0, read, write, *exec);
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_1, read, write, *exec);
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_2, read, write, *exec);
if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_0, flags)) != ESP_OK) {
break;
}
if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_1, flags)) != ESP_OK) {
break;
}
if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_2, flags)) != ESP_OK) {
break;
}
} else {
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_3, read, write, *exec);
if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_3, flags)) != ESP_OK) {
break;
}
}
}
break;
case MEMPROT_DRAM0_SRAM: {
case MEMPROT_TYPE_DRAM0_SRAM: {
if (low) {
esp_memprot_dram_set_pms_area( MEMPROT_DRAM0_PMS_AREA_0, read, write );
if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_0, flags)) != ESP_OK) {
break;
}
} else {
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_1, read, write);
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_2, read, write);
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_3, read, write);
if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_1, flags)) != ESP_OK) {
break;
}
if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_2, flags)) != ESP_OK) {
break;
}
if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_3, flags)) != ESP_OK) {
break;
}
}
}
break;
case MEMPROT_TYPE_IRAM0_RTCFAST: {
if (low) {
if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO, flags)) != ESP_OK) {
break;
}
} else {
if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI, flags)) != ESP_OK) {
break;
}
}
}
break;
default:
abort();
}
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_set_pms_area() failed (%s) - test_mprot_set_permissions\n", esp_err_to_name(err));
}
}
static void test_memprot_read(mem_type_prot_t mem_type)
static void test_mprot_read(esp_mprot_mem_t mem_type)
{
//get current READ & WRITE permission settings
test_mprot_clear_all_interrupts();
//get current permission settings
bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high;
test_memprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_low : NULL);
test_memprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_high : NULL);
bool is_exec_mem = mem_type & MEMPROT_TYPE_IRAM0_ANY;
test_mprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, is_exec_mem ? &exec_perm_low : NULL);
test_mprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, is_exec_mem ? &exec_perm_high : NULL);
//get testing pointers for low & high regions
volatile uint32_t *ptr_low = test_memprot_addr_low(mem_type);
volatile uint32_t *ptr_high = test_memprot_addr_high(mem_type);
volatile uint32_t *ptr_low = test_mprot_addr_low(mem_type);
volatile uint32_t *ptr_high = test_mprot_addr_high(mem_type);
const uint32_t test_val = 100;
//temporarily allow WRITE for setting the test values
esp_memprot_set_monitor_en(mem_type, false);
test_memprot_set_permissions(true, mem_type, read_perm_low, true, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_low : NULL);
test_memprot_set_permissions(false, mem_type, read_perm_high, true, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_high : NULL);
esp_err_t err = esp_mprot_set_monitor_en(mem_type, false);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_read\n", esp_err_to_name(err));
return;
}
test_mprot_set_permissions(true, mem_type, read_perm_low, true, is_exec_mem ? &exec_perm_low : NULL);
test_mprot_set_permissions(false, mem_type, read_perm_high, true, is_exec_mem ? &exec_perm_high : NULL);
//save testing values
*ptr_low = test_val;
*ptr_high = test_val + 1;
test_memprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_low : NULL);
test_memprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_high : NULL);
esp_memprot_set_monitor_en(mem_type, true);
//restore current PMS settings
test_mprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, is_exec_mem ? &exec_perm_low : NULL);
test_mprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, is_exec_mem ? &exec_perm_high : NULL);
//reenable monitoring
err = esp_mprot_set_monitor_en(mem_type, true);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_read\n", esp_err_to_name(err));
return;
}
//perform READ test in low region
esp_rom_printf("%s read low: ", esp_memprot_mem_type_to_str(mem_type));
esp_memprot_monitor_clear_intr(mem_type);
esp_rom_printf("%s read low: ", esp_mprot_mem_type_to_str(mem_type));
err = esp_mprot_monitor_clear_intr(mem_type, NULL);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_read\n", esp_err_to_name(err));
return;
}
volatile uint32_t val = *ptr_low;
if ( read_perm_low && val != test_val ) {
if (read_perm_low && val != test_val) {
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val );
dump_status_register(mem_type);
test_mprot_dump_status_register(mem_type);
} else {
check_test_result(mem_type, read_perm_low);
test_mprot_check_test_result(mem_type, read_perm_low);
}
//perform READ in high region
esp_rom_printf("%s read high: ", esp_memprot_mem_type_to_str(mem_type));
esp_memprot_monitor_clear_intr(mem_type);
esp_rom_printf("%s read high: ", esp_mprot_mem_type_to_str(mem_type));
err = esp_mprot_monitor_clear_intr(mem_type, NULL);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_read\n", esp_err_to_name(err));
return;
}
val = *ptr_high;
if ( read_perm_high && val != (test_val + 1) ) {
if (read_perm_high && val != (test_val + 1)) {
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
dump_status_register(mem_type);
test_mprot_dump_status_register(mem_type);
} else {
check_test_result(mem_type, read_perm_high);
test_mprot_check_test_result(mem_type, read_perm_high);
}
}
static void test_memprot_write(mem_type_prot_t mem_type)
static void test_mprot_write(esp_mprot_mem_t mem_type)
{
test_mprot_clear_all_interrupts();
//get current READ & WRITE permission settings
bool write_perm_low, write_perm_high, read_perm_low, read_perm_high;
test_memprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, NULL);
test_memprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, NULL);
bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high;
bool is_exec_mem = mem_type & MEMPROT_TYPE_IRAM0_ANY;
test_mprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, is_exec_mem ? &exec_perm_low : NULL);
test_mprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, is_exec_mem ? &exec_perm_high : NULL);
//ensure READ enabled
esp_memprot_set_monitor_en(mem_type, false);
test_memprot_set_permissions(true, mem_type, true, write_perm_low, NULL);
test_memprot_set_permissions(false, mem_type, true, write_perm_high, NULL);
esp_memprot_set_monitor_en(mem_type, true);
esp_err_t err = esp_mprot_set_monitor_en(mem_type, false);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err));
return;
}
//get testing pointers for low & high regions
volatile uint32_t *ptr_low = test_memprot_addr_low(mem_type);
volatile uint32_t *ptr_high = test_memprot_addr_high(mem_type);
test_mprot_set_permissions(true, mem_type, true, write_perm_low, is_exec_mem ? &exec_perm_low : NULL);
test_mprot_set_permissions(false, mem_type, true, write_perm_high, is_exec_mem ? &exec_perm_high : NULL);
err = esp_mprot_set_monitor_en(mem_type, true);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err));
return;
}
volatile uint32_t *ptr_low = test_mprot_addr_low(mem_type);
volatile uint32_t *ptr_high = test_mprot_addr_high(mem_type);
const uint32_t test_val = 10;
//perform WRITE in low region
esp_rom_printf("%s write low: ", esp_memprot_mem_type_to_str(mem_type));
esp_memprot_monitor_clear_intr(mem_type);
esp_rom_printf("%s write low: ", esp_mprot_mem_type_to_str(mem_type));
err = esp_mprot_monitor_clear_intr(mem_type, NULL);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_write\n", esp_err_to_name(err));
return;
}
volatile uint32_t val = 0;
*ptr_low = test_val;
val = *ptr_low;
if ( val != test_val && write_perm_low ) {
if (val != test_val && write_perm_low) {
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
dump_status_register(mem_type);
test_mprot_dump_status_register(mem_type);
} else {
check_test_result(mem_type, write_perm_low);
test_mprot_check_test_result(mem_type, write_perm_low);
}
//perform WRITE in high region
esp_rom_printf("%s write high: ", esp_memprot_mem_type_to_str(mem_type));
esp_memprot_monitor_clear_intr(mem_type);
esp_rom_printf("%s write high: ", esp_mprot_mem_type_to_str(mem_type));
err = esp_mprot_monitor_clear_intr(mem_type, NULL);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_write\n", esp_err_to_name(err));
return;
}
val = 0;
*ptr_high = test_val + 1;
val = *ptr_high;
if ( val != (test_val + 1) && write_perm_high ) {
if (val != (test_val + 1) && write_perm_high) {
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
dump_status_register(mem_type);
test_mprot_dump_status_register(mem_type);
} else {
check_test_result(mem_type, write_perm_high);
test_mprot_check_test_result(mem_type, write_perm_high);
}
//restore original permissions
esp_memprot_set_monitor_en(mem_type, false);
test_memprot_set_permissions(true, mem_type, true, read_perm_low, NULL);
test_memprot_set_permissions(false, mem_type, true, read_perm_high, NULL);
esp_memprot_set_monitor_en(mem_type, true);
err = esp_mprot_set_monitor_en(mem_type, false);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err));
return;
}
test_mprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, is_exec_mem ? &exec_perm_low : NULL);
test_mprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, is_exec_mem ? &exec_perm_high : NULL);
err = esp_mprot_set_monitor_en(mem_type, true);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err));
return;
}
}
static void test_memprot_exec(mem_type_prot_t mem_type)
static void test_mprot_exec(esp_mprot_mem_t mem_type)
{
if ( mem_type != MEMPROT_IRAM0_SRAM ) {
if (!(mem_type & MEMPROT_TYPE_IRAM0_ANY)) {
esp_rom_printf("Error: EXEC test available only for IRAM access.\n" );
return;
}
test_mprot_clear_all_interrupts();
bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high;
//temporarily enable READ/WRITE
test_memprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, &exec_perm_low);
test_memprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, &exec_perm_high);
esp_memprot_set_monitor_en(mem_type, false);
test_memprot_set_permissions(true, mem_type, true, true, &exec_perm_low);
test_memprot_set_permissions(false, mem_type, true, true, &exec_perm_high);
esp_memprot_set_monitor_en(mem_type, true);
test_mprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, &exec_perm_low);
test_mprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, &exec_perm_high);
esp_err_t err = esp_mprot_set_monitor_en(mem_type, false);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err));
return;
}
test_mprot_set_permissions(true, mem_type, true, true, &exec_perm_low);
test_mprot_set_permissions(false, mem_type, true, true, &exec_perm_high);
err = esp_mprot_set_monitor_en(mem_type, true);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err));
return;
}
//get testing pointers for low & high regions, zero 8B slot
void *fnc_ptr_low = test_memprot_addr_low(mem_type);
void *fnc_ptr_high = test_memprot_addr_high(mem_type);
memset( fnc_ptr_low, 0, 8);
memset( fnc_ptr_high, 0, 8);
void *fnc_ptr_low = test_mprot_addr_low(mem_type);
void *fnc_ptr_high = test_mprot_addr_high(mem_type);
memset(fnc_ptr_low, 0, 8);
memset(fnc_ptr_high, 0, 8);
//inject the code to both low & high segments
memcpy( (void *)fnc_ptr_low, (const void *)fnc_buff, sizeof(fnc_buff) );
memcpy( (void *)fnc_ptr_high, (const void *)fnc_buff, sizeof(fnc_buff) );
memcpy((void *)fnc_ptr_low, (const void *)s_fnc_buff, sizeof(s_fnc_buff));
memcpy((void *)fnc_ptr_high, (const void *)s_fnc_buff, sizeof(s_fnc_buff));
uint32_t res = 0;
//LOW REGION: clear the intr flag & try to execute the code injected
esp_rom_printf("%s exec low: ", esp_memprot_mem_type_to_str(mem_type));
esp_memprot_monitor_clear_intr(mem_type);
esp_rom_printf("%s exec low: ", esp_mprot_mem_type_to_str(mem_type));
err = esp_mprot_monitor_clear_intr(mem_type, NULL);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_exec\n", esp_err_to_name(err));
return;
}
fnc_ptr fnc = (fnc_ptr)fnc_ptr_low;
g_override_illegal_instruction = true;
res = fnc( 5 );
res = fnc(5);
g_override_illegal_instruction = false;
//check results
bool fnc_call_ok = res == 10;
if ( fnc_call_ok ) {
check_test_result(mem_type, exec_perm_low);
if (fnc_call_ok) {
test_mprot_check_test_result(mem_type, exec_perm_low);
} else {
if ( !exec_perm_low ) {
check_test_result(mem_type, false);
if (!exec_perm_low) {
test_mprot_check_test_result(mem_type, false);
} else {
esp_rom_printf(" FAULT [injected code not executed]\n");
}
}
//HIGH REGION: clear the intr-on flag & try to execute the code injected
esp_rom_printf("%s exec high: ", esp_memprot_mem_type_to_str(mem_type));
esp_memprot_monitor_clear_intr(mem_type);
esp_rom_printf("%s exec high: ", esp_mprot_mem_type_to_str(mem_type));
err = esp_mprot_monitor_clear_intr(mem_type, NULL);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_exec\n", esp_err_to_name(err));
return;
}
fnc = (fnc_ptr)fnc_ptr_high;
g_override_illegal_instruction = true;
res = fnc( 6 );
res = fnc(6);
g_override_illegal_instruction = false;
fnc_call_ok = res == 12;
if ( fnc_call_ok ) {
check_test_result(mem_type, exec_perm_high);
if (fnc_call_ok) {
test_mprot_check_test_result(mem_type, exec_perm_high);
} else {
if ( !exec_perm_high ) {
check_test_result(mem_type, false);
if (!exec_perm_high) {
test_mprot_check_test_result(mem_type, false);
} else {
esp_rom_printf(" FAULT [injected code not executed]\n");
}
}
//restore original permissions
esp_memprot_set_monitor_en(mem_type, false);
test_memprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, &exec_perm_low);
test_memprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, &exec_perm_high);
esp_memprot_set_monitor_en(mem_type, true);
err = esp_mprot_set_monitor_en(mem_type, false);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err));
return;
}
test_mprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, &exec_perm_low);
test_mprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, &exec_perm_high);
err = esp_mprot_set_monitor_en(mem_type, true);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err));
return;
}
}
/* ********************************************************************************************
* main test runner
*/
void app_main(void)
{
esp_memprot_set_prot_int(false, false, NULL, NULL);
esp_memp_config_t memp_cfg = ESP_MEMPROT_DEFAULT_CONFIG();
memp_cfg.invoke_panic_handler = false;
memp_cfg.lock_feature = false;
test_memprot_read(MEMPROT_IRAM0_SRAM);
test_memprot_write(MEMPROT_IRAM0_SRAM);
test_memprot_exec(MEMPROT_IRAM0_SRAM);
esp_err_t err = esp_mprot_set_prot(&memp_cfg);
if (err != ESP_OK) {
esp_rom_printf("Error: esp_mprot_set_prot() failed (%s) - app_main\n", esp_err_to_name(err));
return;
}
test_memprot_read(MEMPROT_DRAM0_SRAM);
test_memprot_write(MEMPROT_DRAM0_SRAM);
test_mprot_read(MEMPROT_TYPE_IRAM0_SRAM);
test_mprot_write(MEMPROT_TYPE_IRAM0_SRAM);
test_mprot_exec(MEMPROT_TYPE_IRAM0_SRAM);
test_mprot_read(MEMPROT_TYPE_DRAM0_SRAM);
test_mprot_write(MEMPROT_TYPE_DRAM0_SRAM);
test_mprot_read(MEMPROT_TYPE_IRAM0_RTCFAST);
test_mprot_write(MEMPROT_TYPE_IRAM0_RTCFAST);
test_mprot_exec(MEMPROT_TYPE_IRAM0_RTCFAST);
}

View File

@ -1 +0,0 @@
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n

View File

@ -0,0 +1,3 @@
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=n
CONFIG_ESP_SYSTEM_MEMPROT_TEST=y