mirror of
https://github.com/espressif/esp-idf
synced 2025-03-10 01:29:21 -04:00
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:
parent
7c7fbb1fd0
commit
dd938eb952
@ -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})
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
194
components/esp_hw_support/include/esp_memprot.h
Normal file
194
components/esp_hw_support/include/esp_memprot.h
Normal 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
|
28
components/esp_hw_support/include/esp_memprot_err.h
Normal file
28
components/esp_hw_support/include/esp_memprot_err.h
Normal 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
|
36
components/esp_hw_support/include/esp_memprot_types.h
Normal file
36
components/esp_hw_support/include/esp_memprot_types.h
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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}")
|
||||
|
869
components/esp_hw_support/port/esp32c3/esp_memprot.c
Normal file
869
components/esp_hw_support/port/esp32c3/esp_memprot.c
Normal 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;
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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}")
|
||||
|
215
components/esp_hw_support/port/esp32h2/esp_memprot.c
Normal file
215
components/esp_hw_support/port/esp32h2/esp_memprot.c
Normal 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;
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
215
components/esp_hw_support/port/esp32s3/esp_memprot.c
Normal file
215
components/esp_hw_support/port/esp32s3/esp_memprot.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
63
components/esp_hw_support/port/esp_memprot_conv.c
Normal file
63
components/esp_hw_support/port/esp_memprot_conv.c
Normal 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";
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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 = ®s;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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";
|
||||
|
@ -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};
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
100
components/soc/esp32c3/include/soc/memprot_defs.h
Normal file
100
components/soc/esp32c3/include/soc/memprot_defs.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32-S2 | ESP32-C3 |
|
||||
| Supported Targets | ESP32-C3 | ESP32-S2 |
|
||||
| ----------------- | -------- | -------- |
|
||||
|
@ -15,7 +15,8 @@ MEM_TEST_S2 = [
|
||||
|
||||
MEM_TEST_C3 = [
|
||||
['IRAM0_SRAM', 'WRX'],
|
||||
['DRAM0_SRAM', 'WR']
|
||||
['DRAM0_SRAM', 'WR'],
|
||||
['IRAM0_RTCFAST', 'WRX'],
|
||||
]
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n
|
3
tools/test_apps/system/memprot/sdkconfig.defaults
Normal file
3
tools/test_apps/system/memprot/sdkconfig.defaults
Normal file
@ -0,0 +1,3 @@
|
||||
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y
|
||||
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=n
|
||||
CONFIG_ESP_SYSTEM_MEMPROT_TEST=y
|
Loading…
x
Reference in New Issue
Block a user