Compare commits

..

9 Commits

Author SHA1 Message Date
Angus Gratton
ee899cb2aa Merge branch 'feature/ver-4.2' into 'master'
global: bump version to 4.2

See merge request espressif/esp-idf!7335
2020-01-15 13:07:59 +08:00
Ivan Grokhotkov
34fd845242 Merge branch 'bugfix/update_kconfiglib' into 'master'
tools: Update kconfiglib to 13.7.1

Closes IDF-1299

See merge request espressif/esp-idf!7307
2020-01-15 12:11:47 +08:00
Ivan Grokhotkov
80d7db9466 Merge branch 'bugfix/esp32s2_mac_addr_allocation' into 'master'
esp32s2 mac address allocation

Closes IDF-1191

See merge request espressif/esp-idf!7286
2020-01-15 11:58:14 +08:00
Ivan Grokhotkov
da8c06eafc Merge branch 'doc/minor_cxx_additions' into 'master'
doc: small changes for cxx code style

See merge request espressif/esp-idf!7210
2020-01-15 11:36:40 +08:00
Jiang Jiang Jian
5f803b8283 Merge branch 'bugfix/enable_ipv6_address_autoconfig' into 'master'
lw-ip:  Enable IPv6 stateless address autoconfiguration

Closes WIFI-1237

See merge request espressif/esp-idf!6313
2020-01-15 11:27:56 +08:00
Ivan Grokhotkov
5466ff3f4d global: bump version to 4.2 2020-01-15 10:22:22 +08:00
morris
e1f9b283bc esp32s2: mac addr allocation 2020-01-14 15:19:38 +08:00
xiehang
c0148ef1e8 lwip: Enable IPv6 stateless address autoconfiguration 2020-01-14 07:15:26 +00:00
Jakob Hasse
9a10c1bccd doc: small changes for cxx code style 2020-01-07 15:13:41 +08:00
1795 changed files with 71537 additions and 74871 deletions

View File

@@ -38,7 +38,7 @@ If the issue cannot be solved after the steps before, please follow these instru
- Development Kit: [ESP32-Wrover-Kit|ESP32-DevKitC|ESP32-PICO-Kit|ESP32-LyraT|ESP32-LyraTD-MSC|none]
- Kit version (for WroverKit/PicoKit/DevKitC): [v1|v2|v3|v4]
- Module or chip used: [ESP32-WROOM-32|ESP32-WROOM-32D|ESP32-WROOM-32U|ESP32-WROVER|ESP32-WROVER-I|ESP32-WROVER-B|ESP32-WROVER-IB|ESP32-SOLO-1|ESP32-PICO-D4|ESP32]
- IDF version (run ``git describe`` to find it):
- IDF version (run ``git describe --tags`` to find it):
// v3.2-dev-1148-g96cd3b75c
- Build System: [Make|CMake|idf.py]
- Compiler version (run ``xtensa-esp32-elf-gcc --version`` to find it):

View File

@@ -1,75 +0,0 @@
name: docker
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
on:
push:
branches:
- 'master'
- 'release/*'
tags:
- 'v*.*'
env:
# Platforms to build the image for
BUILD_PLATFORMS: linux/amd64
DOCKERHUB_REPO: ${{ github.repository_owner }}/idf
jobs:
docker:
# Disable the job in forks
if: ${{ github.repository_owner == 'espressif' }}
runs-on: ubuntu-latest
steps:
# Depending on the branch/tag, set CLONE_BRANCH_OR_TAG variable (used in the Dockerfile
# as a build arg) and TAG_NAME (used when tagging the image).
#
# The following 3 steps cover the alternatives (tag, release branch, master branch):
- name: Set variables (tags)
if: ${{ github.ref_type == 'tag' }}
run: |
echo "CLONE_BRANCH_OR_TAG=$GITHUB_REF_NAME" >> $GITHUB_ENV
echo "TAG_NAME=$GITHUB_REF_NAME" >> $GITHUB_ENV
- name: Set variables (release branches)
if: ${{ github.ref_type == 'branch' && startsWith(github.ref_name, 'release/') }}
run: |
echo "CLONE_BRANCH_OR_TAG=$GITHUB_REF_NAME" >> $GITHUB_ENV
echo "TAG_NAME=release-${GITHUB_REF_NAME##release/}" >> $GITHUB_ENV
- name: Set variables (main branch)
if: ${{ github.ref_type == 'branch' && github.ref_name == 'master' }}
run: |
echo "CLONE_BRANCH_OR_TAG=master" >> $GITHUB_ENV
echo "TAG_NAME=latest" >> $GITHUB_ENV
# Display the variables set above, just in case.
- name: Check variables
run: |
echo "CLONE_BRANCH_OR_TAG: $CLONE_BRANCH_OR_TAG"
echo "CHECKOUT_REF: $CHECKOUT_REF"
echo "TAG_NAME: $TAG_NAME"
# The following steps are the standard boilerplate from
# https://github.com/marketplace/actions/build-and-push-docker-images
- name: Checkout
uses: actions/checkout@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up QEMU for multiarch builds
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build and push
uses: docker/build-push-action@v3
with:
context: tools/docker
push: true
tags: ${{ env.DOCKERHUB_REPO }}:${{ env.TAG_NAME }}
platforms: ${{ env.BUILD_PLATFORMS }}
build-args: |
IDF_CLONE_URL=${{ github.server_url }}/${{ github.repository }}.git
IDF_CLONE_BRANCH_OR_TAG=${{ env.CLONE_BRANCH_OR_TAG }}

View File

@@ -1,17 +0,0 @@
name: Create zip file with recursive source clone for release
on:
push:
tags:
- v*
jobs:
release_zips:
name: Create release zip file
runs-on: ubuntu-20.04
steps:
- name: Create a recursive clone source zip
uses: espressif/github-actions/release_zips@master
env:
RELEASE_PROJECT_NAME: ESP-IDF
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -8,18 +8,6 @@ stages:
- deploy
- post_check
# pipelines will not be created in such two cases:
# 1. MR push
# 2. push not on "master/release" branches, and not tagged
# This behavior could be changed after the `rules: changes` feature is implemented
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: never
- if: '$CI_COMMIT_REF_NAME != "master" && $CI_COMMIT_BRANCH !~ /^release\/v/ && $CI_COMMIT_TAG !~ /^v\d+\.\d+(\.\d+)?($|-)/ && $CI_PIPELINE_SOURCE == "push"'
when: never
- when: always
variables:
# System environment
@@ -28,8 +16,9 @@ variables:
# GitLab-CI environment
# XXX_ATTEMPTS variables (https://docs.gitlab.com/ce/ci/yaml/README.html#job-stages-attempts) are not defined here.
# Use values from "CI / CD Settings" - "Variables".
# more attempts for more robust
GET_SOURCES_ATTEMPTS: "10"
ARTIFACT_DOWNLOAD_ATTEMPTS: "10"
# GIT_STRATEGY is not defined here.
# Use an option from "CI / CD Settings" - "General pipelines".
@@ -47,21 +36,19 @@ variables:
UNIT_TEST_BUILD_SYSTEM: cmake
EXAMPLE_TEST_BUILD_SYSTEM: cmake
# IDF environment
IDF_PATH: "$CI_PROJECT_DIR"
BATCH_BUILD: "1"
V: "0"
APPLY_BOT_FILTER_SCRIPT: "$CI_PROJECT_DIR/tools/ci/apply_bot_filter.py"
CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py"
CUSTOM_TOOLCHAIN_PATH: "/opt/xtensa-custom"
# Docker images
# Docker images
BOT_DOCKER_IMAGE_TAG: ":latest"
# target test config file, used by assign test job
# target test config file, used by assign test job
CI_TARGET_TEST_CONFIG_FILE: "$CI_PROJECT_DIR/tools/ci/config/target-test.yml"
# target test repo parameters
TEST_ENV_CONFIG_REPO: "https://gitlab-ci-token:${BOT_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/qa/ci-test-runner-configs.git"
# Versioned esp-idf-doc env image to use for all document building jobs
ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env:v7"
@@ -69,6 +56,25 @@ variables:
.apply_bot_filter: &apply_bot_filter
python $APPLY_BOT_FILTER_SCRIPT || exit 0
.setup_custom_toolchain: &setup_custom_toolchain |
if [ "$IDF_XTENSA_TOOLCHAIN_URL" ] ; then
echo "Use a custom toolchain: ${IDF_XTENSA_TOOLCHAIN_URL:-Unknown}"
rm -rf "$CUSTOM_TOOLCHAIN_PATH" &&
mkdir -p -v "$CUSTOM_TOOLCHAIN_PATH" &&
pushd "$CUSTOM_TOOLCHAIN_PATH" &&
curl -sSL -o xtensa-custom.xxx "$IDF_XTENSA_TOOLCHAIN_URL" &&
ls -l xtensa-custom.xxx &&
tar xf xtensa-custom.xxx --strip-components 1 &&
ls -l . &&
popd
PATH=$CUSTOM_TOOLCHAIN_PATH/bin:$PATH
export PATH
fi
.cleanup_custom_toolchain: &cleanup_custom_toolchain |
echo "Cleaning up $CUSTOM_TOOLCHAIN_PATH"
rm -rf "$CUSTOM_TOOLCHAIN_PATH"
.setup_tools_unless_target_test: &setup_tools_unless_target_test |
if [[ "$SETUP_TOOLS" == "1" || "$CI_JOB_STAGE" != "target_test" ]]; then
tools/idf_tools.py --non-interactive install && eval "$(tools/idf_tools.py --non-interactive export)" || exit 1
@@ -78,8 +84,6 @@ variables:
python $SUBMODULE_FETCH_TOOL -s $SUBMODULES_TO_FETCH
before_script:
- source tools/ci/utils.sh
- is_based_on_commits $REQUIRED_ANCESTOR_COMMITS
- source tools/ci/setup_python.sh
# apply bot filter in before script
- *apply_bot_filter
@@ -92,20 +96,22 @@ before_script:
- echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
# Set some options and environment for CI
- source tools/ci/configure_ci_environment.sh
- *setup_tools_unless_target_test
- *fetch_submodules
- *setup_custom_toolchain
# used for check scripts which we want to run unconditionally
.before_script_lesser_nofilter:
variables:
GIT_SUBMODULE_STRATEGY: none
before_script:
- echo "Not setting up GitLab key, not fetching submodules, not applying bot filter"
- source tools/ci/utils.sh
- is_based_on_commits $REQUIRED_ANCESTOR_COMMITS
- source tools/ci/setup_python.sh
- source tools/ci/configure_ci_environment.sh
- *setup_custom_toolchain
# used for everything else where we want to do no prep, except for bot filter
.before_script_lesser:
@@ -113,12 +119,14 @@ before_script:
GIT_SUBMODULE_STRATEGY: none
before_script:
- echo "Not setting up GitLab key, not fetching submodules"
- source tools/ci/utils.sh
- is_based_on_commits $REQUIRED_ANCESTOR_COMMITS
- source tools/ci/setup_python.sh
# apply bot filter in before script
- *apply_bot_filter
- source tools/ci/configure_ci_environment.sh
- *setup_custom_toolchain
after_script:
- *cleanup_custom_toolchain
.check_job_template:
stage: pre_check
@@ -142,27 +150,10 @@ before_script:
- macos_shell
dependencies: []
before_script:
- source tools/ci/utils.sh
- is_based_on_commits $REQUIRED_ANCESTOR_COMMITS
- *apply_bot_filter
- export IDF_TOOLS_PATH="${HOME}/.espressif_runner_${CI_RUNNER_ID}_${CI_CONCURRENT_ID}"
- $IDF_PATH/tools/idf_tools.py install-python-env
# On macOS, these tools need to be installed
- $IDF_PATH/tools/idf_tools.py --non-interactive install cmake ninja
# This adds tools (compilers) and the version-specific Python environment to PATH
- *setup_tools_unless_target_test
# Install packages required by CI scripts into IDF Python environment
- pip install -r $IDF_PATH/tools/ci/python_packages/ttfw_idf/requirements.txt
- *setup_custom_toolchain
- source tools/ci/configure_ci_environment.sh
# Part of tools/ci/setup_python.sh; we don't use pyenv on macOS, so can't run the rest of the script.
- export PYTHONPATH="$IDF_PATH/tools:$IDF_PATH/tools/ci/python_packages:$PYTHONPATH"
- *fetch_submodules
default:
retry:
max: 2
# In case of a runner failure we could hop to another one, or a network error could go away.
when: runner_system_failure
include:
- '/tools/ci/config/pre_check.yml'

View File

@@ -1,6 +0,0 @@
# For the syntax of this file, see:
#
# https://docs.gitlab.com/ee/user/project/code_owners.html#the-syntax-of-code-owners-files
#
* @esp-idf-codeowners/all-maintainers

View File

@@ -1,12 +1,6 @@
cmake_minimum_required(VERSION 3.5)
project(esp-idf C CXX ASM)
if(CMAKE_CURRENT_LIST_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "Current directory '${CMAKE_CURRENT_LIST_DIR}' is not buildable. "
"Change directories to one of the example projects in '${CMAKE_CURRENT_LIST_DIR}/examples' and try "
"again.")
endif()
unset(compile_options)
unset(c_compile_options)
unset(cxx_compile_options)
@@ -16,31 +10,15 @@ unset(link_options)
# Add the following build specifications here, since these seem to be dependent
# on config values on the root Kconfig.
if(NOT BOOTLOADER_BUILD)
if(CONFIG_COMPILER_OPTIMIZATION_SIZE)
list(APPEND compile_options "-Os")
list(APPEND compile_options "-freorder-blocks")
elseif(CONFIG_COMPILER_OPTIMIZATION_DEFAULT)
list(APPEND compile_options "-Og")
elseif(CONFIG_COMPILER_OPTIMIZATION_NONE)
list(APPEND compile_options "-O0")
elseif(CONFIG_COMPILER_OPTIMIZATION_PERF)
list(APPEND compile_options "-O2")
endif()
else() # BOOTLOADER_BUILD
if(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE)
list(APPEND compile_options "-Os")
list(APPEND compile_options "-freorder-blocks")
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG)
list(APPEND compile_options "-Og")
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE)
list(APPEND compile_options "-O0")
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF)
list(APPEND compile_options "-O2")
endif()
if(CONFIG_COMPILER_OPTIMIZATION_SIZE)
list(APPEND compile_options "-Os")
list(APPEND compile_options "-freorder-blocks")
elseif(CONFIG_COMPILER_OPTIMIZATION_DEFAULT)
list(APPEND compile_options "-Og")
elseif(CONFIG_COMPILER_OPTIMIZATION_NONE)
list(APPEND compile_options "-O0")
elseif(CONFIG_COMPILER_OPTIMIZATION_PERF)
list(APPEND compile_options "-O2")
endif()

12
Kconfig
View File

@@ -46,11 +46,12 @@ mainmenu "Espressif IoT Development Framework Configuration"
a crosstool-ng gcc setup that is in your PATH.
config SDK_PYTHON
string "Python interpreter"
string "Python 2 interpreter"
depends on !IDF_CMAKE
default "python"
help
The executable name/path that is used to run python.
The executable name/path that is used to run python. On some systems Python 2.x
may need to be invoked as python2.
(Note: This option is used with the legacy GNU Make build system only.)
@@ -115,7 +116,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
mon reset halt
# Run to a specific point in ROM code,
# where most of initialization is complete.
thb *0x40007d54
thb *0x40007901
c
# Load the application into RAM
load
@@ -171,7 +172,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
prompt "Optimization Level"
default COMPILER_OPTIMIZATION_DEFAULT
help
This option sets compiler optimization level (gcc -O argument) for the app.
This option sets compiler optimization level (gcc -O argument).
- The "Default" setting will add the -0g flag to CFLAGS.
- The "Size" setting will add the -0s flag to CFLAGS.
@@ -189,9 +190,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
Note that custom optimization levels may be unsupported.
Compiler optimization for the IDF bootloader is set separately,
see the BOOTLOADER_COMPILER_OPTIMIZATION setting.
config COMPILER_OPTIMIZATION_DEFAULT
bool "Debug (-Og)"
config COMPILER_OPTIMIZATION_SIZE

View File

@@ -2,7 +2,9 @@
* [中文版](./README_CN.md)
ESP-IDF is the official development framework for the [ESP32](https://espressif.com/en/products/hardware/esp32/overview) chip provided for Windows, Linux and macOS.
[![Documentation Status](https://readthedocs.com/projects/espressif-esp-idf/badge/?version=latest)](https://docs.espressif.com/projects/esp-idf/en/latest/?badge=latest)
ESP-IDF is the official development framework for the [ESP32](https://espressif.com/en/products/hardware/esp32/overview) chip.
# Developing With ESP-IDF
@@ -35,15 +37,25 @@ See the Getting Started guide links above for a detailed setup guide. This is a
## Setup Build Environment
(See the Getting Started guide listed above for a full list of required steps with more details.)
(See Getting Started guide for a full list of required steps with details.)
* Install host build dependencies mentioned in the Getting Started guide.
* Run the install script to set up the build environment. The options include `install.bat` or `install.ps1` for Windows, and `install.sh` for Unix shells.
* Run the export script on Windows (`export.bat`) or source it on Unix (`source export.sh`) in every shell environment before using ESP-IDF.
* Install host build dependencies mentioned in Getting Started guide.
* Add `tools/` directory to the PATH
* Run `python -m pip install -r requirements.txt` to install Python dependencies
## Configuring the Project
`idf.py menuconfig` opens a text-based configuration menu where you can configure the project.
`idf.py menuconfig`
* Opens a text-based configuration menu for the project.
* Use up & down arrow keys to navigate the menu.
* Use Enter key to go into a submenu, Escape key to go out or to exit.
* Type `?` to see a help screen. Enter key exits the help screen.
* Use Space key, or `Y` and `N` keys to enable (Yes) and disable (No) configuration items with checkboxes "`[*]`"
* Pressing `?` while highlighting a configuration item displays help about that item.
* Type `/` to search the configuration items.
Once done configuring, press Escape multiple times to exit and say "Yes" to save the new configuration when prompted.
## Compiling the Project

View File

@@ -30,17 +30,13 @@ endif()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "${include_dirs}"
PRIV_REQUIRES soc esp_common
PRIV_REQUIRES soc
LDFRAGMENTS linker.lf)
# disable --coverage for this component, as it is used as transport
# for gcov
target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-profile-arcs" "-fno-test-coverage")
if(CONFIG_APPTRACE_GCOV_ENABLE)
# disable --coverage for this component, as it is used as transport
# for gcov
target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-profile-arcs" "-fno-test-coverage")
# Force app_trace to also appear later than gcov in link line
idf_component_get_property(app_trace app_trace COMPONENT_LIB)
target_link_libraries(${COMPONENT_LIB} INTERFACE
"-Wl,--undefined=gcov_rtio_atexit" $<TARGET_FILE:${app_trace}> gcov $<TARGET_FILE:${app_trace}> c)
endif()
# Force app_trace to also appear later than gcov in link line
idf_component_get_property(app_trace app_trace COMPONENT_LIB)
target_link_libraries(${COMPONENT_LIB} INTERFACE $<TARGET_FILE:${app_trace}> gcov $<TARGET_FILE:${app_trace}> ${LIBC})

View File

@@ -8,7 +8,11 @@ COMPONENT_ADD_INCLUDEDIRS = include
COMPONENT_ADD_LDFLAGS = -lapp_trace
# do not produce gcov info for this module, it is used as transport for gcov
CFLAGS := $(subst --coverage,,$(CFLAGS))
ifdef CONFIG_SYSVIEW_ENABLE
COMPONENT_ADD_INCLUDEDIRS += \
sys_view/Config \
sys_view/SEGGER \
@@ -22,12 +26,7 @@ COMPONENT_SRCDIRS += \
sys_view/esp32 \
sys_view/ext
else
ifdef CONFIG_APPTRACE_GCOV_ENABLE
# do not produce gcov info for this module, it is used as transport for gcov
CFLAGS := $(subst --coverage,,$(CFLAGS))
COMPONENT_ADD_LDFLAGS += -Wl,--undefined=gcov_rtio_atexit
COMPONENT_SRCDIRS += gcov
endif
endif
COMPONENT_ADD_LDFRAGMENTS += linker.lf

View File

@@ -22,9 +22,8 @@
#include "soc/cpu.h"
#include "soc/timer_periph.h"
#include "esp_app_trace.h"
#include "esp_freertos_hooks.h"
#include "esp_private/dbg_stubs.h"
#include "esp_ipc.h"
#include "hal/timer_ll.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/libc_stubs.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
@@ -38,106 +37,117 @@
#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
#include "esp_log.h"
const static char *TAG = "esp_gcov_rtio";
static volatile bool s_create_gcov_task = false;
static volatile bool s_gcov_task_running = false;
extern void __gcov_dump(void);
extern void __gcov_reset(void);
void gcov_dump_task(void *pvParameter)
{
int dump_result = 0;
bool *running = (bool *)pvParameter;
static struct syscall_stub_table s_gcov_stub_table;
ESP_EARLY_LOGV(TAG, "%s stack use in %d", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL));
static int gcov_stub_lock_try_acquire_recursive(_lock_t *lock)
{
if (*lock && uxSemaphoreGetCount((xSemaphoreHandle)(*lock)) == 0) {
// we can do nothing here, gcov dump is initiated with some resource locked
// which is also used by gcov functions
ESP_EARLY_LOGE(TAG, "Lock 0x%x is busy during GCOV dump! System state can be inconsistent after dump!", lock);
}
return pdTRUE;
}
static void gcov_stub_lock_acquire_recursive(_lock_t *lock)
{
gcov_stub_lock_try_acquire_recursive(lock);
}
static void gcov_stub_lock_release_recursive(_lock_t *lock)
{
}
static int esp_dbg_stub_gcov_dump_do(void)
{
int ret = ESP_OK;
FILE* old_stderr = stderr;
FILE* old_stdout = stdout;
struct syscall_stub_table* old_table = syscall_table_ptr_pro;
ESP_EARLY_LOGV(TAG, "Alloc apptrace down buf %d bytes", ESP_GCOV_DOWN_BUF_SIZE);
void *down_buf = malloc(ESP_GCOV_DOWN_BUF_SIZE);
if (down_buf == NULL) {
ESP_EARLY_LOGE(TAG, "Could not allocate memory for the buffer");
dump_result = ESP_ERR_NO_MEM;
goto gcov_exit;
return ESP_ERR_NO_MEM;
}
ESP_EARLY_LOGV(TAG, "Config apptrace down buf");
esp_apptrace_down_buffer_config(down_buf, ESP_GCOV_DOWN_BUF_SIZE);
ESP_EARLY_LOGV(TAG, "Dump data...");
// incase of dual-core chip APP and PRO CPUs share the same table, so it is safe to save only PRO's table
memcpy(&s_gcov_stub_table, old_table, sizeof(s_gcov_stub_table));
s_gcov_stub_table._lock_acquire_recursive = &gcov_stub_lock_acquire_recursive;
s_gcov_stub_table._lock_release_recursive = &gcov_stub_lock_release_recursive;
s_gcov_stub_table._lock_try_acquire_recursive = &gcov_stub_lock_try_acquire_recursive,
syscall_table_ptr_pro = &s_gcov_stub_table;
stderr = (FILE*) &__sf_fake_stderr;
stdout = (FILE*) &__sf_fake_stdout;
__gcov_dump();
// reset dump status to allow incremental data accumulation
__gcov_reset();
stdout = old_stdout;
stderr = old_stderr;
syscall_table_ptr_pro = old_table;
ESP_EARLY_LOGV(TAG, "Free apptrace down buf");
free(down_buf);
ESP_EARLY_LOGV(TAG, "Finish file transfer session");
dump_result = esp_apptrace_fstop(ESP_APPTRACE_DEST_TRAX);
if (dump_result != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", dump_result);
}
gcov_exit:
ESP_EARLY_LOGV(TAG, "dump_result %d", dump_result);
if (running) {
*running = false;
}
ESP_EARLY_LOGV(TAG, "%s stack use out %d", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL));
vTaskDelete(NULL);
}
void gcov_create_task(void *arg)
{
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
xTaskCreatePinnedToCore(&gcov_dump_task, "gcov_dump_task", 2048, (void *)&s_gcov_task_running, configMAX_PRIORITIES - 1, NULL, 0);
}
void gcov_create_task_tick_hook(void)
{
extern esp_err_t esp_ipc_start_gcov_from_isr(uint32_t cpu_id, esp_ipc_func_t func, void* arg);
if (s_create_gcov_task) {
if (esp_ipc_start_gcov_from_isr(xPortGetCoreID(), &gcov_create_task, NULL) == ESP_OK) {
s_create_gcov_task = false;
}
ret = esp_apptrace_fstop(ESP_APPTRACE_DEST_TRAX);
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret);
}
return ret;
}
/**
* @brief Triggers gcov info dump task
* @brief Triggers gcov info dump.
* This function is to be called by OpenOCD, not by normal user code.
* TODO: what about interrupted flash access (when cache disabled)
* TODO: what about interrupted flash access (when cache disabled)???
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
static int esp_dbg_stub_gcov_entry(void)
{
/* we are in isr context here */
s_create_gcov_task = true;
return ESP_OK;
return esp_dbg_stub_gcov_dump_do();
}
int gcov_rtio_atexit(void (*function)(void) __attribute__ ((unused)))
{
uint32_t capabilities = 0;
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_GCOV, (uint32_t)&esp_dbg_stub_gcov_entry);
if (esp_dbg_stub_entry_get(ESP_DBG_STUB_ENTRY_CAPABILITIES, &capabilities) == ESP_OK) {
esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_CAPABILITIES, capabilities | ESP_DBG_STUB_CAP_GCOV_TASK);
}
esp_register_freertos_tick_hook(gcov_create_task_tick_hook);
return ESP_OK;
return 0;
}
void esp_gcov_dump(void)
{
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
// disable IRQs on this CPU, other CPU is halted by OpenOCD
unsigned irq_state = portENTER_CRITICAL_NESTED();
#if !CONFIG_FREERTOS_UNICORE
int other_core = xPortGetCoreID() ? 0 : 1;
esp_cpu_stall(other_core);
#endif
while (!esp_apptrace_host_is_connected(ESP_APPTRACE_DEST_TRAX)) {
vTaskDelay(pdMS_TO_TICKS(10));
// to avoid complains that task watchdog got triggered for other tasks
timer_ll_wdt_set_protect(&TIMERG0, false);
timer_ll_wdt_feed(&TIMERG0);
timer_ll_wdt_set_protect(&TIMERG0, true);
// to avoid reboot on INT_WDT
timer_ll_wdt_set_protect(&TIMERG1, false);
timer_ll_wdt_feed(&TIMERG1);
timer_ll_wdt_set_protect(&TIMERG1, true);
}
/* We are not in isr context here. Waiting for the completion is safe */
s_gcov_task_running = true;
s_create_gcov_task = true;
while (s_gcov_task_running) {
vTaskDelay(pdMS_TO_TICKS(10));
}
esp_dbg_stub_gcov_dump_do();
#if !CONFIG_FREERTOS_UNICORE
esp_cpu_unstall(other_core);
#endif
portEXIT_CRITICAL_NESTED(irq_state);
}
void *gcov_rtio_fopen(const char *path, const char *mode)
@@ -154,7 +164,7 @@ int gcov_rtio_fclose(void *stream)
size_t gcov_rtio_fread(void *ptr, size_t size, size_t nmemb, void *stream)
{
ESP_EARLY_LOGV(TAG, "%s read %u", __FUNCTION__, size * nmemb);
ESP_EARLY_LOGV(TAG, "%s read %u", __FUNCTION__, size*nmemb);
size_t sz = esp_apptrace_fread(ESP_APPTRACE_DEST_TRAX, ptr, size, nmemb, stream);
ESP_EARLY_LOGV(TAG, "%s actually read %u", __FUNCTION__, sz);
return sz;

View File

@@ -3,11 +3,10 @@ archive: libapp_trace.a
entries:
app_trace (noflash)
app_trace_util (noflash)
if SYSVIEW_ENABLE = y:
SEGGER_SYSVIEW (noflash)
SEGGER_RTT_esp32 (noflash)
SEGGER_SYSVIEW_Config_FreeRTOS (noflash)
SEGGER_SYSVIEW_FreeRTOS (noflash)
SEGGER_SYSVIEW (noflash)
SEGGER_RTT_esp32 (noflash)
SEGGER_SYSVIEW_Config_FreeRTOS (noflash)
SEGGER_SYSVIEW_FreeRTOS (noflash)
[mapping:driver]
archive: libdriver.a

View File

@@ -22,14 +22,4 @@ menu "Application manager"
The PROJECT_NAME variable from the build system will not affect the firmware image.
This value will not be contained in the esp_app_desc structure.
config APP_RETRIEVE_LEN_ELF_SHA
int "The length of APP ELF SHA is stored in RAM(chars)"
default 16
range 8 64
help
At startup, the app will read this many hex characters from the embedded APP ELF SHA-256 hash value
and store it in static RAM. This ensures the app ELF SHA-256 value is always available
if it needs to be printed by the panic handler code.
Changing this value will change the size of a static buffer, in bytes.
endmenu # "Application manager"

View File

@@ -72,38 +72,13 @@ static inline char IRAM_ATTR to_hex_digit(unsigned val)
return (val < 10) ? ('0' + val) : ('a' + val - 10);
}
__attribute__((constructor)) void esp_ota_init_app_elf_sha256(void)
{
esp_ota_get_app_elf_sha256(NULL, 0);
}
/* The esp_app_desc.app_elf_sha256 should be possible to print in panic handler during cache is disabled.
* But because the cache is disabled the reading esp_app_desc.app_elf_sha256 is not right and
* can lead to a complete lock-up of the CPU.
* For this reason we do a reading of esp_app_desc.app_elf_sha256 while start up in esp_ota_init_app_elf_sha256()
* and keep it in the static s_app_elf_sha256 value.
*/
int IRAM_ATTR esp_ota_get_app_elf_sha256(char* dst, size_t size)
{
static char s_app_elf_sha256[CONFIG_APP_RETRIEVE_LEN_ELF_SHA / 2];
static bool first_call = true;
if (first_call) {
first_call = false;
// At -O2 optimization level, GCC optimizes out the copying of the first byte of the app_elf_sha256,
// because it is zero at compile time, and only modified afterwards by esptool.
// Casting to volatile disables the optimization.
const volatile uint8_t* src = (const volatile uint8_t*)esp_app_desc.app_elf_sha256;
for (size_t i = 0; i < sizeof(s_app_elf_sha256); ++i) {
s_app_elf_sha256[i] = src[i];
}
}
if (dst == NULL || size == 0) {
return 0;
}
size_t n = MIN((size - 1) / 2, sizeof(s_app_elf_sha256));
size_t n = MIN((size - 1) / 2, sizeof(esp_app_desc.app_elf_sha256));
const uint8_t* src = esp_app_desc.app_elf_sha256;
for (size_t i = 0; i < n; ++i) {
dst[2*i] = to_hex_digit(s_app_elf_sha256[i] >> 4);
dst[2*i + 1] = to_hex_digit(s_app_elf_sha256[i] & 0xf);
dst[2*i] = to_hex_digit(src[i] >> 4);
dst[2*i + 1] = to_hex_digit(src[i] & 0xf);
}
dst[2*n] = 0;
return 2*n + 1;

View File

@@ -157,8 +157,7 @@ esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
ret = esp_partition_erase_range(partition, 0, partition->size);
} else {
const int aligned_erase_size = (image_size + SPI_FLASH_SEC_SIZE - 1) & ~(SPI_FLASH_SEC_SIZE - 1);
ret = esp_partition_erase_range(partition, 0, aligned_erase_size);
ret = esp_partition_erase_range(partition, 0, (image_size / SPI_FLASH_SEC_SIZE + 1) * SPI_FLASH_SEC_SIZE);
}
if (ret != ESP_OK) {

View File

@@ -87,8 +87,9 @@ class OtatoolTarget():
seq = bytearray(self.otadata[start:start + 4])
crc = bytearray(self.otadata[start + 28:start + 32])
seq = struct.unpack('I', seq)
crc = struct.unpack('I', crc)
seq = struct.unpack('>I', seq)
crc = struct.unpack('>I', crc)
info.append(otadata_info(seq[0], crc[0]))
return info
@@ -102,11 +103,12 @@ class OtatoolTarget():
def switch_ota_partition(self, ota_id):
self._check_otadata_partition()
sys.path.append(PARTTOOL_DIR)
import gen_esp32part as gen
def is_otadata_info_valid(status):
seq = status.seq % (1 << 32)
crc = binascii.crc32(struct.pack('I', seq), 0xFFFFFFFF) % (1 << 32)
crc = hex(binascii.crc32(struct.pack("I", seq), 0xFFFFFFFF) % (1 << 32))
return seq < (int('0xFFFFFFFF', 16) % (1 << 32)) and status.crc == crc
partition_table = self.target.partition_table
@@ -217,8 +219,8 @@ def _read_otadata(target):
otadata_info = target._get_otadata_info()
print(' {:8s} \t {:8s} | \t {:8s} \t {:8s}'.format('OTA_SEQ', 'CRC', 'OTA_SEQ', 'CRC'))
print('Firmware: 0x{:08x} \t0x{:08x} | \t0x{:08x} \t 0x{:08x}'.format(otadata_info[0].seq, otadata_info[0].crc,
print(" {:8s} \t {:8s} | \t {:8s} \t {:8s}".format("OTA_SEQ", "CRC", "OTA_SEQ", "CRC"))
print("Firmware: 0x{:8x} \t0x{:8x} | \t0x{:8x} \t 0x{:8x}".format(otadata_info[0].seq, otadata_info[0].crc,
otadata_info[1].seq, otadata_info[1].crc))
@@ -247,10 +249,6 @@ def _erase_ota_partition(target, ota_id):
def main():
if sys.version_info[0] < 3:
print("WARNING: Support for Python 2 is deprecated and will be removed in future versions.", file=sys.stderr)
elif sys.version_info[0] == 3 and sys.version_info[1] < 6:
print("WARNING: Python 3 versions older than 3.6 are not supported.", file=sys.stderr)
global quiet
parser = argparse.ArgumentParser("ESP-IDF OTA Partitions Tool")

View File

@@ -4,7 +4,7 @@
TEST_CASE("esp_ota_get_app_elf_sha256 test", "[esp_app_desc]")
{
const int sha256_hex_len = CONFIG_APP_RETRIEVE_LEN_ELF_SHA;
const int sha256_hex_len = 64;
char dst[sha256_hex_len + 2];
const char fill = 0xcc;
int res;

View File

@@ -23,7 +23,7 @@
#include "unity.h"
#include "bootloader_common.h"
#include "../include_bootloader/bootloader_flash_priv.h"
#include "../include_bootloader/bootloader_flash.h"
#include "esp_log.h"
#include "esp_ota_ops.h"

View File

@@ -6,7 +6,7 @@ if(BOOTLOADER_BUILD OR NOT CONFIG_APP_BUILD_BOOTLOADER)
endif()
# When secure boot is enabled, do not flash bootloader along with invocation of `idf.py flash`
if(NOT CONFIG_SECURE_BOOT)
if(NOT CONFIG_SECURE_BOOT_ENABLED)
set(flash_bootloader FLASH_IN_PROJECT)
endif()

View File

@@ -1,29 +1,4 @@
menu "Bootloader config"
choice BOOTLOADER_COMPILER_OPTIMIZATION
prompt "Bootloader optimization Level"
default BOOTLOADER_COMPILER_OPTIMIZATION_SIZE
help
This option sets compiler optimization level (gcc -O argument)
for the bootloader.
- The default "Size" setting will add the -0s flag to CFLAGS.
- The "Debug" setting will add the -Og flag to CFLAGS.
- The "Performance" setting will add the -O2 flag to CFLAGS.
- The "None" setting will add the -O0 flag to CFLAGS.
Note that custom optimization levels may be unsupported.
config BOOTLOADER_COMPILER_OPTIMIZATION_SIZE
bool "Size (-Os)"
config BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG
bool "Debug (-Og)"
config BOOTLOADER_COMPILER_OPTIMIZATION_PERF
bool "Optimize for performance (-O2)"
config BOOTLOADER_COMPILER_OPTIMIZATION_NONE
bool "Debug without optimization (-O0)"
endchoice
choice BOOTLOADER_LOG_LEVEL
bool "Bootloader log verbosity"
default BOOTLOADER_LOG_LEVEL_INFO
@@ -53,34 +28,20 @@ menu "Bootloader config"
default 4 if BOOTLOADER_LOG_LEVEL_DEBUG
default 5 if BOOTLOADER_LOG_LEVEL_VERBOSE
config BOOTLOADER_SPI_CUSTOM_WP_PIN
bool "Use custom SPI Flash WP Pin when flash pins set in eFuse (read help)"
depends on IDF_TARGET_ESP32 && (ESPTOOLPY_FLASHMODE_QIO || ESPTOOLPY_FLASHMODE_QOUT)
default y if BOOTLOADER_SPI_WP_PIN != 7 # backwards compatibility, can remove in IDF 5
default n
help
This setting is only used if the SPI flash pins have been overridden by setting the eFuses
SPI_PAD_CONFIG_xxx, and the SPI flash mode is QIO or QOUT.
When this is the case, the eFuse config only defines 3 of the 4 Quad I/O data pins. The WP pin (aka
ESP32 pin "SD_DATA_3" or SPI flash pin "IO2") is not specified in eFuse. The same pin is also used
for external SPIRAM if it is enabled.
If this config item is set to N (default), the correct WP pin will be automatically used for any
Espressif chip or module with integrated flash. If a custom setting is needed, set this config item to
Y and specify the GPIO number connected to the WP.
config BOOTLOADER_SPI_WP_PIN
int "Custom SPI Flash WP Pin"
int "SPI Flash WP Pin when customising pins via eFuse (read help)"
range 0 33
default 7
depends on IDF_TARGET_ESP32 && (ESPTOOLPY_FLASHMODE_QIO || ESPTOOLPY_FLASHMODE_QOUT)
#depends on BOOTLOADER_SPI_CUSTOM_WP_PIN # backwards compatibility, can uncomment in IDF 5
depends on ESPTOOLPY_FLASHMODE_QIO || ESPTOOLPY_FLASHMODE_QOUT
help
The option "Use custom SPI Flash WP Pin" must be set or this value is ignored
This value is ignored unless flash mode is set to QIO or QOUT *and* the SPI flash pins have been
overriden by setting the eFuses SPI_PAD_CONFIG_xxx.
If burning a customized set of SPI flash pins in eFuse and using QIO or QOUT mode for flash, set this
value to the GPIO number of the SPI flash WP pin.
When this is the case, the eFuse config only defines 3 of the 4 Quad I/O data pins. The WP pin (aka ESP32
pin "SD_DATA_3" or SPI flash pin "IO2") is not specified in eFuse. That pin number is compiled into the
bootloader instead.
The default value (GPIO 7) is correct for WP pin on ESP32-D2WD integrated flash.
choice BOOTLOADER_VDDSDIO_BOOST
bool "VDDSDIO LDO voltage"
@@ -263,7 +224,7 @@ menu "Bootloader config"
config BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
bool "Skip image validation when exiting deep sleep"
depends on (SECURE_BOOT && SECURE_BOOT_INSECURE) || !SECURE_BOOT
depends on (SECURE_BOOT_ENABLED && SECURE_BOOT_INSECURE) || !SECURE_BOOT_ENABLED
default n
help
This option disables the normal validation of an image coming out of
@@ -308,15 +269,6 @@ menu "Bootloader config"
in this area of memory, you can increase it. It must be a multiple of 4 bytes.
This area (rtc_retain_mem_t) is reserved and has access from the bootloader and an application.
config BOOTLOADER_FLASH_XMC_SUPPORT
bool "Enable the support for flash chips of XMC (READ HELP FIRST)"
default y
help
Perform the startup flow recommended by XMC. Please consult XMC for the details of this flow.
XMC chips will be forbidden to be used, when this option is disabled.
DON'T DISABLE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.
endmenu # Bootloader
@@ -327,12 +279,12 @@ menu "Security features"
config SECURE_SIGNED_ON_BOOT
bool
default y
depends on SECURE_BOOT || SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
config SECURE_SIGNED_ON_UPDATE
bool
default y
depends on SECURE_BOOT || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
config SECURE_SIGNED_APPS
bool
@@ -346,7 +298,8 @@ menu "Security features"
config SECURE_SIGNED_APPS_NO_SECURE_BOOT
bool "Require signed app images"
depends on !SECURE_BOOT
default n
depends on !SECURE_BOOT_ENABLED
help
Require apps to be signed to verify their integrity.
@@ -355,35 +308,6 @@ menu "Security features"
against remote network access, but not physical access. Compared to using hardware Secure Boot this option
is much simpler to implement.
choice SECURE_SIGNED_APPS_SCHEME
bool "App Signing Scheme"
depends on SECURE_BOOT || SECURE_SIGNED_APPS_NO_SECURE_BOOT
default SECURE_SIGNED_APPS_ECDSA_SCHEME if SECURE_BOOT_V1_ENABLED
default SECURE_SIGNED_APPS_RSA_SCHEME if SECURE_BOOT_V2_ENABLED
help
Select the Secure App signing scheme. Depends on the Chip Revision.
There are two options:
1. ECDSA based secure boot scheme. (Only choice for Secure Boot V1)
Supported in ESP32 and ESP32-ECO3.
2. The RSA based secure boot scheme. (Only choice for Secure Boot V2)
Supported in ESP32-ECO3. (ESP32 Chip Revision 3 onwards)
config SECURE_SIGNED_APPS_ECDSA_SCHEME
bool "ECDSA"
depends on IDF_TARGET_ESP32 && (SECURE_SIGNED_APPS_NO_SECURE_BOOT || SECURE_BOOT_V1_ENABLED)
help
Embeds the ECDSA public key in the bootloader and signs the application with an ECDSA key.
Refer to the documentation before enabling.
config SECURE_SIGNED_APPS_RSA_SCHEME
bool "RSA"
depends on ESP32_REV_MIN_3 && SECURE_BOOT_V2_ENABLED
help
Appends the RSA-3072 based Signature block to the application.
Refer to <Secure Boot Version 2 documentation link> before enabling.
endchoice
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
bool "Bootloader verifies app signatures"
default n
@@ -410,48 +334,23 @@ menu "Security features"
If hardware secure boot is not enabled, this option still adds significant security against network-based
attackers by preventing spoofing of OTA updates.
config SECURE_BOOT
bool "Enable hardware Secure Boot in bootloader (READ DOCS FIRST)"
config SECURE_BOOT_ENABLED
bool "Enable hardware secure boot in bootloader (READ DOCS FIRST)"
default n
help
Build a bootloader which enables Secure Boot on first boot.
Build a bootloader which enables secure boot on first boot.
Once enabled, Secure Boot will not boot a modified bootloader. The bootloader will only load a partition
Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition
table or boot an app if the data has a verified digital signature. There are implications for reflashing
updated apps once secure boot is enabled.
When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.
choice SECURE_BOOT_VERSION
bool "Select secure boot version"
default SECURE_BOOT_V2_ENABLED if ESP32_REV_MIN_3
depends on SECURE_BOOT
help
Select the Secure Boot Version. Depends on the Chip Revision.
Secure Boot V2 is the new RSA based secure boot scheme.
Supported in ESP32-ECO3. (ESP32 Chip Revision 3 onwards)
Secure Boot V1 is the AES based secure boot scheme.
Supported in ESP32 and ESP32-ECO3.
config SECURE_BOOT_V1_ENABLED
bool "Enable Secure Boot version 1"
depends on IDF_TARGET_ESP32
help
Build a bootloader which enables secure boot version 1 on first boot.
Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.
config SECURE_BOOT_V2_ENABLED
bool "Enable Secure Boot version 2"
depends on ESP32_REV_MIN_3
help
Build a bootloader which enables Secure Boot version 2 on first boot.
Refer to Secure Boot V2 section of the ESP-IDF Programmer's Guide for this version before enabling.
endchoice
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
choice SECURE_BOOTLOADER_MODE
bool "Secure bootloader mode"
depends on SECURE_BOOT_V1_ENABLED
depends on SECURE_BOOT_ENABLED
default SECURE_BOOTLOADER_ONE_TIME_FLASH
config SECURE_BOOTLOADER_ONE_TIME_FLASH
@@ -486,8 +385,7 @@ menu "Security features"
If enabled (default), these binary files are signed as part of the build process. The file named in
"Secure boot private signing key" will be used to sign the image.
If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py.
Version 1 to enable ECDSA Based Secure Boot and Version 2 to enable RSA based Secure Boot.
If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py
(for example, on a remote signing server.)
config SECURE_BOOT_SIGNING_KEY
@@ -497,32 +395,28 @@ menu "Security features"
help
Path to the key file used to sign app images.
Key file is an ECDSA private key (NIST256p curve) in PEM format for Secure Boot V1.
Key file is an RSA private key in PEM format for Secure Boot V2.
Key file is an ECDSA private key (NIST256p curve) in PEM format.
Path is evaluated relative to the project directory.
You can generate a new signing key by running the following command:
espsecure.py generate_signing_key secure_boot_signing_key.pem
See the Secure Boot section of the ESP-IDF Programmer's Guide for this version for details.
See https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html for details.
config SECURE_BOOT_VERIFICATION_KEY
string "Secure boot public signature verification key"
depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES && !SECURE_SIGNED_APPS_RSA_SCHEME
depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES
default "signature_verification_key.bin"
help
Path to a public key file used to verify signed images.
Secure Boot V1: This ECDSA public key is compiled into the bootloader and/or
Path to a public key file used to verify signed images. This key is compiled into the bootloader and/or
app, to verify app images.
Secure Boot V2: This RSA public key is compiled into the signature block at
the end of the bootloader/app.
Key file is in raw binary format, and can be extracted from a
PEM formatted private key using the espsecure.py
extract_public_key command.
Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
choice SECURE_BOOTLOADER_KEY_ENCODING
bool "Hardware Key Encoding"
@@ -549,7 +443,7 @@ menu "Security features"
config SECURE_BOOT_INSECURE
bool "Allow potentially insecure options"
depends on SECURE_BOOT
depends on SECURE_BOOT_ENABLED
default N
help
You can disable some of the default protections offered by secure boot, in order to enable testing or a
@@ -557,12 +451,11 @@ menu "Security features"
Only enable these options if you are very sure.
Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
config SECURE_FLASH_ENC_ENABLED
bool "Enable flash encryption on boot (READ DOCS FIRST)"
default N
select SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE
help
If this option is set, flash contents will be encrypted by the bootloader on first boot.
@@ -602,7 +495,7 @@ menu "Security features"
Select Release mode only for production or manufacturing. Once enabled you can not reflash using UART
bootloader
Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version and
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html and
https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html for details.
config SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
@@ -611,7 +504,6 @@ menu "Security features"
config SECURE_FLASH_ENCRYPTION_MODE_RELEASE
bool "Release"
select PARTITION_TABLE_MD5 if !ESP32_COMPATIBLE_PRE_V3_1_BOOTLOADERS
endchoice
@@ -665,18 +557,6 @@ menu "Security features"
image to this length. It is generally not recommended to set this option, unless you have a legacy
partitioning scheme which doesn't support 64KB aligned partition lengths.
config SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
bool "Allow additional read protecting of efuses"
depends on SECURE_BOOT_INSECURE && SECURE_BOOT_V2_ENABLED
help
If not set (default, recommended), on first boot the bootloader will burn the WR_DIS_RD_DIS
efuse when Secure Boot is enabled. This prevents any more efuses from being read protected.
If this option is set, it will remain possible to write the EFUSE_RD_DIS efuse field after Secure
Boot is enabled. This may allow an attacker to read-protect the BLK2 efuse holding the public
key digest, causing an immediate denial of service and possibly allowing an additional fault
injection attack to bypass the signature protection.
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
bool "Leave UART bootloader encryption enabled"
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
@@ -723,23 +603,5 @@ menu "Security features"
the wrong device. The device needs to have flash encryption already enabled using espefuse.py.
endmenu # Potentially Insecure
config SECURE_DISABLE_ROM_DL_MODE
bool "Permanently disable ROM Download Mode"
depends on ESP32_REV_MIN_3
default n
help
If set, during startup the app will burn an eFuse bit to permanently disable the UART ROM
Download Mode. This prevents any future use of esptool.py, espefuse.py and similar tools.
Once disabled, if the SoC is booted with strapping pins set for ROM Download Mode
then an error is printed instead.
It is recommended to enable this option in any production application where Flash
Encryption and/or Secure Boot is enabled and access to Download Mode is not required.
It is also possible to permanently disable Download Mode by calling
esp_efuse_disable_rom_download_mode() at runtime.
endmenu # Security features

View File

@@ -45,7 +45,7 @@ clean: bootloader-clean
bootloader-list-components:
$(BOOTLOADER_MAKE) list-components
ifndef CONFIG_SECURE_BOOT
ifndef CONFIG_SECURE_BOOT_ENABLED
# If secure boot disabled, bootloader flashing is integrated
# with 'make flash' and no warnings are printed.
@@ -115,35 +115,13 @@ $(BOOTLOADER_DIGEST_BIN): $(BOOTLOADER_BIN) $(SECURE_BOOTLOADER_KEY) | check_pyt
@echo "DIGEST $(notdir $@)"
$(ESPSECUREPY) digest_secure_bootloader -k $(SECURE_BOOTLOADER_KEY) -o $@ $<
else ifdef CONFIG_SECURE_BOOT_V2_ENABLED
BOOTLOADER_SIGNED_BIN := $(BOOTLOADER_BUILD_DIR)/bootloader-signed.bin
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
bootloader: $(BOOTLOADER_BIN) $(SDKCONFIG_MAKEFILE) | check_python_dependencies
$(ESPSECUREPY) sign_data --keyfile $(SECURE_BOOT_SIGNING_KEY) --version 2 \
-o $(BOOTLOADER_SIGNED_BIN) $(BOOTLOADER_BIN)
else
bootloader: $(BOOTLOADER_BIN) $(SDKCONFIG_MAKEFILE) | check_python_dependencies
@echo "Bootloader not signed. Sign the bootloader before flashing."
@echo "To sign the bootloader, you can use this command:"
@echo "espsecure.py sign_data --keyfile SECURE_BOOT_SIGNING_KEY --version 2 $(BOOTLOADER_BIN)"
endif
@echo $(SEPARATOR)
@echo "Use the following command to flash the bootloader:"
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
@echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $(BOOTLOADER_SIGNED_BIN)"
else
@echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)"
endif
@echo $(SEPARATOR)
else # CONFIG_SECURE_BOOT && !CONFIG_SECURE_BOOTLOADER_REFLASHABLE \
&& !CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH && !CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
else # CONFIG_SECURE_BOOT_ENABLED && !CONFIG_SECURE_BOOTLOADER_REFLASHABLE && !CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH
bootloader:
@echo "Invalid bootloader target: bad sdkconfig?"
@exit 1
endif
ifndef CONFIG_SECURE_BOOT
ifndef CONFIG_SECURE_BOOT_ENABLED
# don't build bootloader by default if secure boot is enabled
all_binaries: $(BOOTLOADER_BIN)
endif
@@ -153,8 +131,3 @@ bootloader-clean: $(SDKCONFIG_MAKEFILE)
ifdef CONFIG_SECURE_BOOTLOADER_REFLASHABLE
rm -f $(SECURE_BOOTLOADER_KEY) $(BOOTLOADER_DIGEST_BIN)
endif
ifdef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
rm -f $(BOOTLOADER_SIGNED_BIN)
endif
endif

View File

@@ -19,8 +19,8 @@ set(bootloader_binary_files
idf_build_get_property(project_dir PROJECT_DIR)
# There are some additional processing when CONFIG_SECURE_SIGNED_APPS. This happens
# when either CONFIG_SECURE_BOOT_V1_ENABLED or CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES.
# There are some additional processing when CONFIG_CONFIG_SECURE_SIGNED_APPS. This happens
# when either CONFIG_SECURE_BOOT_ENABLED or SECURE_BOOT_BUILD_SIGNED_BINARIES.
# For both cases, the user either sets binaries to be signed during build or not
# using CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES.
#
@@ -29,13 +29,7 @@ idf_build_get_property(project_dir PROJECT_DIR)
if(CONFIG_SECURE_SIGNED_APPS)
add_custom_target(gen_secure_boot_keys)
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
set(secure_apps_signing_scheme "1")
elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
set(secure_apps_signing_scheme "2")
endif()
if(CONFIG_SECURE_BOOT_V1_ENABLED)
if(CONFIG_SECURE_BOOT_ENABLED)
# Check that the configuration is sane
if((CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) OR
(NOT CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND NOT CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH))
@@ -66,8 +60,7 @@ if(CONFIG_SECURE_SIGNED_APPS)
# (to pick up a new signing key if one exists, etc.)
fail_at_build_time(gen_secure_boot_signing_key
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
"\tespsecure.py generate_signing_key --version ${secure_apps_signing_scheme} \
${CONFIG_SECURE_BOOT_SIGNING_KEY}")
"\tespsecure.py generate_signing_key ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
else()
add_custom_target(gen_secure_boot_signing_key)
endif()
@@ -77,7 +70,7 @@ if(CONFIG_SECURE_SIGNED_APPS)
set(ver_key_arg)
add_dependencies(gen_secure_boot_keys gen_secure_boot_signing_key)
elseif(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
else()
get_filename_component(secure_boot_verification_key
${CONFIG_SECURE_BOOT_VERIFICATION_KEY}
@@ -90,7 +83,7 @@ if(CONFIG_SECURE_SIGNED_APPS)
fail_at_build_time(gen_secure_boot_verification_key
"Secure Boot Verification Public Key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} does not exist."
"\tThis can be extracted from the private signing key."
"\tSee docs/security/secure-boot-v1.rst for details.")
"\tSee docs/security/secure-boot.rst for details.")
else()
add_custom_target(gen_secure_boot_verification_key)
endif()

View File

@@ -20,6 +20,3 @@ CONFIG_FLASH_ENCRYPTION_INSECURE CONFIG_SECURE_FLASH_
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
# Secure Boot Scheme
CONFIG_SECURE_BOOT_ENABLED CONFIG_SECURE_BOOT_V1_ENABLED

View File

@@ -83,39 +83,6 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
add_custom_target (gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}")
endif()
if(CONFIG_SECURE_BOOT_V2_ENABLED)
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
get_filename_component(secure_boot_signing_key
"${SECURE_BOOT_SIGNING_KEY}" ABSOLUTE BASE_DIR "${project_dir}")
if(NOT EXISTS "${secure_boot_signing_key}")
message(FATAL_ERROR
"Secure Boot Signing Key Not found."
"\nGenerate the Secure Boot V2 RSA-PSS 3072 Key."
"\nTo generate one, you can use this command:"
"\n\t${espsecurepy} generate_signing_key --version 2 ${SECURE_BOOT_SIGNING_KEY}")
endif()
set(bootloader_unsigned_bin "bootloader-unsigned.bin")
add_custom_command(OUTPUT ".signed_bin_timestamp"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
COMMAND ${ESPSECUREPY} sign_data --version 2 --keyfile "${secure_boot_signing_key}"
-o "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}"
"from ${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
COMMAND ${CMAKE_COMMAND} -E md5sum "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" > "${CMAKE_BINARY_DIR}/.signed_bin_timestamp"
DEPENDS "${build_dir}/.bin_timestamp"
VERBATIM
COMMENT "Generated the signed Bootloader")
else()
add_custom_command(OUTPUT ".signed_bin_timestamp"
VERBATIM
COMMENT "Bootloader generated but not signed")
endif()
add_custom_target (gen_signed_bootloader ALL DEPENDS "${build_dir}/.signed_bin_timestamp")
endif()
if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
add_custom_command(TARGET bootloader.elf POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo
@@ -159,18 +126,4 @@ elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
"* Not recommended to re-use the same secure boot keyfile on multiple production devices."
DEPENDS gen_secure_bootloader_key gen_bootloader_digest_bin
VERBATIM)
elseif(CONFIG_SECURE_BOOT_V2_ENABLED)
add_custom_command(TARGET bootloader.elf POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo
"Bootloader built. Secure boot enabled, so bootloader not flashed automatically."
COMMAND ${CMAKE_COMMAND} -E echo
"Secure boot enabled, so bootloader not flashed automatically."
COMMAND ${CMAKE_COMMAND} -E echo
"\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
DEPENDS gen_signed_bootloader
VERBATIM)
endif()

View File

@@ -32,6 +32,4 @@ CFLAGS += -D BOOTLOADER_BUILD=1
# include the top-level "project" include directory, for sdkconfig.h
CFLAGS += -I$(BUILD_DIR_BASE)/../include
COMPONENT_ADD_LDFLAGS += -l$(COMPONENT_NAME) -Wl,--wrap=longjmp \
include $(IDF_PATH)/make/project.mk

View File

@@ -1,3 +1,3 @@
# only compile the "uECC_verify_antifault.c" file which includes the "micro-ecc/uECC.c" source file
idf_component_register(SRCS "uECC_verify_antifault.c"
INCLUDE_DIRS . micro-ecc)
# only compile the "micro-ecc/uECC.c" source file
idf_component_register(SRCS "micro-ecc/uECC.c"
INCLUDE_DIRS micro-ecc)

View File

@@ -1,6 +1,8 @@
# only compile the "uECC_verify_antifault.c" file which includes the "micro-ecc/uECC.c" source file
COMPONENT_SRCDIRS := .
# only compile the micro-ecc/uECC.c source file
# (SRCDIRS is needed so build system can find the source file)
COMPONENT_SRCDIRS := micro-ecc
COMPONENT_OBJS := micro-ecc/uECC.o
COMPONENT_ADD_INCLUDEDIRS := . micro-ecc
COMPONENT_ADD_INCLUDEDIRS := micro-ecc
COMPONENT_SUBMODULES := micro-ecc

View File

@@ -1,141 +0,0 @@
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license.
Modifications Copyright 2020, Espressif Systems (Shanghai) PTE LTD. Licensed under the BSD
2-clause license.
*/
/* uECC_verify() calls a number of static functions form here and
uses other definitions, so we just build that whole source file here and then append
our modified version uECC_verify_antifault(). */
#include "micro-ecc/uECC.c"
/* Version of uECC_verify() which also copies message_hash into verified_hash,
but only if the signature is valid. Does this in an FI resistant way.
*/
int uECC_verify_antifault(const uint8_t *public_key,
const uint8_t *message_hash,
unsigned hash_size,
const uint8_t *signature,
uECC_Curve curve,
uint8_t *verified_hash) {
uECC_word_t u1[uECC_MAX_WORDS], u2[uECC_MAX_WORDS];
uECC_word_t z[uECC_MAX_WORDS];
uECC_word_t sum[uECC_MAX_WORDS * 2];
uECC_word_t rx[uECC_MAX_WORDS];
uECC_word_t ry[uECC_MAX_WORDS];
uECC_word_t tx[uECC_MAX_WORDS];
uECC_word_t ty[uECC_MAX_WORDS];
uECC_word_t tz[uECC_MAX_WORDS];
const uECC_word_t *points[4];
const uECC_word_t *point;
bitcount_t num_bits;
bitcount_t i;
#if uECC_VLI_NATIVE_LITTLE_ENDIAN
uECC_word_t *_public = (uECC_word_t *)public_key;
#else
uECC_word_t _public[uECC_MAX_WORDS * 2];
#endif
uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS];
wordcount_t num_words = curve->num_words;
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
rx[num_n_words - 1] = 0;
r[num_n_words - 1] = 0;
s[num_n_words - 1] = 0;
#if uECC_VLI_NATIVE_LITTLE_ENDIAN
bcopy((uint8_t *) r, signature, curve->num_bytes);
bcopy((uint8_t *) s, signature + curve->num_bytes, curve->num_bytes);
#else
uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
uECC_vli_bytesToNative(
_public + num_words, public_key + curve->num_bytes, curve->num_bytes);
uECC_vli_bytesToNative(r, signature, curve->num_bytes);
uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
#endif
/* r, s must not be 0. */
if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
return 0;
}
/* r, s must be < n. */
if (uECC_vli_cmp(curve->n, r, num_n_words) != 1 ||
uECC_vli_cmp(curve->n, s, num_n_words) != 1) {
return 0;
}
/* Calculate u1 and u2. */
uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
u1[num_n_words - 1] = 0;
bits2int(u1, message_hash, hash_size, curve);
uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
/* Calculate sum = G + Q. */
uECC_vli_set(sum, _public, num_words);
uECC_vli_set(sum + num_words, _public + num_words, num_words);
uECC_vli_set(tx, curve->G, num_words);
uECC_vli_set(ty, curve->G + num_words, num_words);
uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */
XYcZ_add(tx, ty, sum, sum + num_words, curve);
uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
apply_z(sum, sum + num_words, z, curve);
/* Use Shamir's trick to calculate u1*G + u2*Q */
points[0] = 0;
points[1] = curve->G;
points[2] = _public;
points[3] = sum;
num_bits = smax(uECC_vli_numBits(u1, num_n_words),
uECC_vli_numBits(u2, num_n_words));
point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
uECC_vli_set(rx, point, num_words);
uECC_vli_set(ry, point + num_words, num_words);
uECC_vli_clear(z, num_words);
z[0] = 1;
for (i = num_bits - 2; i >= 0; --i) {
uECC_word_t index;
curve->double_jacobian(rx, ry, z, curve);
index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1);
point = points[index];
if (point) {
uECC_vli_set(tx, point, num_words);
uECC_vli_set(ty, point + num_words, num_words);
apply_z(tx, ty, z, curve);
uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */
XYcZ_add(tx, ty, rx, ry, curve);
uECC_vli_modMult_fast(z, z, tz, curve);
}
}
uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */
apply_z(rx, ry, z, curve);
/* v = x1 (mod n) */
if (uECC_vli_cmp(curve->n, rx, num_n_words) != 1) {
uECC_vli_sub(rx, rx, curve->n, num_n_words);
}
/* Anti-FI addition. Copy message_hash into verified_hash, but do it in a
way that it will only happen if v == r (ie, rx == r)
*/
const uECC_word_t *mhash_words = (const uECC_word_t *)message_hash;
uECC_word_t *vhash_words = (uECC_word_t *)verified_hash;
unsigned hash_words = hash_size / sizeof(uECC_word_t);
for (int w = 0; w < hash_words; w++) {
/* note: using curve->num_words here to encourage compiler to re-read this variable */
vhash_words[w] = mhash_words[w] ^ rx[w % curve->num_words] ^ r[w % curve->num_words];
}
/* Curve may be longer than hash, in which case keep reading the rest of the bytes */
for (int w = hash_words; w < curve->num_words; w++) {
vhash_words[w % hash_words] |= rx[w] ^ r[w];
}
/* Accept only if v == r. */
return (int)(uECC_vli_equal(rx, r, num_words));
}

View File

@@ -1,18 +0,0 @@
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license.
Modifications Copyright 2020, Espressif Systems (Shanghai) PTE LTD. Licensed under the BSD
2-clause license.
*/
#pragma once
#include "uECC.h"
/* Version uECC_verify() that also copies message_hash to verified_hash
if the signature is valid, and does it in a way that is harder to attack
with fault injection.
*/
int uECC_verify_antifault(const uint8_t *public_key,
const uint8_t *message_hash,
unsigned hash_size,
const uint8_t *signature,
uECC_Curve curve,
uint8_t *verified_hash);

View File

@@ -17,9 +17,6 @@ ifdef CONFIG_IDF_TARGET_ESP32
ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
LINKER_SCRIPTS += $(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.spiflash.ld
endif
ifdef CONFIG_ESP32_REV_MIN_3
LINKER_SCRIPTS += $(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.eco3.ld
endif
endif
COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH) $(addprefix -T ,$(LINKER_SCRIPTS))

View File

@@ -44,7 +44,6 @@ SECTIONS
*libbootloader_support.a:bootloader_common.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_efuse_esp32.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
@@ -76,7 +75,6 @@ SECTIONS
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_dram_start = ABSOLUTE(.);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
@@ -153,7 +151,6 @@ SECTIONS
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_dram_end = ABSOLUTE(.);
} >dram_seg
.iram.text :
@@ -165,35 +162,8 @@ SECTIONS
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg
/** This section will be used by the debugger and disassembler to get more information
* about raw data present in the code.
* Indeed, it may be required to add some padding at some points in the code
* in order to align a branch/jump destination on a particular bound.
* Padding these instructions will generate null bytes that shall be
* interpreted as data, and not code by the debugger or disassembler.
* This section will only be present in the ELF file, not in the final binary
* For more details, check GCC-212
*/
.xt.prop 0 :
{
KEEP (*(.xt.prop .gnu.linkonce.prop.*))
}
.xt.lit 0 :
{
KEEP (*(.xt.lit .gnu.linkonce.p.*))
}
}

View File

@@ -37,7 +37,6 @@ SECTIONS
*libbootloader_support.a:bootloader_common.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_efuse_esp32s2.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
@@ -68,7 +67,6 @@ SECTIONS
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_dram_start = ABSOLUTE(.);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
@@ -145,7 +143,7 @@ SECTIONS
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_dram_end = ABSOLUTE(.);
_heap_start = ABSOLUTE(.);
} >dram_seg
.iram.text :
@@ -157,35 +155,8 @@ SECTIONS
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg
/** This section will be used by the debugger and disassembler to get more information
* about raw data present in the code.
* Indeed, it may be required to add some padding at some points in the code
* in order to align a branch/jump destination on a particular bound.
* Padding these instructions will generate null bytes that shall be
* interpreted as data, and not code by the debugger or disassembler.
* This section will only be present in the ELF file, not in the final binary
* For more details, check GCC-212
*/
.xt.prop 0 :
{
KEEP (*(.xt.prop .gnu.linkonce.prop.*))
}
.xt.lit 0 :
{
KEEP (*(.xt.lit .gnu.linkonce.p.*))
}
}

View File

@@ -20,34 +20,22 @@ if(BOOTLOADER_BUILD)
set(include_dirs "include" "include_bootloader")
set(priv_requires micro-ecc spi_flash efuse)
list(APPEND srcs
"src/bootloader_init.c"
"src/${IDF_TARGET}/bootloader_sha.c"
"src/${IDF_TARGET}/flash_encrypt.c"
"src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c"
)
"src/bootloader_init.c"
"src/${IDF_TARGET}/bootloader_sha.c"
"src/${IDF_TARGET}/flash_encrypt.c"
"src/${IDF_TARGET}/secure_boot_signatures.c"
"src/${IDF_TARGET}/secure_boot.c"
"src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c"
)
else()
list(APPEND srcs
"src/idf/bootloader_sha.c")
"src/idf/bootloader_sha.c"
"src/idf/secure_boot_signatures.c")
set(include_dirs "include")
set(priv_include_dirs "include_bootloader")
set(priv_requires spi_flash mbedtls efuse)
endif()
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
if(BOOTLOADER_BUILD)
list(APPEND srcs
"src/${IDF_TARGET}/secure_boot_signatures.c")
else()
list(APPEND srcs
"src/idf/secure_boot_signatures.c")
endif()
endif()
if(CONFIG_SECURE_BOOT AND BOOTLOADER_BUILD)
list(APPEND srcs
"src/${IDF_TARGET}/secure_boot.c")
endif()
set(requires soc) #unfortunately the header directly uses SOC registers
idf_component_register(SRCS "${srcs}"
@@ -56,7 +44,7 @@ idf_component_register(SRCS "${srcs}"
REQUIRES "${requires}"
PRIV_REQUIRES "${priv_requires}")
if(CONFIG_SECURE_SIGNED_APPS AND (CONFIG_SECURE_BOOT_V1_ENABLED OR CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME))
if(CONFIG_SECURE_SIGNED_APPS)
if(BOOTLOADER_BUILD)
# Whether CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES or not, we need verification key to embed
# in the library.

View File

@@ -22,23 +22,11 @@ endif
COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2beta.o \
src/bootloader_efuse_esp32s2beta.o
ifndef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
ifndef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
COMPONENT_OBJEXCLUDE += src/$(IDF_TARGET)/secure_boot_signatures.o \
src/idf/secure_boot_signatures.o
endif
endif
ifndef CONFIG_SECURE_BOOT
COMPONENT_OBJEXCLUDE += src/$(IDF_TARGET)/secure_boot.o
endif
#
# Secure boot signing key support
#
ifdef CONFIG_SECURE_SIGNED_APPS
ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
# this path is created relative to the component build directory
SECURE_BOOT_VERIFICATION_KEY := $(abspath signature_verification_key.bin)
@@ -53,7 +41,7 @@ ORIG_SECURE_BOOT_VERIFICATION_KEY := $(call resolvepath,$(call dequote,$(CONFIG_
$(ORIG_SECURE_BOOT_VERIFICATION_KEY):
@echo "Secure boot verification public key '$@' missing."
@echo "This can be extracted from the private signing key, see"
@echo "docs/security/secure-boot-v1.rst for details."
@echo "docs/security/secure-boot.rst for details."
exit 1
# copy it into the build dir, so the secure boot verification key has
@@ -67,5 +55,4 @@ COMPONENT_EXTRA_CLEAN += $(SECURE_BOOT_VERIFICATION_KEY)
COMPONENT_EMBED_FILES := $(SECURE_BOOT_VERIFICATION_KEY)
endif #CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
endif #CONFIG_SECURE_SIGNED_APPS

View File

@@ -1,61 +0,0 @@
// 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.
#pragma once
#include <stdint.h>
#include <esp_err.h>
#include <esp_spi_flash.h> /* including in bootloader for error values */
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Read flash ID by sending 0x9F command
* @return flash raw ID
* mfg_id = (ID >> 16) & 0xFF;
flash_id = ID & 0xffff;
*/
uint32_t bootloader_read_flash_id(void);
#if SOC_CACHE_SUPPORT_WRAP
/**
* @brief Set the burst mode setting command for specified wrap mode.
*
* @param mode The specified warp mode.
* @return always ESP_OK
*/
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode);
#endif
/**
* @brief Startup flow recommended by XMC. Call at startup before any erase/write operation.
*
* @return ESP_OK When startup successfully, otherwise ESP_FAIL (indiciating you should reboot before erase/write).
*/
esp_err_t bootloader_flash_xmc_startup(void);
/**
* @brief Unlock Flash write protect.
* Please do not call this function in SDK.
*
* @note This can be overridden because it's attribute weak.
*/
esp_err_t bootloader_flash_unlock(void);
#ifdef __cplusplus
}
#endif

View File

@@ -14,7 +14,6 @@
#pragma once
#include "sdkconfig.h"
#include "esp_image_format.h"
#ifdef __cplusplus
@@ -28,14 +27,6 @@ extern "C" {
*/
void bootloader_flash_update_id(void);
/**
* @brief Update the flash size in g_rom_flashchip (global esp_rom_spiflash_chip_t structure).
*
* @param size The size to store, in bytes.
* @return None
*/
void bootloader_flash_update_size(uint32_t size);
/**
* @brief Set the flash CS setup and hold time.
*
@@ -75,22 +66,6 @@ void bootloader_flash_gpio_config(const esp_image_header_t* pfhdr);
*/
void bootloader_flash_dummy_config(const esp_image_header_t* pfhdr);
#ifdef CONFIG_IDF_TARGET_ESP32
/**
* @brief Return the pin number used for custom SPI flash and/or SPIRAM WP pin
*
* Can be determined by eFuse values in most cases, or overriden in configuration
*
* This value is only meaningful if the other SPI flash pins are overriden via eFuse.
*
* This value is only meaningful if flash is set to QIO or QOUT mode, or if
* SPIRAM is enabled.
*
* @return Pin number to use, or -1 if the default should be kept
*/
int bootloader_flash_get_wp_pin(void);
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -128,10 +128,6 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length);
* is enabled but secure boot is not used. This should protect against
* serial re-flashing of an unauthorised code in absence of secure boot.
*
* @note On ESP32 V3 only, write protecting FLASH_CRYPT_CNT will also prevent
* disabling UART Download Mode. If both are wanted, call
* esp_efuse_disable_rom_download_mode() before calling this function.
*
*/
void esp_flash_write_protect_crypt_cnt(void);

View File

@@ -42,9 +42,6 @@ extern "C" {
#define PART_FLAG_ENCRYPTED (1<<0)
/* The md5sum value is found this many bytes after the ESP_PARTITION_MAGIC_MD5 offset */
#define ESP_PARTITION_MD5_OFFSET 16
/* Pre-partition table fixed flash offsets */
#define ESP_BOOTLOADER_DIGEST_OFFSET 0x0
#define ESP_BOOTLOADER_OFFSET 0x1000 /* Offset of bootloader image. Has matching value in bootloader KConfig.projbuild file. */

View File

@@ -169,14 +169,6 @@ esp_err_t esp_image_verify_bootloader(uint32_t *length);
*/
esp_err_t esp_image_verify_bootloader_data(esp_image_metadata_t *data);
/**
* @brief Get the flash size of the image
*
* @param app_flash_size The value configured in the image header
* @return Actual size, in bytes.
*/
int esp_image_get_flash_size(esp_image_flash_size_t app_flash_size);
typedef struct {
uint32_t drom_addr;

View File

@@ -16,18 +16,13 @@
#include <stdbool.h>
#include <esp_err.h>
#include "soc/efuse_periph.h"
#include "esp_image_format.h"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/efuse.h"
#else
#include "esp32/rom/secure_boot.h"
#endif
typedef struct ets_secure_boot_signature ets_secure_boot_signature_t;
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
#ifdef CONFIG_SECURE_BOOT_ENABLED
#if !defined(CONFIG_SECURE_SIGNED_ON_BOOT) || !defined(CONFIG_SECURE_SIGNED_ON_UPDATE) || !defined(CONFIG_SECURE_SIGNED_APPS)
#error "internal sdkconfig error, secure boot should always enable all signature options"
#endif
@@ -52,23 +47,16 @@ extern "C" {
static inline bool esp_secure_boot_enabled(void)
{
#if CONFIG_IDF_TARGET_ESP32
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0;
#elif CONFIG_SECURE_BOOT_V2_ENABLED
return ets_use_secure_boot_v2();
#endif
return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
return ets_efuse_secure_boot_enabled();
#endif
return false; /* Secure Boot not enabled in menuconfig */
}
/** @brief Generate secure digest from bootloader image
*
* @important This function is intended to be called from bootloader code only.
*
* This function is only used in the context of the Secure Boot V1 scheme.
*
* If secure boot is not yet enabled for bootloader, this will:
* 1) generate the secure boot key and burn it on EFUSE
* (without enabling R/W protection)
@@ -85,17 +73,18 @@ static inline bool esp_secure_boot_enabled(void)
*/
esp_err_t esp_secure_boot_generate_digest(void);
/** @brief Enable secure boot V1 if it is not already enabled.
/** @brief Enable secure boot if it is not already enabled.
*
* @important If this function succeeds, secure boot V1 is permanently
* @important If this function succeeds, secure boot is permanently
* enabled on the chip via efuse.
*
* @important This function is intended to be called from bootloader code only.
*
* @important In case of Secure Boot V1, this will enable r/w protection
* of secure boot key on EFUSE, therefore it is to be ensured that
* esp_secure_boot_generate_digest() is called before this .If secure boot is not
* yet enabled for bootloader, this will
* @important This will enable r/w protection of secure boot key on EFUSE,
* therefore it is to be ensured that esp_secure_boot_generate_digest()
* is called before this
*
* If secure boot is not yet enabled for bootloader, this will
* 1) enable R/W protection of secure boot key on EFUSE
* 2) enable secure boot by blowing the EFUSE_RD_ABS_DONE_0 efuse.
*
@@ -111,97 +100,35 @@ esp_err_t esp_secure_boot_generate_digest(void);
*/
esp_err_t esp_secure_boot_permanently_enable(void);
/** @brief Enables secure boot V2 if it is not already enabled.
/** @brief Verify the secure boot signature (determinstic ECDSA w/ SHA256) appended to some binary data in flash.
*
* @important If this function succeeds, secure boot V2 is permanently
* enabled on the chip via efuse.
*
* @important This function is intended to be called from bootloader code only.
*
* @important In case of Secure Boot V2, this will enable write protection
* of secure boot key on EFUSE in BLK2. .If secure boot is not
* yet enabled for bootloader, this will
* 1) enable W protection of secure boot key on EFUSE
* 2) enable secure boot by blowing the EFUSE_RD_ABS_DONE_1 efuse.
*
* This function does not verify secure boot of the bootloader (the
* ROM bootloader does this.)
*
* @param image_data Image metadata of the application to be loaded.
*
* Will fail if efuses have been part-burned in a way that indicates
* secure boot should not or could not be correctly enabled.
*
* @return ESP_ERR_INVALID_STATE if efuse state doesn't allow
* secure boot to be enabled cleanly. ESP_OK if secure boot
* is enabled on this chip from now on.
*/
esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data);
/** @brief Verify the secure boot signature appended to some binary data in flash.
*
* For ECDSA Scheme (Secure Boot V1) - deterministic ECDSA w/ SHA256 image
* For RSA Scheme (Secure Boot V2) - RSA-PSS Verification of the SHA-256 image
*
* Public key is compiled into the calling program in the ECDSA Scheme.
* See the apt docs/security/secure-boot-v1.rst or docs/security/secure-boot-v2.rst for details.
* Public key is compiled into the calling program. See docs/security/secure-boot.rst for details.
*
* @param src_addr Starting offset of the data in flash.
* @param length Length of data in bytes. Signature is appended -after- length bytes.
*
* If flash encryption is enabled, the image will be transparently decrypted while being verified.
*
* @note This function doesn't have any fault injection resistance so should not be called
* during a secure boot itself (but can be called when verifying an update, etc.)
*
* @return ESP_OK if signature is valid, ESP_ERR_INVALID_STATE if
* signature fails, ESP_FAIL for other failures (ie can't read flash).
*/
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length);
/** @brief Verify the secure boot signature block (deterministic ECDSA w/ SHA256) based on the SHA256 hash of some data.
*
* Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated.
* @param sig_block Pointer to signature block data
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
*
*/
/** @brief Secure boot verification block, on-flash data format. */
typedef struct {
uint32_t version;
uint8_t signature[64];
} esp_secure_boot_sig_block_t;
/** @brief Verify the ECDSA secure boot signature block for Secure Boot V1.
*
* Calculates Deterministic ECDSA w/ SHA256 based on the SHA256 hash of the image. ECDSA signature
* verification must be enabled in project configuration to use this function.
*
* Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated.
* @param sig_block Pointer to ECDSA signature block data
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
* @param verified_digest Pointer to 32 byte buffer that will receive verified digest if verification completes. (Used during bootloader implementation only, result is invalid otherwise.)
*
*/
esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest);
/** @brief Verify the RSA secure boot signature block for Secure Boot V2.
*
* Performs RSA-PSS Verification of the SHA-256 image based on the public key
* in the signature block, compared against the public key digest stored in efuse.
*
* Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated.
* @param sig_block Pointer to RSA signature block data
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
* @param verified_digest Pointer to 32 byte buffer that will receive verified digest if verification completes. (Used during bootloader implementation only, result is invalid otherwise.)
*
*/
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest);
/** @brief Legacy ECDSA verification function
*
* @note Deprecated, call either esp_secure_boot_verify_ecdsa_signature_block() or esp_secure_boot_verify_rsa_signature_block() instead.
*
* @param sig_block Pointer to ECDSA signature block data
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
*/
esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest)
__attribute__((deprecated("use esp_secure_boot_verify_ecdsa_signature_block instead")));
esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest);
#define FLASH_OFFS_SECURE_BOOT_IV_DIGEST 0

View File

@@ -18,28 +18,9 @@
#include <stdbool.h>
#include <stdint.h>
#include <esp_err.h>
#include <esp_spi_flash.h> /* including in bootloader for error values */
#include "sdkconfig.h"
#include "bootloader_flash.h"
#define FLASH_SECTOR_SIZE 0x1000
#define FLASH_BLOCK_SIZE 0x10000
#define MMAP_ALIGNED_MASK 0x0000FFFF
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
Suitable for use with the bootloader_execute_flash_command static function.
*/
#define CMD_RDID 0x9F
#define CMD_WRSR 0x01
#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
#define CMD_WREN 0x06
#define CMD_WRDI 0x04
#define CMD_RDSR 0x05
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */
#define CMD_WRAP 0x77 /* Set burst with wrap command */
/* Provide a Flash API for bootloader_support code,
that can be used from bootloader or app code.
@@ -153,29 +134,4 @@ static inline uint32_t bootloader_cache_pages_to_map(uint32_t size, uint32_t vad
return (size + (vaddr - (vaddr & MMU_FLASH_MASK)) + MMU_BLOCK_SIZE - 1) / MMU_BLOCK_SIZE;
}
/**
* @brief Execute a user command on the flash
*
* @param command The command value to execute.
* @param mosi_data MOSI data to send
* @param mosi_len Length of MOSI data, in bits
* @param miso_len Length of MISO data to receive, in bits
* @return Received MISO data
*/
uint32_t bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
/**
* @brief Read the SFDP of the flash
*
* @param sfdp_addr Address of the parameter to read
* @param miso_byte_num Bytes to read
* @return The read SFDP, little endian, 4 bytes at most
*/
uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num);
/**
* @brief Enable the flash write protect (WEL bit).
*/
void bootloader_enable_wp(void);
#endif

View File

@@ -99,27 +99,12 @@ __attribute__((noreturn)) void bootloader_reset(void);
esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len);
/**
* @brief Debug log contents of a buffer as hexadecimal.
* @brief Debug log contents of a buffer as hexadecimal
*
* @note - Only works if component log level is DEBUG or higher.
* - It will print at most 128 bytes from @c buffer.
* @note Only works if component log level is DEBUG or higher.
*
* @param buffer Buffer to log
* @param length Length of buffer in bytes. Maximum length 128 bytes.
* @param label Label to print at beginning of log line.
*/
void bootloader_debug_buffer(const void *buffer, size_t length, const char *label);
/** @brief Generates the digest of the data between offset & offset+length.
*
* This function should be used when the size of the data is larger than 3.2MB.
* The MMU capacity is 3.2MB (50 pages - 64KB each). This function generates the SHA-256
* of the data in chunks of 3.2MB, considering the MMU capacity.
*
* @param[in] flash_offset Offset of the data in flash.
* @param[in] len Length of data in bytes.
* @param[out] digest Pointer to buffer where the digest is written, if ESP_OK is returned.
*
* @return ESP_OK if secure boot digest is generated successfully.
*/
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest);

View File

@@ -13,8 +13,6 @@
// limitations under the License.
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -28,9 +28,8 @@
#include "esp32s2beta/rom/gpio.h"
#endif
#include "esp_flash_partitions.h"
#include "bootloader_flash_priv.h"
#include "bootloader_flash.h"
#include "bootloader_common.h"
#include "bootloader_utility.h"
#include "soc/gpio_periph.h"
#include "soc/rtc.h"
#include "soc/efuse_reg.h"
@@ -188,7 +187,22 @@ esp_err_t bootloader_common_get_sha256_of_partition (uint32_t address, uint32_t
size = data.image_len;
}
// If image is type by data then hash is calculated for entire image.
return bootloader_sha256_flash_contents(address, size, out_sha_256);
const void *partition_bin = bootloader_mmap(address, size);
if (partition_bin == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", address, size);
return ESP_FAIL;
}
bootloader_sha256_handle_t sha_handle = bootloader_sha256_start();
if (sha_handle == NULL) {
bootloader_munmap(partition_bin);
return ESP_ERR_NO_MEM;
}
bootloader_sha256_data(sha_handle, partition_bin, size);
bootloader_sha256_finish(sha_handle, out_sha_256);
bootloader_munmap(partition_bin);
return ESP_OK;
}
int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata, bool *valid_two_otadata, bool max)
@@ -234,15 +248,13 @@ esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t
return ESP_ERR_INVALID_ARG;
}
const uint32_t app_desc_offset = sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t);
const uint32_t mmap_size = app_desc_offset + sizeof(esp_app_desc_t);
const uint8_t *image = bootloader_mmap(partition->offset, mmap_size);
const uint8_t *image = bootloader_mmap(partition->offset, partition->size);
if (image == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", partition->offset, mmap_size);
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", partition->offset, partition->size);
return ESP_FAIL;
}
memcpy(app_desc, image + app_desc_offset, sizeof(esp_app_desc_t));
memcpy(app_desc, image + sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t), sizeof(esp_app_desc_t));
bootloader_munmap(image);
if (app_desc->magic_word != ESP_APP_DESC_MAGIC_WORD) {

View File

@@ -13,44 +13,14 @@
// limitations under the License.
#include <stddef.h>
#include <bootloader_flash_priv.h>
#include <bootloader_flash.h>
#include <esp_log.h>
#include <esp_spi_flash.h> /* including in bootloader for error values */
#include <esp_flash_encrypt.h>
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#if CONFIG_IDF_TARGET_ESP32
# include "soc/spi_struct.h"
# include "soc/spi_reg.h"
/* SPI flash controller */
# define SPIFLASH SPI1
#else
# include "soc/spi_mem_struct.h"
# include "soc/spi_mem_reg.h"
/* SPI flash controller */
# define SPIFLASH SPIMEM1
#endif
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/spi_flash.h"
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#if CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/spi_flash.h"
#include "esp32s2beta/rom/ets_sys.h"
#endif
#define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF)
#define ISSI_ID 0x9D
#define MXIC_ID 0xC2
#define GD_Q_ID_HIGH 0xC8
#define GD_Q_ID_MID 0x40
#define GD_Q_ID_LOW 0x16
#define ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2)
#define ESP_BOOTLOADER_SPIFLASH_QE_GD_SR2 BIT1 // QE position when you write 8 bits(for SR2) at one time.
#define ESP_BOOTLOADER_SPIFLASH_QE_SR1_2BYTE BIT9 // QE position when you write 16 bits at one time.
#ifndef BOOTLOADER_BUILD
/* Normal app version maps to esp_spi_flash.h operations...
*/
@@ -120,7 +90,7 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
return spi_flash_erase_range(start_addr, size);
}
#else //BOOTLOADER_BUILD
#else
/* Bootloader version, uses ROM functions only */
#include <soc/dport_reg.h>
#if CONFIG_IDF_TARGET_ESP32
@@ -348,7 +318,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
return ESP_FAIL;
}
err = bootloader_flash_unlock();
err = spi_to_esp_err(esp_rom_spiflash_unlock());
if (err != ESP_OK) {
return err;
}
@@ -394,332 +364,4 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
}
return spi_to_esp_err(rc);
}
#endif // BOOTLOADER_BUILD
FORCE_INLINE_ATTR bool is_issi_chip(const esp_rom_spiflash_chip_t* chip)
{
return BYTESHIFT(chip->device_id, 2) == ISSI_ID;
}
// For GD25Q32, GD25Q64, GD25Q127C, GD25Q128, which use single command to read/write different SR.
FORCE_INLINE_ATTR bool is_gd_q_chip(const esp_rom_spiflash_chip_t* chip)
{
return BYTESHIFT(chip->device_id, 2) == GD_Q_ID_HIGH && BYTESHIFT(chip->device_id, 1) == GD_Q_ID_MID && BYTESHIFT(chip->device_id, 0) >= GD_Q_ID_LOW;
}
FORCE_INLINE_ATTR bool is_mxic_chip(const esp_rom_spiflash_chip_t* chip)
{
return BYTESHIFT(chip->device_id, 2) == MXIC_ID;
}
esp_err_t IRAM_ATTR __attribute__((weak)) bootloader_flash_unlock(void)
{
// At the beginning status == new_status == status_sr2 == new_status_sr2 == 0.
// If the register doesn't need to be updated, keep them the same (0), so that no command will be actually sent.
uint16_t status = 0; // status for SR1 or SR1+SR2 if writing SR with 01H + 2Bytes.
uint16_t new_status = 0;
uint8_t status_sr2 = 0; // status_sr2 for SR2.
uint8_t new_status_sr2 = 0;
uint8_t sr1_bit_num = 0;
esp_err_t err = ESP_OK;
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
if (is_issi_chip(&g_rom_flashchip) || is_mxic_chip(&g_rom_flashchip)) {
// Currently ISSI & MXIC share the same command and register layout, which is different from the default model.
// If any code here needs to be modified, check both chips.
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
/* Clear all bits in the mask.
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
*/
sr1_bit_num = 8;
new_status = status & (~ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI);
} else if (is_gd_q_chip(&g_rom_flashchip)) {
/* The GD chips behaviour is to clear all bits in SR1 and clear bits in SR2 except QE bit.
Use 01H to write SR1 and 31H to write SR2.
*/
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
sr1_bit_num = 8;
new_status = 0;
status_sr2 = bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8);
new_status_sr2 = status_sr2 & ESP_BOOTLOADER_SPIFLASH_QE_GD_SR2;
} else {
/* For common behaviour, like XMC chips, Use 01H+2Bytes to write both SR1 and SR2*/
status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8) | (bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
/* Clear all bits except QE, if it is set.
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
*/
sr1_bit_num = 16;
new_status = status & ESP_BOOTLOADER_SPIFLASH_QE_SR1_2BYTE;
}
// When SR is written, set to true to indicate that WRDI need to be sent to ensure the protection is ON before return.
bool status_written = false;
// Skip if nothing needs to be changed. Meaningless writing to SR increases the risk during write and wastes time.
if (status != new_status) {
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
bootloader_execute_flash_command(CMD_WRSR, new_status, sr1_bit_num, 0);
status_written = true;
}
if (status_sr2 != new_status_sr2) {
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
bootloader_execute_flash_command(CMD_WRSR2, new_status_sr2, 8, 0);
status_written = true;
}
if (status_written) {
//Call esp_rom_spiflash_wait_idle to make sure previous WRSR is completed.
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0);
}
return err;
}
/* dummy_len_plus values defined in ROM for SPI flash configuration */
extern uint8_t g_rom_spiflash_dummy_len_plus[];
IRAM_ATTR static uint32_t bootloader_flash_execute_command_common(
uint8_t command,
uint32_t addr_len, uint32_t address,
uint8_t dummy_len,
uint8_t mosi_len, uint32_t mosi_data,
uint8_t miso_len)
{
assert(mosi_len <= 32);
assert(miso_len <= 32);
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
uint32_t old_user_reg = SPIFLASH.user.val;
uint32_t old_user1_reg = SPIFLASH.user1.val;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
#else
SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
#endif
//command phase
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = command;
//addr phase
SPIFLASH.user.usr_addr = addr_len > 0;
SPIFLASH.user1.usr_addr_bitlen = addr_len - 1;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.addr = (addr_len > 0)? (address << (32-addr_len)) : 0;
#else
SPIFLASH.addr = address;
#endif
//dummy phase
if (miso_len > 0) {
uint32_t total_dummy = dummy_len + g_rom_spiflash_dummy_len_plus[1];
SPIFLASH.user.usr_dummy = total_dummy > 0;
SPIFLASH.user1.usr_dummy_cyclelen = total_dummy - 1;
} else {
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user1.usr_dummy_cyclelen = 0;
}
//output data
SPIFLASH.user.usr_mosi = mosi_len > 0;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
#else
SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0;
#endif
SPIFLASH.data_buf[0] = mosi_data;
//input data
SPIFLASH.user.usr_miso = miso_len > 0;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
#else
SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
#endif
SPIFLASH.cmd.usr = 1;
while (SPIFLASH.cmd.usr != 0) {
}
SPIFLASH.ctrl.val = old_ctrl_reg;
SPIFLASH.user.val = old_user_reg;
SPIFLASH.user1.val = old_user1_reg;
uint32_t ret = SPIFLASH.data_buf[0];
if (miso_len < 32) {
//set unused bits to 0
ret &= ~(UINT32_MAX << miso_len);
}
return ret;
}
uint32_t IRAM_ATTR bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
{
const uint8_t addr_len = 0;
const uint8_t address = 0;
const uint8_t dummy_len = 0;
return bootloader_flash_execute_command_common(command, addr_len, address,
dummy_len, mosi_len, mosi_data, miso_len);
}
// cmd(0x5A) + 24bit address + 8 cycles dummy
uint32_t IRAM_ATTR bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num)
{
assert(miso_byte_num <= 4);
const uint8_t command = CMD_RDSFDP;
const uint8_t addr_len = 24;
const uint8_t dummy_len = 8;
const uint8_t mosi_len = 0;
const uint32_t mosi_data = 0;
const uint8_t miso_len = miso_byte_num * 8;
return bootloader_flash_execute_command_common(command, addr_len, sfdp_addr,
dummy_len, mosi_len, mosi_data, miso_len);
}
void bootloader_enable_wp(void)
{
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
}
uint32_t IRAM_ATTR bootloader_read_flash_id(void)
{
uint32_t id = bootloader_execute_flash_command(CMD_RDID, 0, 0, 24);
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
return id;
}
#if SOC_CACHE_SUPPORT_WRAP
esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
uint32_t reg_bkp_usr = SPIFLASH.user.val;
SPIFLASH.user.fwrite_dio = 0;
SPIFLASH.user.fwrite_dual = 0;
SPIFLASH.user.fwrite_qio = 1;
SPIFLASH.user.fwrite_quad = 0;
SPIFLASH.ctrl.fcmd_dual = 0;
SPIFLASH.ctrl.fcmd_quad = 0;
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 1;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = CMD_WRAP;
SPIFLASH.user1.usr_addr_bitlen = 23;
SPIFLASH.addr = 0;
SPIFLASH.user.usr_miso = 0;
SPIFLASH.user.usr_mosi = 1;
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
SPIFLASH.cmd.usr = 1;
while(SPIFLASH.cmd.usr != 0)
{ }
SPIFLASH.ctrl.val = reg_bkp_ctrl;
SPIFLASH.user.val = reg_bkp_usr;
return ESP_OK;
}
#endif //SOC_CACHE_SUPPORT_WRAP
/*******************************************************************************
* XMC startup flow
******************************************************************************/
#define XMC_SUPPORT CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT
#define XMC_VENDOR_ID 0x20
#if BOOTLOADER_BUILD
#define BOOTLOADER_FLASH_LOG(level, ...) ESP_LOG##level(TAG, ##__VA_ARGS__)
#else
static DRAM_ATTR char bootloader_flash_tag[] = "bootloader_flash";
#define BOOTLOADER_FLASH_LOG(level, ...) ESP_EARLY_LOG##level(bootloader_flash_tag, ##__VA_ARGS__)
#endif
#if XMC_SUPPORT
//strictly check the model
static IRAM_ATTR bool is_xmc_chip_strict(uint32_t rdid)
{
uint32_t vendor_id = BYTESHIFT(rdid, 2);
uint32_t mfid = BYTESHIFT(rdid, 1);
uint32_t cpid = BYTESHIFT(rdid, 0);
if (vendor_id != XMC_VENDOR_ID) {
return false;
}
bool matched = false;
if (mfid == 0x40) {
if (cpid >= 0x13 && cpid <= 0x20) {
matched = true;
}
} else if (mfid == 0x41) {
if (cpid >= 0x17 && cpid <= 0x20) {
matched = true;
}
} else if (mfid == 0x50) {
if (cpid >= 0x15 && cpid <= 0x16) {
matched = true;
}
}
return matched;
}
esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
{
// If the RDID value is a valid XMC one, may skip the flow
const bool fast_check = true;
if (fast_check && is_xmc_chip_strict(g_rom_flashchip.device_id)) {
BOOTLOADER_FLASH_LOG(D, "XMC chip detected by RDID (%08X), skip.", g_rom_flashchip.device_id);
return ESP_OK;
}
// Check the Manufacturer ID in SFDP registers (JEDEC standard). If not XMC chip, no need to run the flow
const int sfdp_mfid_addr = 0x10;
uint8_t mf_id = (bootloader_flash_read_sfdp(sfdp_mfid_addr, 1) & 0xff);
if (mf_id != XMC_VENDOR_ID) {
BOOTLOADER_FLASH_LOG(D, "non-XMC chip detected by SFDP Read (%02X), skip.", mf_id);
return ESP_OK;
}
BOOTLOADER_FLASH_LOG(I, "XM25QHxxC startup flow");
// Enter DPD
bootloader_execute_flash_command(0xB9, 0, 0, 0);
// Enter UDPD
bootloader_execute_flash_command(0x79, 0, 0, 0);
// Exit UDPD
bootloader_execute_flash_command(0xFF, 0, 0, 0);
// Delay tXUDPD
ets_delay_us(2000);
// Release Power-down
bootloader_execute_flash_command(0xAB, 0, 0, 0);
ets_delay_us(20);
// Read flash ID and check again
g_rom_flashchip.device_id = bootloader_read_flash_id();
if (!is_xmc_chip_strict(g_rom_flashchip.device_id)) {
BOOTLOADER_FLASH_LOG(E, "XMC flash startup fail");
return ESP_FAIL;
}
return ESP_OK;
}
#else
//only compare the vendor id
static IRAM_ATTR bool is_xmc_chip(uint32_t rdid)
{
uint32_t vendor_id = (rdid >> 16) & 0xFF;
return (vendor_id == XMC_VENDOR_ID);
}
esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
{
if (is_xmc_chip(g_rom_flashchip.device_id)) {
BOOTLOADER_FLASH_LOG(E, "XMC chip detected (%08X) while support disabled.", g_rom_flashchip.device_id);
return ESP_FAIL;
}
return ESP_OK;
}
#endif //XMC_SUPPORT

View File

@@ -25,7 +25,6 @@
#include "soc/spi_reg.h"
#include "soc/spi_caps.h"
#include "flash_qio_mode.h"
#include "bootloader_common.h"
#include "bootloader_flash_config.h"
void bootloader_flash_update_id(void)
@@ -33,11 +32,6 @@ void bootloader_flash_update_id(void)
g_rom_flashchip.device_id = bootloader_read_flash_id();
}
void bootloader_flash_update_size(uint32_t size)
{
g_rom_flashchip.chip_size = size;
}
void IRAM_ATTR bootloader_flash_cs_timing_config(void)
{
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
@@ -68,7 +62,6 @@ void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t* pfhdr)
break;
}
esp_rom_spiflash_config_clk(spi_clk_div, 0);
esp_rom_spiflash_config_clk(spi_clk_div, 1);
}
void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
@@ -81,11 +74,18 @@ void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
uint32_t pkg_ver = chip_ver & 0x7;
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 ||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 ||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4 ||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302) {
// For ESP32D2WD or ESP32-PICO series,the SPI pins are already configured
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
// For ESP32D2WD the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
// For ESP32PICOD2 the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
// For ESP32PICOD4 the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
@@ -162,33 +162,4 @@ void IRAM_ATTR bootloader_flash_dummy_config(const esp_image_header_t* pfhdr)
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + g_rom_spiflash_dummy_len_plus[0],
SPI_USR_DUMMY_CYCLELEN_S);
}
#define ESP32_D2WD_WP_GPIO 7 /* ESP32-D2WD & ESP32-PICO-D4 has this GPIO wired to WP pin of flash */
#define ESP32_PICO_V3_GPIO 18 /* ESP32-PICO-V3* use this GPIO for WP pin of flash */
int bootloader_flash_get_wp_pin(void)
{
#if CONFIG_BOOTLOADER_SPI_CUSTOM_WP_PIN
return CONFIG_BOOTLOADER_SPI_WP_PIN; // can be set for bootloader when QIO or QOUT config in use
#elif CONFIG_SPIRAM_CUSTOM_SPIWP_SD3_PIN
return CONFIG_SPIRAM_SPIWP_SD3_PIN; // can be set for app when DIO or DOUT config used for PSRAM only
#else
// no custom value, find it based on the package eFuse value
uint8_t chip_ver;
uint32_t pkg_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
switch(pkg_ver) {
case EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5:
return ESP32_D2WD_WP_GPIO;
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2:
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4:
/* Same package IDs are used for ESP32-PICO-V3 and ESP32-PICO-D4, silicon version differentiates */
chip_ver = bootloader_common_get_chip_revision();
return (chip_ver < 3) ? ESP32_D2WD_WP_GPIO : ESP32_PICO_V3_GPIO;
case EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302:
return ESP32_PICO_V3_GPIO;
default:
return SPI_IOMUX_PIN_NUM_WP;
}
#endif
}

View File

@@ -14,10 +14,9 @@
#include <string.h>
#include <stdint.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "bootloader_init.h"
#include "bootloader_flash_priv.h"
#include "bootloader_flash.h"
#include "bootloader_flash_config.h"
#include "bootloader_random.h"
#include "bootloader_clock.h"
@@ -31,7 +30,7 @@
static const char *TAG = "boot";
esp_image_header_t WORD_ALIGNED_ATTR bootloader_image_hdr;
esp_image_header_t bootloader_image_hdr;
void bootloader_clear_bss_section(void)
{

View File

@@ -57,14 +57,13 @@
#include "esp_secure_boot.h"
#include "esp_flash_encrypt.h"
#include "esp_flash_partitions.h"
#include "bootloader_flash_priv.h"
#include "bootloader_flash.h"
#include "bootloader_random.h"
#include "bootloader_config.h"
#include "bootloader_common.h"
#include "bootloader_utility.h"
#include "bootloader_sha.h"
#include "esp_efuse.h"
#include "esp_fault.h"
static const char *TAG = "boot";
@@ -256,16 +255,9 @@ static esp_err_t write_otadata(esp_ota_select_entry_t *otadata, uint32_t offset,
static bool check_anti_rollback(const esp_partition_pos_t *partition)
{
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
esp_app_desc_t app_desc = {};
esp_app_desc_t app_desc;
esp_err_t err = bootloader_common_get_partition_description(partition, &app_desc);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to get partition description %d", err);
return false;
}
bool sec_ver = esp_efuse_check_secure_version(app_desc.secure_version);
/* Anti FI check */
ESP_FAULT_ASSERT(sec_ver == esp_efuse_check_secure_version(app_desc.secure_version));
return sec_ver;
return err == ESP_OK && esp_efuse_check_secure_version(app_desc.secure_version) == true;
#else
return true;
#endif
@@ -278,8 +270,6 @@ static void update_anti_rollback(const esp_partition_pos_t *partition)
esp_err_t err = bootloader_common_get_partition_description(partition, &app_desc);
if (err == ESP_OK) {
esp_efuse_update_secure_version(app_desc.secure_version);
} else {
ESP_LOGE(TAG, "Failed to get partition description %d", err);
}
}
@@ -565,19 +555,11 @@ static void load_image(const esp_image_metadata_t *image_data)
* then Step 6 enables secure boot.
*/
#if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_SECURE_FLASH_ENC_ENABLED)
#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_SECURE_FLASH_ENC_ENABLED)
esp_err_t err;
#endif
#ifdef CONFIG_SECURE_BOOT_V2_ENABLED
err = esp_secure_boot_v2_permanently_enable(image_data);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Secure Boot v2 failed (%d)", err);
return;
}
#endif
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
#ifdef CONFIG_SECURE_BOOT_ENABLED
/* Steps 1 & 2 (see above for full description):
* 1) Generate secure boot EFUSE key
* 2) Compute digest of plaintext bootloader
@@ -604,7 +586,7 @@ static void load_image(const esp_image_metadata_t *image_data)
}
#endif
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
#ifdef CONFIG_SECURE_BOOT_ENABLED
/* Step 6 (see above for full description):
* 6) Burn EFUSE to enable secure boot
*/
@@ -816,52 +798,21 @@ esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_he
void bootloader_debug_buffer(const void *buffer, size_t length, const char *label)
{
#if CONFIG_BOOTLOADER_LOG_LEVEL >= 4
#if BOOT_LOG_LEVEL >= LOG_LEVEL_DEBUG
assert(length <= 128); // Avoid unbounded VLA size
const uint8_t *bytes = (const uint8_t *)buffer;
const size_t output_len = MIN(length, 128);
char hexbuf[128 * 2 + 1];
bootloader_sha256_hex_to_str(hexbuf, bytes, output_len);
hexbuf[output_len * 2] = '\0';
char hexbuf[length * 2 + 1];
hexbuf[length * 2] = 0;
for (int i = 0; i < length; i++) {
for (int shift = 0; shift < 2; shift++) {
uint8_t nibble = (bytes[i] >> (shift ? 0 : 4)) & 0x0F;
if (nibble < 10) {
hexbuf[i * 2 + shift] = '0' + nibble;
} else {
hexbuf[i * 2 + shift] = 'a' + nibble - 10;
}
}
}
ESP_LOGD(TAG, "%s: %s", label, hexbuf);
#else
(void) buffer;
(void) length;
(void) label;
#endif
}
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
{
if (digest == NULL) {
return ESP_ERR_INVALID_ARG;
}
/* Handling firmware images larger than MMU capacity */
uint32_t mmu_free_pages_count = bootloader_mmap_get_free_pages();
bootloader_sha256_handle_t sha_handle = NULL;
sha_handle = bootloader_sha256_start();
if (sha_handle == NULL) {
return ESP_ERR_NO_MEM;
}
while (len > 0) {
uint32_t mmu_page_offset = ((flash_offset & MMAP_ALIGNED_MASK) != 0) ? 1 : 0; /* Skip 1st MMU Page if it is already populated */
uint32_t partial_image_len = MIN(len, ((mmu_free_pages_count - mmu_page_offset) * SPI_FLASH_MMU_PAGE_SIZE)); /* Read the image that fits in the free MMU pages */
const void * image = bootloader_mmap(flash_offset, partial_image_len);
if (image == NULL) {
bootloader_sha256_finish(sha_handle, NULL);
return ESP_FAIL;
}
bootloader_sha256_data(sha_handle, image, partial_image_len);
bootloader_munmap(image);
flash_offset += partial_image_len;
len -= partial_image_len;
}
bootloader_sha256_finish(sha_handle, digest);
return ESP_OK;
}

View File

@@ -22,7 +22,6 @@
#include "bootloader_clock.h"
#include "bootloader_common.h"
#include "bootloader_flash_config.h"
#include "bootloader_flash_priv.h"
#include "soc/cpu.h"
#include "soc/dport_reg.h"
@@ -54,11 +53,18 @@ void bootloader_configure_spi_pins(int drv)
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
uint32_t pkg_ver = chip_ver & 0x7;
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 ||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 ||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4 ||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302) {
// For ESP32D2WD or ESP32-PICO series,the SPI pins are already configured
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
// For ESP32D2WD the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
// For ESP32PICOD2 the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
// For ESP32PICOD4 the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
@@ -258,7 +264,7 @@ static esp_err_t bootloader_init_spi_flash(void)
}
#endif
bootloader_flash_unlock();
esp_rom_spiflash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
bootloader_enable_qio_mode();
@@ -266,8 +272,6 @@ static esp_err_t bootloader_init_spi_flash(void)
print_flash_info(&bootloader_image_hdr);
update_flash_config(&bootloader_image_hdr);
//ensure the flash is write-protected
bootloader_enable_wp();
return ESP_OK;
}
@@ -453,11 +457,6 @@ esp_err_t bootloader_init(void)
bootloader_print_banner();
// update flash ID
bootloader_flash_update_id();
// Check and run XMC startup flow
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
goto err;
}
// read bootloader header
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
goto err;

View File

@@ -14,7 +14,7 @@
#include <strings.h>
#include "bootloader_flash_priv.h"
#include "bootloader_flash.h"
#include "esp_image_format.h"
#include "esp_flash_encrypt.h"
#include "esp_flash_partitions.h"
@@ -73,10 +73,6 @@ esp_err_t esp_flash_encrypt_check_and_update(void)
static esp_err_t initialise_flash_encryption(void)
{
uint32_t new_wdata0 = 0;
uint32_t new_wdata5 = 0;
uint32_t new_wdata6 = 0;
uint32_t coding_scheme = REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_CODING_SCHEME);
if (coding_scheme != EFUSE_CODING_SCHEME_VAL_NONE && coding_scheme != EFUSE_CODING_SCHEME_VAL_34) {
ESP_LOGE(TAG, "Unknown/unsupported CODING_SCHEME value 0x%x", coding_scheme);
@@ -101,10 +97,11 @@ static esp_err_t initialise_flash_encryption(void)
&& REG_READ(EFUSE_BLK1_RDATA7_REG) == 0) {
ESP_LOGI(TAG, "Generating new flash encryption key...");
esp_efuse_write_random_key(EFUSE_BLK1_WDATA0_REG);
// defer efuse programming step to the end
esp_efuse_burn_new_values();
ESP_LOGI(TAG, "Read & write protecting new key...");
new_wdata0 |= EFUSE_WR_DIS_BLK1 | EFUSE_RD_DIS_BLK1;
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK1 | EFUSE_RD_DIS_BLK1);
esp_efuse_burn_new_values();
} else {
if(!(efuse_key_read_protected && efuse_key_write_protected)) {
@@ -125,36 +122,34 @@ static esp_err_t initialise_flash_encryption(void)
operation does nothing. Please note this is not recommended!
*/
ESP_LOGI(TAG, "Setting CRYPT_CONFIG efuse to 0xF");
new_wdata5 |= EFUSE_FLASH_CRYPT_CONFIG_M;
REG_WRITE(EFUSE_BLK0_WDATA5_REG, EFUSE_FLASH_CRYPT_CONFIG_M);
esp_efuse_burn_new_values();
uint32_t new_wdata6 = 0;
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
ESP_LOGI(TAG, "Disable UART bootloader encryption...");
new_wdata6 |= EFUSE_DISABLE_DL_ENCRYPT;
#else
ESP_LOGW(TAG, "Not disabling UART bootloader encryption");
#endif
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC
ESP_LOGI(TAG, "Disable UART bootloader decryption...");
new_wdata6 |= EFUSE_DISABLE_DL_DECRYPT;
#else
ESP_LOGW(TAG, "Not disabling UART bootloader decryption - SECURITY COMPROMISED");
#endif
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
ESP_LOGI(TAG, "Disable UART bootloader MMU cache...");
new_wdata6 |= EFUSE_DISABLE_DL_CACHE;
#else
ESP_LOGW(TAG, "Not disabling UART bootloader MMU cache - SECURITY COMPROMISED");
#endif
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
ESP_LOGI(TAG, "Disable JTAG...");
new_wdata6 |= EFUSE_RD_DISABLE_JTAG;
#else
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
#endif
#ifndef CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC
ESP_LOGI(TAG, "Disable ROM BASIC interpreter fallback...");
new_wdata6 |= EFUSE_RD_CONSOLE_DEBUG_DISABLE;
@@ -162,16 +157,10 @@ static esp_err_t initialise_flash_encryption(void)
ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED");
#endif
#if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS)
// This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot
// otherwise the Flash Encryption key cannot be read protected
new_wdata0 |= EFUSE_WR_DIS_RD_DIS;
#endif
REG_WRITE(EFUSE_BLK0_WDATA0_REG, new_wdata0);
REG_WRITE(EFUSE_BLK0_WDATA5_REG, new_wdata5);
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
esp_efuse_burn_new_values();
if (new_wdata6 != 0) {
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
esp_efuse_burn_new_values();
}
return ESP_OK;
}
@@ -221,19 +210,16 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry
ESP_LOGD(TAG, "All flash regions checked for encryption pass");
uint32_t new_flash_crypt_cnt;
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
// Go straight to max, permanently enabled
ESP_LOGI(TAG, "Setting FLASH_CRYPT_CNT for permanent encryption");
new_flash_crypt_cnt = EFUSE_FLASH_CRYPT_CNT;
#else
/* Set least significant 0-bit in flash_crypt_cnt */
int ffs_inv = __builtin_ffs((~flash_crypt_cnt) & EFUSE_RD_FLASH_CRYPT_CNT);
/* ffs_inv shouldn't be zero, as zero implies flash_crypt_cnt == EFUSE_RD_FLASH_CRYPT_CNT (0x7F) */
new_flash_crypt_cnt = flash_crypt_cnt + (1 << (ffs_inv - 1));
#endif
uint32_t new_flash_crypt_cnt = flash_crypt_cnt + (1 << (ffs_inv - 1));
ESP_LOGD(TAG, "FLASH_CRYPT_CNT 0x%x -> 0x%x", flash_crypt_cnt, new_flash_crypt_cnt);
uint32_t wdata0_reg = ((new_flash_crypt_cnt & EFUSE_FLASH_CRYPT_CNT) << EFUSE_FLASH_CRYPT_CNT_S);
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
ESP_LOGI(TAG, "Write protecting FLASH_CRYPT_CNT eFuse");
wdata0_reg |= EFUSE_WR_DIS_FLASH_CRYPT_CNT;
#endif
REG_WRITE(EFUSE_BLK0_WDATA0_REG, wdata0_reg);
esp_efuse_burn_new_values();
@@ -250,22 +236,13 @@ static esp_err_t encrypt_bootloader(void)
/* Check for plaintext bootloader (verification will fail if it's already encrypted) */
if (esp_image_verify_bootloader(&image_length) == ESP_OK) {
ESP_LOGD(TAG, "bootloader is plaintext. Encrypting...");
#if CONFIG_SECURE_BOOT_V2_ENABLED
/* The image length obtained from esp_image_verify_bootloader includes the sector boundary padding and the signature block lengths */
if (ESP_BOOTLOADER_OFFSET + image_length > ESP_PARTITION_TABLE_OFFSET) {
ESP_LOGE(TAG, "Bootloader is too large to fit Secure Boot V2 signature sector and partition table (configured offset 0x%x)", ESP_PARTITION_TABLE_OFFSET);
return ESP_ERR_INVALID_STATE;
}
#endif // CONFIG_SECURE_BOOT_V2_ENABLED
err = esp_flash_encrypt_region(ESP_BOOTLOADER_OFFSET, image_length);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);
return err;
}
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
#ifdef CONFIG_SECURE_BOOT_ENABLED
/* If secure boot is enabled and bootloader was plaintext, also
* need to encrypt secure boot IV+digest.
*/
@@ -378,4 +355,4 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)
flash_failed:
ESP_LOGE(TAG, "flash operation failed: 0x%x", err);
return err;
}
}

View File

@@ -20,16 +20,14 @@
#include "esp32/rom/cache.h"
#include "esp32/rom/ets_sys.h"
#include "esp32/rom/crc.h"
#include "esp32/rom/secure_boot.h"
#include "soc/efuse_periph.h"
#include "soc/rtc_periph.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "sdkconfig.h"
#include "bootloader_flash_priv.h"
#include "bootloader_flash.h"
#include "bootloader_random.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
@@ -40,8 +38,8 @@
* from the bootloader code.
*/
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
static const char *TAG = "secure_boot_v1";
static const char* TAG = "secure_boot";
/**
* @function : secure_boot_generate
* @description: generate boot digest (aka "abstract") & iv
@@ -96,6 +94,12 @@ static bool secure_boot_generate(uint32_t image_len){
return true;
}
/* Burn values written to the efuse write registers */
static inline void burn_efuses(void)
{
esp_efuse_burn_new_values();
}
esp_err_t esp_secure_boot_generate_digest(void)
{
esp_err_t err;
@@ -135,7 +139,7 @@ esp_err_t esp_secure_boot_generate_digest(void)
&& REG_READ(EFUSE_BLK2_RDATA7_REG) == 0) {
ESP_LOGI(TAG, "Generating new secure boot key...");
esp_efuse_write_random_key(EFUSE_BLK2_WDATA0_REG);
esp_efuse_burn_new_values();
burn_efuses();
} else {
ESP_LOGW(TAG, "Using pre-loaded secure boot key in EFUSE block 2");
}
@@ -158,9 +162,6 @@ esp_err_t esp_secure_boot_generate_digest(void)
esp_err_t esp_secure_boot_permanently_enable(void)
{
uint32_t new_wdata0 = 0;
uint32_t new_wdata6 = 0;
if (esp_secure_boot_enabled()) {
ESP_LOGI(TAG, "bootloader secure boot is already enabled, continuing..");
return ESP_OK;
@@ -172,7 +173,8 @@ esp_err_t esp_secure_boot_permanently_enable(void)
if (efuse_key_read_protected == false
&& efuse_key_write_protected == false) {
ESP_LOGI(TAG, "Read & write protecting new key...");
new_wdata0 = EFUSE_WR_DIS_BLK2 | EFUSE_RD_DIS_BLK2;
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK2 | EFUSE_RD_DIS_BLK2);
burn_efuses();
efuse_key_read_protected = true;
efuse_key_write_protected = true;
}
@@ -189,7 +191,7 @@ esp_err_t esp_secure_boot_permanently_enable(void)
ESP_LOGI(TAG, "blowing secure boot efuse...");
ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG));
new_wdata6 |= EFUSE_RD_ABS_DONE_0;
uint32_t new_wdata6 = EFUSE_RD_ABS_DONE_0;
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
ESP_LOGI(TAG, "Disable JTAG...");
@@ -205,9 +207,8 @@ esp_err_t esp_secure_boot_permanently_enable(void)
ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED");
#endif
REG_WRITE(EFUSE_BLK0_WDATA0_REG, new_wdata0);
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
esp_efuse_burn_new_values();
burn_efuses();
uint32_t after = REG_READ(EFUSE_BLK0_RDATA6_REG);
ESP_LOGD(TAG, "after updating, EFUSE_BLK0_RDATA6 %x", after);
if (after & EFUSE_RD_ABS_DONE_0) {
@@ -218,228 +219,3 @@ esp_err_t esp_secure_boot_permanently_enable(void)
return ESP_ERR_INVALID_STATE;
}
}
#elif CONFIG_SECURE_BOOT_V2_ENABLED
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
static const char *TAG = "secure_boot_v2";
#define SIG_BLOCK_MAGIC_BYTE 0xe7
#define CRC_SIGN_BLOCK_LEN 1196
#define SIG_BLOCK_PADDING 4096
#define DIGEST_LEN 32
static esp_err_t validate_signature_block(const ets_secure_boot_signature_t *sig_block, uint8_t *digest)
{
uint32_t crc = crc32_le(0, (uint8_t *)sig_block, CRC_SIGN_BLOCK_LEN);
if (sig_block->block[0].magic_byte == SIG_BLOCK_MAGIC_BYTE && sig_block->block[0].block_crc == crc && !memcmp(digest, sig_block->block[0].image_digest, DIGEST_LEN)) {
ESP_LOGI(TAG, "valid signature block found");
return ESP_OK;
}
return ESP_FAIL;
}
static esp_err_t secure_boot_v2_digest_generate(uint32_t flash_offset, uint32_t flash_size, uint8_t *public_key_digest)
{
esp_err_t ret = ESP_FAIL;
uint8_t image_digest[DIGEST_LEN] = {0};
size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "error generating image digest, %d", ret);
return ret;
}
ESP_LOGD(TAG, "reading signature block");
const ets_secure_boot_signature_t *sig_block = bootloader_mmap(sig_block_addr, sizeof(ets_secure_boot_signature_t));
if (sig_block == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", sig_block_addr, sizeof(ets_secure_boot_signature_t));
return ret;
}
/* Validating Signature block */
ret = validate_signature_block(sig_block, image_digest);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "signature block (address 0x%x) validation failed %d", sig_block_addr, ret);
goto done;
}
/* Verifying Signature block */
uint8_t verified_digest[DIGEST_LEN] = {0};
/* Generating the SHA of the public key components in the signature block */
bootloader_sha256_handle_t sig_block_sha;
sig_block_sha = bootloader_sha256_start();
bootloader_sha256_data(sig_block_sha, &sig_block->block[0].key, sizeof(sig_block->block[0].key));
bootloader_sha256_finish(sig_block_sha, public_key_digest);
secure_boot_v2_status_t error;
error = ets_secure_boot_verify_signature(sig_block, image_digest, public_key_digest, verified_digest);
if (error != SBV2_SUCCESS) {
ESP_LOGE(TAG, "secure boot v2 verification failed %d", error);
ret = ESP_FAIL;
goto done;
} else {
ret = ESP_OK;
}
done:
bootloader_munmap(sig_block);
return ret;
}
esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data)
{
uint32_t new_wdata0 = 0;
uint32_t new_wdata6 = 0;
ESP_LOGI(TAG, "enabling secure boot v2...");
esp_err_t ret;
if (esp_secure_boot_enabled()) {
ESP_LOGI(TAG, "secure boot v2 is already enabled. Continuing..");
return ESP_OK;
}
uint32_t coding_scheme = REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_CODING_SCHEME);
if (coding_scheme != EFUSE_CODING_SCHEME_VAL_NONE) {
ESP_LOGE(TAG, "No coding schemes are supported in secure boot v2.(Detected scheme: 0x%x)", coding_scheme);
return ESP_ERR_NOT_SUPPORTED;
}
/* Verify the bootloader */
esp_image_metadata_t bootloader_data = { 0 };
ret = esp_image_verify_bootloader_data(&bootloader_data);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "bootloader image appears invalid! error %d", ret);
return ret;
}
uint8_t boot_pub_key_digest[DIGEST_LEN];
uint32_t dis_reg = REG_READ(EFUSE_BLK0_RDATA0_REG);
bool efuse_key_read_protected = dis_reg & EFUSE_RD_DIS_BLK2;
bool efuse_key_write_protected = dis_reg & EFUSE_WR_DIS_BLK2;
uint32_t efuse_blk2_r0, efuse_blk2_r1, efuse_blk2_r2, efuse_blk2_r3, efuse_blk2_r4, efuse_blk2_r5, efuse_blk2_r6, efuse_blk2_r7;
efuse_blk2_r0 = REG_READ(EFUSE_BLK2_RDATA0_REG);
efuse_blk2_r1 = REG_READ(EFUSE_BLK2_RDATA1_REG);
efuse_blk2_r2 = REG_READ(EFUSE_BLK2_RDATA2_REG);
efuse_blk2_r3 = REG_READ(EFUSE_BLK2_RDATA3_REG);
efuse_blk2_r4 = REG_READ(EFUSE_BLK2_RDATA4_REG);
efuse_blk2_r5 = REG_READ(EFUSE_BLK2_RDATA5_REG);
efuse_blk2_r6 = REG_READ(EFUSE_BLK2_RDATA6_REG);
efuse_blk2_r7 = REG_READ(EFUSE_BLK2_RDATA7_REG);
if (efuse_key_read_protected == true) {
ESP_LOGE(TAG, "Secure Boot v2 digest(BLK2) read protected, aborting....");
return ESP_FAIL;
}
if (efuse_key_write_protected == false
&& efuse_blk2_r0 == 0 && efuse_blk2_r1 == 0
&& efuse_blk2_r2 == 0 && efuse_blk2_r3 == 0
&& efuse_blk2_r4 == 0 && efuse_blk2_r5 == 0
&& efuse_blk2_r6 == 0 && efuse_blk2_r7 == 0) {
/* Verifies the signature block appended to the image matches with the signature block of the app to be loaded */
ret = secure_boot_v2_digest_generate(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, boot_pub_key_digest);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Public key digest generation failed");
return ret;
}
ESP_LOGI(TAG, "Burning public key hash to efuse.");
uint32_t *boot_public_key_digest_ptr = (uint32_t *) boot_pub_key_digest;
for (int i = 0; i < 8 ; i++) {
REG_WRITE(EFUSE_BLK2_WDATA0_REG + 4 * i, boot_public_key_digest_ptr[i]);
ESP_LOGD(TAG, "EFUSE_BLKx_WDATA%d_REG = 0x%08x", i, boot_public_key_digest_ptr[i]);
}
// delay burning until second half of this function
} else {
uint32_t efuse_blk2_digest[8];
efuse_blk2_digest[0] = efuse_blk2_r0;
efuse_blk2_digest[1] = efuse_blk2_r1;
efuse_blk2_digest[2] = efuse_blk2_r2;
efuse_blk2_digest[3] = efuse_blk2_r3;
efuse_blk2_digest[4] = efuse_blk2_r4;
efuse_blk2_digest[5] = efuse_blk2_r5;
efuse_blk2_digest[6] = efuse_blk2_r6;
efuse_blk2_digest[7] = efuse_blk2_r7;
memcpy(boot_pub_key_digest, efuse_blk2_digest, DIGEST_LEN);
ESP_LOGW(TAG, "Using pre-loaded secure boot v2 public key digest in EFUSE block 2");
}
// This case is needed either if a pre-burned digest is present but not write-protected,
// or if we are burning the digest now
if (efuse_key_write_protected == false) {
ESP_LOGI(TAG, "Write protecting public key digest...");
new_wdata0 |= EFUSE_WR_DIS_BLK2; // delay burning until second half of this function
}
uint8_t app_pub_key_digest[DIGEST_LEN];
ret = secure_boot_v2_digest_generate(image_data->start_addr, image_data->image_len - SIG_BLOCK_PADDING, app_pub_key_digest);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Application signature block is invalid.");
return ret;
}
/* Confirming if the public key in the bootloader's signature block matches with the one in the application's signature block */
if (memcmp(boot_pub_key_digest, app_pub_key_digest, DIGEST_LEN) != 0) {
ESP_LOGE(TAG, "Application not signed with a valid private key.");
return ESP_FAIL;
}
if (efuse_key_read_protected) {
ESP_LOGE(TAG, "Efuse BLK2 (public key digest) is read protected. Refusing to blow secure boot efuse.");
return ESP_ERR_INVALID_STATE;
}
ESP_LOGI(TAG, "blowing secure boot efuse...");
ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG));
new_wdata6 |= EFUSE_RD_ABS_DONE_1;
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
ESP_LOGI(TAG, "Disable JTAG...");
new_wdata6 |= EFUSE_RD_DISABLE_JTAG;
#else
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
#endif
#ifndef CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC
ESP_LOGI(TAG, "Disable ROM BASIC interpreter fallback...");
new_wdata6 |= EFUSE_RD_CONSOLE_DEBUG_DISABLE;
#else
ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED");
#endif
#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
bool rd_dis_now = true;
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
/* If flash encryption is not enabled yet then don't read-disable efuses yet, do it later in the boot
when Flash Encryption is being enabled */
rd_dis_now = esp_flash_encryption_enabled();
#endif
if (rd_dis_now) {
ESP_LOGI(TAG, "Prevent read disabling of additional efuses...");
new_wdata0 |= EFUSE_WR_DIS_RD_DIS;
}
#else
ESP_LOGW(TAG, "Allowing read disabling of additional efuses - SECURITY COMPROMISED");
#endif
REG_WRITE(EFUSE_BLK0_WDATA0_REG, new_wdata0);
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
esp_efuse_burn_new_values();
uint32_t after = REG_READ(EFUSE_BLK0_RDATA6_REG);
ESP_LOGD(TAG, "after updating, EFUSE_BLK0_RDATA0 0x%08x EFUSE_BLK0_RDATA6 0x%08x",
REG_READ(EFUSE_BLK0_RDATA0_REG), after);
if (after & EFUSE_RD_ABS_DONE_1) {
ESP_LOGI(TAG, "secure boot v2 is now enabled.");
return ESP_OK;
} else {
ESP_LOGE(TAG, " secure boot v2 not enabled, EFUSE_RD_ABS_DONE_1 is probably write protected!");
return ESP_ERR_INVALID_STATE;
}
}
#endif // CONFIG_SECURE_BOOT_V2_ENABLED

View File

@@ -13,42 +13,64 @@
// limitations under the License.
#include "sdkconfig.h"
#include "bootloader_flash_priv.h"
#include "bootloader_flash.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp_spi_flash.h"
#include "esp_fault.h"
#include "esp32/rom/sha.h"
#include "uECC_verify_antifault.h"
#include "uECC.h"
#include <sys/param.h>
#include <string.h>
static const char *TAG = "secure_boot";
#define DIGEST_LEN 32
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start");
extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end");
#define SIGNATURE_VERIFICATION_KEYLEN 64
#define DIGEST_LEN 32
/* Mmap source address mask */
#define MMAP_ALIGNED_MASK 0x0000FFFF
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[DIGEST_LEN];
uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* ignored in this function */
const uint8_t *data;
const esp_secure_boot_sig_block_t *sigblock;
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest);
if (err != ESP_OK) {
return err;
bootloader_sha256_handle_t handle = bootloader_sha256_start();
uint32_t free_page_count = bootloader_mmap_get_free_pages();
ESP_LOGD(TAG, "free data page_count 0x%08x", free_page_count);
int32_t data_len_remain = length;
uint32_t data_addr = src_addr;
while (data_len_remain > 0) {
uint32_t offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0) ? 1 : 0;
/* Data we could map in case we are not aligned to PAGE boundary is one page size lesser. */
uint32_t data_len = MIN(data_len_remain, ((free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE));
data = (const uint8_t *) bootloader_mmap(data_addr, data_len);
if(!data) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", data_addr, data_len);
bootloader_sha256_finish(handle, NULL);
return ESP_FAIL;
}
bootloader_sha256_data(handle, data, data_len);
bootloader_munmap(data);
data_addr += data_len;
data_len_remain -= data_len;
}
/* Done! Get the digest */
bootloader_sha256_finish(handle, digest);
// Map the signature block
sigblock = (const esp_secure_boot_sig_block_t *) bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t));
if(!sigblock) {
@@ -56,7 +78,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
return ESP_FAIL;
}
// Verify the signature
err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest);
esp_err_t err = esp_secure_boot_verify_signature_block(sigblock, digest);
// Unmap
bootloader_munmap(sigblock);
@@ -64,12 +86,6 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
}
esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest)
{
uint8_t verified_digest[DIGEST_LEN] = { 0 };
return esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest);
}
esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
ptrdiff_t keylen;
@@ -87,98 +103,11 @@ esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig
ESP_LOGD(TAG, "Verifying secure boot signature");
bool is_valid;
is_valid = uECC_verify_antifault(signature_verification_key_start,
is_valid = uECC_verify(signature_verification_key_start,
image_digest,
DIGEST_LEN,
sig_block->signature,
uECC_secp256r1(),
verified_digest);
uECC_secp256r1());
ESP_LOGD(TAG, "Verification result %d", is_valid);
return is_valid ? ESP_OK : ESP_ERR_IMAGE_INVALID;
}
#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[DIGEST_LEN] = {0};
uint8_t verified_digest[DIGEST_LEN] = {0}; // ignored in this function
const uint8_t *data;
/* Padding to round off the input to the nearest 4k boundary */
int padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
ESP_LOGD(TAG, "verifying src_addr 0x%x length", src_addr, padded_length);
data = bootloader_mmap(src_addr, padded_length + sizeof(ets_secure_boot_signature_t));
if (data == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, padded_length);
return ESP_FAIL;
}
/* Calculate digest of main image */
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length);
bootloader_munmap(data);
return err;
}
const ets_secure_boot_signature_t *sig_block = (const ets_secure_boot_signature_t *)(data + padded_length);
err = esp_secure_boot_verify_rsa_signature_block(sig_block, digest, verified_digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
}
bootloader_munmap(data);
return err;
}
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
secure_boot_v2_status_t r;
uint8_t efuse_trusted_digest[DIGEST_LEN] = {0}, sig_block_trusted_digest[DIGEST_LEN] = {0};
memcpy(efuse_trusted_digest, (uint8_t *)EFUSE_BLK2_RDATA0_REG, DIGEST_LEN); /* EFUSE_BLK2_RDATA0_REG - Stores the Secure Boot Public Key Digest */
if (!ets_use_secure_boot_v2()) {
ESP_LOGI(TAG, "Secure Boot eFuse bit(ABS_DONE_1) not yet programmed.");
/* Generating the SHA of the public key components in the signature block */
bootloader_sha256_handle_t sig_block_sha;
sig_block_sha = bootloader_sha256_start();
bootloader_sha256_data(sig_block_sha, &sig_block->block[0].key, sizeof(sig_block->block[0].key));
bootloader_sha256_finish(sig_block_sha, (unsigned char *)sig_block_trusted_digest);
#if CONFIG_SECURE_BOOT_V2_ENABLED
if (memcmp(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN) != 0) {
/* Most likely explanation for this is that BLK2 is empty, and we're going to burn it
after we verify that the signature is valid. However, if BLK2 is not empty then we need to
fail here.
*/
bool all_zeroes = true;
for (int i = 0; i < DIGEST_LEN; i++) {
all_zeroes = all_zeroes && (efuse_trusted_digest[i] == 0);
}
if (!all_zeroes) {
ESP_LOGE(TAG, "Different public key digest burned to eFuse BLK2");
return ESP_ERR_INVALID_STATE;
}
}
ESP_FAULT_ASSERT(!ets_use_secure_boot_v2());
#endif
memcpy(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN);
}
ESP_LOGI(TAG, "Verifying with RSA-PSS...");
r = ets_secure_boot_verify_signature(sig_block, image_digest, efuse_trusted_digest, verified_digest);
if (r != SBV2_SUCCESS) {
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
}
return (r == SBV2_SUCCESS) ? ESP_OK : ESP_ERR_IMAGE_INVALID;
}
#endif

View File

@@ -24,7 +24,6 @@
#include "bootloader_init.h"
#include "bootloader_clock.h"
#include "bootloader_flash_config.h"
#include "bootloader_flash_priv.h"
#include "esp32s2beta/rom/cache.h"
#include "esp32s2beta/rom/ets_sys.h"
@@ -218,7 +217,7 @@ static esp_err_t bootloader_init_spi_flash(void)
}
#endif
bootloader_flash_unlock();
esp_rom_spiflash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
bootloader_enable_qio_mode();
@@ -226,8 +225,6 @@ static esp_err_t bootloader_init_spi_flash(void)
print_flash_info(&bootloader_image_hdr);
update_flash_config(&bootloader_image_hdr);
//ensure the flash is write-protected
bootloader_enable_wp();
return ESP_OK;
}
@@ -379,11 +376,6 @@ esp_err_t bootloader_init(void)
bootloader_print_banner();
// update flash ID
bootloader_flash_update_id();
// Check and run XMC startup flow
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
goto err;
}
// read bootloader header
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
goto err;

View File

@@ -14,7 +14,7 @@
#include <strings.h>
#include "bootloader_flash_priv.h"
#include "bootloader_flash.h"
#include "bootloader_random.h"
#include "bootloader_utility.h"
#include "esp_image_format.h"
@@ -191,15 +191,6 @@ static esp_err_t encrypt_bootloader(void)
/* Check for plaintext bootloader (verification will fail if it's already encrypted) */
if (esp_image_verify_bootloader(&image_length) == ESP_OK) {
ESP_LOGD(TAG, "bootloader is plaintext. Encrypting...");
#if CONFIG_SECURE_BOOT_V2_ENABLED
/* The image length obtained from esp_image_verify_bootloader includes the sector boundary padding and the signature block lengths */
if (ESP_BOOTLOADER_OFFSET + image_length > ESP_PARTITION_TABLE_OFFSET) {
ESP_LOGE(TAG, "Bootloader is too large to fit Secure Boot V2 signature sector and partition table (configured offset 0x%x)", ESP_PARTITION_TABLE_OFFSET);
return ESP_ERR_INVALID_SIZE;
}
#endif // CONFIG_SECURE_BOOT_V2_ENABLED
err = esp_flash_encrypt_region(ESP_BOOTLOADER_OFFSET, image_length);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);

View File

@@ -15,7 +15,7 @@
#include "esp_log.h"
#include "esp32s2beta/rom/secure_boot.h"
static const char *TAG = "secure_boot";
#define TAG "secure_boot"
esp_err_t esp_secure_boot_permanently_enable(void)
{

View File

@@ -27,7 +27,6 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
ets_secure_boot_key_digests_t trusted_keys = { 0 };
uint8_t digest[DIGEST_LEN];
uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */
const uint8_t *data;
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
@@ -38,7 +37,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
}
data = bootloader_mmap(src_addr, length + sizeof(struct ets_secure_boot_sig_block));
if (data == NULL) {
if(data == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(ets_secure_boot_signature_t));
return ESP_FAIL;
}
@@ -58,25 +57,36 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
if (r == ETS_OK) {
const ets_secure_boot_signature_t *sig = (const ets_secure_boot_signature_t *)(data + length);
// TODO: calling this function in IDF app context is unsafe
r = ets_secure_boot_verify_signature(sig, digest, &trusted_keys, verified_digest);
r = ets_secure_boot_verify_signature(sig, digest, &trusted_keys);
}
bootloader_munmap(data);
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
esp_err_t esp_secure_boot_verify_signature_block(uint32_t sig_block_flash_offs, const uint8_t *image_digest)
{
ets_secure_boot_key_digests_t trusted_keys;
assert(sig_block_flash_offs % 4096 == 0); // TODO: enforce this in a better way
const ets_secure_boot_signature_t *sig = bootloader_mmap(sig_block_flash_offs, sizeof(ets_secure_boot_signature_t));
if (sig == NULL) {
ESP_LOGE(TAG, "Failed to mmap data at offset 0x%x", sig_block_flash_offs);
return ESP_FAIL;
}
int r = ets_secure_boot_read_key_digests(&trusted_keys);
if (r != 0) {
ESP_LOGE(TAG, "No trusted key digests were found in efuse!");
} else {
ESP_LOGD(TAG, "Verifying with RSA-PSS...");
// TODO: calling this function in IDF app context is unsafe
r = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest);
r = ets_secure_boot_verify_signature(sig, image_digest, &trusted_keys);
}
bootloader_munmap(sig);
return (r == 0) ? ESP_OK : ESP_ERR_IMAGE_INVALID;
}

View File

@@ -16,16 +16,13 @@
#include <soc/cpu.h>
#include <bootloader_utility.h>
#include <esp_secure_boot.h>
#include <esp_fault.h>
#include <esp_log.h>
#include <esp_attr.h>
#include <esp_spi_flash.h>
#include <bootloader_flash_priv.h>
#include <bootloader_flash.h>
#include <bootloader_random.h>
#include <bootloader_sha.h>
#include "bootloader_util.h"
#include "bootloader_common.h"
#include "soc/soc_memory_layout.h"
#if CONFIG_IDF_TARGET_ESP32
#include <esp32/rom/rtc.h>
#include <esp32/rom/secure_boot.h>
@@ -40,11 +37,11 @@
*/
#ifdef BOOTLOADER_BUILD
#ifdef CONFIG_SECURE_SIGNED_ON_BOOT
#define SECURE_BOOT_CHECK_SIGNATURE 1
#define SECURE_BOOT_CHECK_SIGNATURE
#endif
#else /* !BOOTLOADER_BUILD */
#ifdef CONFIG_SECURE_SIGNED_ON_UPDATE
#define SECURE_BOOT_CHECK_SIGNATURE 1
#define SECURE_BOOT_CHECK_SIGNATURE
#endif
#endif
@@ -58,12 +55,18 @@ static const char *TAG = "esp_image";
/* Headroom to ensure between stack SP (at time of checking) and data loaded from flash */
#define STACK_LOAD_HEADROOM 32768
/* Mmap source address mask */
#define MMAP_ALIGNED_MASK 0x0000FFFF
#ifdef BOOTLOADER_BUILD
/* 64 bits of random data to obfuscate loaded RAM with, until verification is complete
(Means loaded code isn't executable until after the secure boot check.)
*/
static uint32_t ram_obfs_value[2];
/* Range of IRAM used by the loader, defined in ld script */
extern int _loader_text_start;
extern int _loader_text_end;
#endif
/* Return true if load_addr is an address the bootloader should load into */
@@ -94,7 +97,7 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t checksum_word, esp_image_metadata_t *data);
static esp_err_t __attribute__((unused)) verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest);
static esp_err_t __attribute__((unused)) verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data);
static esp_err_t __attribute__((unused)) verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data);
static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data)
@@ -112,11 +115,6 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
uint32_t checksum_word = ESP_ROM_CHECKSUM_INITIAL;
uint32_t *checksum = NULL;
bootloader_sha256_handle_t sha_handle = NULL;
#if SECURE_BOOT_CHECK_SIGNATURE
/* used for anti-FI checks */
uint8_t image_digest[HASH_LEN] = { [ 0 ... 31] = 0xEE };
uint8_t verified_digest[HASH_LEN] = { [ 0 ... 31 ] = 0x01 };
#endif
if (data == NULL || part == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -174,7 +172,6 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
for (int i = 0; i < data->image.segment_count; i++) {
esp_image_segment_header_t *header = &data->segments[i];
ESP_LOGV(TAG, "loading segment header %d at offset 0x%x", i, next_addr);
err = process_segment(i, next_addr, header, silent, do_load, sha_handle, checksum);
if (err != ESP_OK) {
goto err;
@@ -200,14 +197,14 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
}
}
/* For secure boot V1 on ESP32, we don't calculate SHA or verify signature on bootloaders.
For Secure Boot V2, we do verify signature on bootloader which includes the SHA calculation.
/* For secure boot on ESP32, we don't calculate SHA or verify signautre on bootloaders.
For ESP32S2, we do verify signature on botoloaders which includes the SHA calculation.
(For non-secure boot, we don't verify any SHA-256 hash appended to the bootloader because
esptool.py may have rewritten the header - rely on esptool.py having verified the bootloader at flashing time, instead.)
*/
bool verify_sha;
#if CONFIG_SECURE_BOOT_V2_ENABLED
#if defined(CONFIG_SECURE_BOOT_ENABLED) && defined(CONFIG_IDF_TARGET_ESP32S2BETA)
verify_sha = true;
#else // ESP32, or ESP32S2 without secure boot enabled
verify_sha = (data->start_addr != ESP_BOOTLOADER_OFFSET);
@@ -220,18 +217,8 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
#ifdef SECURE_BOOT_CHECK_SIGNATURE
// secure boot images have a signature appended
#if defined(BOOTLOADER_BUILD) && !defined(CONFIG_SECURE_BOOT)
// If secure boot is not enabled in hardware, then
// skip the signature check in bootloader when the debugger is attached.
// This is done to allow for breakpoints in Flash.
if (!esp_cpu_in_ocd_debug_mode()) {
#else // CONFIG_SECURE_BOOT
if (true) {
#endif // end checking for JTAG
err = verify_secure_boot_signature(sha_handle, data, image_digest, verified_digest);
sha_handle = NULL; // verify_secure_boot_signature finishes sha_handle
}
#else // SECURE_BOOT_CHECK_SIGNATURE
err = verify_secure_boot_signature(sha_handle, data);
#else
// No secure boot, but SHA-256 can be appended for basic corruption detection
if (sha_handle != NULL && !esp_cpu_in_ocd_debug_mode()) {
err = verify_simple_hash(sha_handle, data);
@@ -263,28 +250,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
}
#ifdef BOOTLOADER_BUILD
#ifdef SECURE_BOOT_CHECK_SIGNATURE
/* If signature was checked in bootloader build, verified_digest should equal image_digest
This is to detect any fault injection that caused signature verification to not complete normally.
Any attack which bypasses this check should be of limited use as the RAM contents are still obfuscated, therefore we do the check
immediately before we deobfuscate.
Note: the conditions for making this check are the same as for setting verify_sha above, but on ESP32 SB V1 we move the test for
"only verify signature in bootloader" into the macro so it's tested multiple times.
*/
#if CONFIG_SECURE_BOOT_V2_ENABLED
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) == 0);
#else // Secure Boot V1 on ESP32, only verify signatures for apps not bootloaders
ESP_FAULT_ASSERT(data->start_addr == ESP_BOOTLOADER_OFFSET || memcmp(image_digest, verified_digest, HASH_LEN) == 0);
#endif
#endif // SECURE_BOOT_CHECK_SIGNATURE
// Deobfuscate RAM
if (do_load && ram_obfs_value[0] != 0 && ram_obfs_value[1] != 0) {
if (do_load && ram_obfs_value[0] != 0 && ram_obfs_value[1] != 0) { // Need to deobfuscate RAM
for (int i = 0; i < data->image.segment_count; i++) {
uint32_t load_addr = data->segments[i].load_addr;
if (should_load(load_addr)) {
@@ -370,127 +336,6 @@ static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t
return err;
}
#ifdef BOOTLOADER_BUILD
/* Check the region load_addr - load_end doesn't overlap any memory used by the bootloader, registers, or other invalid memory
*/
static bool verify_load_addresses(int segment_index, intptr_t load_addr, intptr_t load_end, bool print_error, bool no_recurse)
{
/* Addresses of static data and the "loader" section of bootloader IRAM, all defined in ld script */
const char *reason = NULL;
extern int _dram_start, _dram_end, _loader_text_start, _loader_text_end;
void *load_addr_p = (void *)load_addr;
void *load_end_p = (void *)load_end;
if (load_end == load_addr) {
return true; // zero-length segments are fine
}
assert(load_end > load_addr); // data_len<16MB is checked in verify_segment_header() which is called before this, so this should always be true
if (esp_ptr_in_dram(load_addr_p) && esp_ptr_in_dram(load_end_p)) { /* Writing to DRAM */
/* Check if we're clobbering the stack */
intptr_t sp = (intptr_t)get_sp();
if (bootloader_util_regions_overlap(sp - STACK_LOAD_HEADROOM, SOC_ROM_STACK_START,
load_addr, load_end)) {
reason = "overlaps bootloader stack";
goto invalid;
}
/* Check if we're clobbering static data
(_dram_start.._dram_end includes bss, data, rodata sections in DRAM)
*/
if (bootloader_util_regions_overlap((intptr_t)&_dram_start, (intptr_t)&_dram_end, load_addr, load_end)) {
reason = "overlaps bootloader data";
goto invalid;
}
/* LAST DRAM CHECK (recursive): for D/IRAM, check the equivalent IRAM addresses if needed
Allow for the possibility that even though both pointers are IRAM, only part of the region is in a D/IRAM
section. In which case we recurse to check the part which falls in D/IRAM.
Note: We start with SOC_DIRAM_DRAM_LOW/HIGH and convert that address to IRAM to account for any reversing of word order
(chip-specific).
*/
if (!no_recurse && bootloader_util_regions_overlap(SOC_DIRAM_DRAM_LOW, SOC_DIRAM_DRAM_HIGH, load_addr, load_end)) {
intptr_t iram_load_addr, iram_load_end;
if (esp_ptr_in_diram_dram(load_addr_p)) {
iram_load_addr = (intptr_t)esp_ptr_diram_dram_to_iram(load_addr_p);
} else {
iram_load_addr = (intptr_t)esp_ptr_diram_dram_to_iram((void *)SOC_DIRAM_DRAM_LOW);
}
if (esp_ptr_in_diram_dram(load_end_p)) {
iram_load_end = (intptr_t)esp_ptr_diram_dram_to_iram(load_end_p);
} else {
iram_load_end = (intptr_t)esp_ptr_diram_dram_to_iram((void *)SOC_DIRAM_DRAM_HIGH);
}
if (iram_load_end < iram_load_addr) {
return verify_load_addresses(segment_index, iram_load_end, iram_load_addr, print_error, true);
} else {
return verify_load_addresses(segment_index, iram_load_addr, iram_load_end, print_error, true);
}
}
}
else if (esp_ptr_in_iram(load_addr_p) && esp_ptr_in_iram(load_end_p)) { /* Writing to IRAM */
/* Check for overlap of 'loader' section of IRAM */
if (bootloader_util_regions_overlap((intptr_t)&_loader_text_start, (intptr_t)&_loader_text_end,
load_addr, load_end)) {
reason = "overlaps loader IRAM";
goto invalid;
}
/* LAST IRAM CHECK (recursive): for D/IRAM, check the equivalent DRAM address if needed
Allow for the possibility that even though both pointers are IRAM, only part of the region is in a D/IRAM
section. In which case we recurse to check the part which falls in D/IRAM.
Note: We start with SOC_DIRAM_IRAM_LOW/HIGH and convert that address to DRAM to account for any reversing of word order
(chip-specific).
*/
if (!no_recurse && bootloader_util_regions_overlap(SOC_DIRAM_IRAM_LOW, SOC_DIRAM_IRAM_HIGH, load_addr, load_end)) {
intptr_t dram_load_addr, dram_load_end;
if (esp_ptr_in_diram_iram(load_addr_p)) {
dram_load_addr = (intptr_t)esp_ptr_diram_iram_to_dram(load_addr_p);
} else {
dram_load_addr = (intptr_t)esp_ptr_diram_iram_to_dram((void *)SOC_DIRAM_IRAM_LOW);
}
if (esp_ptr_in_diram_iram(load_end_p)) {
dram_load_end = (intptr_t)esp_ptr_diram_iram_to_dram(load_end_p);
} else {
dram_load_end = (intptr_t)esp_ptr_diram_iram_to_dram((void *)SOC_DIRAM_IRAM_HIGH);
}
if (dram_load_end < dram_load_addr) {
return verify_load_addresses(segment_index, dram_load_end, dram_load_addr, print_error, true);
} else {
return verify_load_addresses(segment_index, dram_load_addr, dram_load_end, print_error, true);
}
}
/* Sections entirely in RTC memory won't overlap with a vanilla bootloader but are valid load addresses, thus skipping them from the check */
} else if (esp_ptr_in_rtc_iram_fast(load_addr_p) && esp_ptr_in_rtc_iram_fast(load_end_p)){
return true;
} else if (esp_ptr_in_rtc_dram_fast(load_addr_p) && esp_ptr_in_rtc_dram_fast(load_end_p)){
return true;
} else if (esp_ptr_in_rtc_slow(load_addr_p) && esp_ptr_in_rtc_slow(load_end_p)) {
return true;
} else { /* Not a DRAM or an IRAM or RTC Fast IRAM, RTC Fast DRAM or RTC Slow address */
reason = "bad load address range";
goto invalid;
}
return true;
invalid:
if (print_error) {
ESP_LOGE(TAG, "Segment %d 0x%08x-0x%08x invalid: %s", segment_index, load_addr, load_end, reason);
}
return false;
}
#endif // BOOTLOADER_BUILD
static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segment_header_t *header, bool silent, bool do_load, bootloader_sha256_handle_t sha_handle, uint32_t *checksum)
{
esp_err_t err;
@@ -533,9 +378,34 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
#ifdef BOOTLOADER_BUILD
/* Before loading segment, check it doesn't clobber bootloader RAM. */
if (do_load && data_len > 0) {
if (!verify_load_addresses(index, load_addr, load_addr + data_len, true, false)) {
return ESP_ERR_IMAGE_INVALID;
if (do_load) {
const intptr_t load_end = load_addr + data_len;
if (load_end < (intptr_t) SOC_DRAM_HIGH) {
/* Writing to DRAM */
intptr_t sp = (intptr_t)get_sp();
if (load_end > sp - STACK_LOAD_HEADROOM) {
/* Bootloader .data/.rodata/.bss is above the stack, so this
* also checks that we aren't overwriting these segments.
*
* TODO: This assumes specific arrangement of sections we have
* in the ESP32. Rewrite this in a generic way to support other
* layouts.
*/
ESP_LOGE(TAG, "Segment %d end address 0x%08x too high (bootloader stack 0x%08x limit 0x%08x)",
index, load_end, sp, sp - STACK_LOAD_HEADROOM);
return ESP_ERR_IMAGE_INVALID;
}
} else {
/* Writing to IRAM */
const intptr_t loader_iram_start = (intptr_t) &_loader_text_start;
const intptr_t loader_iram_end = (intptr_t) &_loader_text_end;
if (bootloader_util_regions_overlap(loader_iram_start, loader_iram_end,
load_addr, load_end)) {
ESP_LOGE(TAG, "Segment %d (0x%08x-0x%08x) overlaps bootloader IRAM (0x%08x-0x%08x)",
index, load_addr, load_end, loader_iram_start, loader_iram_end);
return ESP_ERR_IMAGE_INVALID;
}
}
}
#endif // BOOTLOADER_BUILD
@@ -545,10 +415,6 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
int32_t data_len_remain = data_len;
while (data_len_remain > 0) {
#if SECURE_BOOT_CHECK_SIGNATURE && defined(BOOTLOADER_BUILD)
/* Double check the address verification done above */
ESP_FAULT_ASSERT(!do_load || verify_load_addresses(0, load_addr, load_addr + data_len_remain, false, false));
#endif
uint32_t offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0) ? 1 : 0;
/* Data we could map in case we are not aligned to PAGE boundary is one page size lesser. */
data_len = MIN(data_len_remain, ((free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE));
@@ -574,7 +440,7 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui
{
// If we are not loading, and the checksum is empty, skip processing this
// segment for data
if (!do_load && checksum == NULL) {
if(!do_load && checksum == NULL) {
ESP_LOGD(TAG, "skipping checksum for segment");
return ESP_OK;
}
@@ -733,7 +599,7 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t
length = (length + 15) & ~15; // Pad to next full 16 byte block
// Verify checksum
WORD_ALIGNED_ATTR uint8_t buf[16];
uint8_t buf[16];
esp_err_t err = bootloader_flash_read(data->start_addr + unpadded_length, buf, length - unpadded_length, true);
uint8_t calc = buf[length - unpadded_length - 1];
uint8_t checksum = (checksum_word >> 24)
@@ -757,9 +623,9 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t
return ESP_OK;
}
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest)
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data)
{
#ifdef SECURE_BOOT_CHECK_SIGNATURE
uint8_t image_hash[HASH_LEN] = { 0 };
uint32_t end = data->start_addr + data->image_len;
ESP_LOGI(TAG, "Verifying image signature...");
@@ -772,36 +638,25 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
bootloader_munmap(simple_hash);
}
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
// End of the image needs to be padded all the way to a 4KB boundary, after the simple hash
// (for apps they are usually already padded due to --secure-pad-v2, only a problem if this option was not used.)
uint32_t padded_end = (end + FLASH_SECTOR_SIZE - 1) & ~(FLASH_SECTOR_SIZE-1);
if (padded_end > end) {
const void *padding = bootloader_mmap(end, padded_end - end);
bootloader_sha256_data(sha_handle, padding, padded_end - end);
#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
// Pad to 4096 byte sector boundary
if (end % FLASH_SECTOR_SIZE != 0) {
uint32_t pad_len = FLASH_SECTOR_SIZE - (end % FLASH_SECTOR_SIZE);
const void *padding = bootloader_mmap(end, pad_len);
bootloader_sha256_data(sha_handle, padding, pad_len);
bootloader_munmap(padding);
end = padded_end;
end += pad_len;
}
#endif
bootloader_sha256_finish(sha_handle, image_digest);
bootloader_sha256_finish(sha_handle, image_hash);
// Log the hash for debugging
bootloader_debug_buffer(image_digest, HASH_LEN, "Calculated secure boot hash");
bootloader_debug_buffer(image_hash, HASH_LEN, "Calculated secure boot hash");
// Use hash to verify signature block
esp_err_t err = ESP_ERR_IMAGE_INVALID;
const void *sig_block;
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) != 0); /* sanity check that these values start differently */
sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t));
err = esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest);
#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) != 0); /* sanity check that these values start differently */
sig_block = bootloader_mmap(end, sizeof(ets_secure_boot_signature_t));
err = esp_secure_boot_verify_rsa_signature_block(sig_block, image_digest, verified_digest);
#endif
const esp_secure_boot_sig_block_t *sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t));
esp_err_t err = esp_secure_boot_verify_signature_block(sig_block, image_hash);
bootloader_munmap(sig_block);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Secure boot signature verification failed");
@@ -822,12 +677,11 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
return ESP_ERR_IMAGE_INVALID;
}
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
#if CONFIG_IDF_TARGET_ESP32S2BETA
// Adjust image length result to include the appended signature
data->image_len = end - data->start_addr + sizeof(ets_secure_boot_signature_t);
#endif
#endif // SECURE_BOOT_CHECK_SIGNATURE
return ESP_OK;
}
@@ -851,21 +705,3 @@ static esp_err_t verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_i
bootloader_munmap(hash);
return ESP_OK;
}
int esp_image_get_flash_size(esp_image_flash_size_t app_flash_size)
{
switch (app_flash_size) {
case ESP_IMAGE_FLASH_SIZE_1MB:
return 1 * 1024 * 1024;
case ESP_IMAGE_FLASH_SIZE_2MB:
return 2 * 1024 * 1024;
case ESP_IMAGE_FLASH_SIZE_4MB:
return 4 * 1024 * 1024;
case ESP_IMAGE_FLASH_SIZE_8MB:
return 8 * 1024 * 1024;
case ESP_IMAGE_FLASH_SIZE_16MB:
return 16 * 1024 * 1024;
default:
return 0;
}
}

View File

@@ -31,25 +31,16 @@ void esp_flash_encryption_init_checks()
// FLASH_CRYPT_CNT *must* be write protected. This will have happened automatically
// if bootloader is IDF V4.0 or newer but may not have happened for previous ESP-IDF bootloaders.
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
#ifdef CONFIG_SECURE_BOOT
#ifdef CONFIG_SECURE_BOOT_ENABLED
if (esp_secure_boot_enabled() && esp_flash_encryption_enabled()) {
bool flash_crypt_cnt_wr_dis = esp_efuse_read_field_bit(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT);
uint8_t flash_crypt_cnt_wr_dis = 0;
esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, &flash_crypt_cnt_wr_dis, 1);
if (!flash_crypt_cnt_wr_dis) {
uint8_t flash_crypt_cnt = 0;
esp_efuse_read_field_blob(ESP_EFUSE_FLASH_CRYPT_CNT, &flash_crypt_cnt,
ESP_EFUSE_FLASH_CRYPT_CNT[0]->bit_count);
if (flash_crypt_cnt == (1<<(ESP_EFUSE_FLASH_CRYPT_CNT[0]->bit_count))-1) {
// If encryption counter is already max, no need to write protect it
// (this distinction is important on ESP32 ECO3 where write-protecting FLASH_CRYPT_CNT also write-protects UART_DL_DIS)
flash_crypt_cnt_wr_dis = true;
}
if (!flash_crypt_cnt_wr_dis) {
ESP_EARLY_LOGE(TAG, "Flash encryption & Secure Boot together requires FLASH_CRYPT_CNT efuse to be write protected. Fixing now...");
esp_flash_write_protect_crypt_cnt();
}
ESP_EARLY_LOGE(TAG, "Flash encryption & Secure Boot together requires FLASH_CRYPT_CNT efuse to be write protected. Fixing now...");
esp_flash_write_protect_crypt_cnt();
}
}
#endif // CONFIG_SECURE_BOOT
#endif // CONFIG_SECURE_BOOT_ENABLED
#endif // CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
// Second check is to print a warning or error if the current running flash encryption mode
@@ -57,44 +48,39 @@ void esp_flash_encryption_init_checks()
mode = esp_get_flash_encryption_mode();
if (mode == ESP_FLASH_ENC_MODE_DEVELOPMENT) {
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
ESP_LOGE(TAG, "Flash encryption settings error: app is configured for RELEASE but efuses are set for DEVELOPMENT");
ESP_LOGE(TAG, "Mismatch found in security options in bootloader menuconfig and efuse settings. Device is not secure.");
ESP_EARLY_LOGE(TAG, "Flash encryption settings error: app is configured for RELEASE but efuses are set for DEVELOPMENT");
ESP_EARLY_LOGE(TAG, "Mismatch found in security options in bootloader menuconfig and efuse settings. Device is not secure.");
#else
ESP_LOGW(TAG, "Flash encryption mode is DEVELOPMENT (not secure)");
ESP_EARLY_LOGW(TAG, "Flash encryption mode is DEVELOPMENT (not secure)");
#endif
} else if (mode == ESP_FLASH_ENC_MODE_RELEASE) {
ESP_LOGI(TAG, "Flash encryption mode is RELEASE");
ESP_EARLY_LOGI(TAG, "Flash encryption mode is RELEASE");
}
}
#endif
void esp_flash_write_protect_crypt_cnt(void)
{
esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT);
uint8_t flash_crypt_cnt_wr_dis = 0;
esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, &flash_crypt_cnt_wr_dis, 1);
if (!flash_crypt_cnt_wr_dis) {
esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, 1);
}
}
esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
{
bool efuse_flash_crypt_cnt_wr_protected;
uint8_t efuse_flash_crypt_cnt_wr_protected = 0;
uint8_t dis_dl_enc = 0, dis_dl_dec = 0, dis_dl_cache = 0;
esp_flash_enc_mode_t mode = ESP_FLASH_ENC_MODE_DEVELOPMENT;
if (esp_flash_encryption_enabled()) {
/* Check if FLASH CRYPT CNT is write protected */
efuse_flash_crypt_cnt_wr_protected = esp_efuse_read_field_bit(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT);
if (!efuse_flash_crypt_cnt_wr_protected) {
uint8_t flash_crypt_cnt = 0;
esp_efuse_read_field_blob(ESP_EFUSE_FLASH_CRYPT_CNT, &flash_crypt_cnt, ESP_EFUSE_FLASH_CRYPT_CNT[0]->bit_count);
if (flash_crypt_cnt == (1 << (ESP_EFUSE_FLASH_CRYPT_CNT[0]->bit_count)) - 1) {
efuse_flash_crypt_cnt_wr_protected = true; // CRYPT_CNT at max is same as write protected
}
}
esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, &efuse_flash_crypt_cnt_wr_protected, 1);
if (efuse_flash_crypt_cnt_wr_protected) {
dis_dl_cache = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_CACHE);
dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_ENCRYPT);
dis_dl_dec = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_DECRYPT);
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_CACHE, &dis_dl_cache, 1);
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_ENCRYPT, &dis_dl_enc, 1);
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_DECRYPT, &dis_dl_dec, 1);
/* Check if DISABLE_DL_DECRYPT, DISABLE_DL_ENCRYPT & DISABLE_DL_CACHE are set */
if ( dis_dl_cache && dis_dl_enc && dis_dl_dec ) {
mode = ESP_FLASH_ENC_MODE_RELEASE;

View File

@@ -52,7 +52,7 @@ esp_err_t esp_partition_table_verify(const esp_partition_info_t *partition_table
MD5Update(&context, (unsigned char *) partition_table, num_parts * sizeof(esp_partition_info_t));
MD5Final(digest, &context);
unsigned char *md5sum = ((unsigned char *) part) + ESP_PARTITION_MD5_OFFSET;
unsigned char *md5sum = ((unsigned char *) part) + 16; // skip the 2B magic number and the 14B fillup bytes
if (memcmp(md5sum, digest, sizeof(digest)) != 0) {
if (log_errors) {

View File

@@ -13,9 +13,7 @@
// limitations under the License.
#include <stddef.h>
#include <stdint.h>
#include "bootloader_flash_config.h"
#include "flash_qio_mode.h"
#include "bootloader_flash_priv.h"
#include "esp_log.h"
#include "esp_err.h"
#if CONFIG_IDF_TARGET_ESP32
@@ -26,10 +24,30 @@
#include "esp32s2beta/rom/efuse.h"
#include "soc/spi_mem_struct.h"
#endif
#include "soc/spi_struct.h"
#include "soc/spi_reg.h"
#include "soc/efuse_periph.h"
#include "soc/io_mux_reg.h"
#include "sdkconfig.h"
/* SPI flash controller */
#if CONFIG_IDF_TARGET_ESP32
#define SPIFLASH SPI1
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#define SPIFLASH SPIMEM1
#endif
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
Suitable for use with the execute_flash_command static function.
*/
#define CMD_RDID 0x9F
#define CMD_WRSR 0x01
#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
#define CMD_WREN 0x06
#define CMD_WRDI 0x04
#define CMD_RDSR 0x05
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
static const char *TAG = "qio_mode";
@@ -66,6 +84,12 @@ static unsigned read_status_8b_xmc25qu64a(void);
/* Write 8 bit status of XM25QU64A */
static void write_status_8b_xmc25qu64a(unsigned new_status);
#define ESP32_D2WD_WP_GPIO 7 /* ESP32-D2WD has this GPIO wired to WP pin of flash */
#ifndef CONFIG_BOOTLOADER_SPI_WP_PIN // Set in menuconfig if SPI flasher config is set to a quad mode
#define CONFIG_BOOTLOADER_SPI_WP_PIN ESP32_D2WD_WP_GPIO
#endif
/* Array of known flash chips and data to enable Quad I/O mode
Manufacturer & flash ID can be tested by running "esptool.py
@@ -85,7 +109,6 @@ const static qio_info_t chip_data[] = {
{ "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
{ "GD", 0xC8, 0x6000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
{ "XM25QU64A", 0x20, 0x3817, 0xFFFF, read_status_8b_xmc25qu64a, write_status_8b_xmc25qu64a, 6 },
{ "TH", 0xcd, 0x6000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
/* Final entry is default entry, if no other IDs have matched.
@@ -107,6 +130,56 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
The command passed here is always the on-the-wire command given to the SPI flash unit.
*/
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
/* dummy_len_plus values defined in ROM for SPI flash configuration */
extern uint8_t g_rom_spiflash_dummy_len_plus[];
uint32_t bootloader_read_flash_id(void)
{
uint32_t id = execute_flash_command(CMD_RDID, 0, 0, 24);
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
return id;
}
#if CONFIG_IDF_TARGET_ESP32S2BETA
#define FLASH_WRAP_CMD 0x77
typedef enum {
FLASH_WRAP_MODE_8B = 0,
FLASH_WRAP_MODE_16B = 2,
FLASH_WRAP_MODE_32B = 4,
FLASH_WRAP_MODE_64B = 6,
FLASH_WRAP_MODE_DISABLE = 1
} spi_flash_wrap_mode_t;
static esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
uint32_t reg_bkp_usr = SPIFLASH.user.val;
SPIFLASH.user.fwrite_dio = 0;
SPIFLASH.user.fwrite_dual = 0;
SPIFLASH.user.fwrite_qio = 1;
SPIFLASH.user.fwrite_quad = 0;
SPIFLASH.ctrl.fcmd_dual = 0;
SPIFLASH.ctrl.fcmd_quad = 0;
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 1;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD;
SPIFLASH.user1.usr_addr_bitlen = 23;
SPIFLASH.addr = 0;
SPIFLASH.user.usr_miso = 0;
SPIFLASH.user.usr_mosi = 1;
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
SPIFLASH.cmd.usr = 1;
while (SPIFLASH.cmd.usr != 0) {
}
SPIFLASH.ctrl.val = reg_bkp_ctrl;
SPIFLASH.user.val = reg_bkp_usr;
return ESP_OK;
}
#endif
void bootloader_enable_qio_mode(void)
{
@@ -139,8 +212,8 @@ void bootloader_enable_qio_mode(void)
enable_qio_mode(chip_data[i].read_status_fn,
chip_data[i].write_status_fn,
chip_data[i].status_qio_bit);
#if SOC_CACHE_SUPPORT_WRAP
bootloader_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
#if CONFIG_IDF_TARGET_ESP32S2BETA
spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
#endif
}
@@ -151,13 +224,31 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
uint32_t status;
const uint32_t spiconfig = ets_efuse_get_spiconfig();
#if CONFIG_IDF_TARGET_ESP32
if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
// spiconfig specifies a custom efuse pin configuration. This config defines all pins -except- WP,
// which is compiled into the bootloader instead.
//
// Most commonly an overriden pin mapping means ESP32-D2WD or ESP32-PICOD4.
//Warn if chip is ESP32-D2WD/ESP32-PICOD4 but someone has changed the WP pin
//assignment from that chip's WP pin.
uint32_t pkg_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
if (CONFIG_BOOTLOADER_SPI_WP_PIN != ESP32_D2WD_WP_GPIO &&
(pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 ||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 ||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4)) {
ESP_LOGW(TAG, "Chip is ESP32-D2WD/ESP32-PICOD4 but flash WP pin is different value to internal flash");
}
}
#endif
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
status = read_status_fn();
ESP_LOGD(TAG, "Initial flash chip status 0x%x", status);
if ((status & (1 << status_qio_bit)) == 0) {
bootloader_execute_flash_command(CMD_WREN, 0, 0, 0);
execute_flash_command(CMD_WREN, 0, 0, 0);
write_status_fn(status | (1 << status_qio_bit));
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
@@ -185,58 +276,108 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
esp_rom_spiflash_config_readmode(mode);
#if CONFIG_IDF_TARGET_ESP32
int wp_pin = bootloader_flash_get_wp_pin();
esp_rom_spiflash_select_qio_pins(wp_pin, spiconfig);
esp_rom_spiflash_select_qio_pins(CONFIG_BOOTLOADER_SPI_WP_PIN, spiconfig);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
esp_rom_spiflash_select_qio_pins(ets_efuse_get_wp_pad(), spiconfig);
if (ets_efuse_get_wp_pad() <= MAX_PAD_GPIO_NUM) {
esp_rom_spiflash_select_qio_pins(ets_efuse_get_wp_pad(), spiconfig);
} else {
esp_rom_spiflash_select_qio_pins(CONFIG_BOOTLOADER_SPI_WP_PIN, spiconfig);
}
#endif
return ESP_OK;
}
static unsigned read_status_8b_rdsr(void)
{
return bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
return execute_flash_command(CMD_RDSR, 0, 0, 8);
}
static unsigned read_status_8b_rdsr2(void)
{
return bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8);
return execute_flash_command(CMD_RDSR2, 0, 0, 8);
}
static unsigned read_status_16b_rdsr_rdsr2(void)
{
return bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8) | (bootloader_execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
return execute_flash_command(CMD_RDSR, 0, 0, 8) | (execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
}
static void write_status_8b_wrsr(unsigned new_status)
{
bootloader_execute_flash_command(CMD_WRSR, new_status, 8, 0);
execute_flash_command(CMD_WRSR, new_status, 8, 0);
}
static void write_status_8b_wrsr2(unsigned new_status)
{
bootloader_execute_flash_command(CMD_WRSR2, new_status, 8, 0);
execute_flash_command(CMD_WRSR2, new_status, 8, 0);
}
static void write_status_16b_wrsr(unsigned new_status)
{
bootloader_execute_flash_command(CMD_WRSR, new_status, 16, 0);
execute_flash_command(CMD_WRSR, new_status, 16, 0);
}
static unsigned read_status_8b_xmc25qu64a(void)
{
bootloader_execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
uint32_t read_status = bootloader_execute_flash_command(CMD_RDSR, 0, 0, 8);
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
uint32_t read_status = execute_flash_command(CMD_RDSR, 0, 0, 8);
execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
return read_status;
}
static void write_status_8b_xmc25qu64a(unsigned new_status)
{
bootloader_execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
bootloader_execute_flash_command(CMD_WRSR, new_status, 8, 0);
execute_flash_command(CMD_WRSR, new_status, 8, 0);
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
}
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
{
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
#elif CONFIG_IDF_TARGET_ESP32S2BETA
SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
#endif
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 0;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = command;
SPIFLASH.user.usr_miso = miso_len > 0;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
#endif
SPIFLASH.user.usr_mosi = mosi_len > 0;
#if CONFIG_IDF_TARGET_ESP32
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0;
#endif
SPIFLASH.data_buf[0] = mosi_data;
if (g_rom_spiflash_dummy_len_plus[1]) {
/* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */
if (miso_len > 0) {
SPIFLASH.user.usr_dummy = 1;
SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1;
} else {
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user1.usr_dummy_cyclelen = 0;
}
}
SPIFLASH.cmd.usr = 1;
while (SPIFLASH.cmd.usr != 0) {
}
SPIFLASH.ctrl.val = old_ctrl_reg;
return SPIFLASH.data_buf[0];
}

View File

@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "bootloader_sha.h"
#include "bootloader_flash_priv.h"
#include <stdbool.h>
#include <string.h>
#include <assert.h>

View File

@@ -13,57 +13,48 @@
// limitations under the License.
#include "sdkconfig.h"
#include "bootloader_flash_priv.h"
#include "bootloader_flash.h"
#include "bootloader_sha.h"
#include "bootloader_utility.h"
#include "esp_log.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "mbedtls/sha256.h"
#include "mbedtls/x509.h"
#include "mbedtls/md.h"
#include "mbedtls/platform.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include <string.h>
#include <sys/param.h>
#define DIGEST_LEN 32
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
static const char *TAG = "secure_boot_v1";
static const char *TAG = "secure_boot";
extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start");
extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end");
#define SIGNATURE_VERIFICATION_KEYLEN 64
#define DIGEST_LEN 32
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[DIGEST_LEN];
uint8_t verified_digest[DIGEST_LEN];
const uint8_t *data;
const esp_secure_boot_sig_block_t *sigblock;
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, length);
return err;
}
// Map the signature block and verify the signature
sigblock = (const esp_secure_boot_sig_block_t *)bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t));
if (sigblock == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t));
data = bootloader_mmap(src_addr, length + sizeof(esp_secure_boot_sig_block_t));
if (data == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length + sizeof(esp_secure_boot_sig_block_t));
return ESP_FAIL;
}
err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest);
bootloader_munmap(sigblock);
// Calculate digest of main image
mbedtls_sha256_ret(data, length, digest, 0);
// Map the signature block and verify the signature
sigblock = (const esp_secure_boot_sig_block_t *)(data + length);
esp_err_t err = esp_secure_boot_verify_signature_block(sigblock, digest);
bootloader_munmap(data);
return err;
}
esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest)
{
#if !(defined(CONFIG_MBEDTLS_ECDSA_C) && defined(CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED))
ESP_LOGE(TAG, "Signature verification requires ECDSA & SECP256R1 curve enabled");
@@ -71,9 +62,6 @@ esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig
#else
ptrdiff_t keylen;
/* Note: in IDF app image verification we don't add any fault injection resistance, boot-time checks only */
memset(verified_digest, 0, DIGEST_LEN);
keylen = signature_verification_key_end - signature_verification_key_start;
if (keylen != SIGNATURE_VERIFICATION_KEYLEN) {
ESP_LOGE(TAG, "Embedded public verification key has wrong length %d", keylen);
@@ -135,147 +123,3 @@ cleanup:
return ret == 0 ? ESP_OK : ESP_ERR_IMAGE_INVALID;
#endif // CONFIG_MBEDTLS_ECDSA_C && CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED
}
#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
static const char *TAG = "secure_boot_v2";
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#define RSA_KEY_SIZE 384 /* RSA 3072 Bits */
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{
uint8_t digest[DIGEST_LEN] = {0};
uint8_t verified_digest[DIGEST_LEN] = {0};
/* Rounding off length to the upper 4k boundary */
uint32_t padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length);
return err;
}
const ets_secure_boot_signature_t *sig_block = bootloader_mmap(src_addr + padded_length, sizeof(ets_secure_boot_signature_t));
if (sig_block == NULL) {
ESP_LOGE(TAG, "Failed to mmap data at offset 0x%x", src_addr + padded_length);
return ESP_FAIL;
}
err = esp_secure_boot_verify_rsa_signature_block(sig_block, digest, verified_digest);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
}
bootloader_munmap(sig_block);
return err;
}
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
{
int i = 0;
#if CONFIG_SECURE_BOOT_V2_ENABLED /* Verify key against efuse block */
uint8_t efuse_trusted_digest[DIGEST_LEN] = {0}, sig_block_trusted_digest[DIGEST_LEN] = {0};
memcpy(efuse_trusted_digest, (uint8_t *) EFUSE_BLK2_RDATA0_REG, sizeof(efuse_trusted_digest));
/* Note: in IDF verification we don't add any fault injection resistance, as we don't expect this to be called
during boot-time verification. */
memset(verified_digest, 0, DIGEST_LEN);
/* Generating the SHA of the public key components in the signature block */
bootloader_sha256_handle_t sig_block_sha;
sig_block_sha = bootloader_sha256_start();
bootloader_sha256_data(sig_block_sha, &sig_block->block[0].key, sizeof(sig_block->block[0].key));
bootloader_sha256_finish(sig_block_sha, (unsigned char *)sig_block_trusted_digest);
if (memcmp(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN) != 0) {
const uint8_t zeroes[DIGEST_LEN] = {0};
/* Can't continue if secure boot is enabled, OR if a different digest is already written in efuse BLK2
(If BLK2 is empty and Secure Boot is disabled then we assume that it will be enabled later.)
*/
if (esp_secure_boot_enabled() || memcmp(efuse_trusted_digest, zeroes, DIGEST_LEN) != 0) {
ESP_LOGE(TAG, "Public key digest in eFuse BLK2 and the signature block don't match.");
return ESP_FAIL;
}
}
#endif
ESP_LOGI(TAG, "Verifying with RSA-PSS...");
int ret = 0;
mbedtls_rsa_context pk;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
unsigned char *sig_be = calloc(1, RSA_KEY_SIZE);
unsigned char *buf = calloc(1, RSA_KEY_SIZE);
if (sig_be == NULL || buf == NULL) {
return ESP_ERR_NO_MEM;
}
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%04x\n", ret);
goto exit;
}
for (i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
const mbedtls_mpi N = { .s = 1,
.n = sizeof(sig_block->block[i].key.n)/sizeof(mbedtls_mpi_uint),
.p = (void *)sig_block->block[i].key.n,
};
const mbedtls_mpi e = { .s = 1,
.n = sizeof(sig_block->block[i].key.e)/sizeof(mbedtls_mpi_uint), // 1
.p = (void *)&sig_block->block[i].key.e,
};
mbedtls_rsa_init(&pk, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
ret = mbedtls_rsa_import(&pk, &N, NULL, NULL, NULL, &e);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_rsa_import, err: %d", ret);
goto exit;
}
ret = mbedtls_rsa_complete(&pk);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_rsa_complete, err: %d", ret);
goto exit;
}
ret = mbedtls_rsa_check_pubkey(&pk);
if (ret != 0) {
ESP_LOGI(TAG, "Key is not an RSA key -%0x", -ret);
goto exit;
}
/* Signature needs to be byte swapped into BE representation */
for (int j = 0; j < RSA_KEY_SIZE; j++) {
sig_be[RSA_KEY_SIZE- j - 1] = sig_block->block[i].signature[j];
}
ret = mbedtls_rsa_public( &pk, sig_be, buf);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_rsa_public failed, err: %d", ret);
goto exit;
}
ret = mbedtls_rsa_rsassa_pss_verify( &pk, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, DIGEST_LEN,
image_digest, sig_be);
if (ret != 0) {
ESP_LOGE(TAG, "Failed mbedtls_rsa_rsassa_pss_verify, err: %d", ret);
} else {
ESP_LOGI(TAG, "Signature verified successfully!");
}
exit:
mbedtls_rsa_free(&pk);
if (ret == 0) {
break;
}
}
free(sig_be);
free(buf);
return (!ret) ? ESP_OK : ESP_ERR_IMAGE_INVALID;
}
#endif

View File

@@ -95,7 +95,6 @@ if(CONFIG_BT_ENABLED)
"host/bluedroid/bta/dm/bta_dm_main.c"
"host/bluedroid/bta/dm/bta_dm_pm.c"
"host/bluedroid/bta/dm/bta_dm_sco.c"
"host/bluedroid/bta/dm/bta_dm_qos.c"
"host/bluedroid/bta/gatt/bta_gatt_common.c"
"host/bluedroid/bta/gatt/bta_gattc_act.c"
"host/bluedroid/bta/gatt/bta_gattc_api.c"
@@ -313,7 +312,6 @@ if(CONFIG_BT_ENABLED)
if(CONFIG_BLE_MESH)
list(APPEND include_dirs
"esp_ble_mesh/mesh_common/include"
"esp_ble_mesh/mesh_common/tinycrypt/include"
"esp_ble_mesh/mesh_core"
"esp_ble_mesh/mesh_core/include"
"esp_ble_mesh/mesh_core/storage"
@@ -325,8 +323,7 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/api/models/include"
"esp_ble_mesh/api")
list(APPEND srcs "esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c"
"esp_ble_mesh/api/core/esp_ble_mesh_common_api.c"
list(APPEND srcs "esp_ble_mesh/api/core/esp_ble_mesh_common_api.c"
"esp_ble_mesh/api/core/esp_ble_mesh_local_data_operation_api.c"
"esp_ble_mesh/api/core/esp_ble_mesh_low_power_api.c"
"esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c"
@@ -338,7 +335,6 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/api/models/esp_ble_mesh_lighting_model_api.c"
"esp_ble_mesh/api/models/esp_ble_mesh_sensor_model_api.c"
"esp_ble_mesh/api/models/esp_ble_mesh_time_scene_model_api.c"
"esp_ble_mesh/btc/btc_ble_mesh_ble.c"
"esp_ble_mesh/btc/btc_ble_mesh_config_model.c"
"esp_ble_mesh/btc/btc_ble_mesh_generic_model.c"
"esp_ble_mesh/btc/btc_ble_mesh_health_model.c"
@@ -346,27 +342,11 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/btc/btc_ble_mesh_prov.c"
"esp_ble_mesh/btc/btc_ble_mesh_sensor_model.c"
"esp_ble_mesh/btc/btc_ble_mesh_time_scene_model.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/aes_decrypt.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/aes_encrypt.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/cbc_mode.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/ccm_mode.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/cmac_mode.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/ctr_mode.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/ctr_prng.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/ecc_dh.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/ecc_dsa.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/ecc_platform_specific.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/ecc.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/hmac_prng.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/hmac.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/sha256.c"
"esp_ble_mesh/mesh_common/tinycrypt/src/utils.c"
"esp_ble_mesh/mesh_common/mesh_aes_encrypt.c"
"esp_ble_mesh/mesh_common/mesh_atomic.c"
"esp_ble_mesh/mesh_common/mesh_buf.c"
"esp_ble_mesh/mesh_common/mesh_common.c"
"esp_ble_mesh/mesh_common/mesh_kernel.c"
"esp_ble_mesh/mesh_common/mesh_mutex.c"
"esp_ble_mesh/mesh_common/mesh_timer.c"
"esp_ble_mesh/mesh_common/mesh_util.c"
"esp_ble_mesh/mesh_core/storage/settings_nvs.c"
"esp_ble_mesh/mesh_core/access.c"
@@ -375,30 +355,27 @@ if(CONFIG_BT_ENABLED)
"esp_ble_mesh/mesh_core/cfg_cli.c"
"esp_ble_mesh/mesh_core/cfg_srv.c"
"esp_ble_mesh/mesh_core/crypto.c"
"esp_ble_mesh/mesh_core/fast_prov.c"
"esp_ble_mesh/mesh_core/friend.c"
"esp_ble_mesh/mesh_core/health_cli.c"
"esp_ble_mesh/mesh_core/health_srv.c"
"esp_ble_mesh/mesh_core/local_operation.c"
"esp_ble_mesh/mesh_core/lpn.c"
"esp_ble_mesh/mesh_core/main.c"
"esp_ble_mesh/mesh_core/net.c"
"esp_ble_mesh/mesh_core/prov.c"
"esp_ble_mesh/mesh_core/provisioner_beacon.c"
"esp_ble_mesh/mesh_core/provisioner_main.c"
"esp_ble_mesh/mesh_core/provisioner_prov.c"
"esp_ble_mesh/mesh_core/proxy_client.c"
"esp_ble_mesh/mesh_core/proxy_server.c"
"esp_ble_mesh/mesh_core/settings_uid.c"
"esp_ble_mesh/mesh_core/settings.c"
"esp_ble_mesh/mesh_core/scan.c"
"esp_ble_mesh/mesh_core/test.c"
"esp_ble_mesh/mesh_core/transport.c"
"esp_ble_mesh/mesh_models/common/device_property.c"
"esp_ble_mesh/mesh_models/client/client_common.c"
"esp_ble_mesh/mesh_models/client/generic_client.c"
"esp_ble_mesh/mesh_models/client/lighting_client.c"
"esp_ble_mesh/mesh_models/client/sensor_client.c"
"esp_ble_mesh/mesh_models/client/time_scene_client.c"
"esp_ble_mesh/mesh_models/server/device_property.c"
"esp_ble_mesh/mesh_models/server/generic_server.c"
"esp_ble_mesh/mesh_models/server/lighting_server.c"
"esp_ble_mesh/mesh_models/server/sensor_server.c"
@@ -504,7 +481,6 @@ if(CONFIG_BT_ENABLED)
"host/nimble/nimble/nimble/host/src/ble_hs_adv.c"
"host/nimble/nimble/nimble/host/src/ble_hs_hci.c"
"host/nimble/nimble/nimble/host/src/ble_hs_hci_util.c"
"host/nimble/nimble/nimble/host/src/ble_hs_resolv.c"
"host/nimble/nimble/nimble/host/store/ram/src/ble_store_ram.c"
"host/nimble/nimble/nimble/host/store/config/src/ble_store_config.c"
"host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c"
@@ -520,8 +496,7 @@ if(CONFIG_BT_ENABLED)
"host/nimble/nimble/porting/nimble/src/mem.c"
"host/nimble/nimble/porting/nimble/src/os_mbuf.c"
"host/nimble/nimble/porting/nimble/src/os_cputime.c"
"host/nimble/esp-hci/src/esp_nimble_hci.c"
"host/nimble/port/src/esp_nimble_mem.c")
"host/nimble/esp-hci/src/esp_nimble_hci.c")
if (CONFIG_BLE_MESH)
list(APPEND srcs "esp_ble_mesh/mesh_core/nimble_host/mesh_bearer_adapt.c")
@@ -568,6 +543,6 @@ idf_component_register(SRCS "${srcs}"
if(CONFIG_BT_ENABLED)
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-implicit-fallthrough -Wno-unused-const-variable)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-L${CMAKE_CURRENT_LIST_DIR}/controller/lib/esp32")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-L${CMAKE_CURRENT_LIST_DIR}/controller/lib")
target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app)
endif()

View File

@@ -78,47 +78,6 @@ menu "Bluetooth"
default 1 if BTDM_CTRL_BR_EDR_SCO_DATA_PATH_PCM
default 0
menuconfig BTDM_CTRL_PCM_ROLE_EDGE_CONFIG
bool "PCM Signal Config (Role and Polar)"
depends on BTDM_CTRL_BR_EDR_SCO_DATA_PATH_PCM
default y
choice BTDM_CTRL_PCM_ROLE
prompt "PCM Role"
depends on BTDM_CTRL_PCM_ROLE_EDGE_CONFIG
help
PCM role can be configured as PCM master or PCM slave
config BTDM_CTRL_PCM_ROLE_MASTER
bool "PCM Master"
config BTDM_CTRL_PCM_ROLE_SLAVE
bool "PCM Slave"
endchoice
choice BTDM_CTRL_PCM_POLAR
prompt "PCM Polar"
depends on BTDM_CTRL_PCM_ROLE_EDGE_CONFIG
help
PCM polarity can be configured as Falling Edge or Rising Edge
config BTDM_CTRL_PCM_POLAR_FALLING_EDGE
bool "Falling Edge"
config BTDM_CTRL_PCM_POLAR_RISING_EDGE
bool "Rising Edge"
endchoice
config BTDM_CTRL_PCM_ROLE_EFF
int
default 0 if BTDM_CTRL_PCM_ROLE_MASTER
default 1 if BTDM_CTRL_PCM_ROLE_SLAVE
default 0
config BTDM_CTRL_PCM_POLAR_EFF
int
default 0 if BTDM_CTRL_PCM_POLAR_FALLING_EDGE
default 1 if BTDM_CTRL_PCM_POLAR_RISING_EDGE
default 0
config BTDM_CTRL_AUTO_LATENCY
bool "Auto latency"
depends on BTDM_CTRL_MODE_BTDM
@@ -132,19 +91,6 @@ menu "Bluetooth"
default BTDM_CTRL_AUTO_LATENCY if BTDM_CTRL_MODE_BTDM
default n
config BTDM_CTRL_LEGACY_AUTH_VENDOR_EVT
bool "Legacy Authentication Vendor Specific Event Enable"
depends on BTDM_CTRL_MODE_BR_EDR_ONLY || BTDM_CTRL_MODE_BTDM
default y
help
To protect from BIAS attack during Legacy authentication,
Legacy authentication Vendor specific event should be enabled
config BTDM_CTRL_LEGACY_AUTH_VENDOR_EVT_EFF
bool
default BTDM_CTRL_LEGACY_AUTH_VENDOR_EVT if BTDM_CTRL_MODE_BR_EDR_ONLY || BTDM_CTRL_MODE_BTDM
default 0
config BTDM_CTRL_BLE_MAX_CONN_EFF
int
@@ -364,7 +310,7 @@ menu "Bluetooth"
int "Maximum number of devices in scan duplicate filter"
depends on BTDM_BLE_SCAN_DUPL
range 10 1000
default 100
default 200
help
Maximum number of devices which can be recorded in scan duplicate filter.
When the maximum amount of device in the filter is reached, the cache will be refreshed.
@@ -380,14 +326,14 @@ menu "Bluetooth"
int "Maximum number of Mesh adv packets in scan duplicate filter"
depends on BTDM_BLE_MESH_SCAN_DUPL_EN
range 10 1000
default 100
default 200
help
Maximum number of adv packets which can be recorded in duplicate scan cache for BLE Mesh.
When the maximum amount of device in the filter is reached, the cache will be refreshed.
config BTDM_CTRL_FULL_SCAN_SUPPORTED
bool "BLE full scan feature supported"
depends on BTDM_CTRL_MODE_BLE_ONLY || BTDM_CTRL_MODE_BTDM
depends on BTDM_CONTROLLER_MODE_BLE_ONLY || BTDM_CONTROLLER_MODE_BTDM
default y
help
The full scan function is mainly used to provide BLE scan performance.
@@ -427,6 +373,21 @@ menu "Bluetooth"
If you set `BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD` to a small value or printf every adv lost event, it
may cause adv packets lost more.
menuconfig BTDM_COEX_BT_OPTIONS
bool "Coexistence Bluetooth Side Options"
depends on ESP32_WIFI_SW_COEXIST_ENABLE
default n
help
Options of Bluetooth Side of WiFi and bluetooth coexistence.
config BTDM_COEX_BLE_ADV_HIGH_PRIORITY
bool "Improve BLE ADV priority for WiFi & BLE coexistence"
depends on BTDM_COEX_BT_OPTIONS
default n
help
Improve BLE ADV coexistence priority to make it better performance.
For example, BLE mesh need to enable this option to improve BLE adv performance.
endmenu
choice BT_HOST

View File

@@ -57,7 +57,6 @@
#endif
#if CONFIG_BLE_MESH
#include "btc_ble_mesh_ble.h"
#include "btc_ble_mesh_prov.h"
#include "btc_ble_mesh_health_model.h"
#include "btc_ble_mesh_config_model.h"
@@ -69,7 +68,7 @@
#define BTC_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
#define BTC_TASK_STACK_SIZE (BT_BTC_TASK_STACK_SIZE + BT_TASK_EXTRA_STACK_SIZE) //by menuconfig
#define BTC_TASK_NAME "BTC_TASK"
#define BTC_TASK_NAME "btcT"
#define BTC_TASK_PRIO (BT_TASK_MAX_PRIORITIES - 6)
osi_thread_t *btc_thread;
@@ -94,9 +93,9 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
#endif ///BLE_INCLUDED == TRUE
[BTC_PID_BLE_HID] = {NULL, NULL},
[BTC_PID_SPPLIKE] = {NULL, NULL},
#if (BLUFI_INCLUDED == TRUE)
#if (GATTS_INCLUDED == TRUE)
[BTC_PID_BLUFI] = {btc_blufi_call_handler, btc_blufi_cb_handler },
#endif ///BLUFI_INCLUDED == TRUE
#endif ///GATTS_INCLUDED == TRUE
[BTC_PID_DM_SEC] = {NULL, btc_dm_sec_cb_handler },
#endif
[BTC_PID_ALARM] = {btc_alarm_handler, NULL },
@@ -125,43 +124,18 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
#if CONFIG_BLE_MESH
[BTC_PID_PROV] = {btc_ble_mesh_prov_call_handler, btc_ble_mesh_prov_cb_handler },
[BTC_PID_MODEL] = {btc_ble_mesh_model_call_handler, btc_ble_mesh_model_cb_handler },
#if CONFIG_BLE_MESH_HEALTH_CLI
[BTC_PID_HEALTH_CLIENT] = {btc_ble_mesh_health_client_call_handler, btc_ble_mesh_health_client_cb_handler },
#endif /* CONFIG_BLE_MESH_HEALTH_CLI */
#if CONFIG_BLE_MESH_HEALTH_SRV
[BTC_PID_HEALTH_SERVER] = {btc_ble_mesh_health_server_call_handler, btc_ble_mesh_health_server_cb_handler },
#endif /* CONFIG_BLE_MESH_HEALTH_SRV */
#if CONFIG_BLE_MESH_CFG_CLI
[BTC_PID_CONFIG_CLIENT] = {btc_ble_mesh_config_client_call_handler, btc_ble_mesh_config_client_cb_handler },
#endif /* CONFIG_BLE_MESH_CFG_CLI */
[BTC_PID_CONFIG_SERVER] = {NULL, btc_ble_mesh_config_server_cb_handler },
#if CONFIG_BLE_MESH_GENERIC_CLIENT
[BTC_PID_GENERIC_CLIENT] = {btc_ble_mesh_generic_client_call_handler, btc_ble_mesh_generic_client_cb_handler },
#endif /* CONFIG_BLE_MESH_GENERIC_CLIENT */
#if CONFIG_BLE_MESH_LIGHTING_CLIENT
[BTC_PID_LIGHTING_CLIENT] = {btc_ble_mesh_lighting_client_call_handler, btc_ble_mesh_lighting_client_cb_handler },
#endif /* CONFIG_BLE_MESH_LIGHTING_CLIENT */
#if CONFIG_BLE_MESH_SENSOR_CLI
[BTC_PID_SENSOR_CLIENT] = {btc_ble_mesh_sensor_client_call_handler, btc_ble_mesh_sensor_client_cb_handler },
#endif /* CONFIG_BLE_MESH_SENSOR_CLI */
#if CONFIG_BLE_MESH_TIME_SCENE_CLIENT
[BTC_PID_TIME_SCENE_CLIENT] = {btc_ble_mesh_time_scene_client_call_handler, btc_ble_mesh_time_scene_client_cb_handler},
#endif /* CONFIG_BLE_MESH_TIME_SCENE_CLIENT */
#if CONFIG_BLE_MESH_GENERIC_SERVER
[BTC_PID_GENERIC_SERVER] = {NULL, btc_ble_mesh_generic_server_cb_handler },
#endif /* CONFIG_BLE_MESH_GENERIC_SERVER */
#if CONFIG_BLE_MESH_LIGHTING_SERVER
[BTC_PID_LIGHTING_SERVER] = {NULL, btc_ble_mesh_lighting_server_cb_handler },
#endif /* CONFIG_BLE_MESH_LIGHTING_SERVER */
#if CONFIG_BLE_MESH_SENSOR_SERVER
[BTC_PID_SENSOR_SERVER] = {NULL, btc_ble_mesh_sensor_server_cb_handler },
#endif /* CONFIG_BLE_MESH_SENSOR_SERVER */
#if CONFIG_BLE_MESH_TIME_SCENE_SERVER
[BTC_PID_TIME_SCENE_SERVER] = {NULL, btc_ble_mesh_time_scene_server_cb_handler},
#endif /* CONFIG_BLE_MESH_TIME_SCENE_SERVER */
#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT
[BTC_PID_BLE_MESH_BLE_COEX] = {btc_ble_mesh_ble_call_handler, btc_ble_mesh_ble_cb_handler },
#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT */
#endif /* #if CONFIG_BLE_MESH */
};
@@ -195,32 +169,7 @@ static void btc_thread_handler(void *arg)
static bt_status_t btc_task_post(btc_msg_t *msg, uint32_t timeout)
{
if (osi_thread_post(btc_thread, btc_thread_handler, msg, 0, timeout) == false) {
return BT_STATUS_BUSY;
}
return BT_STATUS_SUCCESS;
}
/**
* transfer an message to another module in the different task.
* @param msg message
* @param arg paramter
* @param arg_len length of paramter
* @param copy_func deep copy function
* @return BT_STATUS_SUCCESS: success
* others: fail
*/
bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg_deep_copy_t copy_func)
{
btc_msg_t* lmsg;
// arg XOR arg_len
if ((msg == NULL) || ((arg == NULL) == !(arg_len == 0))) {
return BT_STATUS_PARM_INVALID;
}
BTC_TRACE_DEBUG("%s msg %u %u %u %p\n", __func__, msg->sig, msg->pid, msg->act, arg);
btc_msg_t *lmsg;
lmsg = (btc_msg_t *)osi_malloc(sizeof(btc_msg_t));
if (lmsg == NULL) {
@@ -228,52 +177,42 @@ bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg
}
memcpy(lmsg, msg, sizeof(btc_msg_t));
if (arg) {
lmsg->arg = (void *)osi_malloc(arg_len);
if (lmsg->arg == NULL) {
osi_free(lmsg);
return BT_STATUS_NOMEM;
}
memset(lmsg->arg, 0x00, arg_len); //important, avoid arg which have no length
memcpy(lmsg->arg, arg, arg_len);
if (copy_func) {
copy_func(lmsg, lmsg->arg, arg);
}
} else {
lmsg->arg = NULL;
if (osi_thread_post(btc_thread, btc_thread_handler, lmsg, 0, timeout) == false) {
return BT_STATUS_BUSY;
}
return btc_task_post(lmsg, OSI_THREAD_MAX_TIMEOUT);
return BT_STATUS_SUCCESS;
}
/**
* transfer an message to another module in tha same task.
* @param msg message
* @param arg paramter
* @return BT_STATUS_SUCCESS: success
* others: fail
*/
bt_status_t btc_inter_profile_call(btc_msg_t *msg, void *arg)
bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg_deep_copy_t copy_func)
{
btc_msg_t lmsg;
if (msg == NULL) {
return BT_STATUS_PARM_INVALID;
}
msg->arg = arg;
switch (msg->sig) {
case BTC_SIG_API_CALL:
profile_tab[msg->pid].btc_call(msg);
break;
case BTC_SIG_API_CB:
profile_tab[msg->pid].btc_cb(msg);
break;
default:
break;
}
return BT_STATUS_SUCCESS;
}
BTC_TRACE_DEBUG("%s msg %u %u %u %p\n", __func__, msg->sig, msg->pid, msg->act, arg);
memcpy(&lmsg, msg, sizeof(btc_msg_t));
if (arg) {
lmsg.arg = (void *)osi_malloc(arg_len);
if (lmsg.arg == NULL) {
return BT_STATUS_NOMEM;
}
memset(lmsg.arg, 0x00, arg_len); //important, avoid arg which have no length
memcpy(lmsg.arg, arg, arg_len);
if (copy_func) {
copy_func(&lmsg, lmsg.arg, arg);
}
} else {
lmsg.arg = NULL;
}
return btc_task_post(&lmsg, OSI_THREAD_MAX_TIMEOUT);
}
#if BTC_DYNAMIC_MEMORY
@@ -305,13 +244,12 @@ static void btc_deinit_mem(void) {
osi_free(btc_creat_tab_env_ptr);
btc_creat_tab_env_ptr = NULL;
}
#if (BLUFI_INCLUDED == TRUE)
if (blufi_env_ptr) {
osi_free(blufi_env_ptr);
blufi_env_ptr = NULL;
}
#endif
#endif
#if BTC_HF_CLIENT_INCLUDED == TRUE && HFP_DYNAMIC_MEMORY == TRUE
if (hf_client_local_param_ptr) {
@@ -360,13 +298,12 @@ static bt_status_t btc_init_mem(void) {
goto error_exit;
}
memset((void *)btc_creat_tab_env_ptr, 0, sizeof(esp_btc_creat_tab_t));
#if (BLUFI_INCLUDED == TRUE)
if ((blufi_env_ptr = (tBLUFI_ENV *)osi_malloc(sizeof(tBLUFI_ENV))) == NULL) {
goto error_exit;
}
memset((void *)blufi_env_ptr, 0, sizeof(tBLUFI_ENV));
#endif
#endif
#if BTC_HF_CLIENT_INCLUDED == TRUE && HFP_DYNAMIC_MEMORY == TRUE
if ((hf_client_local_param_ptr = (hf_client_local_param_t *)osi_malloc(sizeof(hf_client_local_param_t))) == NULL) {
@@ -394,9 +331,9 @@ error_exit:;
}
#endif ///BTC_DYNAMIC_MEMORY
bt_status_t btc_init(void)
int btc_init(void)
{
btc_thread = osi_thread_create(BTC_TASK_NAME, BTC_TASK_STACK_SIZE, BTC_TASK_PRIO, BTC_TASK_PINNED_TO_CORE, 2);
btc_thread = osi_thread_create("BTC_TASK", BTC_TASK_STACK_SIZE, BTC_TASK_PRIO, BTC_TASK_PINNED_TO_CORE, 2);
if (btc_thread == NULL) {
return BT_STATUS_NOMEM;
}
@@ -441,8 +378,3 @@ bool btc_check_queue_is_congest(void)
return false;
}
int get_btc_work_queue_size(void)
{
return osi_thread_queue_wait_size(btc_thread, 0);
}

View File

@@ -53,9 +53,7 @@ typedef enum {
BTC_PID_GAP_BLE,
BTC_PID_BLE_HID,
BTC_PID_SPPLIKE,
#if (BLUFI_INCLUDED == TRUE)
BTC_PID_BLUFI,
#endif ///BLUFI_INCLUDED == TRUE
BTC_PID_DM_SEC,
BTC_PID_ALARM,
#if (CLASSIC_BT_INCLUDED == TRUE)
@@ -87,7 +85,6 @@ typedef enum {
BTC_PID_LIGHTING_SERVER,
BTC_PID_SENSOR_SERVER,
BTC_PID_TIME_SCENE_SERVER,
BTC_PID_BLE_MESH_BLE_COEX,
#endif /* CONFIG_BLE_MESH */
BTC_PID_NUM,
} btc_pid_t; //btc profile id
@@ -99,29 +96,10 @@ typedef struct {
typedef void (* btc_arg_deep_copy_t)(btc_msg_t *msg, void *dst, void *src);
/**
* transfer an message to another module in the different task.
* @param msg message
* @param arg paramter
* @param arg_len length of paramter
* @param copy_func deep copy function
* @return BT_STATUS_SUCCESS: success
* others: fail
*/
bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg_deep_copy_t copy_func);
/**
* transfer an message to another module in tha same task.
* @param msg message
* @param arg paramter
* @return BT_STATUS_SUCCESS: success
* others: fail
*/
bt_status_t btc_inter_profile_call(btc_msg_t *msg, void *arg);
bt_status_t btc_init(void);
int btc_init(void);
void btc_deinit(void);
bool btc_check_queue_is_congest(void);
int get_btc_work_queue_size(void);
#endif /* __BTC_TASK_H__ */

View File

@@ -42,12 +42,6 @@
#define BTC_DYNAMIC_MEMORY FALSE
#endif
#if UC_BT_BLUEDROID_MEM_DEBUG
#define HEAP_MEMORY_DEBUG TRUE
#else
#define HEAP_MEMORY_DEBUG FALSE
#endif
#ifndef BT_BLE_DYNAMIC_ENV_MEMORY
#define BT_BLE_DYNAMIC_ENV_MEMORY FALSE
#endif

View File

@@ -40,14 +40,14 @@
/**********************************************************
* Thread/Task reference
**********************************************************/
#ifdef CONFIG_BT_BLUEDROID_PINNED_TO_CORE
#define UC_TASK_PINNED_TO_CORE (CONFIG_BT_BLUEDROID_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_BLUEDROID_PINNED_TO_CORE : tskNO_AFFINITY)
#ifdef CONFIG_BLUEDROID_PINNED_TO_CORE
#define UC_TASK_PINNED_TO_CORE (CONFIG_BLUEDROID_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BLUEDROID_PINNED_TO_CORE : tskNO_AFFINITY)
#else
#define UC_TASK_PINNED_TO_CORE (0)
#endif
#ifdef CONFIG_BT_BTC_TASK_STACK_SIZE
#define UC_BTC_TASK_STACK_SIZE CONFIG_BT_BTC_TASK_STACK_SIZE
#ifdef CONFIG_BTC_TASK_STACK_SIZE
#define UC_BTC_TASK_STACK_SIZE CONFIG_BTC_TASK_STACK_SIZE
#else
#define UC_BTC_TASK_STACK_SIZE 4096
#endif
@@ -80,11 +80,4 @@
#define UC_BT_LOG_OSI_TRACE_LEVEL UC_TRACE_LEVEL_WARNING
#endif
//MEMORY DEBUG
#ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG
#define UC_BT_BLUEDROID_MEM_DEBUG TRUE
#else
#define UC_BT_BLUEDROID_MEM_DEBUG FALSE
#endif
#endif /* __BT_USER_CONFIG_H__ */

View File

@@ -143,7 +143,7 @@ static void alarm_cb_handler(struct alarm_t *alarm)
OSI_TRACE_WARNING("%s, invalid state %d\n", __func__, alarm_state);
return;
}
btc_msg_t msg = {0};
btc_msg_t msg;
btc_alarm_args_t arg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_ALARM;
@@ -173,7 +173,7 @@ osi_alarm_t *osi_alarm_new(const char *alarm_name, osi_alarm_callback_t callback
goto end;
}
esp_timer_create_args_t tca = {0};
esp_timer_create_args_t tca;
tca.callback = (esp_timer_cb_t)alarm_cb_handler;
tca.arg = timer_id;
tca.dispatch_method = ESP_TIMER_TASK;
@@ -318,16 +318,3 @@ uint32_t osi_time_get_os_boottime_ms(void)
{
return (uint32_t)(esp_timer_get_time() / 1000);
}
bool osi_alarm_is_active(osi_alarm_t *alarm)
{
assert(alarm != NULL);
assert(alarm_mutex != NULL);
bool is_active = false;
osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT);
is_active = alarm->deadline_us > 0;
osi_mutex_unlock(&alarm_mutex);
return is_active;
}

View File

@@ -267,7 +267,6 @@ bool config_remove_key(config_t *config, const char *section, const char *key)
assert(config != NULL);
assert(section != NULL);
assert(key != NULL);
bool ret;
section_t *sec = section_find(config, section);
entry_t *entry = entry_find(config, section, key);
@@ -275,12 +274,7 @@ bool config_remove_key(config_t *config, const char *section, const char *key)
return false;
}
ret = list_remove(sec->entries, entry);
if (list_length(sec->entries) == 0) {
OSI_TRACE_DEBUG("%s remove section name:%s",__func__, section);
ret &= config_remove_section(config, section);
}
return ret;
return list_remove(sec->entries, entry);
}
const config_section_node_t *config_section_begin(const config_t *config)
@@ -550,12 +544,10 @@ static void config_parse(nvs_handle_t fp, config_t *config)
const size_t keyname_bufsz = sizeof(CONFIG_KEY) + 5 + 1; // including log10(sizeof(i))
char *keyname = osi_calloc(keyname_bufsz);
int buf_size = get_config_size_from_flash(fp);
char *buf = NULL;
char *buf = osi_calloc(buf_size);
if(buf_size == 0) { //First use nvs
goto error;
}
buf = osi_calloc(buf_size);
if (!line || !section || !buf || !keyname) {
err_code |= 0x01;
goto error;

View File

@@ -20,7 +20,6 @@
#define _ALARM_H_
#include <stdint.h>
#include <stdbool.h>
#include "esp_timer.h"
typedef struct alarm_t osi_alarm_t;
@@ -78,8 +77,4 @@ period_ms_t osi_alarm_get_remaining_ms(const osi_alarm_t *alarm);
uint32_t osi_time_get_os_boottime_ms(void);
// This function returns whether the |alarm| which encapsulated
// a one-shot timer is active or not
bool osi_alarm_is_active(osi_alarm_t *alarm);
#endif /*_ALARM_H_*/

View File

@@ -22,10 +22,6 @@ list_t *list_new(list_free_cb callback);
list_node_t *list_free_node(list_t *list, list_node_t *node);
// similar with list_free_node, this function doesn't free the node data
list_node_t *list_delete_node(list_t *list, list_node_t *node);
// Frees the list. This function accepts NULL as an argument, in which case it
// behaves like a no-op.
void list_free(list_t *list);
@@ -79,9 +75,6 @@ bool list_append(list_t *list, void *data);
bool list_remove(list_t *list, void *data);
// similar with list_remove, but do not free the node data
bool list_delete(list_t *list, void *data);
// Removes all elements in the list. Calling this function will return the list to the
// same state it was in after |list_new|. |list| may not be NULL.
void list_clear(list_t *list);

View File

@@ -186,36 +186,6 @@ bool list_remove(list_t *list, void *data)
return false;
}
bool list_delete(list_t *list, void *data)
{
assert(list != NULL);
assert(data != NULL);
if (list_is_empty(list)) {
return false;
}
if (list->head->data == data) {
list_node_t *next = list_delete_node(list, list->head);
if (list->tail == list->head) {
list->tail = next;
}
list->head = next;
return true;
}
for (list_node_t *prev = list->head, *node = list->head->next; node; prev = node, node = node->next)
if (node->data == data) {
prev->next = list_delete_node(list, node);
if (list->tail == node) {
list->tail = prev;
}
return true;
}
return false;
}
void list_clear(list_t *list)
{
assert(list != NULL);
@@ -281,17 +251,3 @@ list_node_t *list_free_node(list_t *list, list_node_t *node)
return next;
}
// remove the element from list but do not free the node data
list_node_t *list_delete_node(list_t *list, list_node_t *node)
{
assert(list != NULL);
assert(node != NULL);
list_node_t *next = node->next;
osi_free(node);
--list->length;
return next;
}

View File

@@ -110,6 +110,7 @@ static void osi_thread_stop(osi_thread_t *thread)
osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priority, osi_thread_core_t core, uint8_t work_queue_num)
{
int ret;
osi_thread_t *thread;
struct osi_thread_start_arg start_arg = {0};
if (stack_size <= 0 ||
@@ -118,17 +119,17 @@ osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priorit
return NULL;
}
osi_thread_t *thread = (osi_thread_t *)osi_calloc(sizeof(osi_thread_t));
thread = (osi_thread_t *)osi_malloc(sizeof(osi_thread_t));
if (thread == NULL) {
goto _err;
}
thread->stop = false;
thread->work_queues = (fixed_queue_t **)osi_calloc(sizeof(fixed_queue_t *) * work_queue_num);
thread->work_queue_num = work_queue_num;
thread->work_queues = (fixed_queue_t **)osi_malloc(sizeof(fixed_queue_t *) * work_queue_num);
if (thread->work_queues == NULL) {
goto _err;
}
thread->work_queue_num = work_queue_num;
for (int i = 0; i < thread->work_queue_num; i++) {
thread->work_queues[i] = fixed_queue_new(DEFAULT_WORK_QUEUE_CAPACITY);

View File

@@ -9,11 +9,11 @@ COMPONENT_ADD_INCLUDEDIRS := include
LIBS := btdm_app
COMPONENT_ADD_LDFLAGS := -lbt -L $(COMPONENT_PATH)/controller/lib/esp32 \
COMPONENT_ADD_LDFLAGS := -lbt -L $(COMPONENT_PATH)/controller/lib \
$(addprefix -l,$(LIBS))
# re-link program if BT binary libs change
COMPONENT_ADD_LINKER_DEPS := $(patsubst %,$(COMPONENT_PATH)/controller/lib/esp32/lib%.a,$(LIBS))
COMPONENT_ADD_LINKER_DEPS := $(patsubst %,$(COMPONENT_PATH)/controller/lib/lib%.a,$(LIBS))
COMPONENT_SUBMODULES += controller/lib
@@ -137,7 +137,6 @@ endif
ifdef CONFIG_BLE_MESH
COMPONENT_ADD_INCLUDEDIRS += esp_ble_mesh/mesh_common/include \
esp_ble_mesh/mesh_common/tinycrypt/include \
esp_ble_mesh/mesh_core \
esp_ble_mesh/mesh_core/include \
esp_ble_mesh/mesh_core/storage \
@@ -150,11 +149,9 @@ COMPONENT_ADD_INCLUDEDIRS += esp_ble_mesh/mesh_common/include \
esp_ble_mesh/api
COMPONENT_SRCDIRS += esp_ble_mesh/mesh_common \
esp_ble_mesh/mesh_common/tinycrypt/src \
esp_ble_mesh/mesh_core \
esp_ble_mesh/mesh_core/storage \
esp_ble_mesh/btc \
esp_ble_mesh/mesh_models/common \
esp_ble_mesh/mesh_models/client \
esp_ble_mesh/mesh_models/server \
esp_ble_mesh/api/core \
@@ -200,8 +197,7 @@ COMPONENT_SRCDIRS += host/nimble/nimble/nimble/host/src
host/nimble/nimble/nimble/host/util/src \
host/nimble/nimble/nimble/host/store/ram/src \
host/nimble/nimble/nimble/host/store/config/src \
host/nimble/esp-hci/src \
host/nimble/port/src
host/nimble/esp-hci/src
ifndef CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS
COMPONENT_SRCDIRS += host/nimble/nimble/ext/tinycrypt/src

File diff suppressed because it is too large Load Diff

View File

@@ -9,8 +9,8 @@ if BLE_MESH
config BLE_MESH_USE_DUPLICATE_SCAN
bool "Support Duplicate Scan in BLE Mesh"
depends on BT_BLUEDROID_ENABLED
select BTDM_BLE_SCAN_DUPL
select BTDM_BLE_MESH_SCAN_DUPL_EN
select BLE_SCAN_DUPLICATE
select BLE_MESH_SCAN_DUPLICATE_EN
default y
help
Enable this option to allow using specific duplicate scan filter
@@ -18,102 +18,6 @@ if BLE_MESH
option in the Bluetooth Controller section in menuconfig, which is
"Scan Duplicate By Device Address and Advertising Data".
choice BLE_MESH_MEM_ALLOC_MODE
prompt "Memory allocation strategy"
default BLE_MESH_MEM_ALLOC_MODE_INTERNAL
help
Allocation strategy for BLE Mesh stack, essentially provides ability to
allocate all required dynamic allocations from,
- Internal DRAM memory only
- External SPIRAM memory only
- Either internal or external memory based on default malloc()
behavior in ESP-IDF
Recommended mode here is always internal, since that is most preferred
from security perspective. But if application requirement does not allow
sufficient free internal memory then alternate mode can be selected.
config BLE_MESH_MEM_ALLOC_MODE_INTERNAL
bool "Internal DRAM"
config BLE_MESH_MEM_ALLOC_MODE_EXTERNAL
bool "External SPIRAM"
depends on ESP32_SPIRAM_SUPPORT
config BLE_MESH_MEM_ALLOC_MODE_DEFAULT
bool "Default alloc mode"
depends on ESP32_SPIRAM_SUPPORT
help
Enable this option to use the default memory allocation strategy when
external SPIRAM is enabled. See the SPIRAM options for more details.
endchoice # BLE_MESH_MEM_ALLOC_MODE
config BLE_MESH_FREERTOS_STATIC_ALLOC
bool "Enable FreeRTOS static allocation"
depends on FREERTOS_SUPPORT_STATIC_ALLOCATION && ESP32_SPIRAM_SUPPORT
default n
help
Enable this option to use FreeRTOS static allocation APIs for BLE Mesh,
which provides the ability to use different dynamic memory (i.e. SPIRAM)
for FreeRTOS objects.
If this option is disabled, the FreeRTOS static allocation APIs will not
be used, and internal DRAM will be allocated for FreeRTOS objects.
choice BLE_MESH_FREERTOS_STATIC_ALLOC_MODE
prompt "Memory allocation for FreeRTOS objects"
depends on BLE_MESH_FREERTOS_STATIC_ALLOC
help
Choose the memory to be used for FreeRTOS objects.
config BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL
bool "External SPIRAM"
depends on ESP32_SPIRAM_SUPPORT
help
If enabled, BLE Mesh allocates dynamic memory from external SPIRAM for
FreeRTOS objects, i.e. mutex, queue, and task stack. External SPIRAM
can only be used for task stack when SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
is enabled. See the SPIRAM options for more details.
endchoice # BLE_MESH_FREERTOS_STATIC_ALLOC_MODE
config BLE_MESH_DEINIT
bool "Support de-initialize BLE Mesh stack"
default y
help
If enabled, users can use the function esp_ble_mesh_deinit() to de-initialize
the whole BLE Mesh stack.
menu "BLE Mesh and BLE coexistence support"
config BLE_MESH_SUPPORT_BLE_ADV
bool "Support sending normal BLE advertising packets"
default n
help
When selected, users can send normal BLE advertising packets
with specific API.
if BLE_MESH_SUPPORT_BLE_ADV
config BLE_MESH_BLE_ADV_BUF_COUNT
int "Number of advertising buffers for BLE advertising packets"
default 3
range 1 255
help
Number of advertising buffers for BLE packets available.
endif # BLE_MESH_SUPPORT_BLE_ADV
config BLE_MESH_SUPPORT_BLE_SCAN
bool "Support scanning normal BLE advertising packets"
default n
help
When selected, users can register a callback and receive normal BLE
advertising packets in the application layer.
endmenu # BLE Mesh and BLE coexistence support
config BLE_MESH_FAST_PROV
bool "Enable BLE Mesh Fast Provisioning"
select BLE_MESH_NODE
@@ -145,7 +49,7 @@ if BLE_MESH
config BLE_MESH_WAIT_FOR_PROV_MAX_DEV_NUM
int "Maximum number of unprovisioned devices that can be added to device queue"
default 10
default 20
range 1 100
help
This option specifies how many unprovisioned devices can be added to device
@@ -153,14 +57,25 @@ if BLE_MESH
queue in the bottom layer which is used to store unprovisioned device
information (e.g. Device UUID, address).
config BLE_MESH_MAX_STORED_NODES
int "Maximum number of nodes whose information can be stored"
default 20
range BLE_MESH_MAX_PROV_NODES 1000
help
This option specifies the maximum number of nodes whose information can be
stored by a Provisioner in its upper layer.
Users can change this value according to the number of nodes whose information
(e.g. Device UUID, unicast address, element number) are going to be stored by
a Provisioner. And the nodes include the provisioned ones and user-added ones.
config BLE_MESH_MAX_PROV_NODES
int "Maximum number of devices that can be provisioned by Provisioner"
default 10
default 20
range 1 1000
help
This option specifies how many devices can be provisioned by a Provisioner.
This value indicates the maximum number of unprovisioned devices which can be
provisioned by a Provisioner. For instance, if the value is 6, it means the
provisioned by a Provisioner. For instanceif the value is 6, it means the
Provisioner can provision up to 6 unprovisioned devices.
Theoretically a Provisioner without the limitation of its memory can provision
up to 32766 unprovisioned devices, here we limit the maximum number to 100
@@ -201,34 +116,12 @@ if BLE_MESH
config BLE_MESH_PROVISIONER_APP_KEY_COUNT
int "Maximum number of application keys that can be owned by Provisioner"
default 3
default 9
range 1 4096
help
This option specifies how many application keys the Provisioner can have.
Indeed, this value decides the number of the application keys which can be added by a Provisioner.
config BLE_MESH_PROVISIONER_RECV_HB
bool "Support receiving Heartbeat messages"
default n
help
When this option is enabled, Provisioner can call specific functions to enable
or disable receiving Heartbeat messages and notify them to the application layer.
if BLE_MESH_PROVISIONER_RECV_HB
config BLE_MESH_PROVISIONER_RECV_HB_FILTER_SIZE
int "Maximum number of filter entries for receiving Heartbeat messages"
default 3
range 1 1000
help
This option specifies how many heartbeat filter entries Provisioner supports.
The heartbeat filter (acceptlist or rejectlist) entries are used to store a
list of SRC and DST which can be used to decide if a heartbeat message will
be processed and notified to the application layer by Provisioner.
Note: The filter is an empty rejectlist by default.
endif # BLE_MESH_PROVISIONER_RECV_HB
endif # BLE_MESH_PROVISIONER
# Virtual option enabled whenever Generic Provisioning layer is needed
@@ -248,19 +141,6 @@ if BLE_MESH
advertising bearer. This option should be enabled if PB-ADV is
going to be used during provisioning procedure.
config BLE_MESH_UNPROVISIONED_BEACON_INTERVAL
int "Interval between two consecutive Unprovisioned Device Beacon"
depends on BLE_MESH_NODE && BLE_MESH_PB_ADV
default 5
default 3 if BLE_MESH_FAST_PROV
range 1 100
help
This option specifies the interval of sending two consecutive unprovisioned
device beacon, users can use this option to change the frequency of sending
unprovisioned device beacon. For example, if the value is 5, it means the
unprovisioned device beacon will send every 5 seconds. When the option of
BLE_MESH_FAST_PROV is selected, the value is better to be 3 seconds, or less.
config BLE_MESH_PB_GATT
bool "Provisioning support using GATT (PB-GATT)"
select BLE_MESH_PROXY
@@ -288,6 +168,15 @@ if BLE_MESH
ability to act as a proxy between a Mesh GATT Client and a Mesh network.
This option should be enabled if a node is going to be a Proxy Server.
config BLE_MESH_GATT_PROXY_CLIENT
bool "BLE Mesh GATT Proxy Client"
select BLE_MESH_PROXY
default n
help
This option enables support for Mesh GATT Proxy Client. The Proxy Client
can use the GATT bearer to send mesh messages to a node that supports the
advertising bearer.
config BLE_MESH_NODE_ID_TIMEOUT
int "Node Identity advertising timeout"
depends on BLE_MESH_GATT_PROXY_SERVER
@@ -302,28 +191,23 @@ if BLE_MESH
node, it will start to advertise using Node Identity during the time
set by this option. And after that, Network ID will be advertised.
config BLE_MESH_PROXY_FILTER_SIZE
int "Maximum number of filter entries per Proxy Client"
depends on BLE_MESH_GATT_PROXY_SERVER
default 4
range 1 32767
help
This option specifies how many Proxy Filter entries the local node supports.
The entries of Proxy filter (whitelist or blacklist) are used to store a
list of addresses which can be used to decide which messages will be forwarded
to the Proxy Client by the Proxy Server.
if BLE_MESH_PROXY
config BLE_MESH_GATT_PROXY_CLIENT
bool "BLE Mesh GATT Proxy Client"
select BLE_MESH_PROXY
default n
help
This option enables support for Mesh GATT Proxy Client. The Proxy Client
can use the GATT bearer to send mesh messages to a node that supports the
advertising bearer.
config BLE_MESH_PROXY_FILTER_SIZE
int "Maximum number of filter entries per Proxy Client"
default 1
default 3 if BLE_MESH_GATT_PROXY_SERVER
range 1 32767
help
This option specifies how many Proxy Filter entries the local node supports.
The entries of Proxy filter (whitelist or blacklist) are used to store a
list of addresses which can be used to decide which messages will be forwarded
to the Proxy Client by the Proxy Server.
endif # BLE_MESH_PROXY
config BLE_MESH_NET_BUF_POOL_USAGE
bool
bool "BLE Mesh net buffer pool usage tracking"
default y
help
Enable BLE Mesh net buffer pool tracking. This option is used to introduce another
@@ -331,20 +215,16 @@ if BLE_MESH
devices. Recommend to enable this option as default.
config BLE_MESH_SETTINGS
bool "Store BLE Mesh configuration persistently"
bool "Store BLE Mesh Node configuration persistently"
default n
help
When selected, the BLE Mesh stack will take care of storing/restoring the BLE
Mesh configuration persistently in flash.
If the device is a BLE Mesh node, when this option is enabled, the configuration
of the device will be stored persistently, including unicast address, NetKey,
AppKey, etc.
And if the device is a BLE Mesh Provisioner, the information of the device will
be stored persistently, including the information of provisioned nodes, NetKey,
AppKey, etc.
When selected, the BLE Mesh stack will take care of storing/restoring the
BLE Mesh configuration persistently in flash. Currently this only supports
storing BLE Mesh node configuration.
Currently enabling this option will only store BLE Mesh nodes' information
in the flash.
if BLE_MESH_SETTINGS
config BLE_MESH_STORE_TIMEOUT
int "Delay (in seconds) before storing anything persistently"
range 0 1000000
@@ -359,7 +239,7 @@ if BLE_MESH
config BLE_MESH_SEQ_STORE_RATE
int "How often the sequence number gets updated in storage"
range 0 1000000
default 0
default 128
help
This value defines how often the local sequence number gets updated in
persistent storage (i.e. flash). e.g. a value of 100 means that the
@@ -374,7 +254,7 @@ if BLE_MESH
config BLE_MESH_RPL_STORE_TIMEOUT
int "Minimum frequency that the RPL gets updated in storage"
range 0 1000000
default 0
default 5
help
This value defines in seconds how soon the RPL (Replay Protection List)
gets written to persistent storage after a change occurs. If the node
@@ -387,73 +267,6 @@ if BLE_MESH
introduce message replay attacks and system security will be in a
vulnerable state.
config BLE_MESH_SETTINGS_BACKWARD_COMPATIBILITY
bool "A specific option for settings backward compatibility"
depends on BLE_MESH_NODE
default n
help
This option is created to solve the issue of failure in recovering
node information after mesh stack updates. In the old version mesh
stack, there is no key of "mesh/role" in nvs. In the new version
mesh stack, key of "mesh/role" is added in nvs, recovering node
information needs to check "mesh/role" key in nvs and implements
selective recovery of mesh node information. Therefore, there may
be failure in recovering node information during node restarting
after OTA.
The new version mesh stack adds the option of "mesh/role" because
we have added the support of storing Provisioner information, while
the old version only supports storing node information.
If users are updating their nodes from old version to new version,
we recommend enabling this option, so that system could set the flag
in advance before recovering node information and make sure the node
information recovering could work as expected.
config BLE_MESH_SPECIFIC_PARTITION
bool "Use a specific NVS partition for BLE Mesh"
default n
help
When selected, the mesh stack will use a specified NVS partition instead of
default NVS partition. Note that the specified partition must be registered
with NVS using nvs_flash_init_partition() API, and the partition must exists
in the csv file.
When Provisioner needs to store a large amount of nodes' information in the
flash (e.g. more than 20), this option is recommended to be enabled.
config BLE_MESH_PARTITION_NAME
string "Name of the NVS partition for BLE Mesh"
depends on BLE_MESH_SPECIFIC_PARTITION
default "ble_mesh"
help
This value defines the name of the specified NVS partition used by the
mesh stack.
config BLE_MESH_USE_MULTIPLE_NAMESPACE
bool "Support using multiple NVS namespaces by Provisioner"
depends on BLE_MESH_PROVISIONER
default n
help
When selected, Provisioner can use different NVS namespaces to store
different instances of mesh information.
For example, if in the first room, Provisioner uses NetKey A, AppKey
A and provisions three devices, these information will be treated as
mesh information instance A. When the Provisioner moves to the second
room, it uses NetKey B, AppKey B and provisions two devices, then the
information will be treated as mesh information instance B.
Here instance A and instance B will be stored in different namespaces.
With this option enabled, Provisioner needs to use specific functions
to open the corresponding NVS namespace, restore the mesh information,
release the mesh information or erase the mesh information.
config BLE_MESH_MAX_NVS_NAMESPACE
int "Maximum number of NVS namespaces"
depends on BLE_MESH_USE_MULTIPLE_NAMESPACE
default 2
range 1 255
help
This option specifies the maximum NVS namespaces supported by Provisioner.
endif # if BLE_MESH_SETTINGS
config BLE_MESH_SUBNET_COUNT
@@ -506,11 +319,6 @@ if BLE_MESH
The replay protection list is used to prevent a node from replay attack,
which will store the source address and sequence number of the received
mesh messages.
For Provisioner, the replay protection list size should not be smaller than
the maximum number of nodes whose information can be stored. And the element
number of each node should also be taken into consideration. For example, if
Provisioner can provision up to 20 nodes and each node contains two elements,
then the replay protection list size of Provisioner should be at least 40.
config BLE_MESH_MSG_CACHE_SIZE
int "Network message cache size"
@@ -561,21 +369,6 @@ if BLE_MESH
stored to flash. E.g. the default value of 4 means that the
state is saved every 24 hours (96 / 4).
config BLE_MESH_IVU_RECOVERY_IVI
bool "Recovery the IV index when the latest whole IV update procedure is missed"
default n
help
According to Section 3.10.5 of Mesh Specification v1.0.1.
If a node in Normal Operation receives a Secure Network beacon with an IV index
equal to the last known IV index+1 and the IV Update Flag set to 0, the node may
update its IV without going to the IV Update in Progress state, or it may initiate
an IV Index Recovery procedure (Section 3.10.6), or it may ignore the Secure
Network beacon. The node makes the choice depending on the time since last IV
update and the likelihood that the node has missed the Secure Network beacons
with the IV update Flag.
When the above situation is encountered, this option can be used to decide whether
to perform the IV index recovery procedure.
config BLE_MESH_TX_SEG_MSG_COUNT
int "Maximum number of simultaneous outgoing segmented messages"
default 1
@@ -610,7 +403,7 @@ if BLE_MESH
config BLE_MESH_TX_SEG_MAX
int "Maximum number of segments in outgoing messages"
default 32
default 20
range 2 32
help
Maximum number of segments supported for outgoing messages.
@@ -794,13 +587,6 @@ if BLE_MESH
help
Maximum number of groups to which the LPN can subscribe.
config BLE_MESH_LPN_SUB_ALL_NODES_ADDR
bool "Automatically subscribe all nodes address"
default n
help
Automatically subscribe all nodes address when friendship
established.
endif # BLE_MESH_LOW_POWER
config BLE_MESH_FRIEND
@@ -951,138 +737,104 @@ if BLE_MESH
uses 0 as the timeout value when sending acknowledged messages, then
the default value will be used which is four seconds.
menu "Support for BLE Mesh Foundation models"
menu "Support for BLE Mesh Client Models"
config BLE_MESH_CFG_CLI
bool "Configuration Client model"
bool "Configuration Client Model"
help
Enable support for Configuration Client model.
Enable support for Configuration client model.
config BLE_MESH_HEALTH_CLI
bool "Health Client model"
bool "Health Client Model"
help
Enable support for Health Client model.
config BLE_MESH_HEALTH_SRV
bool "Health Server model"
default y
help
Enable support for Health Server model.
endmenu #Support for BLE Mesh Foundation models
menu "Support for BLE Mesh Client/Server models"
Enable support for Health client model.
config BLE_MESH_GENERIC_ONOFF_CLI
bool "Generic OnOff Client model"
bool "Generic OnOff Client Model"
help
Enable support for Generic OnOff Client model.
Enable support for Generic OnOff client model.
config BLE_MESH_GENERIC_LEVEL_CLI
bool "Generic Level Client model"
bool "Generic Level Client Model"
help
Enable support for Generic Level Client model.
Enable support for Generic Level client model.
config BLE_MESH_GENERIC_DEF_TRANS_TIME_CLI
bool "Generic Default Transition Time Client model"
bool "Generic Default Transition Time Client Model"
help
Enable support for Generic Default Transition Time Client model.
Enable support for Generic Default Transition Time client model.
config BLE_MESH_GENERIC_POWER_ONOFF_CLI
bool "Generic Power OnOff Client model"
bool "Generic Power Onoff Client Model"
help
Enable support for Generic Power OnOff Client model.
Enable support for Generic Power Onoff client model.
config BLE_MESH_GENERIC_POWER_LEVEL_CLI
bool "Generic Power Level Client model"
bool "Generic Power Level Client Model"
help
Enable support for Generic Power Level Client model.
Enable support for Generic Power Level client model.
config BLE_MESH_GENERIC_BATTERY_CLI
bool "Generic Battery Client model"
bool "Generic Battery Client Model"
help
Enable support for Generic Battery Client model.
Enable support for Generic Battery client model.
config BLE_MESH_GENERIC_LOCATION_CLI
bool "Generic Location Client model"
bool "Generic Location Client Model"
help
Enable support for Generic Location Client model.
Enable support for Generic Location client model.
config BLE_MESH_GENERIC_PROPERTY_CLI
bool "Generic Property Client model"
bool "Generic Property Client Model"
help
Enable support for Generic Property Client model.
Enable support for Generic Property client model.
config BLE_MESH_SENSOR_CLI
bool "Sensor Client model"
bool "Sensor Client Model"
help
Enable support for Sensor Client model.
Enable support for Sensor client model.
config BLE_MESH_TIME_CLI
bool "Time Client model"
bool "Time Client Model"
help
Enable support for Time Client model.
Enable support for Time client model.
config BLE_MESH_SCENE_CLI
bool "Scene Client model"
bool "Scene Client Model"
help
Enable support for Scene Client model.
Enable support for Scene client model.
config BLE_MESH_SCHEDULER_CLI
bool "Scheduler Client model"
bool "Scheduler Client Model"
help
Enable support for Scheduler Client model.
Enable support for Scheduler client model.
config BLE_MESH_LIGHT_LIGHTNESS_CLI
bool "Light Lightness Client model"
bool "Light Lightness Client Model"
help
Enable support for Light Lightness Client model.
Enable support for Light Lightness client model.
config BLE_MESH_LIGHT_CTL_CLI
bool "Light CTL Client model"
bool "Light CTL Client Model"
help
Enable support for Light CTL Client model.
Enable support for Light CTL client model.
config BLE_MESH_LIGHT_HSL_CLI
bool "Light HSL Client model"
bool "Light HSL Client Model"
help
Enable support for Light HSL Client model.
Enable support for Light HSL client model.
config BLE_MESH_LIGHT_XYL_CLI
bool "Light XYL Client model"
bool "Light XYL Client Model"
help
Enable support for Light XYL Client model.
Enable support for Light XYL client model.
config BLE_MESH_LIGHT_LC_CLI
bool "Light LC Client model"
bool "Light LC Client Model"
help
Enable support for Light LC Client model.
Enable support for Light LC client model.
config BLE_MESH_GENERIC_SERVER
bool "Generic server models"
default y
help
Enable support for Generic server models.
config BLE_MESH_SENSOR_SERVER
bool "Sensor server models"
default y
help
Enable support for Sensor server models.
config BLE_MESH_TIME_SCENE_SERVER
bool "Time and Scenes server models"
default y
help
Enable support for Time and Scenes server models.
config BLE_MESH_LIGHTING_SERVER
bool "Lighting server models"
default y
help
Enable support for Lighting server models.
endmenu #Support for BLE Mesh Client/Server models
endmenu
config BLE_MESH_IV_UPDATE_TEST
bool "Test the IV Update Procedure"
@@ -1092,13 +844,6 @@ if BLE_MESH
lets the state to be changed at any time.
If IV Update test mode is going to be used, this option should be enabled.
config BLE_MESH_DISCARD_OLD_SEQ_AUTH
bool
default y
help
This option is used to decide whether discarding the old SeqAuth when
receiving a segmented message.
menu "BLE Mesh specific test option"
config BLE_MESH_SELF_TEST
@@ -1108,26 +853,6 @@ if BLE_MESH
This option adds extra self-tests which are run every time BLE Mesh
networking is initialized.
if BLE_MESH_SELF_TEST
config BLE_MESH_TEST_AUTO_ENTER_NETWORK
bool "Unprovisioned device enters mesh network automatically"
default y
help
With this option enabled, an unprovisioned device can automatically
enters mesh network using a specific test function without the pro-
visioning procedure. And on the Provisioner side, a test function
needs to be invoked to add the node information into the mesh stack.
config BLE_MESH_TEST_USE_WHITE_LIST
bool "Use white list to filter mesh advertising packets"
default n
help
With this option enabled, users can use white list to filter mesh
advertising packets while scanning.
endif # BLE_MESH_SELF_TEST
config BLE_MESH_SHELL
bool "Enable BLE Mesh shell"
default n

View File

@@ -1,110 +0,0 @@
// Copyright 2017-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.
#include <stdint.h>
#include <string.h>
#include "esp_err.h"
#include "btc_ble_mesh_ble.h"
#include "esp_ble_mesh_ble_api.h"
#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT
esp_err_t esp_ble_mesh_register_ble_callback(esp_ble_mesh_ble_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_BLE_MESH_BLE_COEX, callback) == 0 ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT */
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
esp_err_t esp_ble_mesh_start_ble_advertising(const esp_ble_mesh_ble_adv_param_t *param,
const esp_ble_mesh_ble_adv_data_t *data)
{
btc_ble_mesh_ble_args_t arg = {0};
btc_msg_t msg = {0};
if (param == NULL) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_BLE_MESH_BLE_COEX;
msg.act = BTC_BLE_MESH_ACT_START_BLE_ADV;
memcpy(&arg.start_ble_adv.param, param, sizeof(esp_ble_mesh_ble_adv_param_t));
if (data) {
memcpy(&arg.start_ble_adv.data, data, sizeof(esp_ble_mesh_ble_adv_data_t));
}
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_ble_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_stop_ble_advertising(uint8_t index)
{
btc_ble_mesh_ble_args_t arg = {0};
btc_msg_t msg = {0};
if (index >= CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_BLE_MESH_BLE_COEX;
msg.act = BTC_BLE_MESH_ACT_STOP_BLE_ADV;
arg.stop_ble_adv.index = index;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_ble_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN
esp_err_t esp_ble_mesh_start_ble_scanning(esp_ble_mesh_ble_scan_param_t *param)
{
btc_ble_mesh_ble_args_t arg = {0};
btc_msg_t msg = {0};
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_BLE_MESH_BLE_COEX;
msg.act = BTC_BLE_MESH_ACT_START_BLE_SCAN;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_ble_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_stop_ble_scanning(void)
{
btc_ble_mesh_ble_args_t arg = {0};
btc_msg_t msg = {0};
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_BLE_MESH_BLE_COEX;
msg.act = BTC_BLE_MESH_ACT_STOP_BLE_SCAN;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_ble_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */

View File

@@ -17,6 +17,10 @@
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "osi/alarm.h"
#include "esp_err.h"
#include "btc_ble_mesh_prov.h"
@@ -27,7 +31,7 @@ esp_err_t esp_ble_mesh_init(esp_ble_mesh_prov_t *prov, esp_ble_mesh_comp_t *comp
btc_ble_mesh_prov_args_t arg = {0};
SemaphoreHandle_t semaphore = NULL;
btc_msg_t msg = {0};
esp_err_t ret = ESP_OK;
esp_err_t ret;
if (prov == NULL || comp == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -42,7 +46,7 @@ esp_err_t esp_ble_mesh_init(esp_ble_mesh_prov_t *prov, esp_ble_mesh_comp_t *comp
// Create a semaphore
if ((semaphore = xSemaphoreCreateCounting(1, 0)) == NULL) {
BT_ERR("Failed to create semaphore");
LOG_ERROR("%s, Failed to allocate memory for the semaphore", __func__);
return ESP_ERR_NO_MEM;
}
@@ -57,7 +61,7 @@ esp_err_t esp_ble_mesh_init(esp_ble_mesh_prov_t *prov, esp_ble_mesh_comp_t *comp
if (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) != BT_STATUS_SUCCESS) {
vSemaphoreDelete(semaphore);
BT_ERR("Failed to start mesh init");
LOG_ERROR("%s, BLE Mesh initialise failed", __func__);
return ESP_FAIL;
}
@@ -69,25 +73,3 @@ esp_err_t esp_ble_mesh_init(esp_ble_mesh_prov_t *prov, esp_ble_mesh_comp_t *comp
return ESP_OK;
}
#if CONFIG_BLE_MESH_DEINIT
esp_err_t esp_ble_mesh_deinit(esp_ble_mesh_deinit_param_t *param)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (param == NULL) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
arg.mesh_deinit.param.erase_flash = param->erase_flash;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_DEINIT_MESH;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_DEINIT */

View File

@@ -13,7 +13,10 @@
// limitations under the License.
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "esp_err.h"
@@ -33,8 +36,7 @@ uint16_t esp_ble_mesh_get_primary_element_address(void)
return btc_ble_mesh_get_primary_addr();
}
uint16_t *esp_ble_mesh_is_model_subscribed_to_group(esp_ble_mesh_model_t *model,
uint16_t group_addr)
uint16_t *esp_ble_mesh_is_model_subscribed_to_group(esp_ble_mesh_model_t *model, uint16_t group_addr)
{
if (model == NULL) {
return NULL;
@@ -44,9 +46,6 @@ uint16_t *esp_ble_mesh_is_model_subscribed_to_group(esp_ble_mesh_model_t *model,
esp_ble_mesh_elem_t *esp_ble_mesh_find_element(uint16_t element_addr)
{
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(element_addr)) {
return NULL;
}
return btc_ble_mesh_elem_find(element_addr);
}
@@ -56,7 +55,7 @@ uint8_t esp_ble_mesh_get_element_count(void)
}
esp_ble_mesh_model_t *esp_ble_mesh_find_vendor_model(const esp_ble_mesh_elem_t *element,
uint16_t company_id, uint16_t model_id)
uint16_t company_id, uint16_t model_id)
{
if (element == NULL) {
return NULL;
@@ -64,8 +63,7 @@ esp_ble_mesh_model_t *esp_ble_mesh_find_vendor_model(const esp_ble_mesh_elem_t *
return btc_ble_mesh_model_find_vnd(element, company_id, model_id);
}
esp_ble_mesh_model_t *esp_ble_mesh_find_sig_model(const esp_ble_mesh_elem_t *element,
uint16_t model_id)
esp_ble_mesh_model_t *esp_ble_mesh_find_sig_model(const esp_ble_mesh_elem_t *element, uint16_t model_id)
{
if (element == NULL) {
return NULL;
@@ -78,138 +76,3 @@ const esp_ble_mesh_comp_t *esp_ble_mesh_get_composition_data(void)
return btc_ble_mesh_comp_get();
}
esp_err_t esp_ble_mesh_model_subscribe_group_addr(uint16_t element_addr, uint16_t company_id,
uint16_t model_id, uint16_t group_addr)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(element_addr) ||
!ESP_BLE_MESH_ADDR_IS_GROUP(group_addr)) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_MODEL_SUBSCRIBE_GROUP_ADDR;
arg.model_sub_group_addr.element_addr = element_addr;
arg.model_sub_group_addr.company_id = company_id;
arg.model_sub_group_addr.model_id = model_id;
arg.model_sub_group_addr.group_addr = group_addr;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_model_unsubscribe_group_addr(uint16_t element_addr, uint16_t company_id,
uint16_t model_id, uint16_t group_addr)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(element_addr) ||
!ESP_BLE_MESH_ADDR_IS_GROUP(group_addr)) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_MODEL_UNSUBSCRIBE_GROUP_ADDR;
arg.model_unsub_group_addr.element_addr = element_addr;
arg.model_unsub_group_addr.company_id = company_id;
arg.model_unsub_group_addr.model_id = model_id;
arg.model_unsub_group_addr.group_addr = group_addr;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#if CONFIG_BLE_MESH_NODE
const uint8_t *esp_ble_mesh_node_get_local_net_key(uint16_t net_idx)
{
return btc_ble_mesh_node_get_local_net_key(net_idx);
}
const uint8_t *esp_ble_mesh_node_get_local_app_key(uint16_t app_idx)
{
return btc_ble_mesh_node_get_local_app_key(app_idx);
}
esp_err_t esp_ble_mesh_node_add_local_net_key(const uint8_t net_key[16], uint16_t net_idx)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (net_key == NULL || net_idx > 0xFFF) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_NODE_ADD_LOCAL_NET_KEY;
arg.node_add_local_net_key.net_idx = net_idx;
memcpy(arg.node_add_local_net_key.net_key, net_key, 16);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_node_add_local_app_key(const uint8_t app_key[16], uint16_t net_idx, uint16_t app_idx)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (app_key == NULL || net_idx > 0xFFF || app_idx > 0xFFF) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_NODE_ADD_LOCAL_APP_KEY;
arg.node_add_local_app_key.net_idx = net_idx;
arg.node_add_local_app_key.app_idx = app_idx;
memcpy(arg.node_add_local_app_key.app_key, app_key, 16);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_node_bind_app_key_to_local_model(uint16_t element_addr, uint16_t company_id,
uint16_t model_id, uint16_t app_idx)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(element_addr) || app_idx > 0xFFF) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_NODE_BIND_APP_KEY_TO_MODEL;
arg.node_local_mod_app_bind.element_addr = element_addr;
arg.node_local_mod_app_bind.model_id = model_id;
arg.node_local_mod_app_bind.company_id = company_id;
arg.node_local_mod_app_bind.app_idx = app_idx;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_NODE */

View File

@@ -14,6 +14,8 @@
#include <stdint.h>
#include "btc/btc_task.h"
#include "esp_err.h"
#include "btc_ble_mesh_prov.h"

View File

@@ -13,7 +13,10 @@
// limitations under the License.
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "esp_err.h"
@@ -23,28 +26,28 @@
#define ESP_BLE_MESH_TX_SDU_MAX ((CONFIG_BLE_MESH_ADV_BUF_COUNT - 3) * 12)
static esp_err_t ble_mesh_model_send_msg(esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx,
uint32_t opcode,
btc_ble_mesh_model_act_t act,
uint16_t length, uint8_t *data,
int32_t msg_timeout, bool need_rsp,
esp_ble_mesh_dev_role_t device_role)
esp_ble_mesh_msg_ctx_t *ctx,
uint32_t opcode,
btc_ble_mesh_model_act_t act,
uint16_t length, uint8_t *data,
int32_t msg_timeout, bool need_rsp,
esp_ble_mesh_dev_role_t device_role)
{
btc_ble_mesh_model_args_t arg = {0};
uint8_t op_len = 0, mic_len = 0;
uint8_t *msg_data = NULL;
btc_msg_t msg = {0};
esp_err_t status = ESP_OK;
esp_err_t status;
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
if (ctx && ctx->addr == ESP_BLE_MESH_ADDR_UNASSIGNED) {
BT_ERR("Invalid destination address 0x0000");
LOG_ERROR("%s, Invalid destination address 0x0000", __func__);
return ESP_ERR_INVALID_ARG;
}
if (device_role > ROLE_FAST_PROV) {
BT_ERR("Invalid device role 0x%02x", device_role);
LOG_ERROR("%s, Invalid device role 0x%02x", __func__, device_role);
return ESP_ERR_INVALID_ARG;
}
@@ -63,19 +66,19 @@ static esp_err_t ble_mesh_model_send_msg(esp_ble_mesh_model_t *model,
if (act == BTC_BLE_MESH_ACT_MODEL_PUBLISH) {
if (op_len + length > model->pub->msg->size) {
BT_ERR("Too small publication msg size %d", model->pub->msg->size);
LOG_ERROR("%s, Model publication msg size %d is too small", __func__, model->pub->msg->size);
return ESP_ERR_INVALID_ARG;
}
}
if (act == BTC_BLE_MESH_ACT_MODEL_PUBLISH) {
mic_len = ESP_BLE_MESH_MIC_SHORT;
mic_len = 4;
} else {
mic_len = ctx->send_rel ? ESP_BLE_MESH_MIC_LONG : ESP_BLE_MESH_MIC_SHORT;
mic_len = ctx->send_rel ? 8 : 4;
}
if (op_len + length + mic_len > MIN(ESP_BLE_MESH_SDU_MAX_LEN, ESP_BLE_MESH_TX_SDU_MAX)) {
BT_ERR("Too large data length %d", length);
LOG_ERROR("%s, Data length %d is too large", __func__, length);
return ESP_ERR_INVALID_ARG;
}
@@ -83,7 +86,7 @@ static esp_err_t ble_mesh_model_send_msg(esp_ble_mesh_model_t *model,
bt_mesh_model_msg_init(model->pub->msg, opcode);
net_buf_simple_add_mem(model->pub->msg, data, length);
} else {
msg_data = (uint8_t *)bt_mesh_malloc(op_len + length);
msg_data = (uint8_t *)osi_malloc(op_len + length);
if (msg_data == NULL) {
return ESP_ERR_NO_MEM;
}
@@ -112,7 +115,7 @@ static esp_err_t ble_mesh_model_send_msg(esp_ble_mesh_model_t *model,
status = (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_model_args_t), btc_ble_mesh_model_arg_deep_copy)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
bt_mesh_free(msg_data);
osi_free(msg_data);
return status;
}
@@ -126,7 +129,7 @@ esp_err_t esp_ble_mesh_register_custom_model_callback(esp_ble_mesh_model_cb_t ca
esp_err_t esp_ble_mesh_model_msg_opcode_init(uint8_t *data, uint32_t opcode)
{
uint16_t val = 0;
uint16_t val;
if (data == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -158,53 +161,28 @@ esp_err_t esp_ble_mesh_client_model_init(esp_ble_mesh_model_t *model)
if (model == NULL) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return btc_ble_mesh_client_model_init(model);
}
#if CONFIG_BLE_MESH_DEINIT
esp_err_t esp_ble_mesh_client_model_deinit(esp_ble_mesh_model_t *model)
{
if (model == NULL) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return btc_ble_mesh_client_model_deinit(model);
}
#endif /* CONFIG_BLE_MESH_DEINIT */
esp_err_t esp_ble_mesh_server_model_send_msg(esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx,
uint32_t opcode,
uint16_t length, uint8_t *data)
esp_ble_mesh_msg_ctx_t *ctx, uint32_t opcode,
uint16_t length, uint8_t *data)
{
if (model == NULL || ctx == NULL ||
ctx->net_idx == ESP_BLE_MESH_KEY_UNUSED ||
ctx->app_idx == ESP_BLE_MESH_KEY_UNUSED) {
if (!model || !ctx) {
return ESP_ERR_INVALID_ARG;
}
return ble_mesh_model_send_msg(model, ctx, opcode, BTC_BLE_MESH_ACT_SERVER_MODEL_SEND,
length, data, 0, false, ROLE_NODE);
}
esp_err_t esp_ble_mesh_client_model_send_msg(esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx,
uint32_t opcode,
uint16_t length, uint8_t *data,
int32_t msg_timeout, bool need_rsp,
esp_ble_mesh_dev_role_t device_role)
esp_ble_mesh_msg_ctx_t *ctx, uint32_t opcode,
uint16_t length, uint8_t *data, int32_t msg_timeout,
bool need_rsp, esp_ble_mesh_dev_role_t device_role)
{
if (model == NULL || ctx == NULL ||
ctx->net_idx == ESP_BLE_MESH_KEY_UNUSED ||
ctx->app_idx == ESP_BLE_MESH_KEY_UNUSED) {
if (!model || !ctx) {
return ESP_ERR_INVALID_ARG;
}
return ble_mesh_model_send_msg(model, ctx, opcode, BTC_BLE_MESH_ACT_CLIENT_MODEL_SEND,
length, data, msg_timeout, need_rsp, device_role);
}
@@ -213,19 +191,16 @@ esp_err_t esp_ble_mesh_model_publish(esp_ble_mesh_model_t *model, uint32_t opcod
uint16_t length, uint8_t *data,
esp_ble_mesh_dev_role_t device_role)
{
if (model == NULL || model->pub == NULL || model->pub->msg == NULL ||
model->pub->publish_addr == ESP_BLE_MESH_ADDR_UNASSIGNED) {
if (!model || !model->pub || !model->pub->msg) {
return ESP_ERR_INVALID_ARG;
}
return ble_mesh_model_send_msg(model, NULL, opcode, BTC_BLE_MESH_ACT_MODEL_PUBLISH,
length, data, 0, false, device_role);
}
#if CONFIG_BLE_MESH_SERVER_MODEL
esp_err_t esp_ble_mesh_server_model_update_state(esp_ble_mesh_model_t *model,
esp_ble_mesh_server_state_type_t type,
esp_ble_mesh_server_state_value_t *value)
esp_ble_mesh_server_state_type_t type,
esp_ble_mesh_server_state_value_t *value)
{
btc_ble_mesh_model_args_t arg = {0};
btc_msg_t msg = {0};
@@ -247,7 +222,6 @@ esp_err_t esp_ble_mesh_server_model_update_state(esp_ble_mesh_model_t *model,
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_model_args_t), btc_ble_mesh_model_arg_deep_copy)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_SERVER_MODEL */
esp_err_t esp_ble_mesh_node_local_reset(void)
{
@@ -264,7 +238,7 @@ esp_err_t esp_ble_mesh_node_local_reset(void)
#if (CONFIG_BLE_MESH_PROVISIONER)
esp_err_t esp_ble_mesh_provisioner_set_node_name(uint16_t index, const char *name)
esp_err_t esp_ble_mesh_provisioner_set_node_name(int index, const char *name)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
@@ -281,130 +255,27 @@ esp_err_t esp_ble_mesh_provisioner_set_node_name(uint16_t index, const char *nam
arg.set_node_name.index = index;
memset(arg.set_node_name.name, 0, sizeof(arg.set_node_name.name));
strncpy(arg.set_node_name.name, name, ESP_BLE_MESH_NODE_NAME_MAX_LEN);
memcpy(arg.set_node_name.name, name, strlen(name));
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
const char *esp_ble_mesh_provisioner_get_node_name(uint16_t index)
const char *esp_ble_mesh_provisioner_get_node_name(int index)
{
return bt_mesh_provisioner_get_node_name(index);
}
uint16_t esp_ble_mesh_provisioner_get_node_index(const char *name)
int esp_ble_mesh_provisioner_get_node_index(const char *name)
{
if (!name || (strlen(name) > ESP_BLE_MESH_NODE_NAME_MAX_LEN)) {
return ESP_BLE_MESH_INVALID_NODE_INDEX;
return -EINVAL;
}
return bt_mesh_provisioner_get_node_index(name);
}
esp_err_t esp_ble_mesh_provisioner_store_node_comp_data(uint16_t unicast_addr,
uint8_t *data, uint16_t length)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(unicast_addr) || !data || length <= 14) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_STORE_NODE_COMP_DATA;
arg.store_node_comp_data.unicast_addr = unicast_addr;
arg.store_node_comp_data.length = length;
arg.store_node_comp_data.data = data;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), btc_ble_mesh_prov_arg_deep_copy)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_ble_mesh_node_t *esp_ble_mesh_provisioner_get_node_with_uuid(const uint8_t uuid[16])
{
if (!uuid) {
return NULL;
}
return btc_ble_mesh_provisioner_get_node_with_uuid(uuid);
}
esp_ble_mesh_node_t *esp_ble_mesh_provisioner_get_node_with_addr(uint16_t unicast_addr)
{
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(unicast_addr)) {
return NULL;
}
return btc_ble_mesh_provisioner_get_node_with_addr(unicast_addr);
}
esp_ble_mesh_node_t *esp_ble_mesh_provisioner_get_node_with_name(const char *name)
{
if (!name || (strlen(name) > ESP_BLE_MESH_NODE_NAME_MAX_LEN)) {
return NULL;
}
return btc_ble_mesh_provisioner_get_node_with_name(name);
}
uint16_t esp_ble_mesh_provisioner_get_prov_node_count(void)
{
return btc_ble_mesh_provisioner_get_prov_node_count();
}
const esp_ble_mesh_node_t **esp_ble_mesh_provisioner_get_node_table_entry(void)
{
return btc_ble_mesh_provisioner_get_node_table_entry();
}
esp_err_t esp_ble_mesh_provisioner_delete_node_with_uuid(const uint8_t uuid[16])
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!uuid) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DELETE_NODE_WITH_UUID;
memcpy(arg.delete_node_with_uuid.uuid, uuid, 16);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_delete_node_with_addr(uint16_t unicast_addr)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(unicast_addr)) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DELETE_NODE_WITH_ADDR;
arg.delete_node_with_addr.unicast_addr = unicast_addr;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_add_local_app_key(const uint8_t app_key[16],
uint16_t net_idx, uint16_t app_idx)
uint16_t net_idx, uint16_t app_idx)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
@@ -413,7 +284,7 @@ esp_err_t esp_ble_mesh_provisioner_add_local_app_key(const uint8_t app_key[16],
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_ADD_LOCAL_APP_KEY;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_SET_LOCAL_APP_KEY;
arg.add_local_app_key.net_idx = net_idx;
arg.add_local_app_key.app_idx = app_idx;
@@ -426,36 +297,13 @@ esp_err_t esp_ble_mesh_provisioner_add_local_app_key(const uint8_t app_key[16],
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_update_local_app_key(const uint8_t app_key[16],
uint16_t net_idx, uint16_t app_idx)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (app_key == NULL) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_UPDATE_LOCAL_APP_KEY;
memcpy(arg.update_local_app_key.app_key, app_key, 16);
arg.update_local_app_key.net_idx = net_idx;
arg.update_local_app_key.app_idx = app_idx;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
const uint8_t *esp_ble_mesh_provisioner_get_local_app_key(uint16_t net_idx, uint16_t app_idx)
{
return bt_mesh_provisioner_local_app_key_get(net_idx, app_idx);
}
esp_err_t esp_ble_mesh_provisioner_bind_app_key_to_local_model(uint16_t element_addr, uint16_t app_idx,
uint16_t model_id, uint16_t company_id)
uint16_t model_id, uint16_t company_id)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
@@ -503,271 +351,11 @@ esp_err_t esp_ble_mesh_provisioner_add_local_net_key(const uint8_t net_key[16],
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_update_local_net_key(const uint8_t net_key[16], uint16_t net_idx)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (net_key == NULL) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_UPDATE_LOCAL_NET_KEY;
memcpy(arg.update_local_net_key.net_key, net_key, 16);
arg.update_local_net_key.net_idx = net_idx;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
const uint8_t *esp_ble_mesh_provisioner_get_local_net_key(uint16_t net_idx)
{
return bt_mesh_provisioner_local_net_key_get(net_idx);
}
#if CONFIG_BLE_MESH_PROVISIONER_RECV_HB
esp_err_t esp_ble_mesh_provisioner_recv_heartbeat(bool enable)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_ENABLE_HEARTBEAT_RECV;
arg.enable_heartbeat_recv.enable = enable;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_type(uint8_t type)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (type > ESP_BLE_MESH_HEARTBEAT_FILTER_REJECTLIST) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_SET_HEARTBEAT_FILTER_TYPE;
arg.set_heartbeat_filter_type.type = type;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_info(uint8_t op, esp_ble_mesh_heartbeat_filter_info_t *info)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (op > ESP_BLE_MESH_HEARTBEAT_FILTER_REMOVE || info == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(info->hb_src) &&
!ESP_BLE_MESH_ADDR_IS_UNICAST(info->hb_dst) &&
!ESP_BLE_MESH_ADDR_IS_GROUP(info->hb_dst)) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_SET_HEARTBEAT_FILTER_INFO;
arg.set_heartbeat_filter_info.op = op;
arg.set_heartbeat_filter_info.hb_src = info->hb_src;
arg.set_heartbeat_filter_info.hb_dst = info->hb_dst;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_PROVISIONER_RECV_HB */
#if CONFIG_BLE_MESH_SETTINGS
esp_err_t esp_ble_mesh_provisioner_direct_erase_settings(void)
{
btc_msg_t msg = {0};
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DIRECT_ERASE_SETTINGS;
return (btc_transfer_context(&msg, NULL, 0, NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_SETTINGS */
#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE
esp_err_t esp_ble_mesh_provisioner_open_settings_with_index(uint8_t index)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (index >= CONFIG_BLE_MESH_MAX_NVS_NAMESPACE) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_INDEX;
arg.open_settings_with_index.index = index;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_open_settings_with_uid(const char *uid)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!uid || strlen(uid) > ESP_BLE_MESH_SETTINGS_UID_SIZE) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_UID;
strncpy(arg.open_settings_with_uid.uid, uid, ESP_BLE_MESH_SETTINGS_UID_SIZE);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_close_settings_with_index(uint8_t index, bool erase)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (index >= CONFIG_BLE_MESH_MAX_NVS_NAMESPACE) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX;
arg.close_settings_with_index.index = index;
arg.close_settings_with_index.erase = erase;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_close_settings_with_uid(const char *uid, bool erase)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!uid || strlen(uid) > ESP_BLE_MESH_SETTINGS_UID_SIZE) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_UID;
strncpy(arg.close_settings_with_uid.uid, uid, ESP_BLE_MESH_SETTINGS_UID_SIZE);
arg.close_settings_with_uid.erase = erase;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_delete_settings_with_index(uint8_t index)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (index >= CONFIG_BLE_MESH_MAX_NVS_NAMESPACE) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_INDEX;
arg.delete_settings_with_index.index = index;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_delete_settings_with_uid(const char *uid)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!uid || strlen(uid) > ESP_BLE_MESH_SETTINGS_UID_SIZE) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_UID;
strncpy(arg.delete_settings_with_uid.uid, uid, ESP_BLE_MESH_SETTINGS_UID_SIZE);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
const char *esp_ble_mesh_provisioner_get_settings_uid(uint8_t index)
{
if (index >= CONFIG_BLE_MESH_MAX_NVS_NAMESPACE) {
return NULL;
}
return btc_ble_mesh_provisioner_get_settings_uid(index);
}
uint8_t esp_ble_mesh_provisioner_get_settings_index(const char *uid)
{
if (!uid || strlen(uid) > ESP_BLE_MESH_SETTINGS_UID_SIZE) {
return ESP_BLE_MESH_INVALID_SETTINGS_IDX;
}
return btc_ble_mesh_provisioner_get_settings_index(uid);
}
uint8_t esp_ble_mesh_provisioner_get_free_settings_count(void)
{
return btc_ble_mesh_provisioner_get_free_settings_count();
}
#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */
#endif /* CONFIG_BLE_MESH_PROVISIONER */
#if (CONFIG_BLE_MESH_FAST_PROV)

View File

@@ -13,7 +13,9 @@
// limitations under the License.
#include <stdint.h>
#include <string.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "esp_err.h"
@@ -35,29 +37,11 @@ bool esp_ble_mesh_node_is_provisioned(void)
return bt_mesh_is_provisioned();
}
static bool prov_bearers_valid(esp_ble_mesh_prov_bearer_t bearers)
{
if ((!(bearers & (ESP_BLE_MESH_PROV_ADV | ESP_BLE_MESH_PROV_GATT))) ||
(IS_ENABLED(CONFIG_BLE_MESH_PB_ADV) &&
!IS_ENABLED(CONFIG_BLE_MESH_PB_GATT) &&
!(bearers & ESP_BLE_MESH_PROV_ADV)) ||
(!IS_ENABLED(CONFIG_BLE_MESH_PB_ADV) &&
IS_ENABLED(CONFIG_BLE_MESH_PB_GATT) &&
!(bearers & ESP_BLE_MESH_PROV_GATT))) {
return false;
}
return true;
}
esp_err_t esp_ble_mesh_node_prov_enable(esp_ble_mesh_prov_bearer_t bearers)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (prov_bearers_valid(bearers) == false) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
@@ -74,10 +58,6 @@ esp_err_t esp_ble_mesh_node_prov_disable(esp_ble_mesh_prov_bearer_t bearers)
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (prov_bearers_valid(bearers) == false) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
@@ -90,7 +70,7 @@ esp_err_t esp_ble_mesh_node_prov_disable(esp_ble_mesh_prov_bearer_t bearers)
}
esp_err_t esp_ble_mesh_node_set_oob_pub_key(uint8_t pub_key_x[32], uint8_t pub_key_y[32],
uint8_t private_key[32])
uint8_t private_key[32])
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
@@ -138,7 +118,7 @@ esp_err_t esp_ble_mesh_node_input_string(const char *string)
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!string || strlen(string) > ESP_BLE_MESH_PROV_INPUT_OOB_MAX_LEN) {
if (!string) {
return ESP_ERR_INVALID_ARG;
}
@@ -148,8 +128,7 @@ esp_err_t esp_ble_mesh_node_input_string(const char *string)
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_INPUT_STRING;
memset(arg.input_string.string, 0, sizeof(arg.input_string.string));
strncpy(arg.input_string.string, string,
MIN(strlen(string), sizeof(arg.input_string.string)));
strncpy(arg.input_string.string, string, strlen(string));
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
@@ -171,15 +150,14 @@ esp_err_t esp_ble_mesh_set_unprovisioned_device_name(const char *name)
msg.act = BTC_BLE_MESH_ACT_SET_DEVICE_NAME;
memset(arg.set_device_name.name, 0, sizeof(arg.set_device_name.name));
strncpy(arg.set_device_name.name, name, ESP_BLE_MESH_DEVICE_NAME_MAX_LEN);
memcpy(arg.set_device_name.name, name, strlen(name));
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#if (CONFIG_BLE_MESH_PROVISIONER)
esp_err_t esp_ble_mesh_provisioner_read_oob_pub_key(uint8_t link_idx, uint8_t pub_key_x[32],
uint8_t pub_key_y[32])
uint8_t pub_key_y[32])
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
@@ -207,8 +185,7 @@ esp_err_t esp_ble_mesh_provisioner_input_string(const char *string, uint8_t link
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!string || strlen(string) > ESP_BLE_MESH_PROV_OUTPUT_OOB_MAX_LEN ||
link_idx >= MAX_PROV_LINK_IDX) {
if (!string || link_idx >= MAX_PROV_LINK_IDX) {
return ESP_ERR_INVALID_ARG;
}
@@ -219,8 +196,7 @@ esp_err_t esp_ble_mesh_provisioner_input_string(const char *string, uint8_t link
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_INPUT_STR;
memset(arg.provisioner_input_str.string, 0, sizeof(arg.provisioner_input_str.string));
strncpy(arg.provisioner_input_str.string, string,
MIN(strlen(string), sizeof(arg.provisioner_input_str.string)));
strncpy(arg.provisioner_input_str.string, string, strlen(string));
arg.provisioner_input_str.link_idx = link_idx;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
@@ -254,10 +230,6 @@ esp_err_t esp_ble_mesh_provisioner_prov_enable(esp_ble_mesh_prov_bearer_t bearer
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (prov_bearers_valid(bearers) == false) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
@@ -275,10 +247,6 @@ esp_err_t esp_ble_mesh_provisioner_prov_disable(esp_ble_mesh_prov_bearer_t beare
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (prov_bearers_valid(bearers) == false) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
@@ -292,7 +260,7 @@ esp_err_t esp_ble_mesh_provisioner_prov_disable(esp_ble_mesh_prov_bearer_t beare
}
esp_err_t esp_ble_mesh_provisioner_add_unprov_dev(esp_ble_mesh_unprov_dev_add_t *add_dev,
esp_ble_mesh_dev_add_flag_t flags)
esp_ble_mesh_dev_add_flag_t flags)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
@@ -317,40 +285,6 @@ esp_err_t esp_ble_mesh_provisioner_add_unprov_dev(esp_ble_mesh_unprov_dev_add_t
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_prov_device_with_addr(const uint8_t uuid[16],
esp_ble_mesh_bd_addr_t addr,
esp_ble_mesh_addr_type_t addr_type,
esp_ble_mesh_prov_bearer_t bearer,
uint16_t oob_info, uint16_t unicast_addr)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (uuid == NULL || (bearer == ESP_BLE_MESH_PROV_GATT && (addr == NULL ||
addr_type > ESP_BLE_MESH_ADDR_TYPE_RANDOM)) ||
(bearer != ESP_BLE_MESH_PROV_ADV && bearer != ESP_BLE_MESH_PROV_GATT) ||
!ESP_BLE_MESH_ADDR_IS_UNICAST(unicast_addr)) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_PROV_DEV_WITH_ADDR;
memcpy(arg.provisioner_prov_dev_with_addr.uuid, uuid, 16);
if (addr) {
memcpy(arg.provisioner_prov_dev_with_addr.addr, addr, BD_ADDR_LEN);
arg.provisioner_prov_dev_with_addr.addr_type = addr_type;
}
arg.provisioner_prov_dev_with_addr.bearer = bearer;
arg.provisioner_prov_dev_with_addr.oob_info = oob_info;
arg.provisioner_prov_dev_with_addr.unicast_addr = unicast_addr;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_delete_dev(esp_ble_mesh_device_delete_t *del_dev)
{
uint8_t val = DEL_DEV_ADDR_FLAG | DEL_DEV_UUID_FLAG;
@@ -379,15 +313,11 @@ esp_err_t esp_ble_mesh_provisioner_delete_dev(esp_ble_mesh_device_delete_t *del_
}
esp_err_t esp_ble_mesh_provisioner_set_dev_uuid_match(const uint8_t *match_val, uint8_t match_len,
uint8_t offset, bool prov_after_match)
uint8_t offset, bool prov_after_match)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (match_len + offset > ESP_BLE_MESH_OCTET16_LEN) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
@@ -432,47 +362,6 @@ esp_err_t esp_ble_mesh_provisioner_set_prov_data_info(esp_ble_mesh_prov_data_inf
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_set_static_oob_value(const uint8_t *value, uint8_t length)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (value == NULL || length == 0 || length > 16) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_SET_STATIC_OOB_VAL;
arg.set_static_oob_val.length = length;
memcpy(arg.set_static_oob_val.value, value, length);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_set_primary_elem_addr(uint16_t addr)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(addr)) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_SET_PRIMARY_ELEM_ADDR;
arg.set_primary_elem_addr.addr = addr;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_PROVISIONER */
/* The following APIs are for fast provisioning */
@@ -484,8 +373,7 @@ esp_err_t esp_ble_mesh_set_fast_prov_info(esp_ble_mesh_fast_prov_info_t *fast_pr
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (fast_prov_info == NULL || (fast_prov_info->offset +
fast_prov_info->match_len > ESP_BLE_MESH_OCTET16_LEN)) {
if (fast_prov_info == NULL) {
return ESP_ERR_INVALID_ARG;
}

View File

@@ -13,7 +13,9 @@
// limitations under the License.
#include <stdint.h>
#include <string.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "esp_err.h"
@@ -60,8 +62,7 @@ esp_err_t esp_ble_mesh_proxy_gatt_disable(void)
}
esp_err_t esp_ble_mesh_proxy_client_connect(esp_ble_mesh_bd_addr_t addr,
esp_ble_mesh_addr_type_t addr_type,
uint16_t net_idx)
esp_ble_mesh_addr_type_t addr_type, uint16_t net_idx)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
@@ -101,8 +102,8 @@ esp_err_t esp_ble_mesh_proxy_client_disconnect(uint8_t conn_handle)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_proxy_client_set_filter_type(uint8_t conn_handle, uint16_t net_idx,
esp_ble_mesh_proxy_filter_type_t filter_type)
esp_err_t esp_ble_mesh_proxy_client_set_filter_type(uint8_t conn_handle,
uint16_t net_idx, esp_ble_mesh_proxy_filter_type_t filter_type)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
@@ -125,8 +126,8 @@ esp_err_t esp_ble_mesh_proxy_client_set_filter_type(uint8_t conn_handle, uint16_
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_proxy_client_add_filter_addr(uint8_t conn_handle, uint16_t net_idx,
uint16_t *addr, uint16_t addr_num)
esp_err_t esp_ble_mesh_proxy_client_add_filter_addr(uint8_t conn_handle,
uint16_t net_idx, uint16_t *addr, uint16_t addr_num)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
@@ -150,8 +151,8 @@ esp_err_t esp_ble_mesh_proxy_client_add_filter_addr(uint8_t conn_handle, uint16_
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_proxy_client_remove_filter_addr(uint8_t conn_handle, uint16_t net_idx,
uint16_t *addr, uint16_t addr_num)
esp_err_t esp_ble_mesh_proxy_client_remove_filter_addr(uint8_t conn_handle,
uint16_t net_idx, uint16_t *addr, uint16_t addr_num)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};

View File

@@ -1,190 +0,0 @@
// Copyright 2017-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.
#ifndef _ESP_BLE_MESH_BLE_API_H_
#define _ESP_BLE_MESH_BLE_API_H_
#include "esp_ble_mesh_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/** This enum value is the event of BLE operations */
typedef enum {
ESP_BLE_MESH_START_BLE_ADVERTISING_COMP_EVT, /*!< Start BLE advertising completion event */
ESP_BLE_MESH_STOP_BLE_ADVERTISING_COMP_EVT, /*!< Stop BLE advertising completion event */
ESP_BLE_MESH_START_BLE_SCANNING_COMP_EVT, /*!< Start BLE scanning completion event */
ESP_BLE_MESH_STOP_BLE_SCANNING_COMP_EVT, /*!< Stop BLE scanning completion event */
ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT, /*!< Scanning BLE advertising packets event */
ESP_BLE_MESH_BLE_EVT_MAX,
} esp_ble_mesh_ble_cb_event_t;
/** BLE operation callback parameters */
typedef union {
/**
* @brief ESP_BLE_MESH_START_BLE_ADVERTISING_COMP_EVT
*/
struct {
int err_code; /*!< Indicate the result of starting BLE advertising */
uint8_t index; /*!< Index of the BLE advertising */
} start_ble_advertising_comp; /*!< Event parameters of ESP_BLE_MESH_START_BLE_ADVERTISING_COMP_EVT */
/**
* @brief ESP_BLE_MESH_STOP_BLE_ADVERTISING_COMP_EVT
*/
struct {
int err_code; /*!< Indicate the result of stopping BLE advertising */
uint8_t index; /*!< Index of the BLE advertising */
} stop_ble_advertising_comp; /*!< Event parameters of ESP_BLE_MESH_STOP_BLE_ADVERTISING_COMP_EVT */
/**
* @brief ESP_BLE_MESH_START_BLE_SCANNING_COMP_EVT
*/
struct {
int err_code; /*!< Indicate the result of starting BLE scanning */
} start_ble_scan_comp; /*!< Event parameters of ESP_BLE_MESH_START_BLE_SCANNING_COMP_EVT */
/**
* @brief ESP_BLE_MESH_STOP_BLE_SCANNING_COMP_EVT
*/
struct {
int err_code; /*!< Indicate the result of stopping BLE scanning */
} stop_ble_scan_comp; /*!< Event parameters of ESP_BLE_MESH_STOP_BLE_SCANNING_COMP_EVT */
/**
* @brief ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT
*/
struct {
uint8_t addr[6]; /*!< Device address */
uint8_t addr_type; /*!< Device address type */
uint8_t adv_type; /*!< Advertising data type */
uint8_t *data; /*!< Advertising data */
uint16_t length; /*!< Advertising data length */
int8_t rssi; /*!< RSSI of the advertising packet */
} scan_ble_adv_pkt; /*!< Event parameters of ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT */
} esp_ble_mesh_ble_cb_param_t;
/**
* @brief BLE scanning callback function type
*
* @param event: BLE scanning callback event type
* @param param: BLE scanning callback parameter
*/
typedef void (* esp_ble_mesh_ble_cb_t)(esp_ble_mesh_ble_cb_event_t event,
esp_ble_mesh_ble_cb_param_t *param);
/**
* @brief Register BLE scanning callback.
*
* @param[in] callback: Pointer to the BLE scaning callback function.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_register_ble_callback(esp_ble_mesh_ble_cb_t callback);
/** Count for sending BLE advertising packet infinitely */
#define ESP_BLE_MESH_BLE_ADV_INFINITE 0xFFFF
/*!< This enum value is the priority of BLE advertising packet */
typedef enum {
ESP_BLE_MESH_BLE_ADV_PRIO_LOW,
ESP_BLE_MESH_BLE_ADV_PRIO_HIGH,
} esp_ble_mesh_ble_adv_priority_t;
/** Context of BLE advertising parameters. */
typedef struct {
uint16_t interval; /*!< BLE advertising interval */
uint8_t adv_type; /*!< BLE advertising type */
uint8_t own_addr_type; /*!< Own address type */
uint8_t peer_addr_type; /*!< Peer address type */
uint8_t peer_addr[BD_ADDR_LEN]; /*!< Peer address */
uint16_t duration; /*!< Duration is milliseconds */
uint16_t period; /*!< Period in milliseconds */
uint16_t count; /*!< Number of advertising duration */
uint8_t priority:2; /*!< Priority of BLE advertising packet */
} esp_ble_mesh_ble_adv_param_t;
/** Context of BLE advertising data. */
typedef struct {
uint8_t adv_data_len; /*!< Advertising data length */
uint8_t adv_data[31]; /*!< Advertising data */
uint8_t scan_rsp_data_len; /*!< Scan response data length */
uint8_t scan_rsp_data[31]; /*!< Scan response data */
} esp_ble_mesh_ble_adv_data_t;
/**
* @brief This function is called to start BLE advertising with the corresponding data
* and parameters while BLE Mesh is working at the same time.
*
* @note 1. When this function is called, the BLE advertising packet will be posted to
* the BLE mesh adv queue in the mesh stack and waited to be sent.
* 2. In the BLE advertising parameters, the "duration" means the time used for
* sending the BLE advertising packet each time, it shall not be smaller than the
* advertising interval. When the packet is sent successfully, it will be posted
* to the adv queue again after the "period" time if the "count" is bigger than 0.
* The "count" means how many durations the packet will be sent after it is sent
* successfully for the first time. And if the "count" is set to 0xFFFF, which
* means the packet will be sent infinitely.
* 3. The "priority" means the priority of BLE advertising packet compared with
* BLE Mesh packets. Currently two options (i.e. low/high) are provided. If the
* "priority" is high, the BLE advertising packet will be posted to the front of
* adv queue. Otherwise it will be posted to the back of adv queue.
*
* @param[in] param: Pointer to the BLE advertising parameters
* @param[in] data: Pointer to the BLE advertising data and scan response data
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_start_ble_advertising(const esp_ble_mesh_ble_adv_param_t *param,
const esp_ble_mesh_ble_adv_data_t *data);
/**
* @brief This function is called to stop BLE advertising with the corresponding index.
*
* @param[in] index: Index of BLE advertising
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_stop_ble_advertising(uint8_t index);
/** Context of BLE scanning parameters. */
typedef struct {
uint32_t duration; /*!< Duration used to scan normal BLE advertising packets */
} esp_ble_mesh_ble_scan_param_t;
/**
* @brief This function is called to start scanning normal BLE advertising packets
* and notifying the packets to the application layer.
*
* @param[in] param: Pointer to the BLE scanning parameters
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_start_ble_scanning(esp_ble_mesh_ble_scan_param_t *param);
/**
* @brief This function is called to stop notifying normal BLE advertising packets
* to the application layer.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_stop_ble_scanning(void);
#ifdef __cplusplus
}
#endif
#endif /* _ESP_BLE_MESH_BLE_API_H_ */

View File

@@ -17,10 +17,6 @@
#include "esp_ble_mesh_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize BLE Mesh module.
* This API initializes provisioning capabilities and composition data information.
@@ -38,20 +34,4 @@ extern "C" {
*/
esp_err_t esp_ble_mesh_init(esp_ble_mesh_prov_t *prov, esp_ble_mesh_comp_t *comp);
/**
* @brief De-initialize BLE Mesh module.
*
* @note This function shall be invoked after esp_ble_mesh_client_model_deinit().
*
* @param[in] param: Pointer to the structure of BLE Mesh deinit parameters.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_deinit(esp_ble_mesh_deinit_param_t *param);
#ifdef __cplusplus
}
#endif
#endif /* _ESP_BLE_MESH_COMMON_API_H_ */

View File

@@ -17,10 +17,6 @@
#include "esp_ble_mesh_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Get the model publish period, the unit is ms.
*
@@ -55,8 +51,7 @@ uint16_t esp_ble_mesh_get_primary_element_address(void);
* to 0x0000 in order to unsubscribe the model from the group.
*
*/
uint16_t *esp_ble_mesh_is_model_subscribed_to_group(esp_ble_mesh_model_t *model,
uint16_t group_addr);
uint16_t *esp_ble_mesh_is_model_subscribed_to_group(esp_ble_mesh_model_t *model, uint16_t group_addr);
/**
* @brief Find the BLE Mesh element pointer via the element address.
@@ -88,7 +83,7 @@ uint8_t esp_ble_mesh_get_element_count(void);
*
*/
esp_ble_mesh_model_t *esp_ble_mesh_find_vendor_model(const esp_ble_mesh_elem_t *element,
uint16_t company_id, uint16_t model_id);
uint16_t company_id, uint16_t model_id);
/**
* @brief Find the SIG model with the given element and Model id.
@@ -99,8 +94,7 @@ esp_ble_mesh_model_t *esp_ble_mesh_find_vendor_model(const esp_ble_mesh_elem_t *
* @return Pointer to the SIG Model on success, or NULL on failure which means the SIG Model is not found.
*
*/
esp_ble_mesh_model_t *esp_ble_mesh_find_sig_model(const esp_ble_mesh_elem_t *element,
uint16_t model_id);
esp_ble_mesh_model_t *esp_ble_mesh_find_sig_model(const esp_ble_mesh_elem_t *element, uint16_t model_id);
/**
* @brief Get the Composition data which has been registered.
@@ -110,106 +104,4 @@ esp_ble_mesh_model_t *esp_ble_mesh_find_sig_model(const esp_ble_mesh_elem_t *ele
*/
const esp_ble_mesh_comp_t *esp_ble_mesh_get_composition_data(void);
/**
* @brief A local model of node or Provisioner subscribes a group address.
*
* @note This function shall not be invoked before node is provisioned or Provisioner is enabled.
*
* @param[in] element_addr: Unicast address of the element to which the model belongs.
* @param[in] company_id: A 16-bit company identifier.
* @param[in] model_id: A 16-bit model identifier.
* @param[in] group_addr: The group address to be subscribed.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_model_subscribe_group_addr(uint16_t element_addr, uint16_t company_id,
uint16_t model_id, uint16_t group_addr);
/**
* @brief A local model of node or Provisioner unsubscribes a group address.
*
* @note This function shall not be invoked before node is provisioned or Provisioner is enabled.
*
* @param[in] element_addr: Unicast address of the element to which the model belongs.
* @param[in] company_id: A 16-bit company identifier.
* @param[in] model_id: A 16-bit model identifier.
* @param[in] group_addr: The subscribed group address.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_model_unsubscribe_group_addr(uint16_t element_addr, uint16_t company_id,
uint16_t model_id, uint16_t group_addr);
/**
* @brief This function is called by Node to get the local NetKey.
*
* @param[in] net_idx: NetKey index.
*
* @return NetKey on success, or NULL on failure.
*
*/
const uint8_t *esp_ble_mesh_node_get_local_net_key(uint16_t net_idx);
/**
* @brief This function is called by Node to get the local AppKey.
*
* @param[in] app_idx: AppKey index.
*
* @return AppKey on success, or NULL on failure.
*
*/
const uint8_t *esp_ble_mesh_node_get_local_app_key(uint16_t app_idx);
/**
* @brief This function is called by Node to add a local NetKey.
*
* @param[in] net_key: NetKey to be added.
* @param[in] net_idx: NetKey Index.
*
* @note This function can only be called after the device is provisioned.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_node_add_local_net_key(const uint8_t net_key[16], uint16_t net_idx);
/**
* @brief This function is called by Node to add a local AppKey.
*
* @param[in] app_key: AppKey to be added.
* @param[in] net_idx: NetKey Index.
* @param[in] app_idx: AppKey Index.
*
* @note The net_idx must be an existing one.
* This function can only be called after the device is provisioned.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_node_add_local_app_key(const uint8_t app_key[16], uint16_t net_idx, uint16_t app_idx);
/**
* @brief This function is called by Node to bind AppKey to model locally.
*
* @param[in] element_addr: Node local element address
* @param[in] company_id: Node local company id
* @param[in] model_id: Node local model id
* @param[in] app_idx: Node local appkey index
*
* @note If going to bind app_key with local vendor model, the company_id
* shall be set to 0xFFFF.
* This function can only be called after the device is provisioned.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_node_bind_app_key_to_local_model(uint16_t element_addr, uint16_t company_id,
uint16_t model_id, uint16_t app_idx);
#ifdef __cplusplus
}
#endif
#endif /* _ESP_BLE_MESH_LOCAL_DATA_OPERATION_API_H_ */

View File

@@ -17,10 +17,6 @@
#include "esp_ble_mesh_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable BLE Mesh device LPN functionality.
*
@@ -62,8 +58,4 @@ esp_err_t esp_ble_mesh_lpn_disable(bool force);
*/
esp_err_t esp_ble_mesh_lpn_poll(void);
#ifdef __cplusplus
}
#endif
#endif /* _ESP_BLE_MESH_LOW_POWER_API_H_ */

View File

@@ -17,13 +17,9 @@
#include "esp_ble_mesh_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief: event, event code of user-defined model events; param, parameters of user-defined model events */
typedef void (* esp_ble_mesh_model_cb_t)(esp_ble_mesh_model_cb_event_t event,
esp_ble_mesh_model_cb_param_t *param);
esp_ble_mesh_model_cb_param_t *param);
/**
* @brief Register BLE Mesh callback for user-defined models' operations.
@@ -79,18 +75,6 @@ esp_err_t esp_ble_mesh_model_msg_opcode_init(uint8_t *data, uint32_t opcode);
*/
esp_err_t esp_ble_mesh_client_model_init(esp_ble_mesh_model_t *model);
/**
* @brief De-initialize the user-defined client model.
*
* @note This function shall be invoked before esp_ble_mesh_deinit() is called.
*
* @param[in] model: Pointer of the Client model.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_client_model_deinit(esp_ble_mesh_model_t *model);
/**
* @brief Send server model messages(such as server model status messages).
*
@@ -104,9 +88,8 @@ esp_err_t esp_ble_mesh_client_model_deinit(esp_ble_mesh_model_t *model);
*
*/
esp_err_t esp_ble_mesh_server_model_send_msg(esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx,
uint32_t opcode,
uint16_t length, uint8_t *data);
esp_ble_mesh_msg_ctx_t *ctx, uint32_t opcode,
uint16_t length, uint8_t *data);
/**
* @brief Send client model message (such as model get, set, etc).
@@ -124,11 +107,9 @@ esp_err_t esp_ble_mesh_server_model_send_msg(esp_ble_mesh_model_t *model,
*
*/
esp_err_t esp_ble_mesh_client_model_send_msg(esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx,
uint32_t opcode,
uint16_t length, uint8_t *data,
int32_t msg_timeout, bool need_rsp,
esp_ble_mesh_dev_role_t device_role);
esp_ble_mesh_msg_ctx_t *ctx, uint32_t opcode,
uint16_t length, uint8_t *data, int32_t msg_timeout,
bool need_rsp, esp_ble_mesh_dev_role_t device_role);
/**
* @brief Send a model publication message.
@@ -169,8 +150,8 @@ esp_err_t esp_ble_mesh_model_publish(esp_ble_mesh_model_t *model, uint32_t opcod
*
*/
esp_err_t esp_ble_mesh_server_model_update_state(esp_ble_mesh_model_t *model,
esp_ble_mesh_server_state_type_t type,
esp_ble_mesh_server_state_value_t *value);
esp_ble_mesh_server_state_type_t type,
esp_ble_mesh_server_state_value_t *value);
/**
* @brief Reset the provisioning procedure of the local BLE Mesh node.
@@ -195,7 +176,7 @@ esp_err_t esp_ble_mesh_node_local_reset(void);
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_set_node_name(uint16_t index, const char *name);
esp_err_t esp_ble_mesh_provisioner_set_node_name(int index, const char *name);
/**
* @brief This function is called to get the node (provisioned device) name.
@@ -207,119 +188,20 @@ esp_err_t esp_ble_mesh_provisioner_set_node_name(uint16_t index, const char *nam
* @return Node name on success, or NULL on failure.
*
*/
const char *esp_ble_mesh_provisioner_get_node_name(uint16_t index);
const char *esp_ble_mesh_provisioner_get_node_name(int index);
/**
* @brief This function is called to get the node (provisioned device) index.
*
* @param[in] name: Name of the node (end by '\0').
*
* @return Node index on success, or an invalid value (0xFFFF) on failure.
* @return Node index on success, or (negative) error code from errno.h on failure.
*
*/
uint16_t esp_ble_mesh_provisioner_get_node_index(const char *name);
int esp_ble_mesh_provisioner_get_node_index(const char *name);
/**
* @brief This function is called to store the Composition Data of the node.
*
* @param[in] unicast_addr: Element address of the node
* @param[in] data: Pointer of Composition Data
* @param[in] length: Length of Composition Data
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_store_node_comp_data(uint16_t unicast_addr,
uint8_t *data, uint16_t length);
/**
* @brief This function is called to get the provisioned node information
* with the node device uuid.
*
* @param[in] uuid: Device UUID of the node
*
* @return Pointer of the node info struct or NULL on failure.
*
*/
esp_ble_mesh_node_t *esp_ble_mesh_provisioner_get_node_with_uuid(const uint8_t uuid[16]);
/**
* @brief This function is called to get the provisioned node information
* with the node unicast address.
*
* @param[in] unicast_addr: Unicast address of the node
*
* @return Pointer of the node info struct or NULL on failure.
*
*/
esp_ble_mesh_node_t *esp_ble_mesh_provisioner_get_node_with_addr(uint16_t unicast_addr);
/**
* @brief This function is called to get the provisioned node information
* with the node name.
*
* @param[in] name: Name of the node (end by '\0').
*
* @return Pointer of the node info struct or NULL on failure.
*
*/
esp_ble_mesh_node_t *esp_ble_mesh_provisioner_get_node_with_name(const char *name);
/**
* @brief This function is called by Provisioner to get provisioned node count.
*
* @return Number of the provisioned nodes.
*
*/
uint16_t esp_ble_mesh_provisioner_get_prov_node_count(void);
/**
* @brief This function is called by Provisioner to get the entry of the node table.
*
* @note After invoking the function to get the entry of nodes, users can use the "for"
* loop combined with the macro CONFIG_BLE_MESH_MAX_PROV_NODES to get each node's
* information. Before trying to read the node's information, users need to check
* if the node exists, i.e. if the *(esp_ble_mesh_node_t **node) is NULL.
* For example:
* ```
* const esp_ble_mesh_node_t **entry = esp_ble_mesh_provisioner_get_node_table_entry();
* for (int i = 0; i < CONFIG_BLE_MESH_MAX_PROV_NODES; i++) {
* const esp_ble_mesh_node_t *node = entry[i];
* if (node) {
* ......
* }
* }
* ```
*
* @return Pointer to the start of the node table.
*
*/
const esp_ble_mesh_node_t **esp_ble_mesh_provisioner_get_node_table_entry(void);
/**
* @brief This function is called to delete the provisioned node information
* with the node device uuid.
*
* @param[in] uuid: Device UUID of the node
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_delete_node_with_uuid(const uint8_t uuid[16]);
/**
* @brief This function is called to delete the provisioned node information
* with the node unicast address.
*
* @param[in] unicast_addr: Unicast address of the node
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_delete_node_with_addr(uint16_t unicast_addr);
/**
* @brief This function is called to add a local AppKey for Provisioner.
* @brief This function is called to set the app key for the local BLE Mesh stack.
*
* @param[in] app_key: The app key to be set for the local BLE Mesh stack.
* @param[in] net_idx: The network key index.
@@ -333,21 +215,7 @@ esp_err_t esp_ble_mesh_provisioner_delete_node_with_addr(uint16_t unicast_addr);
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_add_local_app_key(const uint8_t app_key[16],
uint16_t net_idx, uint16_t app_idx);
/**
* @brief This function is used to update a local AppKey for Provisioner.
*
* @param[in] app_key: Value of the AppKey.
* @param[in] net_idx: Corresponding NetKey Index.
* @param[in] app_idx: The AppKey Index
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_update_local_app_key(const uint8_t app_key[16],
uint16_t net_idx, uint16_t app_idx);
esp_err_t esp_ble_mesh_provisioner_add_local_app_key(const uint8_t app_key[16], uint16_t net_idx, uint16_t app_idx);
/**
* @brief This function is called by Provisioner to get the local app key value.
@@ -375,7 +243,7 @@ const uint8_t *esp_ble_mesh_provisioner_get_local_app_key(uint16_t net_idx, uint
*
*/
esp_err_t esp_ble_mesh_provisioner_bind_app_key_to_local_model(uint16_t element_addr, uint16_t app_idx,
uint16_t model_id, uint16_t company_id);
uint16_t model_id, uint16_t company_id);
/**
* @brief This function is called by Provisioner to add local network key.
@@ -392,17 +260,6 @@ esp_err_t esp_ble_mesh_provisioner_bind_app_key_to_local_model(uint16_t element_
*/
esp_err_t esp_ble_mesh_provisioner_add_local_net_key(const uint8_t net_key[16], uint16_t net_idx);
/**
* @brief This function is called by Provisioner to update a local network key.
*
* @param[in] net_key: Value of the NetKey.
* @param[in] net_idx: The NetKey Index.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_update_local_net_key(const uint8_t net_key[16], uint16_t net_idx);
/**
* @brief This function is called by Provisioner to get the local network key value.
*
@@ -413,231 +270,6 @@ esp_err_t esp_ble_mesh_provisioner_update_local_net_key(const uint8_t net_key[16
*/
const uint8_t *esp_ble_mesh_provisioner_get_local_net_key(uint16_t net_idx);
/**
* @brief This function is called by Provisioner to enable or disable receiving
* heartbeat messages.
*
* @note If enabling receiving heartbeat message successfully, the filter will
* be an empty rejectlist by default, which means all heartbeat messages
* received by the Provisioner will be reported to the application layer.
*
* @param[in] enable: Enable or disable receiving heartbeat messages.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_recv_heartbeat(bool enable);
/**
* @brief This function is called by Provisioner to set the heartbeat filter type.
*
* @note 1. If the filter type is not the same with the current value, then all the
* filter entries will be cleaned.
* 2. If the previous type is rejectlist, and changed to acceptlist, then the
* filter will be an empty acceptlist, which means no heartbeat messages
* will be reported. Users need to add SRC or DST into the filter entry,
* then heartbeat messages from the SRC or to the DST will be reported.
*
* @param[in] type: Heartbeat filter type (acceptlist or rejectlist).
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_type(uint8_t type);
/**
* @brief This function is called by Provisioner to add or remove a heartbeat filter entry.
*
* @note 1. If the operation is "ADD", the "hb_src" can be set to the SRC (can only be a
* unicast address) of heartbeat messages, and the "hb_dst" can be set to the
* DST (unicast address or group address), at least one of them needs to be set.
* - If only one of them is set, the filter entry will only use the configured
* SRC or DST to filter heartbeat messages.
* - If both of them are set, the SRC and DST will both be used to decide if a
* heartbeat message will be handled.
* - If SRC or DST already exists in some filter entry, then the corresponding
* entry will be cleaned firstly, then a new entry will be allocated to store
* the information.
* 2. If the operation is "REMOVE", the "hb_src" can be set to the SRC (can only be
* a unicast address) of heartbeat messages, and the "hb_dst" can be set to the
* DST (unicast address or group address), at least one of them needs to be set.
* - The filter entry with the same SRC or DST will be removed.
*
* @param[in] op: Add or REMOVE
* @param[in] info: Heartbeat filter entry information, including:
* hb_src - Heartbeat source address;
* hb_dst - Heartbeat destination address;
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_set_heartbeat_filter_info(uint8_t op, esp_ble_mesh_heartbeat_filter_info_t *info);
/**
* @brief This function is called by Provisioner to directly erase the mesh
* information from nvs namespace.
*
* @note This function can be invoked when the mesh stack is not initialized
* or has been de-initialized.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_direct_erase_settings(void);
/**
* @brief This function is called by Provisioner to open a nvs namespace
* for storing mesh information.
*
* @note Before open another nvs namespace, the previously opened nvs
* namespace must be closed firstly.
*
* @param[in] index: Settings index.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_open_settings_with_index(uint8_t index);
/**
* @brief This function is called by Provisioner to open a nvs namespace
* for storing mesh information.
*
* @note Before open another nvs namespace, the previously opened nvs
* namespace must be closed firstly.
*
* @param[in] uid: Settings user id.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_open_settings_with_uid(const char *uid);
/**
* @brief This function is called by Provisioner to close a nvs namespace
* which is opened previously for storing mesh information.
*
* @note 1. Before closing the nvs namespace, it must be open.
* 2. When the function is invoked, the Provisioner functionality
* will be disabled firstly, and:
* a) If the "erase" flag is set to false, the mesh information
* will be cleaned (e.g. removing NetKey, AppKey, nodes, etc)
* from the mesh stack.
* b) If the "erase" flag is set to true, the mesh information
* stored in the nvs namespace will also be erased besides
* been cleaned from the mesh stack.
* 3. If Provisioner tries to work properly again, we can invoke the
* open function to open a new nvs namespace or a previously added
* one, and restore the mesh information from it if not erased.
* 4. The working process shall be as following:
* a) Open settings A
* b) Start to provision and control nodes
* c) Close settings A
* d) Open settings B
* e) Start to provision and control other nodes
* f) Close settings B
* g) ......
*
* @param[in] index: Settings index.
* @param[in] erase: Indicate if erasing mesh information.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_close_settings_with_index(uint8_t index, bool erase);
/**
* @brief This function is called by Provisioner to close a nvs namespace
* which is opened previously for storing mesh information.
*
* @note 1. Before closing the nvs namespace, it must be open.
* 2. When the function is invoked, the Provisioner functionality
* will be disabled firstly, and:
* a) If the "erase" flag is set to false, the mesh information
* will be cleaned (e.g. removing NetKey, AppKey, nodes, etc)
* from the mesh stack.
* b) If the "erase" flag is set to true, the mesh information
* stored in the nvs namespace will also be erased besides
* been cleaned from the mesh stack.
* 3. If Provisioner tries to work properly again, we can invoke the
* open function to open a new nvs namespace or a previously added
* one, and restore the mesh information from it if not erased.
* 4. The working process shall be as following:
* a) Open settings A
* b) Start to provision and control nodes
* c) Close settings A
* d) Open settings B
* e) Start to provision and control other nodes
* f) Close settings B
* g) ......
*
* @param[in] uid: Settings user id.
* @param[in] erase: Indicate if erasing mesh information.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_close_settings_with_uid(const char *uid, bool erase);
/**
* @brief This function is called by Provisioner to erase the mesh information
* and settings user id from a nvs namespace.
*
* @note When this function is called, the nvs namespace must not be open.
* This function is used to erase the mesh information and settings
* user id which are not used currently.
*
* @param[in] index: Settings index.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_delete_settings_with_index(uint8_t index);
/**
* @brief This function is called by Provisioner to erase the mesh information
* and settings user id from a nvs namespace.
*
* @note When this function is called, the nvs namespace must not be open.
* This function is used to erase the mesh information and settings
* user id which are not used currently.
*
* @param[in] uid: Settings user id.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_delete_settings_with_uid(const char *uid);
/**
* @brief This function is called by Provisioner to get settings user id.
*
* @param[in] index: Settings index.
*
* @return Setting user id on success or NULL on failure.
*
*/
const char *esp_ble_mesh_provisioner_get_settings_uid(uint8_t index);
/**
* @brief This function is called by Provisioner to get settings index.
*
* @param[in] uid: Settings user id.
*
* @return Settings index.
*
*/
uint8_t esp_ble_mesh_provisioner_get_settings_index(const char *uid);
/**
* @brief This function is called by Provisioner to get the number of free
* settings user id.
*
* @return Number of free settings user id.
*
*/
uint8_t esp_ble_mesh_provisioner_get_free_settings_count(void);
/**
* @brief This function is called to get fast provisioning application key.
*
@@ -649,8 +281,4 @@ uint8_t esp_ble_mesh_provisioner_get_free_settings_count(void);
*/
const uint8_t *esp_ble_mesh_get_fast_prov_app_key(uint16_t net_idx, uint16_t app_idx);
#ifdef __cplusplus
}
#endif
#endif /* _ESP_BLE_MESH_NETWORKING_API_H_ */

View File

@@ -17,10 +17,6 @@
#include "esp_ble_mesh_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief: event, event code of provisioning events; param, parameters of provisioning events */
typedef void (* esp_ble_mesh_prov_cb_t)(esp_ble_mesh_prov_cb_event_t event,
esp_ble_mesh_prov_cb_param_t *param);
@@ -69,12 +65,6 @@ esp_err_t esp_ble_mesh_node_prov_disable(esp_ble_mesh_prov_bearer_t bearers);
/**
* @brief Unprovisioned device set own oob public key & private key pair.
*
* @note In order to avoid suffering brute-forcing attack (CVE-2020-26559).
* The Bluetooth SIG recommends that potentially vulnerable mesh provisioners
* use an out-of-band mechanism to exchange the public keys.
* So as an unprovisioned device, it should use this function to input
* the Public Key exchanged through the out-of-band mechanism.
*
* @param[in] pub_key_x: Unprovisioned device's Public Key X
* @param[in] pub_key_y: Unprovisioned device's Public Key Y
* @param[in] private_key: Unprovisioned device's Private Key
@@ -82,7 +72,7 @@ esp_err_t esp_ble_mesh_node_prov_disable(esp_ble_mesh_prov_bearer_t bearers);
* @return ESP_OK on success or error code otherwise.
*/
esp_err_t esp_ble_mesh_node_set_oob_pub_key(uint8_t pub_key_x[32], uint8_t pub_key_y[32],
uint8_t private_key[32]);
uint8_t private_key[32]);
/**
* @brief Provide provisioning input OOB number.
@@ -127,10 +117,6 @@ esp_err_t esp_ble_mesh_set_unprovisioned_device_name(const char *name);
/**
* @brief Provisioner inputs unprovisioned device's oob public key.
*
* @note In order to avoid suffering brute-forcing attack (CVE-2020-26559).
* The Bluetooth SIG recommends that potentially vulnerable mesh provisioners
* use an out-of-band mechanism to exchange the public keys.
*
* @param[in] link_idx: The provisioning link index
* @param[in] pub_key_x: Unprovisioned device's Public Key X
* @param[in] pub_key_y: Unprovisioned device's Public Key Y
@@ -138,7 +124,7 @@ esp_err_t esp_ble_mesh_set_unprovisioned_device_name(const char *name);
* @return ESP_OK on success or error code otherwise.
*/
esp_err_t esp_ble_mesh_provisioner_read_oob_pub_key(uint8_t link_idx, uint8_t pub_key_x[32],
uint8_t pub_key_y[32]);
uint8_t pub_key_y[32]);
/**
* @brief Provide provisioning input OOB string.
@@ -242,42 +228,15 @@ esp_err_t esp_ble_mesh_provisioner_prov_disable(esp_ble_mesh_prov_bearer_t beare
*
*/
esp_err_t esp_ble_mesh_provisioner_add_unprov_dev(esp_ble_mesh_unprov_dev_add_t *add_dev,
esp_ble_mesh_dev_add_flag_t flags);
/** @brief Provision an unprovisioned device and assign a fixed unicast address for it in advance.
*
* @param[in] uuid: Device UUID of the unprovisioned device
* @param[in] addr: Device address of the unprovisioned device
* @param[in] addr_type: Device address type of the unprovisioned device
* @param[in] bearer: Provisioning bearer going to be used by Provisioner
* @param[in] oob_info: OOB info of the unprovisioned device
* @param[in] unicast_addr: Unicast address going to be allocated for the unprovisioned device
*
* @return Zero on success or (negative) error code otherwise.
*
* @note: 1. Currently address type only supports public address and static random address.
* 2. Bearer must be equal to ESP_BLE_MESH_PROV_ADV or ESP_BLE_MESH_PROV_GATT, since
* Provisioner will start to provision a device immediately once this function is
* invoked. And the input bearer must be identical with the one within the parameters
* of the ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT event.
* 3. If this function is used by a Provisioner to provision devices, the application
* should take care of the assigned unicast address and avoid overlap of the unicast
* addresses of different nodes.
* 4. Recommend to use only one of the functions "esp_ble_mesh_provisioner_add_unprov_dev"
* and "esp_ble_mesh_provisioner_prov_device_with_addr" by a Provisioner.
*/
esp_err_t esp_ble_mesh_provisioner_prov_device_with_addr(const uint8_t uuid[16],
esp_ble_mesh_bd_addr_t addr,
esp_ble_mesh_addr_type_t addr_type,
esp_ble_mesh_prov_bearer_t bearer,
uint16_t oob_info, uint16_t unicast_addr);
esp_ble_mesh_dev_add_flag_t flags);
/**
* @brief Delete device from queue, and reset current provisioning link with the device.
* @brief Delete device from queue, reset current provisioning link and reset the node.
*
* @note If the device is in the queue, remove it from the queue; if the device is
* being provisioned, terminate the provisioning procedure. Either one of the
* device address or device UUID can be used as input.
* @note If the device is in the queue, remove it from the queue; if the device is being
* provisioned, terminate the provisioning procedure; if the device has already
* been provisioned, reset the device. And either one of the addr or device UUID
* can be input.
*
* @param[in] del_dev: Pointer to a struct containing the device information.
*
@@ -301,8 +260,8 @@ esp_err_t esp_ble_mesh_provisioner_delete_dev(esp_ble_mesh_device_delete_t *del_
*
*/
typedef void (*esp_ble_mesh_prov_adv_cb_t)(const esp_ble_mesh_bd_addr_t addr, const esp_ble_mesh_addr_type_t addr_type,
const uint8_t adv_type, const uint8_t *dev_uuid,
uint16_t oob_info, esp_ble_mesh_prov_bearer_t bearer);
const uint8_t adv_type, const uint8_t *dev_uuid,
uint16_t oob_info, esp_ble_mesh_prov_bearer_t bearer);
/**
* @brief This function is called by Provisioner to set the part of the device UUID
@@ -318,7 +277,7 @@ typedef void (*esp_ble_mesh_prov_adv_cb_t)(const esp_ble_mesh_bd_addr_t addr, co
*
*/
esp_err_t esp_ble_mesh_provisioner_set_dev_uuid_match(const uint8_t *match_val, uint8_t match_len,
uint8_t offset, bool prov_after_match);
uint8_t offset, bool prov_after_match);
/**
* @brief This function is called by Provisioner to set provisioning data information
@@ -331,49 +290,6 @@ esp_err_t esp_ble_mesh_provisioner_set_dev_uuid_match(const uint8_t *match_val,
*/
esp_err_t esp_ble_mesh_provisioner_set_prov_data_info(esp_ble_mesh_prov_data_info_t *prov_data_info);
/**
* @brief This function is called by Provisioner to set static oob value used for provisioning.
*
* @note The Bluetooth SIG recommends that mesh implementations enforce a randomly selected
* AuthValue using all of the available bits, where permitted by the implementation.
* A large entropy helps ensure that a brute-force of the AuthValue, even a static
* AuthValue, cannot normally be completed in a reasonable time (CVE-2020-26557).
*
* AuthValues selected using a cryptographically secure random or pseudorandom number
* generator and having the maximum permitted entropy (128-bits) will be most difficult
* to brute-force. AuthValues with reduced entropy or generated in a predictable manner
* will not grant the same level of protection against this vulnerability. Selecting a
* new AuthValue with each provisioning attempt can also make it more difficult to launch
* a brute-force attack by requiring the attacker to restart the search with each
* provisioning attempt (CVE-2020-26556).
*
* @param[in] value: Pointer to the static oob value.
* @param[in] length: Length of the static oob value.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_set_static_oob_value(const uint8_t *value, uint8_t length);
/**
* @brief This function is called by Provisioner to set own Primary element address.
*
* @note This API must be invoked when BLE Mesh initialization is completed successfully,
* and can be invoked before Provisioner functionality is enabled.
* Once this API is invoked successfully, the prov_unicast_addr value in the struct
* esp_ble_mesh_prov_t will be ignored, and Provisioner will use this address as its
* own primary element address.
* And if the unicast address going to assigned for the next unprovisioned device is
* smaller than the input address + element number of Provisioner, then the address
* for the next unprovisioned device will be recalculated internally.
*
* @param[in] addr: Unicast address of the Primary element of Provisioner.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_set_primary_elem_addr(uint16_t addr);
/**
* @brief This function is called to set provisioning data information before starting
* fast provisioning.
@@ -395,8 +311,4 @@ esp_err_t esp_ble_mesh_set_fast_prov_info(esp_ble_mesh_fast_prov_info_t *fast_pr
*/
esp_err_t esp_ble_mesh_set_fast_prov_action(esp_ble_mesh_fast_prov_action_t action);
#ifdef __cplusplus
}
#endif
#endif /* _ESP_BLE_MESH_PROVISIONING_API_H_ */

View File

@@ -17,10 +17,6 @@
#include "esp_ble_mesh_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable advertising with Node Identity.
*
@@ -65,8 +61,7 @@ esp_err_t esp_ble_mesh_proxy_gatt_disable(void);
*
*/
esp_err_t esp_ble_mesh_proxy_client_connect(esp_ble_mesh_bd_addr_t addr,
esp_ble_mesh_addr_type_t addr_type,
uint16_t net_idx);
esp_ble_mesh_addr_type_t addr_type, uint16_t net_idx);
/**
* @brief Proxy Client terminates a connection with the Proxy Server.
@@ -88,8 +83,8 @@ esp_err_t esp_ble_mesh_proxy_client_disconnect(uint8_t conn_handle);
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_proxy_client_set_filter_type(uint8_t conn_handle, uint16_t net_idx,
esp_ble_mesh_proxy_filter_type_t filter_type);
esp_err_t esp_ble_mesh_proxy_client_set_filter_type(uint8_t conn_handle,
uint16_t net_idx, esp_ble_mesh_proxy_filter_type_t filter_type);
/**
* @brief Proxy Client adds address to the Proxy Server filter list.
@@ -102,8 +97,8 @@ esp_err_t esp_ble_mesh_proxy_client_set_filter_type(uint8_t conn_handle, uint16_
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_proxy_client_add_filter_addr(uint8_t conn_handle, uint16_t net_idx,
uint16_t *addr, uint16_t addr_num);
esp_err_t esp_ble_mesh_proxy_client_add_filter_addr(uint8_t conn_handle,
uint16_t net_idx, uint16_t *addr, uint16_t addr_num);
/**
* @brief Proxy Client removes address from the Proxy Server filter list.
@@ -116,12 +111,8 @@ esp_err_t esp_ble_mesh_proxy_client_add_filter_addr(uint8_t conn_handle, uint16_
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_proxy_client_remove_filter_addr(uint8_t conn_handle, uint16_t net_idx,
uint16_t *addr, uint16_t addr_num);
#ifdef __cplusplus
}
#endif
esp_err_t esp_ble_mesh_proxy_client_remove_filter_addr(uint8_t conn_handle,
uint16_t net_idx, uint16_t *addr, uint16_t addr_num);
#endif /* _ESP_BLE_MESH_PROXY_API_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -14,12 +14,12 @@
#include <stdint.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "btc_ble_mesh_config_model.h"
#include "esp_ble_mesh_config_model_api.h"
#if CONFIG_BLE_MESH_CFG_CLI
esp_err_t esp_ble_mesh_register_config_client_callback(esp_ble_mesh_cfg_client_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
@@ -27,35 +27,20 @@ esp_err_t esp_ble_mesh_register_config_client_callback(esp_ble_mesh_cfg_client_c
return (btc_profile_cb_set(BTC_PID_CONFIG_CLIENT, callback) == 0 ? ESP_OK : ESP_FAIL);
}
static bool config_client_get_need_param(esp_ble_mesh_opcode_t opcode)
esp_err_t esp_ble_mesh_register_config_server_callback(esp_ble_mesh_cfg_server_cb_t callback)
{
switch (opcode) {
case ESP_BLE_MESH_MODEL_OP_COMPOSITION_DATA_GET:
case ESP_BLE_MESH_MODEL_OP_MODEL_PUB_GET:
case ESP_BLE_MESH_MODEL_OP_SIG_MODEL_SUB_GET:
case ESP_BLE_MESH_MODEL_OP_VENDOR_MODEL_SUB_GET:
case ESP_BLE_MESH_MODEL_OP_APP_KEY_GET:
case ESP_BLE_MESH_MODEL_OP_NODE_IDENTITY_GET:
case ESP_BLE_MESH_MODEL_OP_SIG_MODEL_APP_GET:
case ESP_BLE_MESH_MODEL_OP_VENDOR_MODEL_APP_GET:
case ESP_BLE_MESH_MODEL_OP_KEY_REFRESH_PHASE_GET:
case ESP_BLE_MESH_MODEL_OP_LPN_POLLTIMEOUT_GET:
return true;
default:
return false;
}
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_CONFIG_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_config_client_get_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_cfg_client_get_state_t *get_state)
esp_ble_mesh_cfg_client_get_state_t *get_state)
{
btc_ble_mesh_config_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
!ESP_BLE_MESH_ADDR_IS_UNICAST(params->ctx.addr) ||
(config_client_get_need_param(params->opcode) && get_state == NULL)) {
if (!params || !params->model || !params->ctx.addr || !get_state) {
return ESP_ERR_INVALID_ARG;
}
@@ -72,15 +57,12 @@ esp_err_t esp_ble_mesh_config_client_get_state(esp_ble_mesh_client_common_param_
}
esp_err_t esp_ble_mesh_config_client_set_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_cfg_client_set_state_t *set_state)
esp_ble_mesh_cfg_client_set_state_t *set_state)
{
btc_ble_mesh_config_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
!ESP_BLE_MESH_ADDR_IS_UNICAST(params->ctx.addr) ||
(params->opcode != ESP_BLE_MESH_MODEL_OP_NODE_RESET && set_state == NULL)) {
if (!params || !params->model || !params->ctx.addr || !set_state) {
return ESP_ERR_INVALID_ARG;
}
@@ -95,11 +77,3 @@ esp_err_t esp_ble_mesh_config_client_set_state(esp_ble_mesh_client_common_param_
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_config_client_args_t), btc_ble_mesh_config_client_arg_deep_copy)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_CFG_CLI */
esp_err_t esp_ble_mesh_register_config_server_callback(esp_ble_mesh_cfg_server_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_CONFIG_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL);
}

View File

@@ -14,12 +14,12 @@
#include <stdint.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "btc_ble_mesh_generic_model.h"
#include "esp_ble_mesh_generic_model_api.h"
#if CONFIG_BLE_MESH_GENERIC_CLIENT
esp_err_t esp_ble_mesh_register_generic_client_callback(esp_ble_mesh_generic_client_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
@@ -27,30 +27,13 @@ esp_err_t esp_ble_mesh_register_generic_client_callback(esp_ble_mesh_generic_cli
return (btc_profile_cb_set(BTC_PID_GENERIC_CLIENT, callback) == 0 ? ESP_OK : ESP_FAIL);
}
static bool generic_client_get_need_param(esp_ble_mesh_opcode_t opcode)
{
switch (opcode) {
case ESP_BLE_MESH_MODEL_OP_GEN_USER_PROPERTY_GET:
case ESP_BLE_MESH_MODEL_OP_GEN_ADMIN_PROPERTY_GET:
case ESP_BLE_MESH_MODEL_OP_GEN_MANUFACTURER_PROPERTY_GET:
case ESP_BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_GET:
return true;
default:
return false;
}
}
esp_err_t esp_ble_mesh_generic_client_get_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_generic_client_get_state_t *get_state)
esp_ble_mesh_generic_client_get_state_t *get_state)
{
btc_ble_mesh_generic_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.app_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.addr == ESP_BLE_MESH_ADDR_UNASSIGNED ||
(generic_client_get_need_param(params->opcode) && get_state == NULL)) {
if (!params || !params->model || !params->ctx.addr || !get_state) {
return ESP_ERR_INVALID_ARG;
}
@@ -67,15 +50,12 @@ esp_err_t esp_ble_mesh_generic_client_get_state(esp_ble_mesh_client_common_param
}
esp_err_t esp_ble_mesh_generic_client_set_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_generic_client_set_state_t *set_state)
esp_ble_mesh_generic_client_set_state_t *set_state)
{
btc_ble_mesh_generic_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL || set_state == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.app_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.addr == ESP_BLE_MESH_ADDR_UNASSIGNED) {
if (!params || !params->model || !params->ctx.addr || !set_state) {
return ESP_ERR_INVALID_ARG;
}
@@ -90,13 +70,10 @@ esp_err_t esp_ble_mesh_generic_client_set_state(esp_ble_mesh_client_common_param
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_generic_client_args_t), btc_ble_mesh_generic_client_arg_deep_copy)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_GENERIC_CLIENT */
#if CONFIG_BLE_MESH_GENERIC_SERVER
esp_err_t esp_ble_mesh_register_generic_server_callback(esp_ble_mesh_generic_server_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_GENERIC_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_GENERIC_SERVER */

View File

@@ -14,12 +14,12 @@
#include <stdint.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "btc_ble_mesh_health_model.h"
#include "esp_ble_mesh_health_model_api.h"
#if CONFIG_BLE_MESH_HEALTH_CLI
esp_err_t esp_ble_mesh_register_health_client_callback(esp_ble_mesh_health_client_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
@@ -27,17 +27,20 @@ esp_err_t esp_ble_mesh_register_health_client_callback(esp_ble_mesh_health_clien
return (btc_profile_cb_set(BTC_PID_HEALTH_CLIENT, callback) == 0 ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_register_health_server_callback(esp_ble_mesh_health_server_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_HEALTH_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_health_client_get_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_health_client_get_state_t *get_state)
esp_ble_mesh_health_client_get_state_t *get_state)
{
btc_ble_mesh_health_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.app_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.addr == ESP_BLE_MESH_ADDR_UNASSIGNED ||
(params->opcode == ESP_BLE_MESH_MODEL_OP_HEALTH_FAULT_GET && get_state == NULL)) {
if (!params || !params->model || !params->ctx.addr || !get_state) {
return ESP_ERR_INVALID_ARG;
}
@@ -54,15 +57,12 @@ esp_err_t esp_ble_mesh_health_client_get_state(esp_ble_mesh_client_common_param_
}
esp_err_t esp_ble_mesh_health_client_set_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_health_client_set_state_t *set_state)
esp_ble_mesh_health_client_set_state_t *set_state)
{
btc_ble_mesh_health_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL || set_state == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.app_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.addr == ESP_BLE_MESH_ADDR_UNASSIGNED) {
if (!params || !params->model || !params->ctx.addr || !set_state) {
return ESP_ERR_INVALID_ARG;
}
@@ -77,15 +77,6 @@ esp_err_t esp_ble_mesh_health_client_set_state(esp_ble_mesh_client_common_param_
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_health_client_args_t), btc_ble_mesh_health_client_arg_deep_copy)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_HEALTH_CLI */
#if CONFIG_BLE_MESH_HEALTH_SRV
esp_err_t esp_ble_mesh_register_health_server_callback(esp_ble_mesh_health_server_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_HEALTH_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_health_server_fault_update(esp_ble_mesh_elem_t *element)
{
@@ -106,4 +97,3 @@ esp_err_t esp_ble_mesh_health_server_fault_update(esp_ble_mesh_elem_t *element)
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_health_server_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_HEALTH_SRV */

View File

@@ -14,12 +14,12 @@
#include <stdint.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "btc_ble_mesh_lighting_model.h"
#include "esp_ble_mesh_lighting_model_api.h"
#if CONFIG_BLE_MESH_LIGHTING_CLIENT
esp_err_t esp_ble_mesh_register_light_client_callback(esp_ble_mesh_light_client_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
@@ -28,16 +28,12 @@ esp_err_t esp_ble_mesh_register_light_client_callback(esp_ble_mesh_light_client_
}
esp_err_t esp_ble_mesh_light_client_get_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_light_client_get_state_t *get_state)
esp_ble_mesh_light_client_get_state_t *get_state)
{
btc_ble_mesh_lighting_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.app_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.addr == ESP_BLE_MESH_ADDR_UNASSIGNED ||
(params->opcode == ESP_BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_GET && get_state == NULL)) {
if (!params || !params->model || !params->ctx.addr || !get_state) {
return ESP_ERR_INVALID_ARG;
}
@@ -54,15 +50,12 @@ esp_err_t esp_ble_mesh_light_client_get_state(esp_ble_mesh_client_common_param_t
}
esp_err_t esp_ble_mesh_light_client_set_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_light_client_set_state_t *set_state)
esp_ble_mesh_light_client_set_state_t *set_state)
{
btc_ble_mesh_lighting_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL || set_state == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.app_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.addr == ESP_BLE_MESH_ADDR_UNASSIGNED) {
if (!params || !params->model || !params->ctx.addr || !set_state) {
return ESP_ERR_INVALID_ARG;
}
@@ -77,13 +70,10 @@ esp_err_t esp_ble_mesh_light_client_set_state(esp_ble_mesh_client_common_param_t
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_lighting_client_args_t), btc_ble_mesh_lighting_client_arg_deep_copy)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_LIGHTING_CLIENT */
#if CONFIG_BLE_MESH_LIGHTING_SERVER
esp_err_t esp_ble_mesh_register_lighting_server_callback(esp_ble_mesh_lighting_server_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_LIGHTING_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_LIGHTING_SERVER */

View File

@@ -14,12 +14,12 @@
#include <stdint.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "btc_ble_mesh_sensor_model.h"
#include "esp_ble_mesh_sensor_model_api.h"
#if CONFIG_BLE_MESH_SENSOR_CLI
esp_err_t esp_ble_mesh_register_sensor_client_callback(esp_ble_mesh_sensor_client_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
@@ -28,15 +28,12 @@ esp_err_t esp_ble_mesh_register_sensor_client_callback(esp_ble_mesh_sensor_clien
}
esp_err_t esp_ble_mesh_sensor_client_get_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_sensor_client_get_state_t *get_state)
esp_ble_mesh_sensor_client_get_state_t *get_state)
{
btc_ble_mesh_sensor_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL || get_state == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.app_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.addr == ESP_BLE_MESH_ADDR_UNASSIGNED) {
if (!params || !params->model || !params->ctx.addr || !get_state) {
return ESP_ERR_INVALID_ARG;
}
@@ -53,15 +50,12 @@ esp_err_t esp_ble_mesh_sensor_client_get_state(esp_ble_mesh_client_common_param_
}
esp_err_t esp_ble_mesh_sensor_client_set_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_sensor_client_set_state_t *set_state)
esp_ble_mesh_sensor_client_set_state_t *set_state)
{
btc_ble_mesh_sensor_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL || set_state == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.app_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.addr == ESP_BLE_MESH_ADDR_UNASSIGNED) {
if (!params || !params->model || !params->ctx.addr || !set_state) {
return ESP_ERR_INVALID_ARG;
}
@@ -76,13 +70,12 @@ esp_err_t esp_ble_mesh_sensor_client_set_state(esp_ble_mesh_client_common_param_
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_sensor_client_args_t), btc_ble_mesh_sensor_client_arg_deep_copy)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_SENSOR_CLI */
#if CONFIG_BLE_MESH_SENSOR_SERVER
esp_err_t esp_ble_mesh_register_sensor_server_callback(esp_ble_mesh_sensor_server_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_SENSOR_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_SENSOR_SERVER */

View File

@@ -14,12 +14,12 @@
#include <stdint.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "btc_ble_mesh_time_scene_model.h"
#include "esp_ble_mesh_time_scene_model_api.h"
#if CONFIG_BLE_MESH_TIME_SCENE_CLIENT
esp_err_t esp_ble_mesh_register_time_scene_client_callback(esp_ble_mesh_time_scene_client_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
@@ -28,16 +28,12 @@ esp_err_t esp_ble_mesh_register_time_scene_client_callback(esp_ble_mesh_time_sce
}
esp_err_t esp_ble_mesh_time_scene_client_get_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_time_scene_client_get_state_t *get_state)
esp_ble_mesh_time_scene_client_get_state_t *get_state)
{
btc_ble_mesh_time_scene_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.app_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.addr == ESP_BLE_MESH_ADDR_UNASSIGNED ||
(params->opcode == ESP_BLE_MESH_MODEL_OP_SCHEDULER_ACT_GET && get_state == NULL)) {
if (!params || !params->model || !params->ctx.addr || !get_state) {
return ESP_ERR_INVALID_ARG;
}
@@ -54,15 +50,12 @@ esp_err_t esp_ble_mesh_time_scene_client_get_state(esp_ble_mesh_client_common_pa
}
esp_err_t esp_ble_mesh_time_scene_client_set_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_time_scene_client_set_state_t *set_state)
esp_ble_mesh_time_scene_client_set_state_t *set_state)
{
btc_ble_mesh_time_scene_client_args_t arg = {0};
btc_msg_t msg = {0};
if (params == NULL || params->model == NULL || set_state == NULL ||
params->ctx.net_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.app_idx == ESP_BLE_MESH_KEY_UNUSED ||
params->ctx.addr == ESP_BLE_MESH_ADDR_UNASSIGNED) {
if (!params || !params->model || !params->ctx.addr || !set_state) {
return ESP_ERR_INVALID_ARG;
}
@@ -77,13 +70,11 @@ esp_err_t esp_ble_mesh_time_scene_client_set_state(esp_ble_mesh_client_common_pa
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_time_scene_client_args_t), btc_ble_mesh_time_scene_client_arg_deep_copy)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_TIME_SCENE_CLIENT */
#if CONFIG_BLE_MESH_TIME_SCENE_SERVER
esp_err_t esp_ble_mesh_register_time_scene_server_callback(esp_ble_mesh_time_scene_server_cb_t callback)
{
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_TIME_SCENE_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_TIME_SCENE_SERVER */

View File

@@ -17,10 +17,6 @@
#include "esp_ble_mesh_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @def ESP_BLE_MESH_MODEL_CFG_SRV
*
* @brief Define a new Config Server Model.
@@ -756,7 +752,7 @@ typedef enum {
* @param param: Pointer to callback parameter
*/
typedef void (* esp_ble_mesh_cfg_client_cb_t)(esp_ble_mesh_cfg_client_cb_event_t event,
esp_ble_mesh_cfg_client_cb_param_t *param);
esp_ble_mesh_cfg_client_cb_param_t *param);
/**
* @brief Configuration Server Model callback function type
@@ -764,7 +760,7 @@ typedef void (* esp_ble_mesh_cfg_client_cb_t)(esp_ble_mesh_cfg_client_cb_event_t
* @param param: Pointer to callback parameter
*/
typedef void (* esp_ble_mesh_cfg_server_cb_t)(esp_ble_mesh_cfg_server_cb_event_t event,
esp_ble_mesh_cfg_server_cb_param_t *param);
esp_ble_mesh_cfg_server_cb_param_t *param);
/**
* @brief Register BLE Mesh Config Client Model callback.
@@ -800,7 +796,7 @@ esp_err_t esp_ble_mesh_register_config_server_callback(esp_ble_mesh_cfg_server_c
*
*/
esp_err_t esp_ble_mesh_config_client_get_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_cfg_client_get_state_t *get_state);
esp_ble_mesh_cfg_client_get_state_t *get_state);
/**
* @brief Set the value of the Configuration Server Model states using the Config Client Model set messages.
@@ -816,11 +812,7 @@ esp_err_t esp_ble_mesh_config_client_get_state(esp_ble_mesh_client_common_param_
*
*/
esp_err_t esp_ble_mesh_config_client_set_state(esp_ble_mesh_client_common_param_t *params,
esp_ble_mesh_cfg_client_set_state_t *set_state);
esp_ble_mesh_cfg_client_set_state_t *set_state);
#ifdef __cplusplus
}
#endif
#endif /* _ESP_BLE_MESH_CONFIG_MODEL_API_H_ */
#endif /** _ESP_BLE_MESH_CONFIG_MODEL_API_H_ */

Some files were not shown because too many files have changed in this diff Show More