forked from espressif/esp-idf
Compare commits
43 Commits
v4.2-dev
...
v4.0-beta1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
310beae373 | ||
|
|
cf0caaec11 | ||
|
|
ea1037742d | ||
|
|
465d46e9dd | ||
|
|
ebcb3a22b8 | ||
|
|
61ba1c3026 | ||
|
|
90bbea65c1 | ||
|
|
cb3d458050 | ||
|
|
b72ff61899 | ||
|
|
7bb8b5ba9e | ||
|
|
1f5f6adcb6 | ||
|
|
16ee476a77 | ||
|
|
674ecc3b56 | ||
|
|
43efee5232 | ||
|
|
5dab23ea98 | ||
|
|
79afd2d580 | ||
|
|
a8e8919bbf | ||
|
|
ba0f4f17ed | ||
|
|
a63b3c4fe6 | ||
|
|
6b8c75d87c | ||
|
|
68d82abe52 | ||
|
|
ec31f235e9 | ||
|
|
7e9d90b180 | ||
|
|
d4fcbe37f3 | ||
|
|
b9a5f764ba | ||
|
|
764b70d7e6 | ||
|
|
a1496b90e5 | ||
|
|
622d6d5504 | ||
|
|
1b903111b6 | ||
|
|
69ef694178 | ||
|
|
81651b47a4 | ||
|
|
30dc86179c | ||
|
|
eff3ac05b3 | ||
|
|
e5349d47a8 | ||
|
|
4253adf42b | ||
|
|
088ed65194 | ||
|
|
0ce94950b7 | ||
|
|
ae8b2684d7 | ||
|
|
9c51f679a7 | ||
|
|
5c07acad46 | ||
|
|
70af759dd2 | ||
|
|
76191a0f55 | ||
|
|
f0c3114f2f |
1
.flake8
1
.flake8
@@ -152,7 +152,6 @@ exclude =
|
||||
examples/build_system/cmake/import_lib/main/lib/tinyxml2,
|
||||
# other third-party libraries
|
||||
tools/kconfig_new/kconfiglib.py,
|
||||
tools/kconfig_new/menuconfig.py,
|
||||
# autogenerated scripts
|
||||
components/protocomm/python/constants_pb2.py,
|
||||
components/protocomm/python/sec0_pb2.py,
|
||||
|
||||
16
.github/ISSUE_TEMPLATE/config.yml
vendored
16
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,16 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: ESP-IDF Programming Guide
|
||||
url: https://docs.espressif.com/projects/esp-idf/en/latest/
|
||||
about: Documentation for configuring and using ESP-IDF
|
||||
- name: Espressif documentation page
|
||||
url: https://www.espressif.com/en/support/download/documents
|
||||
about: Hardware documentation (datasheets, Technical Reference Manual, etc)
|
||||
- name: Forum
|
||||
url: https://esp32.com
|
||||
about: For questions about using ESP-IDF and/or ESP32 series chips. Please submit all questions starting "How do I..." here.
|
||||
- name: Hardware-related services
|
||||
url: https://www.espressif.com/en/products/hardware-services
|
||||
about: Espressif service providing hardware design and certification support
|
||||
|
||||
|
||||
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,26 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for ESP-IDF
|
||||
title: ''
|
||||
labels: 'Type: Feature Request'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
Please give as many details as you can. Include suggestions for useful APIs or interfaces if relevant.
|
||||
|
||||
**Additional context**
|
||||
|
||||
Add any other context or screenshots about the feature request here.
|
||||
22
.github/main.workflow
vendored
Normal file
22
.github/main.workflow
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
workflow "Sync issues to JIRA" {
|
||||
on = "issues"
|
||||
resolves = ["Sync to JIRA"]
|
||||
}
|
||||
|
||||
workflow "Sync issue and PR comments to JIRA" {
|
||||
on = "issue_comment"
|
||||
resolves = ["Sync to JIRA"]
|
||||
}
|
||||
|
||||
workflow "Sync PRs to JIRA" {
|
||||
on = "pull_request"
|
||||
resolves = ["Sync to JIRA"]
|
||||
}
|
||||
|
||||
action "Sync to JIRA" {
|
||||
uses = "espressif/github-actions/sync_issues_to_jira@master"
|
||||
secrets = ["GITHUB_TOKEN", "JIRA_URL", "JIRA_USER", "JIRA_PASS"]
|
||||
env = {
|
||||
JIRA_PROJECT = "IDFGH"
|
||||
}
|
||||
}
|
||||
19
.github/workflows/issue_comment.yml
vendored
19
.github/workflows/issue_comment.yml
vendored
@@ -1,19 +0,0 @@
|
||||
name: Sync issue comments to JIRA
|
||||
|
||||
# This workflow will be triggered when new issue comment is created (including PR comments)
|
||||
on: issue_comment
|
||||
|
||||
jobs:
|
||||
sync_issue_comments_to_jira:
|
||||
name: Sync Issue Comments to Jira
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Sync issue comments to JIRA
|
||||
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
||||
JIRA_PROJECT: IDFGH
|
||||
JIRA_URL: ${{ secrets.JIRA_URL }}
|
||||
JIRA_USER: ${{ secrets.JIRA_USER }}
|
||||
19
.github/workflows/new_issues.yml
vendored
19
.github/workflows/new_issues.yml
vendored
@@ -1,19 +0,0 @@
|
||||
name: Sync issues to Jira
|
||||
|
||||
# This workflow will be triggered when a new issue is opened
|
||||
on: issues
|
||||
|
||||
jobs:
|
||||
sync_issues_to_jira:
|
||||
name: Sync issues to Jira
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Sync GitHub issues to Jira project
|
||||
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
||||
JIRA_PROJECT: IDFGH
|
||||
JIRA_URL: ${{ secrets.JIRA_URL }}
|
||||
JIRA_USER: ${{ secrets.JIRA_USER }}
|
||||
24
.github/workflows/new_prs.yml
vendored
24
.github/workflows/new_prs.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: Sync remain PRs to Jira
|
||||
|
||||
# This workflow will be triggered every hour, to sync remaining PRs (i.e. PRs with zero comment) to Jira project
|
||||
# Note that, PRs can also get synced when new PR comment is created
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 * * * *"
|
||||
|
||||
jobs:
|
||||
sync_prs_to_jira:
|
||||
name: Sync PRs to Jira
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Sync PRs to Jira project
|
||||
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||
with:
|
||||
cron_job: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
||||
JIRA_PROJECT: IDFGH
|
||||
JIRA_URL: ${{ secrets.JIRA_URL }}
|
||||
JIRA_USER: ${{ secrets.JIRA_USER }}
|
||||
32
.github/workflows/python_lint.yml
vendored
32
.github/workflows/python_lint.yml
vendored
@@ -1,32 +0,0 @@
|
||||
name: Python CI
|
||||
|
||||
# This workflow will be triggered when a PR modifies some python relevant files
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "**.py"
|
||||
- "requirements.txt"
|
||||
|
||||
jobs:
|
||||
python_lint:
|
||||
name: python lint
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [2.7, 3.5, 3.6, 3.7]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
- name: Set up Python environment
|
||||
uses: actions/setup-python@master
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
pip install flake8
|
||||
flake8 . --config=.flake8
|
||||
16
.gitignore
vendored
16
.gitignore
vendored
@@ -63,20 +63,8 @@ test_multi_heap_host
|
||||
# VS Code Settings
|
||||
.vscode/
|
||||
|
||||
# VIM files
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Clion IDE CMake build & config
|
||||
.idea/
|
||||
cmake-build-*/
|
||||
|
||||
# Results for the checking of the Python coding style and static analysis
|
||||
.mypy_cache
|
||||
# Results for the checking of the Python coding style
|
||||
flake8_output.txt
|
||||
|
||||
# ESP-IDF default build directory name
|
||||
# ESP-IDF library
|
||||
build
|
||||
|
||||
# lock files for examples and components
|
||||
dependencies.lock
|
||||
@@ -1,10 +1,9 @@
|
||||
stages:
|
||||
- pre_check
|
||||
- build
|
||||
- assign_test
|
||||
- host_test
|
||||
- target_test
|
||||
- post_check
|
||||
- check
|
||||
- deploy
|
||||
- post_check
|
||||
|
||||
@@ -23,19 +22,11 @@ variables:
|
||||
# GIT_STRATEGY is not defined here.
|
||||
# Use an option from "CI / CD Settings" - "General pipelines".
|
||||
|
||||
# we will download archive for each submodule instead of clone.
|
||||
# we don't do "recursive" when fetch submodule as they're not used in CI now.
|
||||
GIT_SUBMODULE_STRATEGY: none
|
||||
SUBMODULE_FETCH_TOOL: "tools/ci/ci_fetch_submodule.py"
|
||||
# by default we will fetch all submodules
|
||||
# jobs can overwrite this variable to only fetch submodules they required
|
||||
# set to "none" if don't need to fetch submodules
|
||||
SUBMODULES_TO_FETCH: "all"
|
||||
# tell build system do not check submodule update as we download archive instead of clone
|
||||
IDF_SKIP_CHECK_SUBMODULES: 1
|
||||
# "normal" strategy for fetching only top-level submodules since nothing requires the sub-submodules code for building IDF.
|
||||
# If the "recursive" strategy is used we have a problem with using relative URLs for sub-submodules.
|
||||
GIT_SUBMODULE_STRATEGY: normal
|
||||
|
||||
UNIT_TEST_BUILD_SYSTEM: cmake
|
||||
EXAMPLE_TEST_BUILD_SYSTEM: cmake
|
||||
UNIT_TEST_BUILD_SYSTEM: make
|
||||
# IDF environment
|
||||
|
||||
IDF_PATH: "$CI_PROJECT_DIR"
|
||||
@@ -51,7 +42,6 @@ variables:
|
||||
CI_TARGET_TEST_CONFIG_FILE: "$CI_PROJECT_DIR/tools/ci/config/target-test.yml"
|
||||
|
||||
|
||||
|
||||
# before each job, we need to check if this job is filtered by bot stage/job filter
|
||||
.apply_bot_filter: &apply_bot_filter
|
||||
python $APPLY_BOT_FILTER_SCRIPT || exit 0
|
||||
@@ -76,14 +66,16 @@ variables:
|
||||
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
|
||||
if [ "$CI_JOB_STAGE" != "target_test" ]; then
|
||||
tools/idf_tools.py --non-interactive install && eval "$(tools/idf_tools.py --non-interactive export)" || exit 1
|
||||
fi
|
||||
|
||||
.fetch_submodules: &fetch_submodules |
|
||||
python $SUBMODULE_FETCH_TOOL -s $SUBMODULES_TO_FETCH
|
||||
.show_submodule_urls: &show_submodule_urls |
|
||||
git config --get-regexp '^submodule\..*\.url$' || true
|
||||
|
||||
before_script:
|
||||
- echo "Running common script"
|
||||
- *show_submodule_urls
|
||||
- source tools/ci/setup_python.sh
|
||||
# apply bot filter in before script
|
||||
- *apply_bot_filter
|
||||
@@ -99,8 +91,6 @@ before_script:
|
||||
|
||||
- *setup_tools_unless_target_test
|
||||
|
||||
- *fetch_submodules
|
||||
|
||||
- *setup_custom_toolchain
|
||||
|
||||
# used for check scripts which we want to run unconditionally
|
||||
@@ -129,7 +119,7 @@ after_script:
|
||||
- *cleanup_custom_toolchain
|
||||
|
||||
.check_job_template:
|
||||
stage: pre_check
|
||||
stage: check
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
|
||||
tags:
|
||||
- host_test
|
||||
@@ -137,29 +127,17 @@ after_script:
|
||||
extends: .before_script_lesser_nofilter
|
||||
|
||||
.check_job_template_with_filter:
|
||||
stage: pre_check
|
||||
stage: check
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
|
||||
tags:
|
||||
- host_test
|
||||
dependencies: []
|
||||
extends: .before_script_lesser_nofilter
|
||||
|
||||
.macos_build_template:
|
||||
stage: build
|
||||
tags:
|
||||
- macos_shell
|
||||
dependencies: []
|
||||
before_script:
|
||||
- *apply_bot_filter
|
||||
- *setup_tools_unless_target_test
|
||||
- *setup_custom_toolchain
|
||||
- source tools/ci/configure_ci_environment.sh
|
||||
|
||||
include:
|
||||
- '/tools/ci/config/pre_check.yml'
|
||||
- '/tools/ci/config/build.yml'
|
||||
- '/tools/ci/config/assign-test.yml'
|
||||
- '/tools/ci/config/host-test.yml'
|
||||
- '/tools/ci/config/target-test.yml'
|
||||
- '/tools/ci/config/post_check.yml'
|
||||
- '/tools/ci/config/check.yml'
|
||||
- '/tools/ci/config/deploy.yml'
|
||||
|
||||
13
.gitmodules
vendored
13
.gitmodules
vendored
@@ -67,15 +67,10 @@
|
||||
path = examples/build_system/cmake/import_lib/main/lib/tinyxml2
|
||||
url = ../../leethomason/tinyxml2.git
|
||||
|
||||
[submodule "components/esp_wifi/lib_esp32"]
|
||||
path = components/esp_wifi/lib_esp32
|
||||
url = ../../espressif/esp32-wifi-lib.git
|
||||
|
||||
[submodule "components/bt/host/nimble/nimble"]
|
||||
path = components/bt/host/nimble/nimble
|
||||
url = ../../espressif/esp-nimble.git
|
||||
|
||||
[submodule "components/cbor/tinycbor"]
|
||||
path = components/cbor/tinycbor
|
||||
url = ../../intel/tinycbor.git
|
||||
|
||||
[submodule "components/esp_wifi/lib"]
|
||||
path = components/esp_wifi/lib
|
||||
url = ../../espressif/esp32-wifi-lib.git
|
||||
|
||||
|
||||
7
.travis.yml
Normal file
7
.travis.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
language: python
|
||||
sudo: false
|
||||
python:
|
||||
- "3.4"
|
||||
script:
|
||||
- pip install flake8
|
||||
- travis_wait 20 python -m flake8 --config=.flake8 .
|
||||
@@ -5,21 +5,15 @@ unset(compile_options)
|
||||
unset(c_compile_options)
|
||||
unset(cxx_compile_options)
|
||||
unset(compile_definitions)
|
||||
unset(link_options)
|
||||
|
||||
# Add the following build specifications here, since these seem to be dependent
|
||||
# on config values on the root Kconfig.
|
||||
|
||||
if(CONFIG_COMPILER_OPTIMIZATION_SIZE)
|
||||
if(CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE)
|
||||
list(APPEND compile_options "-Os")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
elseif(CONFIG_COMPILER_OPTIMIZATION_DEFAULT)
|
||||
else()
|
||||
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()
|
||||
|
||||
if(CONFIG_COMPILER_CXX_EXCEPTIONS)
|
||||
@@ -28,28 +22,24 @@ else()
|
||||
list(APPEND cxx_compile_options "-fno-exceptions")
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_CXX_RTTI)
|
||||
list(APPEND cxx_compile_options "-frtti")
|
||||
else()
|
||||
list(APPEND cxx_compile_options "-fno-rtti")
|
||||
list(APPEND link_options "-fno-rtti") # used to invoke correct multilib variant (no-rtti) during linking
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_DISABLE_GCC8_WARNINGS)
|
||||
list(APPEND compile_options "-Wno-parentheses"
|
||||
"-Wno-sizeof-pointer-memaccess"
|
||||
"-Wno-clobbered")
|
||||
|
||||
list(APPEND compile_options "-Wno-format-overflow"
|
||||
"-Wno-stringop-truncation"
|
||||
"-Wno-misleading-indentation"
|
||||
"-Wno-cast-function-type"
|
||||
"-Wno-implicit-fallthrough"
|
||||
"-Wno-unused-const-variable"
|
||||
"-Wno-switch-unreachable"
|
||||
"-Wno-format-truncation"
|
||||
"-Wno-memset-elt-size"
|
||||
"-Wno-int-in-bool-context")
|
||||
# doesn't use GCC_NOT_5_2_0 because idf_set_global_variables was not called before
|
||||
if(GCC_NOT_5_2_0)
|
||||
list(APPEND compile_options "-Wno-format-overflow"
|
||||
"-Wno-stringop-truncation"
|
||||
"-Wno-misleading-indentation"
|
||||
"-Wno-cast-function-type"
|
||||
"-Wno-implicit-fallthrough"
|
||||
"-Wno-unused-const-variable"
|
||||
"-Wno-switch-unreachable"
|
||||
"-Wno-format-truncation"
|
||||
"-Wno-memset-elt-size"
|
||||
"-Wno-int-in-bool-context")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE)
|
||||
@@ -64,13 +54,11 @@ elseif(CONFIG_COMPILER_STACK_CHECK_MODE_ALL)
|
||||
list(APPEND compile_options "-fstack-protector-all")
|
||||
endif()
|
||||
|
||||
list(APPEND link_options "-fno-lto")
|
||||
|
||||
idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
|
||||
idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND)
|
||||
idf_build_set_property(CXX_COMPILE_OPTIONS "${cxx_compile_options}" APPEND)
|
||||
idf_build_set_property(COMPILE_DEFINITIONS "${compile_definitions}" APPEND)
|
||||
idf_build_set_property(LINK_OPTIONS "${link_options}" APPEND)
|
||||
|
||||
idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS)
|
||||
|
||||
|
||||
175
Kconfig
175
Kconfig
@@ -4,13 +4,21 @@
|
||||
#
|
||||
mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
# Hidden option to support checking for this specific target in C code and Kconfig files
|
||||
config IDF_TARGET_ESP32
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32"
|
||||
default "n"
|
||||
|
||||
config IDF_CMAKE
|
||||
bool
|
||||
option env="IDF_CMAKE"
|
||||
|
||||
config IDF_ENV_FPGA
|
||||
# This option is for internal use only
|
||||
bool
|
||||
|
||||
config IDF_TARGET_ENV
|
||||
# A proxy to get environment variable $IDF_TARGET
|
||||
string
|
||||
option env="IDF_TARGET"
|
||||
|
||||
config IDF_TARGET
|
||||
# This option records the IDF target when sdkconfig is generated the first time.
|
||||
@@ -18,29 +26,14 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
# the build system is responsible for detecting the mismatch between
|
||||
# CONFIG_IDF_TARGET and $IDF_TARGET.
|
||||
string
|
||||
default "$IDF_TARGET"
|
||||
default "IDF_TARGET_NOT_SET" if IDF_TARGET_ENV=""
|
||||
default IDF_TARGET_ENV
|
||||
|
||||
config IDF_TARGET_ESP32
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32"
|
||||
|
||||
config IDF_TARGET_ESP32S2BETA
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32s2beta"
|
||||
select FREERTOS_UNICORE
|
||||
|
||||
config IDF_FIRMWARE_CHIP_ID
|
||||
hex
|
||||
default 0x0000 if IDF_TARGET_ESP32
|
||||
# note: S2 beta uses Chip ID 0 still, S2 will use 0x0002
|
||||
default 0x0000 if IDF_TARGET_ESP32S2BETA
|
||||
default 0xFFFF
|
||||
|
||||
menu "SDK tool configuration"
|
||||
config SDK_TOOLPREFIX
|
||||
string "Compiler toolchain path/prefix"
|
||||
default "xtensa-esp32-elf-" if IDF_TARGET_ESP32
|
||||
default "xtensa-esp32s2-elf-" if IDF_TARGET_ESP32S2BETA
|
||||
default "xtensa-esp32-elf-"
|
||||
help
|
||||
The prefix/path that is used to call the toolchain. The default setting assumes
|
||||
a crosstool-ng gcc setup that is in your PATH.
|
||||
@@ -69,136 +62,32 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
(Note: this option is used with the legacy GNU Make build system only.)
|
||||
|
||||
config SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS
|
||||
bool "Toolchain supports time_t wide 64-bits"
|
||||
default n
|
||||
help
|
||||
Enable this option in case you have a custom toolchain which supports time_t wide 64-bits.
|
||||
This option checks time_t is 64-bits and disables ROM time functions
|
||||
to use the time functions from the toolchain instead.
|
||||
This option allows resolving the Y2K38 problem.
|
||||
See "Setup Linux Toolchain from Scratch" to build
|
||||
a custom toolchain which supports 64-bits time_t.
|
||||
|
||||
Note: ESP-IDF does not currently come with any pre-compiled toolchain
|
||||
that supports 64-bit wide time_t.
|
||||
This will change in a future major release,
|
||||
but currently 64-bit time_t requires a custom built toolchain.
|
||||
|
||||
endmenu # SDK tool configuration
|
||||
|
||||
menu "Build type"
|
||||
|
||||
choice APP_BUILD_TYPE
|
||||
prompt "Application build type"
|
||||
default APP_BUILD_TYPE_APP_2NDBOOT
|
||||
help
|
||||
Select the way the application is built.
|
||||
|
||||
By default, the application is built as a binary file in a format compatible with
|
||||
the ESP32 bootloader. In addition to this application, 2nd stage bootloader is
|
||||
also built. Application and bootloader binaries can be written into flash and
|
||||
loaded/executed from there.
|
||||
|
||||
Another option, useful for only very small and limited applications, is to only link
|
||||
the .elf file of the application, such that it can be loaded directly into RAM over
|
||||
JTAG. Note that since IRAM and DRAM sizes are very limited, it is not possible to
|
||||
build any complex application this way. However for kinds of testing and debugging,
|
||||
this option may provide faster iterations, since the application does not need to be
|
||||
written into flash.
|
||||
Note that at the moment, ESP-IDF does not contain all the startup code required to
|
||||
initialize the CPUs and ROM memory (data/bss). Therefore it is necessary to execute
|
||||
a bit of ROM code prior to executing the application. A gdbinit file may look as follows:
|
||||
|
||||
# Connect to a running instance of OpenOCD
|
||||
target remote :3333
|
||||
# Reset and halt the target
|
||||
mon reset halt
|
||||
# Run to a specific point in ROM code,
|
||||
# where most of initialization is complete.
|
||||
thb *0x40007901
|
||||
c
|
||||
# Load the application into RAM
|
||||
load
|
||||
# Run till app_main
|
||||
tb app_main
|
||||
c
|
||||
|
||||
Execute this gdbinit file as follows:
|
||||
|
||||
xtensa-esp32-elf-gdb build/app-name.elf -x gdbinit
|
||||
|
||||
Recommended sdkconfig.defaults for building loadable ELF files is as follows.
|
||||
CONFIG_APP_BUILD_TYPE_ELF_RAM is required, other options help reduce application
|
||||
memory footprint.
|
||||
|
||||
CONFIG_APP_BUILD_TYPE_ELF_RAM=y
|
||||
CONFIG_VFS_SUPPORT_TERMIOS=
|
||||
CONFIG_NEWLIB_NANO_FORMAT=y
|
||||
CONFIG_ESP32_PANIC_PRINT_HALT=y
|
||||
CONFIG_ESP32_DEBUG_STUBS_ENABLE=
|
||||
CONFIG_ESP_ERR_TO_NAME_LOOKUP=
|
||||
|
||||
|
||||
config APP_BUILD_TYPE_APP_2NDBOOT
|
||||
bool
|
||||
prompt "Default (binary application + 2nd stage bootloader)"
|
||||
select APP_BUILD_GENERATE_BINARIES
|
||||
select APP_BUILD_BOOTLOADER
|
||||
select APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
config APP_BUILD_TYPE_ELF_RAM
|
||||
bool
|
||||
prompt "ELF file, loadable into RAM (EXPERIMENTAL))"
|
||||
endchoice # APP_BUILD_TYPE
|
||||
|
||||
# Hidden options, set according to the choice above
|
||||
config APP_BUILD_GENERATE_BINARIES
|
||||
bool # Whether to generate .bin files or not
|
||||
|
||||
config APP_BUILD_BOOTLOADER
|
||||
bool # Whether to build the bootloader
|
||||
|
||||
config APP_BUILD_USE_FLASH_SECTIONS
|
||||
bool # Whether to place code/data into memory-mapped flash sections
|
||||
|
||||
endmenu # Build type
|
||||
|
||||
source "$COMPONENT_KCONFIGS_PROJBUILD_SOURCE_FILE"
|
||||
source "$COMPONENT_KCONFIGS_PROJBUILD"
|
||||
|
||||
menu "Compiler options"
|
||||
|
||||
choice COMPILER_OPTIMIZATION
|
||||
prompt "Optimization Level"
|
||||
default COMPILER_OPTIMIZATION_DEFAULT
|
||||
default COMPILER_OPTIMIZATION_LEVEL_DEBUG
|
||||
help
|
||||
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.
|
||||
- The "Performance" setting will add the -O2 flag to CFLAGS.
|
||||
- The "None" setting will add the -O0 flag to CFLAGS.
|
||||
- for "Release" setting, -Os flag is added to CFLAGS.
|
||||
- for "Debug" setting, -Og flag is added to CFLAGS.
|
||||
|
||||
The "Size" setting cause the compiled code to be smaller and faster, but
|
||||
may lead to difficulties of correlating code addresses to source file
|
||||
lines when debugging.
|
||||
"Release" with -Os produces smaller & faster compiled code but it
|
||||
may be harder to correlated code addresses to source files when debugging.
|
||||
|
||||
The "Performance" setting causes the compiled code to be larger and faster,
|
||||
but will be easier to correlated code addresses to source file lines.
|
||||
To add custom optimization settings, set CFLAGS and/or CPPFLAGS
|
||||
in project makefile, before including $(IDF_PATH)/make/project.mk. Note that
|
||||
custom optimization levels may be unsupported.
|
||||
|
||||
"None" with -O0 produces compiled code without optimization.
|
||||
|
||||
Note that custom optimization levels may be unsupported.
|
||||
|
||||
config COMPILER_OPTIMIZATION_DEFAULT
|
||||
config COMPILER_OPTIMIZATION_LEVEL_DEBUG
|
||||
bool "Debug (-Og)"
|
||||
config COMPILER_OPTIMIZATION_SIZE
|
||||
bool "Optimize for size (-Os)"
|
||||
config COMPILER_OPTIMIZATION_PERF
|
||||
bool "Optimize for performance (-O2)"
|
||||
config COMPILER_OPTIMIZATION_NONE
|
||||
bool "Debug without optimization (-O0)"
|
||||
|
||||
config COMPILER_OPTIMIZATION_LEVEL_RELEASE
|
||||
bool "Release (-Os)"
|
||||
endchoice
|
||||
|
||||
choice COMPILER_OPTIMIZATION_ASSERTION_LEVEL
|
||||
@@ -256,14 +145,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
Size (in bytes) of the emergency memory pool for C++ exceptions. This pool will be used to allocate
|
||||
memory for thrown exceptions when there is not enough memory on the heap.
|
||||
|
||||
config COMPILER_CXX_RTTI
|
||||
bool "Enable C++ run-time type info (RTTI)"
|
||||
default n
|
||||
help
|
||||
Enabling this option compiles all C++ files with RTTI support enabled.
|
||||
This increases binary size (typically by tens of kB) but allows using
|
||||
dynamic_cast conversion and typeid operator.
|
||||
|
||||
choice COMPILER_STACK_CHECK_MODE
|
||||
prompt "Stack smashing protection mode"
|
||||
default COMPILER_STACK_CHECK_MODE_NONE
|
||||
@@ -330,12 +211,12 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
endmenu # Compiler Options
|
||||
|
||||
menu "Component config"
|
||||
source "$COMPONENT_KCONFIGS_SOURCE_FILE"
|
||||
source "$COMPONENT_KCONFIGS"
|
||||
endmenu
|
||||
|
||||
menu "Compatibility options"
|
||||
config LEGACY_INCLUDE_COMMON_HEADERS
|
||||
bool "Include headers across components as before IDF v4.0"
|
||||
bool "Include headers accross components as before IDF v4.0"
|
||||
default n
|
||||
help
|
||||
Soc, esp32, and driver components, the most common
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
# Espressif IoT Development Framework
|
||||
|
||||
* [中文版](./README_CN.md)
|
||||
|
||||
[](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.
|
||||
|
||||
112
README_CN.md
112
README_CN.md
@@ -1,112 +0,0 @@
|
||||
# Espressif 物联网开发框架
|
||||
|
||||
* [English Version](./README.md)
|
||||
|
||||
[](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/?badge=latest)
|
||||
|
||||
ESP-IDF 是由乐鑫官方推出的针对 [ESP32](https://espressif.com/en/products/hardware/esp32/overview) 系列芯片的开发框架。
|
||||
|
||||
# 使用 ESP-IDF 进行开发
|
||||
|
||||
## 搭建 ESP-IDF 开发环境
|
||||
|
||||
请参阅如下指南搭建 ESP-IDF 的开发环境:
|
||||
|
||||
* [ESP-IDF 稳定版本的入门指南](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/)
|
||||
* [ESP-IDF 开发版本(master 分支)的入门指南](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/)
|
||||
|
||||
### 非 GitHub 分叉的 ESP-IDF 项目
|
||||
|
||||
ESP-IDF 中的子模块采用相对路径([详见 .gitmodules 文件](.gitmodules)),所以它们会指向 GitHub。
|
||||
如果 ESP-IDF 被分叉到的仓库不在 GitHub 上,那么你需要在克隆结束后运行该[脚本](tools/set-submodules-to-github.sh)。它会为所有的子模块设置绝对路径,接着可以通过 `git submodule update --init --recursive` 完成子模块的更新。
|
||||
如果 ESP-IDF 是从 GitHub 上克隆得到,则不需要此步骤。
|
||||
|
||||
## 寻找项目
|
||||
|
||||
除了入门指南中提到的 [esp-idf 模板项目](https://github.com/espressif/esp-idf-template),ESP-IDF 的 [examples](examples) 目录下还带有很多其它示例项目。
|
||||
|
||||
一旦找到了需要的项目,便可以进入该目录,执行配置和构建操作。
|
||||
|
||||
如果要基于示例工程开始你自己的项目,请将示例工程复制到 ESP-IDF 目录之外。
|
||||
|
||||
# 快速参考
|
||||
|
||||
详细的使用方法请参考上面入门指南的链接,这里仅仅列举一些 ESP-IDF 项目开发中常用的命令:
|
||||
|
||||
## 设置构建环境
|
||||
|
||||
(请参考入门指南中列出的详细步骤。)
|
||||
* 在主机中安装入门指南中提到的构建所依赖的工具。
|
||||
* 将 ESP-IDF 中的 `tools/` 目录加入 PATH 环境变量中。
|
||||
* 运行 `python -m pip install -r requirements.txt` 安装 Python 依赖库。
|
||||
|
||||
## 配置项目
|
||||
|
||||
`idf.py menuconfig`
|
||||
|
||||
* 打开项目的文本配置菜单。
|
||||
* 使用上下键浏览菜单。
|
||||
* 使用回车键进入子菜单,退出键返回上一级菜单或者退出配置。
|
||||
* 输入 `?` 查看帮助界面,按下回车键可以退出帮助界面。
|
||||
* 使用空格键或者 `Y` 和 `N` 按键来启用和禁用带复选框“`[*]`”的配置项。
|
||||
* 高亮某个配置项的同时按下 `?` 键可以显示该选项的帮助文档。
|
||||
* 输入 `/` 可以搜索指定的配置项。
|
||||
|
||||
一旦配置完成,请按下退出键多次以退出配置界面,当提示是否保存新的的配置时,选择 “Yes”。
|
||||
|
||||
## 编译项目
|
||||
|
||||
`idf.py build`
|
||||
|
||||
编译应用程序,引导程序,并根据配置生成分区表。
|
||||
|
||||
## 烧写项目
|
||||
|
||||
当构建结束,终端会打印出一条命令行,告知如何使用 esptool.py 工具烧写项目到芯片中。但是你还可以运行下面这条命令来自动烧写:
|
||||
|
||||
`idf.py -p PORT flash`
|
||||
|
||||
将其中的 PORT 替换为系统中实际串口的名字(比如 Windows 下的 `COM3`,Linux 下的 `/dev/ttyUSB0`,或者 MacOS 下的 `/dev/cu.usbserial-X`。如果省略 `-p` 选项,`idf.py flash` 会尝试使用第一个可用的串口进行烧写。
|
||||
|
||||
这会烧写整个项目(包括应用程序,引导程序和分区表)到芯片中,此外还可以使用 `idf.py menuconfig` 来调整串口烧写相关的配置。
|
||||
|
||||
你也不必先运行 `idf.py build`,再运行 `idf.py flash`,`idf.py flash` 会根据需要自动重新构建项目。
|
||||
|
||||
## 观察串口输入
|
||||
|
||||
`idf.py monitor` 会调用 [idf_monitor 工具](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html)来显示 ESP32 的串口输出。`idf_monitor` 还包含一系列的功能来解析程序崩溃后的输出结果并与设备进行交互。更多详细内容,请参阅[文档](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html).
|
||||
|
||||
输入 `Ctrl-]` 可退出监视器。
|
||||
|
||||
想要一次性执行构建,烧写和监视,可以运行如下命令:
|
||||
|
||||
`idf.py flash monitor`
|
||||
|
||||
## 仅编译并烧写应用程序
|
||||
|
||||
在第一次烧写过后,你可能只想构建并烧写你的应用程序,不包括引导程序和分区表:
|
||||
|
||||
* `idf.py app` - 仅构建应用程序。
|
||||
* `idf.py app-flash` - 仅烧写应用程序。
|
||||
|
||||
`idf.py app-flash` 会自动判断是否有源文件发生了改变而后重新构建应用程序。
|
||||
|
||||
(在正常的开发中,即使引导程序和分区表没有发生变化,每次都重新烧写它们并不会带来什么危害。)
|
||||
|
||||
## 擦除 Flash
|
||||
|
||||
`idf.py flash` 并不会擦除 Flash 上所有的内容,但是有时候我们需要设备恢复到完全擦除的状态,尤其是分区表发生了变化或者 OTA 应用升级。要擦除整块 Flash 请运行 `idf.py erase_flash`。
|
||||
|
||||
这条命令还可以和其余命令整合在一起,`idf.py -p PORT erase_flash flash` 会擦除一切然后重新烧写新的应用程序,引导程序和分区表。
|
||||
|
||||
# 其它参考资源
|
||||
|
||||
* 最新版的文档:https://docs.espressif.com/projects/esp-idf/ ,该文档是由本仓库 [docs 目录](docs) 构建得到。
|
||||
|
||||
* 可以前往 [esp32.com 论坛](https://esp32.com/) 提问,挖掘社区资源。
|
||||
|
||||
* 如果你在使用中发现了错误或者需要新的功能,请先[查看 GitHub Issues](https://github.com/espressif/esp-idf/issues),确保该问题不会被重复提交。
|
||||
|
||||
* 如果你有兴趣为 ESP-IDF 作贡献,请先阅读[贡献指南](https://docs.espressif.com/projects/esp-idf/en/latest/contribute/index.html)。
|
||||
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
The latest support policy for ESP-IDF can be found at [https://github.com/espressif/esp-idf/blob/master/SUPPORT_POLICY.md](https://github.com/espressif/esp-idf/blob/master/SUPPORT_POLICY.md)
|
||||
|
||||
Support Period Policy
|
||||
=====================
|
||||
|
||||
* [中文版](./SUPPORT_POLICY_CN.md)
|
||||
|
||||
Each ESP-IDF major and minor release (V4.0, V4.1, etc) is supported for
|
||||
18 months after the initial stable release date.
|
||||
|
||||
Supported means that the ESP-IDF team will continue to apply bug fixes,
|
||||
security fixes, etc to the release branch on GitHub, and periodically
|
||||
make new bugfix releases as needed.
|
||||
|
||||
Users are encouraged to upgrade to a newer ESP-IDF release before the
|
||||
support period finishes and the release becomes End of Life (EOL). It is
|
||||
our policy to not continue fixing bugs in End of Life releases.
|
||||
|
||||
Pre-release versions (betas, previews, `-rc` and `-dev` versions, etc)
|
||||
are not covered by any support period. Sometimes a particular feature is
|
||||
marked as \"Preview\" in a release, which means it is also not covered
|
||||
by the support period.
|
||||
|
||||
The ESP-IDF Programming Guide has information about the
|
||||
[different versions of ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/latest/versions.html)
|
||||
(major, minor, bugfix, etc).
|
||||
|
||||
Long Term Support releases
|
||||
--------------------------
|
||||
|
||||
Some releases (starting with ESP-IDF V3.3) are designated Long Term
|
||||
Support (LTS). LTS releases are supported for 30 months (2.5 years)
|
||||
after the initial stable release date.
|
||||
|
||||
A new LTS release will be made at least every 18 months. This means
|
||||
there will always be a period of at least 12 months to upgrade from the
|
||||
previous LTS release to the following LTS release.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
ESP-IDF V3.3 was released in September 2019 and is a Long Term Support
|
||||
(LTS) release, meaning it will be supported for 30 months until February
|
||||
2022.
|
||||
|
||||
- The first V3.3 release was `v3.3` in September 2019.
|
||||
- The ESP-IDF team continues to backport bug fixes, security fixes,
|
||||
etc to the release branch `release/v3.3`.
|
||||
- Periodically stable bugfix releases are created from the release
|
||||
branch. For example `v3.3.1`, `v3.3.2`, etc. Users are encouraged to
|
||||
always update to the latest bugfix release.
|
||||
- V3.3 bugfix releases continue until February 2022, when all V3.3.x
|
||||
releases become End of Life.
|
||||
|
||||
Existing Releases
|
||||
-----------------
|
||||
|
||||
ESP-IDF release V3.3 and all newer releases will follow this support
|
||||
period policy. The support period for each release will be announced
|
||||
when the release is made.
|
||||
|
||||
For releases made before the support period policy was announced,
|
||||
the following support periods apply:
|
||||
|
||||
- ESP-IDF V3.1.x and V3.2.x will both be supported until October 2020.
|
||||
- ESP-IDF V3.0.9 (planned for October 2019) will be the last V3.0
|
||||
bugfix release. ESP-IDF V3.0.x is End of Life from October 2019.
|
||||
- ESP-IDF versions before V3.0 are already End of Life.
|
||||
@@ -1,43 +0,0 @@
|
||||
有关 ESP-IDF 的最新支持政策,详见 [支持期限政策](./SUPPORT_POLICY_CN.md)。
|
||||
支持期限政策
|
||||
=================
|
||||
|
||||
* [English Version](./SUPPORT_POLICY.md)
|
||||
|
||||
ESP-IDF 的每个主要版本和次要版本(如 V4.0、V4.1 等)自其首次稳定版本发布之日起将维护 18 个月。
|
||||
|
||||
维护意味着 ESP-IDF 团队将会对 GitHub 上的发布分支继续进行 bug 修复、安全修补等,并根据需求定期发布新的 bugfix 版本。
|
||||
|
||||
在某一版本支持期限结束,停止更新维护 (EOL) 前,建议用户升级到较新的 ESP-IDF 版本。根据《支持期限政策》,我们将停止对 EOL 版本进行 bug 修复。
|
||||
|
||||
《支持期限政策》不适用于预发布版本(包括 beta、preview、`-rc` 和 `-dev` 版本等)。有时,在发布的版本中存在被标记为 "Preview" 的特定功能,则该功能也不在支持期限内。
|
||||
|
||||
有关 [ ESP-IDF 不同版本](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/versions.html)(主要版本、次要版本、bugfix 版本等)信息,可参阅《ESP-IDF 编程指南》。
|
||||
|
||||
长期支持版本
|
||||
------------
|
||||
|
||||
有些发布版本(从 ESP-IDF V3.3 开始)属于长期支持 (LTS) 版本。LTS 版本将自其首次稳定版本发布之日起维护 30 个月(2.5 年)。
|
||||
|
||||
我们将至少每 18 个月发布一个新的 LTS 版本。这意味着将至少有 12 个月的期限可更新至下一个 LTS 版本。
|
||||
|
||||
示例
|
||||
-----
|
||||
|
||||
ESP-IDF V3.3 于 2019 年 9 月发布,属于 LTS 版本,将维护 30 个月至 2022 年 2 月停止。
|
||||
|
||||
- V3.3 的首个发布版本为 2019 年 9 月发布的 `v3.3`。
|
||||
- ESP-IDF 团队将持续进行 bug 修复、安全修补等更新,并 backport 至分支 `release/v3.3`。
|
||||
- 定期从 release 分支创建稳定的 bugfix 版本,比如,`v3.3.1`、`v3.3.2` 等,并建议用户保持使用最新的 bugfix 版本。
|
||||
- V3.3 的 bugfix 版本发布将持续至 2022 年 2 月,届时所有 V3.3.x 将停止更新维护。
|
||||
|
||||
现有版本
|
||||
--------
|
||||
|
||||
ESP-IDF V3.3 及所有后续更新版本都将遵守该《支持期限政策》。每一版本发布时将同时公布其支持期限。
|
||||
|
||||
对于该政策公布之日前发布的版本,应适用下述支持期限:
|
||||
|
||||
- ESP-IDF V3.1.x 和 V3.2.x 将维护至 2020 年 10 月。
|
||||
- ESP-IDF V3.0.9(计划 2019 年 10 月发布)将是 V3.0 的最后一个 bugfix 版本。ESP-IDF V3.0.x 自 2019 年 10 月起停止更新维护 (EOL)。
|
||||
- ESP-IDF 中 V3.0 之前的版本均已停止更新维护 (EOL)。
|
||||
@@ -23,9 +23,6 @@ endif()
|
||||
|
||||
if(CONFIG_HEAP_TRACING_TOHOST)
|
||||
list(APPEND srcs "heap_trace_tohost.c")
|
||||
set_source_files_properties(heap_trace_tohost.c
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
-Wno-frame-address)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
@@ -36,7 +33,4 @@ idf_component_register(SRCS "${srcs}"
|
||||
# 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 $<TARGET_FILE:${app_trace}> gcov $<TARGET_FILE:${app_trace}> ${LIBC})
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC gcov ${LIBC} ${LIBM} gcc)
|
||||
|
||||
@@ -1,56 +1,54 @@
|
||||
menu "Application Level Tracing"
|
||||
|
||||
choice APPTRACE_DESTINATION
|
||||
choice ESP32_APPTRACE_DESTINATION
|
||||
prompt "Data Destination"
|
||||
default APPTRACE_DEST_NONE
|
||||
default ESP32_APPTRACE_DEST_NONE
|
||||
help
|
||||
Select destination for application trace: trace memory or none (to disable).
|
||||
|
||||
config APPTRACE_DEST_TRAX
|
||||
config ESP32_APPTRACE_DEST_TRAX
|
||||
bool "Trace memory"
|
||||
select APPTRACE_ENABLE
|
||||
config APPTRACE_DEST_NONE
|
||||
select ESP32_APPTRACE_ENABLE
|
||||
config ESP32_APPTRACE_DEST_NONE
|
||||
bool "None"
|
||||
endchoice
|
||||
|
||||
config APPTRACE_ENABLE
|
||||
config ESP32_APPTRACE_ENABLE
|
||||
bool
|
||||
depends on !ESP32_TRAX && !ESP32S2_TRAX
|
||||
depends on !ESP32_TRAX
|
||||
select ESP32_MEMMAP_TRACEMEM
|
||||
select ESP32S2_MEMMAP_TRACEMEM
|
||||
select ESP32_MEMMAP_TRACEMEM_TWOBANKS
|
||||
select ESP32S2_MEMMAP_TRACEMEM_TWOBANKS
|
||||
default n
|
||||
help
|
||||
Enables/disable application tracing module.
|
||||
|
||||
config APPTRACE_LOCK_ENABLE
|
||||
config ESP32_APPTRACE_LOCK_ENABLE
|
||||
bool
|
||||
default !SYSVIEW_ENABLE
|
||||
help
|
||||
Enables/disable application tracing module internal sync lock.
|
||||
|
||||
config APPTRACE_ONPANIC_HOST_FLUSH_TMO
|
||||
config ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO
|
||||
int "Timeout for flushing last trace data to host on panic"
|
||||
depends on APPTRACE_ENABLE
|
||||
depends on ESP32_APPTRACE_ENABLE
|
||||
range -1 5000
|
||||
default -1
|
||||
help
|
||||
Timeout for flushing last trace data to host in case of panic. In ms.
|
||||
Use -1 to disable timeout and wait forever.
|
||||
|
||||
config APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
config ESP32_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
int "Threshold for flushing last trace data to host on panic"
|
||||
depends on APPTRACE_DEST_TRAX
|
||||
depends on ESP32_APPTRACE_DEST_TRAX
|
||||
range 0 16384
|
||||
default 0
|
||||
help
|
||||
Threshold for flushing last trace data to host on panic in post-mortem mode.
|
||||
This is minimal amount of data needed to perform flush. In bytes.
|
||||
|
||||
config APPTRACE_PENDING_DATA_SIZE_MAX
|
||||
config ESP32_APPTRACE_PENDING_DATA_SIZE_MAX
|
||||
int "Size of the pending data buffer"
|
||||
depends on APPTRACE_DEST_TRAX
|
||||
depends on ESP32_APPTRACE_DEST_TRAX
|
||||
default 0
|
||||
help
|
||||
Size of the buffer for events in bytes. It is useful for buffering events from
|
||||
@@ -58,10 +56,10 @@ menu "Application Level Tracing"
|
||||
events will be discarded when main HW buffer is full.
|
||||
|
||||
menu "FreeRTOS SystemView Tracing"
|
||||
depends on APPTRACE_ENABLE
|
||||
depends on ESP32_APPTRACE_ENABLE
|
||||
config SYSVIEW_ENABLE
|
||||
bool "SystemView Tracing Enable"
|
||||
depends on APPTRACE_ENABLE
|
||||
depends on ESP32_APPTRACE_ENABLE
|
||||
default n
|
||||
help
|
||||
Enables supporrt for SEGGER SystemView tracing functionality.
|
||||
@@ -210,11 +208,10 @@ menu "Application Level Tracing"
|
||||
|
||||
endmenu
|
||||
|
||||
config APPTRACE_GCOV_ENABLE
|
||||
config ESP32_GCOV_ENABLE
|
||||
bool "GCOV to Host Enable"
|
||||
depends on APPTRACE_ENABLE && !SYSVIEW_ENABLE
|
||||
select ESP_DEBUG_STUBS_ENABLE
|
||||
default n
|
||||
depends on ESP32_DEBUG_STUBS_ENABLE && ESP32_APPTRACE_ENABLE && !SYSVIEW_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables support for GCOV data transfer to host.
|
||||
|
||||
|
||||
@@ -76,11 +76,11 @@
|
||||
// It can happen that system panic occurs when there are very small amount of data which are not exposed to host yet (e.g. crash just after the
|
||||
// TRAX block switch). In this case the previous 16KB of collected data will be dropped and host will see the latest, but very small piece of trace.
|
||||
// It can be insufficient to diagnose the problem. To avoid such situations there is menuconfig option
|
||||
// CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
// CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
// which controls the threshold for flushing data in case of panic.
|
||||
// - Streaming mode. Tracing module enters this mode when host connects to target and sets respective bits in control registers (per core).
|
||||
// In this mode before switching the block tracing module waits for the host to read all the data from the previously exposed block.
|
||||
// On panic tracing module also waits (timeout is configured via menuconfig via CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO) for the host to read all data.
|
||||
// On panic tracing module also waits (timeout is configured via menuconfig via CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO) for the host to read all data.
|
||||
|
||||
// 4. Communication Protocol
|
||||
// =========================
|
||||
@@ -114,7 +114,7 @@
|
||||
// has not completed reading of the previous one yet. So in this case time critical tracing calls (which can not be delayed for too long time due to
|
||||
// the lack of free memory in TRAX block) can be dropped. To avoid such scenarios tracing module implements data buffering. Buffered data will be sent
|
||||
// to the host later when TRAX block switch occurs. The maximum size of the buffered data is controlled by menuconfig option
|
||||
// CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX.
|
||||
// CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX.
|
||||
|
||||
// 4.4 Target Connection/Disconnection
|
||||
// -----------------------------------
|
||||
@@ -158,16 +158,13 @@
|
||||
#include <sys/param.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "soc/sensitive_reg.h"
|
||||
#endif
|
||||
#include "eri.h"
|
||||
#include "trax.h"
|
||||
#include "soc/timer_periph.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_app_trace.h"
|
||||
|
||||
#if CONFIG_APPTRACE_ENABLE
|
||||
#if CONFIG_ESP32_APPTRACE_ENABLE
|
||||
#define ESP_APPTRACE_MAX_VPRINTF_ARGS 256
|
||||
#define ESP_APPTRACE_HOST_BUF_SIZE 256
|
||||
|
||||
@@ -205,16 +202,10 @@ const static char *TAG = "esp_apptrace";
|
||||
#define ESP_APPTRACE_LOGO( format, ... ) ESP_APPTRACE_LOG_LEV(E, ESP_LOG_NONE, format, ##__VA_ARGS__)
|
||||
|
||||
// TODO: move these (and same definitions in trax.c to dport_reg.h)
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define TRACEMEM_MUX_PROBLK0_APPBLK1 0
|
||||
#define TRACEMEM_MUX_BLK0_ONLY 1
|
||||
#define TRACEMEM_MUX_BLK1_ONLY 2
|
||||
#define TRACEMEM_MUX_PROBLK1_APPBLK0 3
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define TRACEMEM_MUX_BLK0_NUM 19
|
||||
#define TRACEMEM_MUX_BLK1_NUM 20
|
||||
#define TRACEMEM_BLK_NUM2ADDR(_n_) (0x3FFB8000UL + 0x4000UL*((_n_)-4))
|
||||
#endif
|
||||
|
||||
// TRAX is disabled, so we use its registers for our own purposes
|
||||
// | 31..XXXXXX..24 | 23 .(host_connect). 23 | 22 .(host_data). 22| 21..(block_id)..15 | 14..(block_len)..0 |
|
||||
@@ -239,17 +230,10 @@ const static char *TAG = "esp_apptrace";
|
||||
#endif
|
||||
#define ESP_APPTRACE_USR_BLOCK_RAW_SZ(_s_) ((_s_) + sizeof(esp_tracedata_hdr_t))
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
static volatile uint8_t *s_trax_blocks[] = {
|
||||
(volatile uint8_t *) 0x3FFFC000,
|
||||
(volatile uint8_t *) 0x3FFF8000
|
||||
};
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
static volatile uint8_t *s_trax_blocks[] = {
|
||||
(volatile uint8_t *)TRACEMEM_BLK_NUM2ADDR(TRACEMEM_MUX_BLK0_NUM),
|
||||
(volatile uint8_t *)TRACEMEM_BLK_NUM2ADDR(TRACEMEM_MUX_BLK1_NUM)
|
||||
};
|
||||
#endif
|
||||
|
||||
#define ESP_APPTRACE_TRAX_BLOCKS_NUM (sizeof(s_trax_blocks)/sizeof(s_trax_blocks[0]))
|
||||
|
||||
@@ -309,17 +293,17 @@ typedef struct {
|
||||
typedef struct {
|
||||
volatile esp_apptrace_trax_state_t state; // state
|
||||
esp_apptrace_mem_block_t blocks[ESP_APPTRACE_TRAX_BLOCKS_NUM]; // memory blocks
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
// ring buffer control struct for pending user blocks
|
||||
esp_apptrace_rb_t rb_pend;
|
||||
// storage for pending user blocks
|
||||
uint8_t pending_data[CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX + 1];
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
uint8_t pending_data[CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX + 1];
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
// ring buffer control struct for pending user data chunks sizes,
|
||||
// every chunk contains whole number of user blocks and fit into TRAX memory block
|
||||
esp_apptrace_rb_t rb_pend_chunk_sz;
|
||||
// storage for above ring buffer data
|
||||
uint16_t pending_chunk_sz[CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX/ESP_APPTRACE_TRAX_BLOCK_SIZE + 2];
|
||||
uint16_t pending_chunk_sz[CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX/ESP_APPTRACE_TRAX_BLOCK_SIZE + 2];
|
||||
// current (accumulated) pending user data chunk size
|
||||
uint16_t cur_pending_chunk_sz;
|
||||
#endif
|
||||
@@ -376,7 +360,7 @@ static esp_apptrace_hw_t s_trace_hw[ESP_APPTRACE_HW_MAX] = {
|
||||
}
|
||||
};
|
||||
|
||||
static inline int esp_apptrace_log_lock(void)
|
||||
static inline int esp_apptrace_log_lock()
|
||||
{
|
||||
#if ESP_APPTRACE_PRINT_LOCK
|
||||
esp_apptrace_tmo_t tmo;
|
||||
@@ -388,29 +372,29 @@ static inline int esp_apptrace_log_lock(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void esp_apptrace_log_unlock(void)
|
||||
static inline void esp_apptrace_log_unlock()
|
||||
{
|
||||
#if ESP_APPTRACE_PRINT_LOCK
|
||||
esp_apptrace_lock_give(&s_log_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline esp_err_t esp_apptrace_lock_initialize(esp_apptrace_lock_t *lock)
|
||||
static inline esp_err_t esp_apptrace_lock_initialize()
|
||||
{
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_init(lock);
|
||||
#if CONFIG_ESP32_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_init(&s_trace_buf.lock);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t esp_apptrace_lock_cleanup(void)
|
||||
static inline esp_err_t esp_apptrace_lock_cleanup()
|
||||
{
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_lock(esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
#if CONFIG_ESP32_APPTRACE_LOCK_ENABLE
|
||||
esp_err_t ret = esp_apptrace_lock_take(&s_trace_buf.lock, tmo);
|
||||
if (ret != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
@@ -419,28 +403,17 @@ esp_err_t esp_apptrace_lock(esp_apptrace_tmo_t *tmo)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_unlock(void)
|
||||
esp_err_t esp_apptrace_unlock()
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
#if CONFIG_ESP32_APPTRACE_LOCK_ENABLE
|
||||
ret = esp_apptrace_lock_give(&s_trace_buf.lock);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
|
||||
static inline void esp_apptrace_trax_select_memory_block(int block_num)
|
||||
{
|
||||
// select memory block to be exposed to the TRAX module (accessed by host)
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
DPORT_WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, block_num ? TRACEMEM_MUX_BLK0_ONLY : TRACEMEM_MUX_BLK1_ONLY);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
DPORT_WRITE_PERI_REG(DPORT_PMS_OCCUPY_3_REG, block_num ? BIT(TRACEMEM_MUX_BLK0_NUM-4) : BIT(TRACEMEM_MUX_BLK1_NUM-4));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void esp_apptrace_trax_init(void)
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
static void esp_apptrace_trax_init()
|
||||
{
|
||||
// Stop trace, if any (on the current CPU)
|
||||
eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TRSTP);
|
||||
@@ -453,7 +426,7 @@ static void esp_apptrace_trax_init(void)
|
||||
ESP_APPTRACE_LOGI("Initialized TRAX on CPU%d", xPortGetCoreID());
|
||||
}
|
||||
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
// keep the size of buffered data for copying to TRAX mem block.
|
||||
// Only whole user blocks should be copied from buffer to TRAX block upon the switch
|
||||
static void esp_apptrace_trax_pend_chunk_sz_update(uint16_t size)
|
||||
@@ -476,7 +449,7 @@ static void esp_apptrace_trax_pend_chunk_sz_update(uint16_t size)
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t esp_apptrace_trax_pend_chunk_sz_get(void)
|
||||
static uint16_t esp_apptrace_trax_pend_chunk_sz_get()
|
||||
{
|
||||
uint16_t ch_sz;
|
||||
ESP_APPTRACE_LOGD("Get chunk enter %d w-r-s %d-%d-%d", s_trace_buf.trax.cur_pending_chunk_sz,
|
||||
@@ -494,7 +467,7 @@ static uint16_t esp_apptrace_trax_pend_chunk_sz_get(void)
|
||||
#endif
|
||||
|
||||
// assumed to be protected by caller from multi-core/thread access
|
||||
static esp_err_t esp_apptrace_trax_block_switch(void)
|
||||
static esp_err_t esp_apptrace_trax_block_switch()
|
||||
{
|
||||
int prev_block_num = s_trace_buf.trax.state.in_block % 2;
|
||||
int new_block_num = prev_block_num ? (0) : (1);
|
||||
@@ -526,7 +499,7 @@ static esp_err_t esp_apptrace_trax_block_switch(void)
|
||||
// switch to new block
|
||||
s_trace_buf.trax.state.in_block++;
|
||||
|
||||
esp_apptrace_trax_select_memory_block(new_block_num);
|
||||
DPORT_WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, new_block_num ? TRACEMEM_MUX_BLK0_ONLY : TRACEMEM_MUX_BLK1_ONLY);
|
||||
// handle data from host
|
||||
esp_hostdata_hdr_t *hdr = (esp_hostdata_hdr_t *)s_trace_buf.trax.blocks[new_block_num].start;
|
||||
if (ctrl_reg & ESP_APPTRACE_TRAX_HOST_DATA && hdr->block_sz > 0) {
|
||||
@@ -544,9 +517,9 @@ static esp_err_t esp_apptrace_trax_block_switch(void)
|
||||
}
|
||||
hdr->block_sz = 0;
|
||||
}
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
// copy pending data to TRAX block if any
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
uint16_t max_chunk_sz = esp_apptrace_trax_pend_chunk_sz_get();
|
||||
#else
|
||||
uint16_t max_chunk_sz = s_trace_buf.trax.blocks[new_block_num].sz;
|
||||
@@ -554,7 +527,7 @@ static esp_err_t esp_apptrace_trax_block_switch(void)
|
||||
while (s_trace_buf.trax.state.markers[new_block_num] < max_chunk_sz) {
|
||||
uint32_t read_sz = esp_apptrace_rb_read_size_get(&s_trace_buf.trax.rb_pend);
|
||||
if (read_sz == 0) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
/* theres is a bug: esp_apptrace_trax_pend_chunk_sz_get returned wrong value,
|
||||
it must be greater or equal to one returned by esp_apptrace_rb_read_size_get */
|
||||
ESP_APPTRACE_LOGE("No pended bytes, must be > 0 and <= %d!", max_chunk_sz);
|
||||
@@ -697,7 +670,7 @@ static inline uint8_t *esp_apptrace_trax_wait4buf(uint16_t size, esp_apptrace_tm
|
||||
return NULL;
|
||||
}
|
||||
// check if we still have pending data
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
if (esp_apptrace_rb_read_size_get(&s_trace_buf.trax.rb_pend) > 0) {
|
||||
// if after TRAX block switch still have pending data (not all pending data have been pumped to TRAX block)
|
||||
// alloc new pending buffer
|
||||
@@ -711,7 +684,7 @@ static inline uint8_t *esp_apptrace_trax_wait4buf(uint16_t size, esp_apptrace_tm
|
||||
{
|
||||
// update block pointers
|
||||
if (ESP_APPTRACE_TRAX_INBLOCK_MARKER() + size > ESP_APPTRACE_TRAX_INBLOCK_GET()->sz) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
*pended = 1;
|
||||
ptr = esp_apptrace_rb_produce(&s_trace_buf.trax.rb_pend, size);
|
||||
if (ptr == NULL) {
|
||||
@@ -741,7 +714,7 @@ static uint8_t *esp_apptrace_trax_get_buffer(uint32_t size, esp_apptrace_tmo_t *
|
||||
return NULL;
|
||||
}
|
||||
// check for data in the pending buffer
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
if (esp_apptrace_rb_read_size_get(&s_trace_buf.trax.rb_pend) > 0) {
|
||||
// if we have buffered data try to switch TRAX block
|
||||
esp_apptrace_trax_block_switch();
|
||||
@@ -756,7 +729,7 @@ static uint8_t *esp_apptrace_trax_get_buffer(uint32_t size, esp_apptrace_tmo_t *
|
||||
buf_ptr = esp_apptrace_trax_wait4buf(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf);
|
||||
if (buf_ptr) {
|
||||
if (pended_buf) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
esp_apptrace_trax_pend_chunk_sz_update(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
#endif
|
||||
} else {
|
||||
@@ -766,18 +739,18 @@ static uint8_t *esp_apptrace_trax_get_buffer(uint32_t size, esp_apptrace_tmo_t *
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
esp_apptrace_trax_pend_chunk_sz_update(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
#endif
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (ESP_APPTRACE_TRAX_INBLOCK_MARKER() + ESP_APPTRACE_USR_BLOCK_RAW_SZ(size) > ESP_APPTRACE_TRAX_INBLOCK_GET()->sz) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
ESP_APPTRACE_LOGD("TRAX full. Get %d bytes from PEND buffer", size);
|
||||
buf_ptr = esp_apptrace_rb_produce(&s_trace_buf.trax.rb_pend, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
if (buf_ptr) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
esp_apptrace_trax_pend_chunk_sz_update(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
#endif
|
||||
}
|
||||
@@ -788,7 +761,7 @@ static uint8_t *esp_apptrace_trax_get_buffer(uint32_t size, esp_apptrace_tmo_t *
|
||||
buf_ptr = esp_apptrace_trax_wait4buf(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf);
|
||||
if (buf_ptr) {
|
||||
if (pended_buf) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
esp_apptrace_trax_pend_chunk_sz_update(ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
#endif
|
||||
} else {
|
||||
@@ -872,7 +845,7 @@ static esp_err_t esp_apptrace_trax_status_reg_get(uint32_t *val)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_dest_init(void)
|
||||
static esp_err_t esp_apptrace_trax_dest_init()
|
||||
{
|
||||
for (int i = 0; i < ESP_APPTRACE_TRAX_BLOCKS_NUM; i++) {
|
||||
s_trace_buf.trax.blocks[i].start = (uint8_t *)s_trax_blocks[i];
|
||||
@@ -880,29 +853,28 @@ static esp_err_t esp_apptrace_trax_dest_init(void)
|
||||
s_trace_buf.trax.state.markers[i] = 0;
|
||||
}
|
||||
s_trace_buf.trax.state.in_block = ESP_APPTRACE_TRAX_INBLOCK_START;
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
esp_apptrace_rb_init(&s_trace_buf.trax.rb_pend, s_trace_buf.trax.pending_data,
|
||||
sizeof(s_trace_buf.trax.pending_data));
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
#if CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX > ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
s_trace_buf.trax.cur_pending_chunk_sz = 0;
|
||||
esp_apptrace_rb_init(&s_trace_buf.trax.rb_pend_chunk_sz, (uint8_t *)s_trace_buf.trax.pending_chunk_sz,
|
||||
sizeof(s_trace_buf.trax.pending_chunk_sz));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
DPORT_WRITE_PERI_REG(DPORT_PRO_TRACEMEM_ENA_REG, DPORT_PRO_TRACEMEM_ENA_M);
|
||||
#if CONFIG_FREERTOS_UNICORE == 0
|
||||
DPORT_WRITE_PERI_REG(DPORT_APP_TRACEMEM_ENA_REG, DPORT_APP_TRACEMEM_ENA_M);
|
||||
#endif
|
||||
#endif
|
||||
esp_apptrace_trax_select_memory_block(0);
|
||||
// Expose block 1 to host, block 0 is current trace input buffer
|
||||
DPORT_WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, TRACEMEM_MUX_BLK1_ONLY);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t esp_apptrace_init(void)
|
||||
esp_err_t esp_apptrace_init()
|
||||
{
|
||||
int res;
|
||||
|
||||
@@ -915,7 +887,7 @@ esp_err_t esp_apptrace_init(void)
|
||||
ESP_APPTRACE_LOGE("Failed to init log lock (%d)!", res);
|
||||
return res;
|
||||
}
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
res = esp_apptrace_trax_dest_init();
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to init TRAX dest data (%d)!", res);
|
||||
@@ -925,7 +897,7 @@ esp_err_t esp_apptrace_init(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
// init TRAX on this CPU
|
||||
esp_apptrace_trax_init();
|
||||
#endif
|
||||
@@ -947,7 +919,7 @@ esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *buf, uint32_t *size,
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -984,7 +956,7 @@ uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size,
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1008,7 +980,7 @@ esp_err_t esp_apptrace_down_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, u
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1033,7 +1005,7 @@ esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1069,7 +1041,7 @@ int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const c
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1133,7 +1105,7 @@ uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, uint32_t size, uint32
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1157,7 +1129,7 @@ esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1181,7 +1153,7 @@ esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, u
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1225,7 +1197,7 @@ bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest)
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1243,7 +1215,7 @@ esp_err_t esp_apptrace_status_reg_set(esp_apptrace_dest_t dest, uint32_t val)
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
@@ -1261,7 +1233,7 @@ esp_err_t esp_apptrace_status_reg_get(esp_apptrace_dest_t dest, uint32_t *val)
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
|
||||
if (dest == ESP_APPTRACE_DEST_TRAX) {
|
||||
#if CONFIG_APPTRACE_DEST_TRAX
|
||||
#if CONFIG_ESP32_APPTRACE_DEST_TRAX
|
||||
hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX);
|
||||
#else
|
||||
ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!");
|
||||
|
||||
@@ -15,12 +15,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/clk.h"
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////// TIMEOUT /////////////////////////////////////
|
||||
|
||||
@@ -14,23 +14,15 @@
|
||||
|
||||
// This module implements runtime file I/O API for GCOV.
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_task_wdt.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/timer_periph.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_private/dbg_stubs.h"
|
||||
#include "hal/timer_ll.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/libc_stubs.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/libc_stubs.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_APPTRACE_GCOV_ENABLE
|
||||
#if CONFIG_ESP32_GCOV_ENABLE
|
||||
|
||||
#define ESP_GCOV_DOWN_BUF_SIZE 4200
|
||||
|
||||
@@ -38,37 +30,37 @@
|
||||
#include "esp_log.h"
|
||||
const static char *TAG = "esp_gcov_rtio";
|
||||
|
||||
extern void __gcov_dump(void);
|
||||
extern void __gcov_reset(void);
|
||||
#if GCC_NOT_5_2_0
|
||||
void __gcov_dump(void);
|
||||
void __gcov_reset(void);
|
||||
#else
|
||||
/* The next code for old GCC */
|
||||
|
||||
static struct syscall_stub_table s_gcov_stub_table;
|
||||
|
||||
|
||||
static int gcov_stub_lock_try_acquire_recursive(_lock_t *lock)
|
||||
static void (*s_gcov_exit)(void);
|
||||
/* Root of a program/shared-object state */
|
||||
struct gcov_root
|
||||
{
|
||||
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;
|
||||
}
|
||||
void *list;
|
||||
unsigned dumped : 1; /* counts have been dumped. */
|
||||
unsigned run_counted : 1; /* run has been accounted for. */
|
||||
struct gcov_root *next;
|
||||
struct gcov_root *prev;
|
||||
};
|
||||
|
||||
static void gcov_stub_lock_acquire_recursive(_lock_t *lock)
|
||||
{
|
||||
gcov_stub_lock_try_acquire_recursive(lock);
|
||||
}
|
||||
/* Per-dynamic-object gcov state. */
|
||||
extern struct gcov_root __gcov_root;
|
||||
|
||||
static void gcov_stub_lock_release_recursive(_lock_t *lock)
|
||||
static void esp_gcov_reset_status(void)
|
||||
{
|
||||
__gcov_root.dumped = 0;
|
||||
__gcov_root.run_counted = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
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);
|
||||
@@ -79,22 +71,18 @@ static int esp_dbg_stub_gcov_dump_do(void)
|
||||
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;
|
||||
#if GCC_NOT_5_2_0
|
||||
__gcov_dump();
|
||||
// reset dump status to allow incremental data accumulation
|
||||
__gcov_reset();
|
||||
stdout = old_stdout;
|
||||
stderr = old_stderr;
|
||||
syscall_table_ptr_pro = old_table;
|
||||
|
||||
#else
|
||||
ESP_EARLY_LOGV(TAG, "Check for dump handler %p", s_gcov_exit);
|
||||
if (s_gcov_exit) {
|
||||
s_gcov_exit();
|
||||
// reset dump status to allow incremental data accumulation
|
||||
esp_gcov_reset_status();
|
||||
}
|
||||
#endif
|
||||
ESP_EARLY_LOGV(TAG, "Free apptrace down buf");
|
||||
free(down_buf);
|
||||
ESP_EARLY_LOGV(TAG, "Finish file transfer session");
|
||||
@@ -114,17 +102,19 @@ static int esp_dbg_stub_gcov_dump_do(void)
|
||||
*/
|
||||
static int esp_dbg_stub_gcov_entry(void)
|
||||
{
|
||||
#if GCC_NOT_5_2_0
|
||||
return esp_dbg_stub_gcov_dump_do();
|
||||
#else
|
||||
int ret = ESP_OK;
|
||||
// disable IRQs on this CPU, other CPU is halted by OpenOCD
|
||||
unsigned irq_state = portENTER_CRITICAL_NESTED();
|
||||
ret = esp_dbg_stub_gcov_dump_do();
|
||||
portEXIT_CRITICAL_NESTED(irq_state);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
int gcov_rtio_atexit(void (*function)(void) __attribute__ ((unused)))
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
|
||||
esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_GCOV, (uint32_t)&esp_dbg_stub_gcov_entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void esp_gcov_dump(void)
|
||||
void esp_gcov_dump()
|
||||
{
|
||||
// disable IRQs on this CPU, other CPU is halted by OpenOCD
|
||||
unsigned irq_state = portENTER_CRITICAL_NESTED();
|
||||
@@ -134,13 +124,13 @@ void esp_gcov_dump(void)
|
||||
#endif
|
||||
while (!esp_apptrace_host_is_connected(ESP_APPTRACE_DEST_TRAX)) {
|
||||
// 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);
|
||||
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
|
||||
TIMERG0.wdt_feed=1;
|
||||
TIMERG0.wdt_wprotect=0;
|
||||
// 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);
|
||||
TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
|
||||
TIMERG1.wdt_feed=1;
|
||||
TIMERG1.wdt_wprotect=0;
|
||||
}
|
||||
|
||||
esp_dbg_stub_gcov_dump_do();
|
||||
@@ -150,6 +140,18 @@ void esp_gcov_dump(void)
|
||||
portEXIT_CRITICAL_NESTED(irq_state);
|
||||
}
|
||||
|
||||
int gcov_rtio_atexit(void (*function)(void) __attribute__ ((unused)))
|
||||
{
|
||||
#if GCC_NOT_5_2_0
|
||||
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
|
||||
#else
|
||||
ESP_EARLY_LOGV(TAG, "%s %p", __FUNCTION__, function);
|
||||
s_gcov_exit = function;
|
||||
#endif
|
||||
esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_GCOV, (uint32_t)&esp_dbg_stub_gcov_entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *gcov_rtio_fopen(const char *path, const char *mode)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "%s '%s' '%s'", __FUNCTION__, path, mode);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
static bool s_tracing;
|
||||
|
||||
esp_err_t heap_trace_init_tohost(void)
|
||||
esp_err_t heap_trace_init_tohost()
|
||||
{
|
||||
if (s_tracing) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <string.h>
|
||||
#include "esp_app_trace.h"
|
||||
|
||||
#if CONFIG_APPTRACE_ENABLE
|
||||
#if CONFIG_ESP32_APPTRACE_ENABLE
|
||||
|
||||
#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
|
||||
#include "esp_log.h"
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Application trace data destinations bits.
|
||||
*/
|
||||
@@ -37,7 +33,7 @@ typedef enum {
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_init(void);
|
||||
esp_err_t esp_apptrace_init();
|
||||
|
||||
/**
|
||||
* @brief Configures down buffer.
|
||||
@@ -266,8 +262,4 @@ int esp_apptrace_fstop(esp_apptrace_dest_t dest);
|
||||
*/
|
||||
void esp_gcov_dump(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
#ifndef ESP_APP_TRACE_UTIL_H_
|
||||
#define ESP_APP_TRACE_UTIL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
@@ -168,8 +164,4 @@ uint32_t esp_apptrace_rb_read_size_get(esp_apptrace_rb_t *rb);
|
||||
*/
|
||||
uint32_t esp_apptrace_rb_write_size_get(esp_apptrace_rb_t *rb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //ESP_APP_TRACE_UTIL_H_
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
#ifndef ESP_SYSVIEW_TRACE_H_
|
||||
#define ESP_SYSVIEW_TRACE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "esp_err.h"
|
||||
#include "SEGGER_RTT.h" // SEGGER_RTT_ESP32_Flush
|
||||
@@ -81,8 +77,4 @@ void esp_sysview_heap_trace_alloc(void *addr, uint32_t size, const void *callers
|
||||
*/
|
||||
void esp_sysview_heap_trace_free(void *addr, const void *callers);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //ESP_SYSVIEW_TRACE_H_
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
# sdkconfig replacement configurations for deprecated options formatted as
|
||||
# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION
|
||||
|
||||
CONFIG_ESP32_APPTRACE_DESTINATION CONFIG_APPTRACE_DESTINATION
|
||||
CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE
|
||||
CONFIG_ESP32_APPTRACE_DEST_TRAX CONFIG_APPTRACE_DEST_TRAX
|
||||
CONFIG_ESP32_APPTRACE_ENABLE CONFIG_APPTRACE_ENABLE
|
||||
CONFIG_ESP32_APPTRACE_LOCK_ENABLE CONFIG_APPTRACE_LOCK_ENABLE
|
||||
CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO
|
||||
CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX
|
||||
CONFIG_ESP32_GCOV_ENABLE CONFIG_APPTRACE_GCOV_ENABLE
|
||||
CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
|
||||
@@ -285,12 +285,12 @@ Revision: $Rev: 5626 $
|
||||
* RTT lock configuration fallback
|
||||
*/
|
||||
#ifndef SEGGER_RTT_LOCK
|
||||
void SEGGER_SYSVIEW_X_RTT_Lock(void);
|
||||
void SEGGER_SYSVIEW_X_RTT_Lock();
|
||||
#define SEGGER_RTT_LOCK() SEGGER_SYSVIEW_X_RTT_Lock() // Lock RTT (nestable) (i.e. disable interrupts)
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_UNLOCK
|
||||
void SEGGER_SYSVIEW_X_RTT_Unlock(void);
|
||||
void SEGGER_SYSVIEW_X_RTT_Unlock();
|
||||
#define SEGGER_RTT_UNLOCK() SEGGER_SYSVIEW_X_RTT_Unlock() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -65,8 +65,6 @@ Revision: $Rev: 5927 $
|
||||
#ifndef SEGGER_SYSVIEW_CONF_H
|
||||
#define SEGGER_SYSVIEW_CONF_H
|
||||
|
||||
#include "soc/soc.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, fixed
|
||||
@@ -149,7 +147,7 @@ Revision: $Rev: 5927 $
|
||||
* SystemView Id configuration
|
||||
*/
|
||||
//TODO: optimise it
|
||||
#define SEGGER_SYSVIEW_ID_BASE SOC_DROM_LOW // Default value for the lowest Id reported by the application. Can be overridden by the application via SEGGER_SYSVIEW_SetRAMBase(). (i.e. 0x20000000 when all Ids are an address in this RAM)
|
||||
#define SEGGER_SYSVIEW_ID_BASE 0x3F400000 // Default value for the lowest Id reported by the application. Can be overridden by the application via SEGGER_SYSVIEW_SetRAMBase(). (i.e. 0x20000000 when all Ids are an address in this RAM)
|
||||
#define SEGGER_SYSVIEW_ID_SHIFT 0 // Number of bits to shift the Id to save bandwidth. (i.e. 2 when Ids are 4 byte aligned)
|
||||
|
||||
/*********************************************************************
|
||||
@@ -168,7 +166,7 @@ Revision: $Rev: 5927 $
|
||||
#define SEGGER_SYSVIEW_GET_INTERRUPT_ID() SEGGER_SYSVIEW_X_GetInterruptId() // Get the currently active interrupt Id from the user-provided function.
|
||||
#endif
|
||||
|
||||
unsigned SEGGER_SYSVIEW_X_SysView_Lock(void);
|
||||
unsigned SEGGER_SYSVIEW_X_SysView_Lock();
|
||||
void SEGGER_SYSVIEW_X_SysView_Unlock(unsigned int_state);
|
||||
// to be recursive save IRQ status on the stack of the caller
|
||||
#define SEGGER_SYSVIEW_LOCK() unsigned _SYSVIEW_int_state = SEGGER_SYSVIEW_X_SysView_Lock()
|
||||
|
||||
@@ -63,26 +63,11 @@ Revision: $Rev: 3734 $
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/clk.h"
|
||||
#endif
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/interrupts.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/clk.h"
|
||||
#endif
|
||||
|
||||
|
||||
extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
|
||||
@@ -96,7 +81,7 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
#define SYSVIEW_APP_NAME "FreeRTOS Application"
|
||||
|
||||
// The target device name
|
||||
#define SYSVIEW_DEVICE_NAME CONFIG_IDF_TARGET
|
||||
#define SYSVIEW_DEVICE_NAME "ESP32"
|
||||
|
||||
// Determine which timer to use as timestamp source
|
||||
#if CONFIG_SYSVIEW_TS_SOURCE_CCOUNT
|
||||
@@ -138,18 +123,14 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
|
||||
#if TS_USE_CCOUNT
|
||||
// CCOUNT is incremented at CPU frequency
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000)
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ * 1000000)
|
||||
#endif
|
||||
#endif // TS_USE_CCOUNT
|
||||
|
||||
// System Frequency.
|
||||
#define SYSVIEW_CPU_FREQ (esp_clk_cpu_freq())
|
||||
|
||||
// The lowest RAM address used for IDs (pointers)
|
||||
#define SYSVIEW_RAM_BASE (SOC_DROM_LOW)
|
||||
#define SYSVIEW_RAM_BASE (0x3F400000)
|
||||
|
||||
#if CONFIG_FREERTOS_CORETIMER_0
|
||||
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
|
||||
@@ -166,6 +147,78 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
|
||||
static esp_apptrace_lock_t s_sys_view_lock = {.mux = portMUX_INITIALIZER_UNLOCKED, .int_state = 0};
|
||||
|
||||
static const char * const s_isr_names[] = {
|
||||
[0] = "WIFI_MAC",
|
||||
[1] = "WIFI_NMI",
|
||||
[2] = "WIFI_BB",
|
||||
[3] = "BT_MAC",
|
||||
[4] = "BT_BB",
|
||||
[5] = "BT_BB_NMI",
|
||||
[6] = "RWBT",
|
||||
[7] = "RWBLE",
|
||||
[8] = "RWBT_NMI",
|
||||
[9] = "RWBLE_NMI",
|
||||
[10] = "SLC0",
|
||||
[11] = "SLC1",
|
||||
[12] = "UHCI0",
|
||||
[13] = "UHCI1",
|
||||
[14] = "TG0_T0_LEVEL",
|
||||
[15] = "TG0_T1_LEVEL",
|
||||
[16] = "TG0_WDT_LEVEL",
|
||||
[17] = "TG0_LACT_LEVEL",
|
||||
[18] = "TG1_T0_LEVEL",
|
||||
[19] = "TG1_T1_LEVEL",
|
||||
[20] = "TG1_WDT_LEVEL",
|
||||
[21] = "TG1_LACT_LEVEL",
|
||||
[22] = "GPIO",
|
||||
[23] = "GPIO_NMI",
|
||||
[24] = "FROM_CPU0",
|
||||
[25] = "FROM_CPU1",
|
||||
[26] = "FROM_CPU2",
|
||||
[27] = "FROM_CPU3",
|
||||
[28] = "SPI0",
|
||||
[29] = "SPI1",
|
||||
[30] = "SPI2",
|
||||
[31] = "SPI3",
|
||||
[32] = "I2S0",
|
||||
[33] = "I2S1",
|
||||
[34] = "UART0",
|
||||
[35] = "UART1",
|
||||
[36] = "UART2",
|
||||
[37] = "SDIO_HOST",
|
||||
[38] = "ETH_MAC",
|
||||
[39] = "PWM0",
|
||||
[40] = "PWM1",
|
||||
[41] = "PWM2",
|
||||
[42] = "PWM3",
|
||||
[43] = "LEDC",
|
||||
[44] = "EFUSE",
|
||||
[45] = "CAN",
|
||||
[46] = "RTC_CORE",
|
||||
[47] = "RMT",
|
||||
[48] = "PCNT",
|
||||
[49] = "I2C_EXT0",
|
||||
[50] = "I2C_EXT1",
|
||||
[51] = "RSA",
|
||||
[52] = "SPI1_DMA",
|
||||
[53] = "SPI2_DMA",
|
||||
[54] = "SPI3_DMA",
|
||||
[55] = "WDT",
|
||||
[56] = "TIMER1",
|
||||
[57] = "TIMER2",
|
||||
[58] = "TG0_T0_EDGE",
|
||||
[59] = "TG0_T1_EDGE",
|
||||
[60] = "TG0_WDT_EDGE",
|
||||
[61] = "TG0_LACT_EDGE",
|
||||
[62] = "TG1_T0_EDGE",
|
||||
[63] = "TG1_T1_EDGE",
|
||||
[64] = "TG1_WDT_EDGE",
|
||||
[65] = "TG1_LACT_EDGE",
|
||||
[66] = "MMU_IA",
|
||||
[67] = "MPU_IA",
|
||||
[68] = "CACHE_IA",
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _cbSendSystemDesc()
|
||||
@@ -178,9 +231,9 @@ static void _cbSendSystemDesc(void) {
|
||||
SEGGER_SYSVIEW_SendSysDesc("N="SYSVIEW_APP_NAME",D="SYSVIEW_DEVICE_NAME",C=Xtensa,O=FreeRTOS");
|
||||
snprintf(irq_str, sizeof(irq_str), "I#%d=SysTick", SYSTICK_INTR_ID);
|
||||
SEGGER_SYSVIEW_SendSysDesc(irq_str);
|
||||
size_t isr_count = sizeof(esp_isr_names)/sizeof(esp_isr_names[0]);
|
||||
size_t isr_count = sizeof(s_isr_names)/sizeof(s_isr_names[0]);
|
||||
for (size_t i = 0; i < isr_count; ++i) {
|
||||
snprintf(irq_str, sizeof(irq_str), "I#%d=%s", ETS_INTERNAL_INTR_SOURCE_OFF + i, esp_isr_names[i]);
|
||||
snprintf(irq_str, sizeof(irq_str), "I#%d=%s", ETS_INTERNAL_INTR_SOURCE_OFF + i, s_isr_names[i]);
|
||||
SEGGER_SYSVIEW_SendSysDesc(irq_str);
|
||||
}
|
||||
}
|
||||
@@ -191,7 +244,7 @@ static void _cbSendSystemDesc(void) {
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
static void SEGGER_SYSVIEW_TS_Init(void)
|
||||
static void SEGGER_SYSVIEW_TS_Init()
|
||||
{
|
||||
/* We only need to initialize something if we use Timer Group.
|
||||
* esp_timer and ccount can be used as is.
|
||||
@@ -263,7 +316,7 @@ void SEGGER_SYSVIEW_Conf(void) {
|
||||
SEGGER_SYSVIEW_DisableEvents(disable_evts);
|
||||
}
|
||||
|
||||
U32 SEGGER_SYSVIEW_X_GetTimestamp(void)
|
||||
U32 SEGGER_SYSVIEW_X_GetTimestamp()
|
||||
{
|
||||
#if TS_USE_TIMERGROUP
|
||||
uint64_t ts = 0;
|
||||
@@ -276,15 +329,15 @@ U32 SEGGER_SYSVIEW_X_GetTimestamp(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void SEGGER_SYSVIEW_X_RTT_Lock(void)
|
||||
void SEGGER_SYSVIEW_X_RTT_Lock()
|
||||
{
|
||||
}
|
||||
|
||||
void SEGGER_SYSVIEW_X_RTT_Unlock(void)
|
||||
void SEGGER_SYSVIEW_X_RTT_Unlock()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned SEGGER_SYSVIEW_X_SysView_Lock(void)
|
||||
unsigned SEGGER_SYSVIEW_X_SysView_Lock()
|
||||
{
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, SEGGER_LOCK_WAIT_TMO);
|
||||
|
||||
@@ -18,11 +18,7 @@
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#include "SEGGER_SYSVIEW_Conf.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#endif
|
||||
#include "esp_app_trace.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
#if CONFIG_APPTRACE_ENABLE == 1
|
||||
#if CONFIG_ESP32_APPTRACE_ENABLE == 1
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
|
||||
@@ -125,7 +125,7 @@ typedef struct {
|
||||
static SemaphoreHandle_t s_print_lock;
|
||||
#endif
|
||||
|
||||
static uint64_t esp_apptrace_test_ts_get(void);
|
||||
static uint64_t esp_apptrace_test_ts_get();
|
||||
|
||||
static void esp_apptrace_test_timer_isr(void *arg)
|
||||
{
|
||||
@@ -145,16 +145,56 @@ static void esp_apptrace_test_timer_isr(void *arg)
|
||||
}
|
||||
|
||||
tim_arg->data.wr_cnt++;
|
||||
timer_group_clr_intr_status_in_isr(tim_arg->group, tim_arg->id);
|
||||
timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->id);
|
||||
if (tim_arg->group == 0) {
|
||||
if (tim_arg->id == 0) {
|
||||
TIMERG0.int_clr_timers.t0 = 1;
|
||||
TIMERG0.hw_timer[0].update = 1;
|
||||
TIMERG0.hw_timer[0].config.alarm_en = 1;
|
||||
} else {
|
||||
TIMERG0.int_clr_timers.t1 = 1;
|
||||
TIMERG0.hw_timer[1].update = 1;
|
||||
TIMERG0.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
}
|
||||
if (tim_arg->group == 1) {
|
||||
if (tim_arg->id == 0) {
|
||||
TIMERG1.int_clr_timers.t0 = 1;
|
||||
TIMERG1.hw_timer[0].update = 1;
|
||||
TIMERG1.hw_timer[0].config.alarm_en = 1;
|
||||
} else {
|
||||
TIMERG1.int_clr_timers.t1 = 1;
|
||||
TIMERG1.hw_timer[1].update = 1;
|
||||
TIMERG1.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_apptrace_test_timer_isr_crash(void *arg)
|
||||
{
|
||||
esp_apptrace_test_timer_arg_t *tim_arg = (esp_apptrace_test_timer_arg_t *)arg;
|
||||
|
||||
timer_group_clr_intr_status_in_isr(tim_arg->group, tim_arg->id);
|
||||
timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->id);
|
||||
if (tim_arg->group == 0) {
|
||||
if (tim_arg->id == 0) {
|
||||
TIMERG0.int_clr_timers.t0 = 1;
|
||||
TIMERG0.hw_timer[0].update = 1;
|
||||
TIMERG0.hw_timer[0].config.alarm_en = 1;
|
||||
} else {
|
||||
TIMERG0.int_clr_timers.t1 = 1;
|
||||
TIMERG0.hw_timer[1].update = 1;
|
||||
TIMERG0.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
}
|
||||
if (tim_arg->group == 1) {
|
||||
if (tim_arg->id == 0) {
|
||||
TIMERG1.int_clr_timers.t0 = 1;
|
||||
TIMERG1.hw_timer[0].update = 1;
|
||||
TIMERG1.hw_timer[0].config.alarm_en = 1;
|
||||
} else {
|
||||
TIMERG1.int_clr_timers.t1 = 1;
|
||||
TIMERG1.hw_timer[1].update = 1;
|
||||
TIMERG1.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
}
|
||||
if (tim_arg->data.wr_cnt < ESP_APPTRACE_TEST_BLOCKS_BEFORE_CRASH) {
|
||||
uint32_t *ts = (uint32_t *)(tim_arg->data.buf + sizeof(uint32_t));
|
||||
*ts = (uint32_t)esp_apptrace_test_ts_get();//xthal_get_ccount();//xTaskGetTickCount();
|
||||
@@ -343,7 +383,7 @@ static void esp_apptrace_test_task_crash(void *p)
|
||||
|
||||
static int s_ts_timer_group, s_ts_timer_idx;
|
||||
|
||||
static uint64_t esp_apptrace_test_ts_get(void)
|
||||
static uint64_t esp_apptrace_test_ts_get()
|
||||
{
|
||||
uint64_t ts = 0;
|
||||
timer_get_counter_value(s_ts_timer_group, s_ts_timer_idx, &ts);
|
||||
@@ -373,7 +413,7 @@ static void esp_apptrace_test_ts_init(int timer_group, int timer_idx)
|
||||
timer_start(timer_group, timer_idx);
|
||||
}
|
||||
|
||||
static void esp_apptrace_test_ts_cleanup(void)
|
||||
static void esp_apptrace_test_ts_cleanup()
|
||||
{
|
||||
timer_config_t config;
|
||||
|
||||
@@ -810,8 +850,28 @@ static void esp_sysview_test_timer_isr(void *arg)
|
||||
|
||||
//ESP_APPTRACE_TEST_LOGI("tim-%d: IRQ %d/%d\n", tim_arg->id, tim_arg->group, tim_arg->timer);
|
||||
|
||||
timer_group_clr_intr_status_in_isr(tim_arg->group, tim_arg->id);
|
||||
timer_group_enable_alarm_in_isr(tim_arg->group, tim_arg->id);
|
||||
if (tim_arg->group == 0) {
|
||||
if (tim_arg->timer == 0) {
|
||||
TIMERG0.int_clr_timers.t0 = 1;
|
||||
TIMERG0.hw_timer[0].update = 1;
|
||||
TIMERG0.hw_timer[0].config.alarm_en = 1;
|
||||
} else {
|
||||
TIMERG0.int_clr_timers.t1 = 1;
|
||||
TIMERG0.hw_timer[1].update = 1;
|
||||
TIMERG0.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
}
|
||||
if (tim_arg->group == 1) {
|
||||
if (tim_arg->timer == 0) {
|
||||
TIMERG1.int_clr_timers.t0 = 1;
|
||||
TIMERG1.hw_timer[0].update = 1;
|
||||
TIMERG1.hw_timer[0].config.alarm_en = 1;
|
||||
} else {
|
||||
TIMERG1.int_clr_timers.t1 = 1;
|
||||
TIMERG1.hw_timer[1].update = 1;
|
||||
TIMERG1.hw_timer[1].config.alarm_en = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_sysviewtrace_test_task(void *p)
|
||||
|
||||
@@ -29,11 +29,8 @@ if(NOT BOOTLOADER_BUILD)
|
||||
|
||||
idf_build_get_property(idf_path IDF_PATH)
|
||||
idf_build_get_property(python PYTHON)
|
||||
|
||||
idf_component_get_property(partition_table_dir partition_table COMPONENT_DIR)
|
||||
|
||||
add_custom_command(OUTPUT ${blank_otadata_file}
|
||||
COMMAND ${python} ${partition_table_dir}/gen_empty_partition.py
|
||||
COMMAND ${python} ${idf_path}/components/partition_table/gen_empty_partition.py
|
||||
${otadata_size} ${blank_otadata_file})
|
||||
|
||||
add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file})
|
||||
|
||||
@@ -40,6 +40,9 @@ read_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_pytho
|
||||
--partition-table-offset $(partition_table_offset) \
|
||||
read_otadata
|
||||
|
||||
erase_ota: erase_otadata
|
||||
@echo "WARNING: erase_ota is deprecated. Use erase_otadata instead."
|
||||
|
||||
all: blank_ota_data
|
||||
flash: blank_ota_data
|
||||
ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include "esp_efuse.h"
|
||||
|
||||
|
||||
#define SUB_TYPE_ID(i) (i & 0x0F)
|
||||
#define SUB_TYPE_ID(i) (i & 0x0F)
|
||||
|
||||
typedef struct ota_ops_entry_ {
|
||||
uint32_t handle;
|
||||
@@ -200,7 +200,7 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
|
||||
// must erase the partition before writing to it
|
||||
assert(it->erased_size > 0 && "must erase the partition before writing to it");
|
||||
if (it->wrote_size == 0 && it->partial_bytes == 0 && size > 0 && data_bytes[0] != ESP_IMAGE_HEADER_MAGIC) {
|
||||
ESP_LOGE(TAG, "OTA image has invalid magic byte (expected 0xE9, saw 0x%02x)", data_bytes[0]);
|
||||
ESP_LOGE(TAG, "OTA image has invalid magic byte (expected 0xE9, saw 0x%02x", data_bytes[0]);
|
||||
return ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
}
|
||||
|
||||
@@ -687,12 +687,12 @@ static esp_err_t esp_ota_current_ota_is_workable(bool valid)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_mark_app_valid_cancel_rollback(void)
|
||||
esp_err_t esp_ota_mark_app_valid_cancel_rollback()
|
||||
{
|
||||
return esp_ota_current_ota_is_workable(true);
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot(void)
|
||||
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot()
|
||||
{
|
||||
return esp_ota_current_ota_is_workable(false);
|
||||
}
|
||||
@@ -715,7 +715,7 @@ static int get_last_invalid_otadata(const esp_ota_select_entry_t *two_otadata)
|
||||
return num_invalid_otadata;
|
||||
}
|
||||
|
||||
const esp_partition_t* esp_ota_get_last_invalid_partition(void)
|
||||
const esp_partition_t* esp_ota_get_last_invalid_partition()
|
||||
{
|
||||
esp_ota_select_entry_t otadata[2];
|
||||
if (read_otadata(otadata) == NULL) {
|
||||
|
||||
@@ -221,7 +221,7 @@ esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, es
|
||||
* @return
|
||||
* - ESP_OK: if successful.
|
||||
*/
|
||||
esp_err_t esp_ota_mark_app_valid_cancel_rollback(void);
|
||||
esp_err_t esp_ota_mark_app_valid_cancel_rollback();
|
||||
|
||||
/**
|
||||
* @brief This function is called to roll back to the previously workable app with reboot.
|
||||
@@ -233,14 +233,14 @@ esp_err_t esp_ota_mark_app_valid_cancel_rollback(void);
|
||||
* - ESP_FAIL: if not successful.
|
||||
* - ESP_ERR_OTA_ROLLBACK_FAILED: The rollback is not possible due to flash does not have any apps.
|
||||
*/
|
||||
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot(void);
|
||||
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot();
|
||||
|
||||
/**
|
||||
* @brief Returns last partition with invalid state (ESP_OTA_IMG_INVALID or ESP_OTA_IMG_ABORTED).
|
||||
*
|
||||
* @return partition.
|
||||
*/
|
||||
const esp_partition_t* esp_ota_get_last_invalid_partition(void);
|
||||
const esp_partition_t* esp_ota_get_last_invalid_partition();
|
||||
|
||||
/**
|
||||
* @brief Returns state for given partition.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
idf_component_register(SRC_DIRS "."
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES unity test_utils app_update bootloader_support nvs_flash
|
||||
)
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES unity test_utils app_update bootloader_support nvs_flash)
|
||||
@@ -58,7 +58,7 @@ TEST_CASE("esp_ota_get_next_update_partition logic", "[ota]")
|
||||
TEST_ASSERT_NOT_NULL(ota_1);
|
||||
TEST_ASSERT_NULL(ota_2); /* this partition shouldn't exist in test partition table */
|
||||
|
||||
TEST_ASSERT_EQUAL_PTR(factory, running); /* this may not be true if/when we get OTA tests that do OTA updates */
|
||||
TEST_ASSERT_EQUAL_PTR(factory, running); /* this may not be true if/when we get OTA tests that do OTA updates */
|
||||
|
||||
/* (The test steps verify subtypes before verifying pointer equality, because the failure messages are more readable
|
||||
this way.)
|
||||
|
||||
@@ -7,13 +7,9 @@
|
||||
#include "string.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#endif
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@@ -122,7 +118,7 @@ static void reboot_as_deep_sleep(void)
|
||||
|
||||
/* @brief Copies a current app to next partition (OTA0-15), after that ESP is rebooting and run this (the next) OTAx.
|
||||
*/
|
||||
static void copy_current_app_to_next_part_and_reboot(void)
|
||||
static void copy_current_app_to_next_part_and_reboot()
|
||||
{
|
||||
const esp_partition_t *cur_app = esp_ota_get_running_partition();
|
||||
copy_current_app_to_next_part(cur_app, get_next_update_partition());
|
||||
@@ -268,19 +264,19 @@ static void test_flow1(void)
|
||||
case 2:
|
||||
ESP_LOGI(TAG, "Factory");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
mark_app_valid();
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 4:
|
||||
ESP_LOGI(TAG, "OTA1");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
|
||||
mark_app_valid();
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 5:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
@@ -311,7 +307,7 @@ static void test_flow2(void)
|
||||
case 2:
|
||||
ESP_LOGI(TAG, "Factory");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
@@ -348,13 +344,13 @@ static void test_flow3(void)
|
||||
case 2:
|
||||
ESP_LOGI(TAG, "Factory");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
mark_app_valid();
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 4:
|
||||
ESP_LOGI(TAG, "OTA1");
|
||||
@@ -406,7 +402,7 @@ static void test_flow4(void)
|
||||
nvs_close(handle);
|
||||
nvs_flash_deinit();
|
||||
|
||||
copy_current_app_to_next_part_and_reboot();
|
||||
copy_current_app_to_next_part_and_reboot(cur_app);
|
||||
break;
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
@@ -448,7 +444,7 @@ static void test_flow4(void)
|
||||
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
|
||||
// 3 Stage: run OTA0 -> check it -> set_pin_factory_reset -> reboot --//--
|
||||
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, sets pin_factory_reset, factory", "[app_update][timeout=90][ignore][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow4, test_flow4, test_flow4);
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, sets pin_factory_reset, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow4, test_flow4, test_flow4);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_APP_TEST
|
||||
@@ -491,7 +487,7 @@ static void test_flow5(void)
|
||||
// 2 Stage: run factory -> check it -> copy factory to Test and set pin_test_app -> reboot --//--
|
||||
// 3 Stage: run test -> check it -> reset pin_test_app -> reboot --//--
|
||||
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, test, factory", "[app_update][timeout=90][ignore][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow5, test_flow5, test_flow5);
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, test, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow5, test_flow5, test_flow5);
|
||||
#endif
|
||||
|
||||
static const esp_partition_t* app_update(void)
|
||||
|
||||
Submodule components/asio/asio updated: 3b66e5b051...55efc179b7
@@ -22,12 +22,8 @@
|
||||
# define ASIO_NO_EXCEPTIONS
|
||||
# endif // CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
|
||||
# ifndef CONFIG_COMPILER_RTTI
|
||||
# define ASIO_NO_TYPEID
|
||||
# endif // CONFIG_COMPILER_RTTI
|
||||
|
||||
//
|
||||
// LWIP compatibility inet and address macros/functions
|
||||
// LWIP compatifility inet and address macros/functions
|
||||
//
|
||||
# define LWIP_COMPAT_SOCKET_INET 1
|
||||
# define LWIP_COMPAT_SOCKET_ADDR 1
|
||||
@@ -38,6 +34,12 @@
|
||||
# define ASIO_DISABLE_SERIAL_PORT
|
||||
# define ASIO_SEPARATE_COMPILATION
|
||||
# define ASIO_STANDALONE
|
||||
# define ASIO_NO_TYPEID
|
||||
# define ASIO_DISABLE_SIGNAL
|
||||
# define ASIO_HAS_PTHREADS
|
||||
# define ASIO_DISABLE_EPOLL
|
||||
# define ASIO_DISABLE_EVENTFD
|
||||
# define ASIO_DISABLE_SIGNAL
|
||||
# define ASIO_DISABLE_SIGACTION
|
||||
|
||||
#endif // _ESP_ASIO_CONFIG_H_
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
idf_component_register(PRIV_REQUIRES partition_table)
|
||||
|
||||
# Do not generate flash file when building bootloader or is in early expansion of the build
|
||||
if(BOOTLOADER_BUILD OR NOT CONFIG_APP_BUILD_BOOTLOADER)
|
||||
if(BOOTLOADER_BUILD)
|
||||
return()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -204,13 +204,10 @@ menu "Bootloader config"
|
||||
config BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD
|
||||
int "Size of the efuse secure version field"
|
||||
depends on BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
range 1 32 if IDF_TARGET_ESP32
|
||||
default 32 if IDF_TARGET_ESP32
|
||||
range 1 16 if IDF_TARGET_ESP32S2BETA
|
||||
default 16 if IDF_TARGET_ESP32S2BETA
|
||||
range 1 32
|
||||
default 32
|
||||
help
|
||||
The size of the efuse secure version field.
|
||||
Its length is limited to 32 bits for ESP32 and 16 bits for ESP32S2BETA.
|
||||
The size of the efuse secure version field. Its length is limited to 32 bits.
|
||||
This determines how many times the security version can be increased.
|
||||
|
||||
config BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
|
||||
@@ -222,53 +219,6 @@ menu "Bootloader config"
|
||||
It allow to test anti-rollback implemention without permanent write eFuse bits.
|
||||
In partition table should be exist this partition `emul_efuse, data, 5, , 0x2000`.
|
||||
|
||||
config BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
|
||||
bool "Skip image validation when exiting deep sleep"
|
||||
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
|
||||
deep sleep (checksums, SHA256, and signature). This is a trade-off
|
||||
between wakeup performance from deep sleep, and image integrity checks.
|
||||
|
||||
Only enable this if you know what you are doing. It should not be used
|
||||
in conjunction with using deep_sleep() entry and changing the active OTA
|
||||
partition as this would skip the validation upon first load of the new
|
||||
OTA partition.
|
||||
|
||||
config BOOTLOADER_RESERVE_RTC_SIZE
|
||||
hex
|
||||
default 0x10 if BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP || BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||
default 0
|
||||
help
|
||||
Reserve RTC FAST memory for Skip image validation. This option in bytes.
|
||||
This option reserves an area in the RTC FAST memory (access only PRO_CPU).
|
||||
Used to save the addresses of the selected application.
|
||||
When a wakeup occurs (from Deep sleep), the bootloader retrieves it and
|
||||
loads the application without validation.
|
||||
|
||||
config BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||
bool "Reserve RTC FAST memory for custom purposes"
|
||||
default n
|
||||
help
|
||||
This option allows the customer to place data in the RTC FAST memory,
|
||||
this area remains valid when rebooted, except for power loss.
|
||||
This memory is located at a fixed address and is available
|
||||
for both the bootloader and the application.
|
||||
(The application and bootoloader must be compiled with the same option).
|
||||
The RTC FAST memory has access only through PRO_CPU.
|
||||
|
||||
config BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE
|
||||
hex "Size in bytes for custom purposes"
|
||||
range 0 0x10
|
||||
default 0
|
||||
depends on BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||
help
|
||||
This option reserves in RTC FAST memory the area for custom purposes.
|
||||
If you want to create your own bootloader and save more information
|
||||
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.
|
||||
|
||||
endmenu # Bootloader
|
||||
|
||||
|
||||
@@ -284,15 +234,12 @@ menu "Security features"
|
||||
config SECURE_SIGNED_ON_UPDATE
|
||||
bool
|
||||
default y
|
||||
select MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
|
||||
config SECURE_SIGNED_APPS
|
||||
bool
|
||||
default y
|
||||
select MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
select MBEDTLS_ECP_C
|
||||
select MBEDTLS_ECDH_C
|
||||
select MBEDTLS_ECDSA_C
|
||||
depends on SECURE_SIGNED_ON_BOOT || SECURE_SIGNED_ON_UPDATE
|
||||
|
||||
|
||||
@@ -391,7 +338,7 @@ menu "Security features"
|
||||
config SECURE_BOOT_SIGNING_KEY
|
||||
string "Secure boot private signing key"
|
||||
depends on SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
default "secure_boot_signing_key.pem"
|
||||
default secure_boot_signing_key.pem
|
||||
help
|
||||
Path to the key file used to sign app images.
|
||||
|
||||
@@ -407,7 +354,7 @@ menu "Security features"
|
||||
config SECURE_BOOT_VERIFICATION_KEY
|
||||
string "Secure boot public signature verification key"
|
||||
depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
default "signature_verification_key.bin"
|
||||
default signature_verification_key.bin
|
||||
help
|
||||
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.
|
||||
@@ -421,7 +368,7 @@ menu "Security features"
|
||||
choice SECURE_BOOTLOADER_KEY_ENCODING
|
||||
bool "Hardware Key Encoding"
|
||||
depends on SECURE_BOOTLOADER_REFLASHABLE
|
||||
default SECURE_BOOTLOADER_KEY_ENCODING_256BIT
|
||||
default SECURE_BOOTLOADER_NO_ENCODING
|
||||
help
|
||||
|
||||
In reflashable secure bootloader mode, a hardware key is derived from the signing key (with SHA-256) and
|
||||
@@ -465,26 +412,6 @@ menu "Security features"
|
||||
Read https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html
|
||||
before enabling.
|
||||
|
||||
choice SECURE_FLASH_ENCRYPTION_KEYSIZE
|
||||
bool "Size of generated AES-XTS key"
|
||||
default SECURE_FLASH_ENCRYPTION_AES128
|
||||
depends on IDF_TARGET_ESP32S2BETA && SECURE_FLASH_ENC_ENABLED
|
||||
help
|
||||
Size of generated AES-XTS key.
|
||||
|
||||
AES-128 uses a 256-bit key (32 bytes) which occupies one Efuse key block.
|
||||
AES-256 uses a 512-bit key (64 bytes) which occupies two Efuse key blocks.
|
||||
|
||||
This setting is ignored if either type of key is already burned to Efuse before the first boot.
|
||||
In this case, the pre-burned key is used and no new key is generated.
|
||||
|
||||
config SECURE_FLASH_ENCRYPTION_AES128
|
||||
bool "AES-128 (256-bit key)"
|
||||
|
||||
config SECURE_FLASH_ENCRYPTION_AES256
|
||||
bool "AES-256 (512-bit key)"
|
||||
endchoice
|
||||
|
||||
choice SECURE_FLASH_ENCRYPTION_MODE
|
||||
bool "Enable usage mode"
|
||||
depends on SECURE_FLASH_ENC_ENABLED
|
||||
@@ -588,20 +515,6 @@ menu "Security features"
|
||||
|
||||
Only set this option in testing environments.
|
||||
|
||||
config SECURE_FLASH_REQUIRE_ALREADY_ENABLED
|
||||
bool "Require flash encryption to be already enabled"
|
||||
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
default N
|
||||
help
|
||||
If not set (default), and flash encryption is not yet enabled in eFuses, the 2nd stage bootloader
|
||||
will enable flash encryption: generate the flash encryption key and program eFuses.
|
||||
If this option is set, and flash encryption is not yet enabled, the bootloader will error out and
|
||||
reboot.
|
||||
If flash encryption is enabled in eFuses, this option does not change the bootloader behavior.
|
||||
|
||||
Only use this option in testing environments, to avoid accidentally enabling flash encryption on
|
||||
the wrong device. The device needs to have flash encryption already enabled using espefuse.py.
|
||||
|
||||
endmenu # Potentially Insecure
|
||||
endmenu # Security features
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
set(BOOTLOADER_OFFSET 0x1000)
|
||||
|
||||
# Do not generate flash file when building bootloader
|
||||
if(BOOTLOADER_BUILD OR NOT CONFIG_APP_BUILD_BOOTLOADER)
|
||||
if(BOOTLOADER_BUILD)
|
||||
return()
|
||||
endif()
|
||||
|
||||
@@ -67,7 +67,6 @@ if(CONFIG_SECURE_SIGNED_APPS)
|
||||
|
||||
set(SECURE_BOOT_SIGNING_KEY ${secure_boot_signing_key}) # needed by some other components
|
||||
set(sign_key_arg "-DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}")
|
||||
set(ver_key_arg)
|
||||
|
||||
add_dependencies(gen_secure_boot_keys gen_secure_boot_signing_key)
|
||||
else()
|
||||
@@ -88,34 +87,27 @@ if(CONFIG_SECURE_SIGNED_APPS)
|
||||
add_custom_target(gen_secure_boot_verification_key)
|
||||
endif()
|
||||
|
||||
set(sign_key_arg)
|
||||
set(ver_key_arg "-DSECURE_BOOT_VERIFICATION_KEY=${secure_boot_verification_key}")
|
||||
|
||||
add_dependencies(gen_secure_boot_keys gen_secure_boot_verification_key)
|
||||
endif()
|
||||
else()
|
||||
set(sign_key_arg)
|
||||
set(ver_key_arg)
|
||||
endif()
|
||||
|
||||
idf_build_get_property(idf_path IDF_PATH)
|
||||
idf_build_get_property(idf_target IDF_TARGET)
|
||||
idf_build_get_property(sdkconfig SDKCONFIG)
|
||||
idf_build_get_property(python PYTHON)
|
||||
idf_build_get_property(extra_cmake_args EXTRA_CMAKE_ARGS)
|
||||
|
||||
externalproject_add(bootloader
|
||||
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject"
|
||||
BINARY_DIR "${BOOTLOADER_BUILD_DIR}"
|
||||
CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target}
|
||||
-DPYTHON_DEPS_CHECKED=1 -DPYTHON=${python}
|
||||
-DPYTHON_DEPS_CHECKED=1
|
||||
-DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR}
|
||||
${sign_key_arg} ${ver_key_arg}
|
||||
# LEGACY_INCLUDE_COMMON_HEADERS has to be passed in via cache variable since
|
||||
# the bootloader common component requirements depends on this and
|
||||
# config variables are not available before project() call.
|
||||
-DLEGACY_INCLUDE_COMMON_HEADERS=${CONFIG_LEGACY_INCLUDE_COMMON_HEADERS}
|
||||
${extra_cmake_args}
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_ALWAYS 1 # no easy way around this...
|
||||
BUILD_BYPRODUCTS ${bootloader_binary_files}
|
||||
@@ -132,4 +124,4 @@ endif()
|
||||
# So for now we just have the top-level build remove the final build products...
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
${bootloader_binary_files})
|
||||
${bootloader_binary_files})
|
||||
@@ -75,8 +75,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
add_custom_command(OUTPUT "${bootloader_digest_bin}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}"
|
||||
COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}"
|
||||
-o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin"
|
||||
MAIN_DEPENDENCY "${CMAKE_BINARY_DIR}/.bin_timestamp"
|
||||
-o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin"
|
||||
DEPENDS gen_secure_bootloader_key gen_project_binary
|
||||
VERBATIM)
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@ idf_component_register(SRCS "bootloader_start.c"
|
||||
REQUIRES bootloader bootloader_support)
|
||||
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
set(scripts "ld/${target}/bootloader.ld"
|
||||
"ld/${target}/bootloader.rom.ld")
|
||||
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${scripts}")
|
||||
set(scripts "${target}.bootloader.ld"
|
||||
"${target}.bootloader.rom.ld")
|
||||
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${scripts}")
|
||||
4
components/bootloader/subproject/main/Makefile.projbuild
Normal file
4
components/bootloader/subproject/main/Makefile.projbuild
Normal file
@@ -0,0 +1,4 @@
|
||||
# Submodules normally added in component.mk, but fully qualified
|
||||
# paths can be added at this level (we need binary librtc to be
|
||||
# available to link bootloader).
|
||||
COMPONENT_SUBMODULES += $(IDF_PATH)/components/esp_wifi/lib_esp32
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -11,39 +11,38 @@
|
||||
// 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 <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "bootloader_config.h"
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_image_format.h"
|
||||
|
||||
static const char *TAG = "boot";
|
||||
static const char* TAG = "boot";
|
||||
|
||||
static int select_partition_number(bootloader_state_t *bs);
|
||||
static int select_partition_number (bootloader_state_t *bs);
|
||||
static int selected_boot_partition(const bootloader_state_t *bs);
|
||||
|
||||
/*
|
||||
* We arrive here after the ROM bootloader finished loading this second stage bootloader from flash.
|
||||
* The hardware is mostly uninitialized, flash cache is down and the app CPU is in reset.
|
||||
* We do have a stack, so we can do the initialization in C.
|
||||
*/
|
||||
void __attribute__((noreturn)) call_start_cpu0(void)
|
||||
void __attribute__((noreturn)) call_start_cpu0()
|
||||
{
|
||||
// 1. Hardware initialization
|
||||
if (bootloader_init() != ESP_OK) {
|
||||
bootloader_reset();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
|
||||
// If this boot is a wake up from the deep sleep then go to the short way,
|
||||
// try to load the application which worked before deep sleep.
|
||||
// It skips a lot of checks due to it was done before (while first boot).
|
||||
bootloader_utility_load_boot_image_from_deep_sleep();
|
||||
// If it is not successful try to load an application as usual.
|
||||
#endif
|
||||
|
||||
// 2. Select the number of boot partition
|
||||
bootloader_state_t bs = {0};
|
||||
bootloader_state_t bs = { 0 };
|
||||
int boot_index = select_partition_number(&bs);
|
||||
if (boot_index == INVALID_INDEX) {
|
||||
bootloader_reset();
|
||||
@@ -54,7 +53,7 @@ void __attribute__((noreturn)) call_start_cpu0(void)
|
||||
}
|
||||
|
||||
// Select the number of boot partition
|
||||
static int select_partition_number(bootloader_state_t *bs)
|
||||
static int select_partition_number (bootloader_state_t *bs)
|
||||
{
|
||||
// 1. Load partition table
|
||||
if (!bootloader_utility_load_partition_table(bs)) {
|
||||
@@ -75,8 +74,7 @@ static int selected_boot_partition(const bootloader_state_t *bs)
|
||||
int boot_index = bootloader_utility_get_selected_boot_partition(bs);
|
||||
if (boot_index == INVALID_INDEX) {
|
||||
return boot_index; // Unrecoverable failure (not due to corrupt ota data or bad partition contents)
|
||||
}
|
||||
if (bootloader_common_get_reset_reason(0) != DEEPSLEEP_RESET) {
|
||||
} else {
|
||||
// Factory firmware.
|
||||
#ifdef CONFIG_BOOTLOADER_FACTORY_RESET
|
||||
if (bootloader_common_check_long_hold_gpio(CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET, CONFIG_BOOTLOADER_HOLD_TIME_GPIO) == 1) {
|
||||
@@ -93,7 +91,7 @@ static int selected_boot_partition(const bootloader_state_t *bs)
|
||||
return bootloader_utility_get_selected_boot_partition(bs);
|
||||
}
|
||||
#endif
|
||||
// TEST firmware.
|
||||
// TEST firmware.
|
||||
#ifdef CONFIG_BOOTLOADER_APP_TEST
|
||||
if (bootloader_common_check_long_hold_gpio(CONFIG_BOOTLOADER_NUM_PIN_APP_TEST, CONFIG_BOOTLOADER_HOLD_TIME_GPIO) == 1) {
|
||||
ESP_LOGI(TAG, "Detect a boot condition of the test firmware");
|
||||
@@ -115,7 +113,7 @@ static int selected_boot_partition(const bootloader_state_t *bs)
|
||||
}
|
||||
|
||||
// Return global reent struct if any newlib functions are linked to bootloader
|
||||
struct _reent *__getreent(void)
|
||||
{
|
||||
struct _reent* __getreent() {
|
||||
return _GLOBAL_REENT;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,17 +6,14 @@
|
||||
#
|
||||
|
||||
LINKER_SCRIPTS := \
|
||||
$(COMPONENT_PATH)/ld/$(IDF_TARGET)/bootloader.ld \
|
||||
$(COMPONENT_PATH)/ld/$(IDF_TARGET)/bootloader.rom.ld \
|
||||
$(IDF_TARGET).bootloader.ld \
|
||||
$(IDF_TARGET).bootloader.rom.ld \
|
||||
$(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.ld \
|
||||
$(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.newlib-funcs.ld \
|
||||
$(IDF_PATH)/components/$(IDF_TARGET)/ld/$(IDF_TARGET).peripherals.ld
|
||||
|
||||
# SPI driver patch for ROM is only needed in ESP32
|
||||
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
|
||||
ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
LINKER_SCRIPTS += $(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.spiflash.ld
|
||||
endif
|
||||
|
||||
COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH) $(addprefix -T ,$(LINKER_SCRIPTS))
|
||||
|
||||
@@ -40,7 +40,6 @@ SECTIONS
|
||||
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
|
||||
*liblog.a:(.literal .text .literal.* .text.*)
|
||||
*libgcc.a:(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_clock.*(.literal .text .literal.* .text.*)
|
||||
*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.*)
|
||||
@@ -54,7 +53,6 @@ SECTIONS
|
||||
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libsoc.a:rtc_wdt.*(.literal .text .literal.* .text.*)
|
||||
*libsoc.a:rtc_clk.*(.literal .text .literal.* .text.*)
|
||||
*libefuse.a:*.*(.literal .text .literal.* .text.*)
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
Linker file used to link the bootloader.
|
||||
*/
|
||||
|
||||
|
||||
/* Simplified memory map for the bootloader
|
||||
|
||||
The main purpose is to make sure the bootloader can load into main memory
|
||||
without overwriting itself.
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* I/O */
|
||||
dport0_seg (RW) : org = 0x3FF00000, len = 0x10
|
||||
iram_loader_seg (RWX) : org = 0x40062000, len = 0x4000 /* 16KB, IRAM */
|
||||
iram_seg (RWX) : org = 0x40066000, len = 0x4000 /* 16KB, IRAM */
|
||||
/* 8k at the end of DRAM, before ROM data & stack */
|
||||
dram_seg (RW) : org = 0x3FFFA000, len = 0x2000
|
||||
}
|
||||
|
||||
/* Default entry point: */
|
||||
ENTRY(call_start_cpu0);
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.iram_loader.text :
|
||||
{
|
||||
. = ALIGN (16);
|
||||
_loader_text_start = ABSOLUTE(.);
|
||||
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
|
||||
*liblog.a:(.literal .text .literal.* .text.*)
|
||||
*libgcc.a:(.literal .text .literal.* .text.*)
|
||||
*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_utility.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*)
|
||||
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libsoc.a:rtc_wdt.*(.literal .text .literal.* .text.*)
|
||||
*libefuse.a:*.*(.literal .text .literal.* .text.*)
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_loader_text_end = ABSOLUTE(.);
|
||||
} > iram_loader_seg
|
||||
|
||||
.iram.text :
|
||||
{
|
||||
. = ALIGN (16);
|
||||
*(.entry.text)
|
||||
*(.init.literal)
|
||||
*(.init)
|
||||
} > iram_seg
|
||||
|
||||
|
||||
/* Shared RAM */
|
||||
.dram0.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} >dram_seg
|
||||
|
||||
.dram0.data :
|
||||
{
|
||||
_data_start = ABSOLUTE(.);
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
*(.jcr)
|
||||
_data_end = ABSOLUTE(.);
|
||||
} >dram_seg
|
||||
|
||||
.dram0.rodata :
|
||||
{
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
|
||||
*(.xt_except_table)
|
||||
*(.gcc_except_table)
|
||||
*(.gnu.linkonce.e.*)
|
||||
*(.gnu.version_r)
|
||||
*(.eh_frame)
|
||||
. = (. + 3) & ~ 3;
|
||||
/* C++ constructor and destructor tables, properly ordered: */
|
||||
__init_array_start = ABSOLUTE(.);
|
||||
KEEP (*crtbegin.*(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
__init_array_end = ABSOLUTE(.);
|
||||
KEEP (*crtbegin.*(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
/* C++ exception handlers table: */
|
||||
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
|
||||
*(.xt_except_desc)
|
||||
*(.gnu.linkonce.h.*)
|
||||
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
|
||||
*(.xt_except_desc_end)
|
||||
*(.dynamic)
|
||||
*(.gnu.version_d)
|
||||
_rodata_end = ABSOLUTE(.);
|
||||
/* Literals are also RO data. */
|
||||
_lit4_start = ABSOLUTE(.);
|
||||
*(*.lit4)
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
} >dram_seg
|
||||
|
||||
.iram.text :
|
||||
{
|
||||
_stext = .;
|
||||
_text_start = ABSOLUTE(.);
|
||||
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.iram .iram.*) /* catch stray IRAM_ATTR */
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} > iram_seg
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* ESP32S2 ROM address table
|
||||
* Generated for ROM with MD5sum: f054d40c5f6b9207d3827460a6f5748c
|
||||
*/
|
||||
PROVIDE ( ets_update_cpu_frequency = 0x4000d954 );
|
||||
|
||||
/* ToDo: Following address may need modification */
|
||||
PROVIDE ( MD5Final = 0x400056e8 );
|
||||
PROVIDE ( MD5Init = 0x40005648 );
|
||||
PROVIDE ( MD5Update = 0x40005668 );
|
||||
/* bootloader will use following functions from xtensa hal library */
|
||||
xthal_get_ccount = 0x40015cbc;
|
||||
xthal_get_ccompare = 0x40015ce8;
|
||||
xthal_set_ccompare = 0x40015cc4;
|
||||
@@ -1,103 +1,65 @@
|
||||
set(srcs
|
||||
set(srcs
|
||||
"src/bootloader_clock.c"
|
||||
"src/bootloader_common.c"
|
||||
"src/bootloader_flash.c"
|
||||
"src/bootloader_flash_config.c"
|
||||
"src/bootloader_random.c"
|
||||
"src/bootloader_utility.c"
|
||||
"src/esp_image_format.c"
|
||||
"src/flash_encrypt.c"
|
||||
"src/flash_partitions.c"
|
||||
"src/flash_qio_mode.c"
|
||||
"src/bootloader_flash_config_${IDF_TARGET}.c"
|
||||
"src/bootloader_efuse_${IDF_TARGET}.c"
|
||||
)
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
# Not supported on ESP32S2Beta yet
|
||||
list(APPEND srcs "src/flash_encrypt.c")
|
||||
endif()
|
||||
"src/flash_qio_mode.c")
|
||||
|
||||
if(BOOTLOADER_BUILD)
|
||||
set(include_dirs "include" "include_bootloader")
|
||||
set(requires soc) #unfortunately the header directly uses SOC registers
|
||||
set(priv_requires micro-ecc spi_flash efuse)
|
||||
list(APPEND srcs
|
||||
list(APPEND srcs
|
||||
"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"
|
||||
)
|
||||
"src/${IDF_TARGET}/secure_boot.c")
|
||||
else()
|
||||
list(APPEND srcs
|
||||
list(APPEND srcs
|
||||
"src/idf/bootloader_sha.c"
|
||||
"src/idf/secure_boot_signatures.c")
|
||||
set(include_dirs "include")
|
||||
set(priv_include_dirs "include_bootloader")
|
||||
set(requires soc) #unfortunately the header directly uses SOC registers
|
||||
set(priv_requires spi_flash mbedtls efuse)
|
||||
endif()
|
||||
|
||||
set(requires soc) #unfortunately the header directly uses SOC registers
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
|
||||
REQUIRES "${requires}"
|
||||
PRIV_REQUIRES "${priv_requires}")
|
||||
|
||||
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.
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
# We generate the key from the signing key. The signing key is passed from the main project.
|
||||
get_filename_component(secure_boot_signing_key
|
||||
"${SECURE_BOOT_SIGNING_KEY}"
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
get_filename_component(secure_boot_verification_key
|
||||
"signature_verification_key.bin"
|
||||
ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
add_custom_command(OUTPUT "${secure_boot_verification_key}"
|
||||
COMMAND ${ESPSECUREPY}
|
||||
if(BOOTLOADER_BUILD AND CONFIG_SECURE_SIGNED_APPS)
|
||||
# Whether CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES or not, we need verification key to embed
|
||||
# in the library.
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
# We generate the key from the signing key. The signing key is passed from the main project.
|
||||
get_filename_component(secure_boot_signing_key
|
||||
"${SECURE_BOOT_SIGNING_KEY}"
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
get_filename_component(secure_boot_verification_key
|
||||
"signature_verification_key.bin"
|
||||
ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
add_custom_command(OUTPUT "${secure_boot_verification_key}"
|
||||
COMMAND ${ESPSECUREPY}
|
||||
extract_public_key --keyfile "${secure_boot_signing_key}"
|
||||
"${secure_boot_verification_key}"
|
||||
DEPENDS ${secure_boot_signing_key}
|
||||
VERBATIM)
|
||||
else()
|
||||
# We expect to 'inherit' the verification key passed from main project.
|
||||
get_filename_component(secure_boot_verification_key
|
||||
${SECURE_BOOT_VERIFICATION_KEY}
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
endif()
|
||||
else() # normal app build
|
||||
idf_build_get_property(project_dir PROJECT_DIR)
|
||||
|
||||
if(CONFIG_SECURE_BOOT_VERIFICATION_KEY)
|
||||
# verification-only build supplies verification key
|
||||
set(secure_boot_verification_key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY})
|
||||
get_filename_component(secure_boot_verification_key
|
||||
${secure_boot_verification_key}
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
else()
|
||||
# sign at build time, extracts key from signing key
|
||||
set(secure_boot_verification_key "${CMAKE_BINARY_DIR}/signature_verification_key.bin")
|
||||
get_filename_component(secure_boot_signing_key
|
||||
${CONFIG_SECURE_BOOT_SIGNING_KEY}
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
|
||||
add_custom_command(OUTPUT "${secure_boot_verification_key}"
|
||||
COMMAND ${ESPSECUREPY}
|
||||
extract_public_key --keyfile "${secure_boot_signing_key}"
|
||||
"${secure_boot_verification_key}"
|
||||
WORKING_DIRECTORY ${project_dir}
|
||||
DEPENDS ${secure_boot_signing_key}
|
||||
VERBATIM)
|
||||
endif()
|
||||
VERBATIM)
|
||||
else()
|
||||
# We expect to 'inherit' the verification key passed from main project.
|
||||
get_filename_component(secure_boot_verification_key
|
||||
${SECURE_BOOT_VERIFICATION_KEY}
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
endif()
|
||||
|
||||
# Embed the verification key in the binary (app & bootloader)
|
||||
#
|
||||
target_add_binary_data(${COMPONENT_LIB} "${secure_boot_verification_key}" "BINARY"
|
||||
RENAME_TO signature_verification_key_bin)
|
||||
target_add_binary_data(${COMPONENT_LIB} "${secure_boot_verification_key}" "BINARY")
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${secure_boot_verification_key}")
|
||||
|
||||
@@ -19,9 +19,6 @@ ifndef IS_BOOTLOADER_BUILD
|
||||
COMPONENT_OBJEXCLUDE := src/bootloader_init.o
|
||||
endif
|
||||
|
||||
COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2beta.o \
|
||||
src/bootloader_efuse_esp32s2beta.o
|
||||
|
||||
#
|
||||
# Secure boot signing key support
|
||||
#
|
||||
@@ -49,10 +46,10 @@ $(ORIG_SECURE_BOOT_VERIFICATION_KEY):
|
||||
$(SECURE_BOOT_VERIFICATION_KEY): $(ORIG_SECURE_BOOT_VERIFICATION_KEY) $(SDKCONFIG_MAKEFILE)
|
||||
$(summary) CP $< $@
|
||||
cp $< $@
|
||||
endif #CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
endif
|
||||
|
||||
COMPONENT_EXTRA_CLEAN += $(SECURE_BOOT_VERIFICATION_KEY)
|
||||
|
||||
COMPONENT_EMBED_FILES := $(SECURE_BOOT_VERIFICATION_KEY)
|
||||
|
||||
endif #CONFIG_SECURE_SIGNED_APPS
|
||||
endif
|
||||
|
||||
@@ -24,11 +24,6 @@ extern "C" {
|
||||
*/
|
||||
void bootloader_clock_configure(void);
|
||||
|
||||
/** @brief Return the rated maximum frequency of this chip
|
||||
*/
|
||||
int bootloader_clock_get_rated_freq_mhz(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -15,13 +15,6 @@
|
||||
#pragma once
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_app_format.h"
|
||||
// RESET_REASON is declared in rom/rtc.h
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -34,11 +27,6 @@ typedef enum {
|
||||
GPIO_NOT_HOLD = 0 /*!< If the GPIO input is not low */
|
||||
} esp_comm_gpio_hold_t;
|
||||
|
||||
typedef enum {
|
||||
ESP_IMAGE_BOOTLOADER,
|
||||
ESP_IMAGE_APPLICATION
|
||||
} esp_image_type;
|
||||
|
||||
/**
|
||||
* @brief Calculate crc for the OTA data select.
|
||||
*
|
||||
@@ -94,13 +82,6 @@ bool bootloader_common_erase_part_type_data(const char *list_erase, bool ota_dat
|
||||
*/
|
||||
bool bootloader_common_label_search(const char *list, char *label);
|
||||
|
||||
/**
|
||||
* @brief Configure default SPI pin modes and drive strengths
|
||||
*
|
||||
* @param drv GPIO drive level (determined by clock frequency)
|
||||
*/
|
||||
void bootloader_configure_spi_pins(int drv);
|
||||
|
||||
/**
|
||||
* @brief Calculates a sha-256 for a given partition or returns a appended digest.
|
||||
*
|
||||
@@ -148,7 +129,7 @@ int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata,
|
||||
|
||||
/**
|
||||
* @brief Returns esp_app_desc structure for app partition. This structure includes app version.
|
||||
*
|
||||
*
|
||||
* Returns a description for the requested app partition.
|
||||
* @param[in] partition App partition description.
|
||||
* @param[out] app_desc Structure of info about app.
|
||||
@@ -160,98 +141,10 @@ int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata,
|
||||
*/
|
||||
esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc);
|
||||
|
||||
/**
|
||||
* @brief Get chip revision
|
||||
*
|
||||
* @return Chip revision number
|
||||
*/
|
||||
uint8_t bootloader_common_get_chip_revision(void);
|
||||
|
||||
/**
|
||||
* @brief Query reset reason
|
||||
*
|
||||
* @param cpu_no CPU number
|
||||
* @return reset reason enumeration
|
||||
*/
|
||||
RESET_REASON bootloader_common_get_reset_reason(int cpu_no);
|
||||
|
||||
/**
|
||||
* @brief Check if the image (bootloader and application) has valid chip ID and revision
|
||||
*
|
||||
* @param[in] img_hdr: image header
|
||||
* @param[in] type: image type, bootloader or application
|
||||
* @return
|
||||
* - ESP_OK: image and chip are matched well
|
||||
* - ESP_FAIL: image doesn't match to the chip
|
||||
*/
|
||||
esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hdr, esp_image_type type);
|
||||
|
||||
/**
|
||||
* @brief Configure VDDSDIO, call this API to rise VDDSDIO to 1.9V when VDDSDIO regulator is enabled as 1.8V mode.
|
||||
*/
|
||||
void bootloader_common_vddsdio_configure(void);
|
||||
|
||||
#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
|
||||
/**
|
||||
* @brief Returns partition from rtc_retain_mem
|
||||
*
|
||||
* Uses to get the partition of application which was worked before to go to the deep sleep.
|
||||
* This partition was stored in rtc_retain_mem.
|
||||
* Note: This function operates the RTC FAST memory which available only for PRO_CPU.
|
||||
* Make sure that this function is used only PRO_CPU.
|
||||
*
|
||||
* @return partition: If rtc_retain_mem is valid.
|
||||
* - NULL: If it is not valid.
|
||||
*/
|
||||
esp_partition_pos_t* bootloader_common_get_rtc_retain_mem_partition(void);
|
||||
|
||||
/**
|
||||
* @brief Update the partition and reboot_counter in rtc_retain_mem.
|
||||
*
|
||||
* This function saves the partition of application for fast booting from the deep sleep.
|
||||
* An algorithm uses this partition to avoid reading the otadata and does not validate an image.
|
||||
* Note: This function operates the RTC FAST memory which available only for PRO_CPU.
|
||||
* Make sure that this function is used only PRO_CPU.
|
||||
*
|
||||
* @param[in] partition App partition description. Can be NULL, in this case rtc_retain_mem.partition is not updated.
|
||||
* @param[in] reboot_counter If true then update reboot_counter.
|
||||
*
|
||||
*/
|
||||
void bootloader_common_update_rtc_retain_mem(esp_partition_pos_t* partition, bool reboot_counter);
|
||||
|
||||
/**
|
||||
* @brief Reset entire rtc_retain_mem.
|
||||
*
|
||||
* Note: This function operates the RTC FAST memory which available only for PRO_CPU.
|
||||
* Make sure that this function is used only PRO_CPU.
|
||||
*/
|
||||
void bootloader_common_reset_rtc_retain_mem(void);
|
||||
|
||||
/**
|
||||
* @brief Returns reboot_counter from rtc_retain_mem
|
||||
*
|
||||
* The reboot_counter counts the number of reboots. Reset only when power is off.
|
||||
* The very first launch of the application will be from 1.
|
||||
* Overflow is not possible, it will stop at the value UINT16_MAX.
|
||||
* Note: This function operates the RTC FAST memory which available only for PRO_CPU.
|
||||
* Make sure that this function is used only PRO_CPU.
|
||||
*
|
||||
* @return reboot_counter: 1..65535
|
||||
* - 0: If rtc_retain_mem is not valid.
|
||||
*/
|
||||
uint16_t bootloader_common_get_rtc_retain_mem_reboot_counter(void);
|
||||
|
||||
/**
|
||||
* @brief Returns rtc_retain_mem
|
||||
*
|
||||
* Note: This function operates the RTC FAST memory which available only for PRO_CPU.
|
||||
* Make sure that this function is used only PRO_CPU.
|
||||
*
|
||||
* @return rtc_retain_mem
|
||||
*/
|
||||
rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void);
|
||||
|
||||
#endif
|
||||
void bootloader_common_vddsdio_configure();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ extern "C" {
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void bootloader_flash_update_id(void);
|
||||
void bootloader_flash_update_id();
|
||||
|
||||
/**
|
||||
* @brief Set the flash CS setup and hold time.
|
||||
@@ -35,7 +35,7 @@ void bootloader_flash_update_id(void);
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void bootloader_flash_cs_timing_config(void);
|
||||
void bootloader_flash_cs_timing_config();
|
||||
|
||||
/**
|
||||
* @brief Configure SPI flash clock.
|
||||
|
||||
@@ -13,19 +13,6 @@
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief ESP chip ID
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_CHIP_ID_ESP32 = 0x0000, /*!< chip ID: ESP32 */
|
||||
ESP_CHIP_ID_INVALID = 0xFFFF /*!< Invalid chip ID (we defined it to make sure the esp_chip_id_t is 2 bytes size) */
|
||||
} __attribute__((packed)) esp_chip_id_t;
|
||||
|
||||
/** @cond */
|
||||
_Static_assert(sizeof(esp_chip_id_t) == 2, "esp_chip_id_t should be 16 bit");
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief SPI flash mode, used in esp_image_header_t
|
||||
*/
|
||||
@@ -76,9 +63,7 @@ typedef struct {
|
||||
* the IDF bootloader uses software to configure the WP
|
||||
* pin and sets this field to 0xEE=disabled) */
|
||||
uint8_t spi_pin_drv[3]; /*!< Drive settings for the SPI flash pins (read by ROM bootloader) */
|
||||
esp_chip_id_t chip_id; /*!< Chip identification number */
|
||||
uint8_t min_chip_rev; /*!< Minimum chip revision supported by image */
|
||||
uint8_t reserved[8]; /*!< Reserved bytes in additional header space, currently unused */
|
||||
uint8_t reserved[11]; /*!< Reserved bytes in ESP32 additional header space, currently unused */
|
||||
uint8_t hash_appended; /*!< If 1, a SHA256 digest "simple hash" (of the entire image) is appended after the checksum.
|
||||
* Included in image length. This digest
|
||||
* is separate to secure boot and only used for detecting corruption.
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "esp_spi_flash.h"
|
||||
#endif
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -47,17 +46,11 @@ typedef enum {
|
||||
*
|
||||
* @return true if flash encryption is enabled.
|
||||
*/
|
||||
static inline /** @cond */ IRAM_ATTR /** @endcond */ bool esp_flash_encryption_enabled(void)
|
||||
{
|
||||
uint32_t flash_crypt_cnt;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_RD_FLASH_CRYPT_CNT);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
flash_crypt_cnt = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG, EFUSE_SPI_BOOT_CRYPT_CNT);
|
||||
#endif
|
||||
static inline /** @cond */ IRAM_ATTR /** @endcond */ bool esp_flash_encryption_enabled(void) {
|
||||
uint32_t flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_RD_FLASH_CRYPT_CNT);
|
||||
/* __builtin_parity is in flash, so we calculate parity inline */
|
||||
bool enabled = false;
|
||||
while (flash_crypt_cnt) {
|
||||
while(flash_crypt_cnt) {
|
||||
if (flash_crypt_cnt & 1) {
|
||||
enabled = !enabled;
|
||||
}
|
||||
@@ -129,7 +122,7 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length);
|
||||
* serial re-flashing of an unauthorised code in absence of secure boot.
|
||||
*
|
||||
*/
|
||||
void esp_flash_write_protect_crypt_cnt(void);
|
||||
void esp_flash_write_protect_crypt_cnt();
|
||||
|
||||
/** @brief Return the flash encryption mode
|
||||
*
|
||||
@@ -138,22 +131,7 @@ void esp_flash_write_protect_crypt_cnt(void);
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
esp_flash_enc_mode_t esp_get_flash_encryption_mode(void);
|
||||
|
||||
|
||||
/** @brief Check the flash encryption mode during startup
|
||||
*
|
||||
* @note This function is called automatically during app startup,
|
||||
* it doesn't need to be called from the app.
|
||||
*
|
||||
* Verifies the flash encryption config during startup:
|
||||
*
|
||||
* - Correct any insecure flash encryption settings if hardware
|
||||
* Secure Boot is enabled.
|
||||
* - Log warnings if the efuse config doesn't match the project
|
||||
* config in any way
|
||||
*/
|
||||
void esp_flash_encryption_init_checks(void);
|
||||
esp_flash_enc_mode_t esp_get_flash_encryption_mode();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -98,6 +98,12 @@ typedef struct {
|
||||
esp_err_t esp_partition_table_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions);
|
||||
|
||||
|
||||
/* This function is included for compatibility with the ESP-IDF v3.x API */
|
||||
inline static __attribute__((deprecated)) esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions)
|
||||
{
|
||||
return esp_partition_table_verify(partition_table, log_errors, num_partitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the region on the main flash is safe to write.
|
||||
*
|
||||
|
||||
@@ -42,42 +42,44 @@ typedef struct {
|
||||
uint8_t image_digest[32]; /* appended SHA-256 digest */
|
||||
} esp_image_metadata_t;
|
||||
|
||||
/* Mode selection for esp_image_load() */
|
||||
typedef enum {
|
||||
ESP_IMAGE_VERIFY, /* Verify image contents, not load to memory, load metadata. Print errors. */
|
||||
ESP_IMAGE_VERIFY_SILENT, /* Verify image contents, not load to memory, load metadata. Don't print errors. */
|
||||
ESP_IMAGE_VERIFY, /* Verify image contents, load metadata. Print errors. */
|
||||
ESP_IMAGE_VERIFY_SILENT, /* Verify image contents, load metadata. Don't print errors. */
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
ESP_IMAGE_LOAD, /* Verify image contents, load to memory, load metadata. Print errors. */
|
||||
ESP_IMAGE_LOAD_NO_VALIDATE, /* Not verify image contents, load to memory, load metadata. Print errors. */
|
||||
ESP_IMAGE_LOAD, /* Verify image contents, load to memory. Print errors. */
|
||||
#endif
|
||||
} esp_image_load_mode_t;
|
||||
|
||||
typedef struct {
|
||||
esp_partition_pos_t partition; /*!< Partition of application which worked before goes to the deep sleep. */
|
||||
uint16_t reboot_counter; /*!< Reboot counter. Reset only when power is off. */
|
||||
uint16_t reserve; /*!< Reserve */
|
||||
#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||
uint8_t custom[CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE]; /*!< Reserve for custom propose */
|
||||
#endif
|
||||
uint32_t crc; /*!< Check sum crc32 */
|
||||
} rtc_retain_mem_t;
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||
_Static_assert(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE % 4 == 0, "CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE must be a multiple of 4 bytes");
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) || defined(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC)
|
||||
_Static_assert(CONFIG_BOOTLOADER_RESERVE_RTC_SIZE % 4 == 0, "CONFIG_BOOTLOADER_RESERVE_RTC_SIZE must be a multiple of 4 bytes");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||
#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE)
|
||||
#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP)
|
||||
#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP) || defined(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC)
|
||||
_Static_assert(sizeof(rtc_retain_mem_t) <= ESP_BOOTLOADER_RESERVE_RTC, "Reserved RTC area must exceed size of rtc_retain_mem_t");
|
||||
#endif
|
||||
/**
|
||||
* @brief Verify and (optionally, in bootloader mode) load an app image.
|
||||
*
|
||||
* This name is deprecated and is included for compatibility with the ESP-IDF v3.x API.
|
||||
* It will be removed in V4.0 version.
|
||||
* Function has been renamed to esp_image_verify().
|
||||
* Use function esp_image_verify() to verify a image. And use function bootloader_load_image() to load image from a bootloader space.
|
||||
*
|
||||
* If encryption is enabled, data will be transparently decrypted.
|
||||
*
|
||||
* @param mode Mode of operation (verify, silent verify, or load).
|
||||
* @param part Partition to load the app from.
|
||||
* @param[inout] data Pointer to the image metadata structure which is be filled in by this function. 'start_addr' member should be set (to the start address of the image.) Other fields will all be initialised by this function.
|
||||
*
|
||||
* Image validation checks:
|
||||
* - Magic byte.
|
||||
* - Partition smaller than 16MB.
|
||||
* - All segments & image fit in partition.
|
||||
* - 8 bit image checksum is valid.
|
||||
* - SHA-256 of image is valid (if image has this appended).
|
||||
* - (Signature) if signature verification is enabled.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if verify or load was successful
|
||||
* - ESP_ERR_IMAGE_FLASH_FAIL if a SPI flash error occurs
|
||||
* - ESP_ERR_IMAGE_INVALID if the image appears invalid.
|
||||
* - ESP_ERR_INVALID_ARG if the partition or data pointers are invalid.
|
||||
*/
|
||||
esp_err_t esp_image_load(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Verify an app image.
|
||||
@@ -132,24 +134,6 @@ esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t
|
||||
*/
|
||||
esp_err_t bootloader_load_image(const esp_partition_pos_t *part, esp_image_metadata_t *data);
|
||||
|
||||
/**
|
||||
* @brief Load an app image without verification (available only in space of bootloader).
|
||||
*
|
||||
* If encryption is enabled, data will be transparently decrypted.
|
||||
*
|
||||
* @param part Partition to load the app from.
|
||||
* @param[inout] data Pointer to the image metadata structure which is be filled in by this function.
|
||||
* 'start_addr' member should be set (to the start address of the image.)
|
||||
* Other fields will all be initialised by this function.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if verify or load was successful
|
||||
* - ESP_ERR_IMAGE_FLASH_FAIL if a SPI flash error occurs
|
||||
* - ESP_ERR_IMAGE_INVALID if the image appears invalid.
|
||||
* - ESP_ERR_INVALID_ARG if the partition or data pointers are invalid.
|
||||
*/
|
||||
esp_err_t bootloader_load_image_no_verify(const esp_partition_pos_t *part, esp_image_metadata_t *data);
|
||||
|
||||
/**
|
||||
* @brief Verify the bootloader image.
|
||||
*
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
#include "soc/efuse_periph.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
#if !defined(CONFIG_SECURE_SIGNED_ON_BOOT) || !defined(CONFIG_SECURE_SIGNED_ON_UPDATE) || !defined(CONFIG_SECURE_SIGNED_APPS)
|
||||
@@ -39,18 +36,14 @@ extern "C" {
|
||||
|
||||
/** @brief Is secure boot currently enabled in hardware?
|
||||
*
|
||||
* This means that the ROM bootloader code will only boot
|
||||
* a verified secure bootloader from now on.
|
||||
* Secure boot is enabled if the ABS_DONE_0 efuse is blown. This means
|
||||
* that the ROM bootloader code will only boot a verified secure
|
||||
* bootloader digest from now on.
|
||||
*
|
||||
* @return true if secure boot is enabled.
|
||||
*/
|
||||
static inline bool esp_secure_boot_enabled(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
static inline bool esp_secure_boot_enabled(void) {
|
||||
return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
return ets_efuse_secure_boot_enabled();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @brief Generate secure digest from bootloader image
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <esp_err.h>
|
||||
#include "esp_spi_flash.h"
|
||||
|
||||
#define FLASH_SECTOR_SIZE 0x1000
|
||||
#define FLASH_BLOCK_SIZE 0x10000
|
||||
@@ -34,7 +35,7 @@
|
||||
*
|
||||
* @return Number of free pages
|
||||
*/
|
||||
uint32_t bootloader_mmap_get_free_pages(void);
|
||||
uint32_t bootloader_mmap_get_free_pages();
|
||||
|
||||
/**
|
||||
* @brief Map a region of flash to data memory
|
||||
|
||||
@@ -14,37 +14,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_image_format.h"
|
||||
|
||||
/**@{*/
|
||||
/**
|
||||
* @brief labels from bootloader linker script: bootloader.ld
|
||||
*
|
||||
*/
|
||||
extern int _bss_start;
|
||||
extern int _bss_end;
|
||||
extern int _data_start;
|
||||
extern int _data_end;
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* @brief bootloader image header
|
||||
*
|
||||
*/
|
||||
extern esp_image_header_t bootloader_image_hdr;
|
||||
|
||||
/**@{*/
|
||||
/**
|
||||
* @brief Common initialization steps that are applied to all targets.
|
||||
*
|
||||
*/
|
||||
esp_err_t bootloader_read_bootloader_header(void);
|
||||
esp_err_t bootloader_check_bootloader_validity(void);
|
||||
void bootloader_clear_bss_section(void);
|
||||
void bootloader_config_wdt(void);
|
||||
void bootloader_enable_random(void);
|
||||
void bootloader_print_banner(void);
|
||||
/**@}*/
|
||||
|
||||
/* @brief Prepares hardware for work.
|
||||
*
|
||||
@@ -56,4 +25,4 @@ void bootloader_print_banner(void);
|
||||
* @return ESP_OK - If the setting is successful.
|
||||
* ESP_FAIL - If the setting is not successful.
|
||||
*/
|
||||
esp_err_t bootloader_init(void);
|
||||
esp_err_t bootloader_init();
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
typedef void *bootloader_sha256_handle_t;
|
||||
|
||||
bootloader_sha256_handle_t bootloader_sha256_start(void);
|
||||
bootloader_sha256_handle_t bootloader_sha256_start();
|
||||
|
||||
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len);
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include "bootloader_config.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "bootloader_config.h"
|
||||
|
||||
/**
|
||||
* @brief Load partition table.
|
||||
@@ -55,16 +54,6 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
|
||||
*/
|
||||
__attribute__((noreturn)) void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index);
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
|
||||
/**
|
||||
* @brief Load that application which was worked before we go to the deep sleep.
|
||||
*
|
||||
* Checks the reboot reason if it is the deep sleep and has a valid partition in the RTC memory
|
||||
* then try to load the application which was worked before we go to the deep sleep.
|
||||
*
|
||||
*/
|
||||
void bootloader_utility_load_boot_image_from_deep_sleep(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Software reset the ESP32
|
||||
@@ -97,14 +86,3 @@ __attribute__((noreturn)) void bootloader_reset(void);
|
||||
* ESP_ERR_INVALID_ARG: Error in the passed arguments
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @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);
|
||||
|
||||
@@ -30,7 +30,7 @@ void bootloader_enable_qio_mode(void);
|
||||
* mfg_id = (ID >> 16) & 0xFF;
|
||||
flash_id = ID & 0xffff;
|
||||
*/
|
||||
uint32_t bootloader_read_flash_id(void);
|
||||
uint32_t bootloader_read_flash_id();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -11,21 +11,14 @@
|
||||
// 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 "sdkconfig.h"
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#else
|
||||
#include "esp32s2beta/rom/uart.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#endif
|
||||
|
||||
void bootloader_clock_configure(void)
|
||||
void bootloader_clock_configure()
|
||||
{
|
||||
// ROM bootloader may have put a lot of text into UART0 FIFO.
|
||||
// Wait for it to be printed.
|
||||
@@ -34,30 +27,23 @@ void bootloader_clock_configure(void)
|
||||
// and will be done with the bootloader much earlier than UART FIFO is empty.
|
||||
uart_tx_wait_idle(0);
|
||||
|
||||
/* Set CPU to 80MHz. Keep other clocks unmodified. */
|
||||
int cpu_freq_mhz = 80;
|
||||
|
||||
/* On ESP32 rev 0, switching to 80/160 MHz if clock was previously set to
|
||||
* 240 MHz may cause the chip to lock up (see section 3.5 of the errata
|
||||
* document). For rev. 0, switch to 240 instead if it has been enabled
|
||||
* previously.
|
||||
*/
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Set CPU to 80MHz. Keep other clocks unmodified. */
|
||||
int cpu_freq_mhz = 80;
|
||||
|
||||
uint32_t chip_ver_reg = REG_READ(EFUSE_BLK0_RDATA3_REG);
|
||||
if ((chip_ver_reg & EFUSE_RD_CHIP_VER_REV1_M) == 0 &&
|
||||
DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL) == DPORT_CPUPERIOD_SEL_240) {
|
||||
cpu_freq_mhz = 240;
|
||||
}
|
||||
#endif
|
||||
|
||||
rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT();
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ;
|
||||
clk_cfg.cpu_freq_mhz = cpu_freq_mhz;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
clk_cfg.xtal_freq = RTC_XTAL_FREQ_40M;
|
||||
clk_cfg.cpu_freq = RTC_CPU_FREQ_80M;
|
||||
#endif
|
||||
clk_cfg.slow_freq = rtc_clk_slow_freq_get();
|
||||
clk_cfg.fast_freq = rtc_clk_fast_freq_get();
|
||||
rtc_clk_init(clk_cfg);
|
||||
@@ -72,12 +58,3 @@ void bootloader_clock_configure(void)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
|
||||
int esp_clk_apb_freq(void)
|
||||
{
|
||||
return rtc_clk_apb_freq_get();
|
||||
}
|
||||
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
@@ -17,22 +17,14 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/crc.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/crc.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#endif
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "sys/param.h"
|
||||
@@ -264,7 +256,7 @@ esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void bootloader_common_vddsdio_configure(void)
|
||||
void bootloader_common_vddsdio_configure()
|
||||
{
|
||||
#if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
|
||||
rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
|
||||
@@ -278,91 +270,3 @@ void bootloader_common_vddsdio_configure(void)
|
||||
}
|
||||
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
|
||||
}
|
||||
|
||||
|
||||
esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hdr, esp_image_type type)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
esp_chip_id_t chip_id = CONFIG_IDF_FIRMWARE_CHIP_ID;
|
||||
if (chip_id != img_hdr->chip_id) {
|
||||
ESP_LOGE(TAG, "mismatch chip ID, expected %d, found %d", chip_id, img_hdr->chip_id);
|
||||
err = ESP_FAIL;
|
||||
}
|
||||
uint8_t revision = bootloader_common_get_chip_revision();
|
||||
if (revision < img_hdr->min_chip_rev) {
|
||||
ESP_LOGE(TAG, "can't run on lower chip revision, expected %d, found %d", revision, img_hdr->min_chip_rev);
|
||||
err = ESP_FAIL;
|
||||
} else if (revision != img_hdr->min_chip_rev) {
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
ESP_LOGI(TAG, "chip revision: %d, min. %s chip revision: %d", revision, type == ESP_IMAGE_BOOTLOADER ? "bootloader" : "application", img_hdr->min_chip_rev);
|
||||
#endif
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
RESET_REASON bootloader_common_get_reset_reason(int cpu_no)
|
||||
{
|
||||
return rtc_get_reset_reason(cpu_no);
|
||||
}
|
||||
|
||||
#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
|
||||
|
||||
rtc_retain_mem_t *const rtc_retain_mem = (rtc_retain_mem_t *)(SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t));
|
||||
|
||||
static bool check_rtc_retain_mem(void)
|
||||
{
|
||||
return crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, sizeof(rtc_retain_mem_t) - sizeof(rtc_retain_mem->crc)) == rtc_retain_mem->crc && rtc_retain_mem->crc != UINT32_MAX;
|
||||
}
|
||||
|
||||
static void update_rtc_retain_mem_crc(void)
|
||||
{
|
||||
rtc_retain_mem->crc = crc32_le(UINT32_MAX, (uint8_t*)rtc_retain_mem, sizeof(rtc_retain_mem_t) - sizeof(rtc_retain_mem->crc));
|
||||
}
|
||||
|
||||
void bootloader_common_reset_rtc_retain_mem(void)
|
||||
{
|
||||
memset(rtc_retain_mem, 0, sizeof(rtc_retain_mem_t));
|
||||
}
|
||||
|
||||
uint16_t bootloader_common_get_rtc_retain_mem_reboot_counter(void)
|
||||
{
|
||||
if (check_rtc_retain_mem()) {
|
||||
return rtc_retain_mem->reboot_counter;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_partition_pos_t* bootloader_common_get_rtc_retain_mem_partition(void)
|
||||
{
|
||||
if (check_rtc_retain_mem()) {
|
||||
return &rtc_retain_mem->partition;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bootloader_common_update_rtc_retain_mem(esp_partition_pos_t* partition, bool reboot_counter)
|
||||
{
|
||||
if (reboot_counter) {
|
||||
if (!check_rtc_retain_mem()) {
|
||||
bootloader_common_reset_rtc_retain_mem();
|
||||
}
|
||||
if (++rtc_retain_mem->reboot_counter == 0) {
|
||||
// do not allow to overflow. Stop it.
|
||||
--rtc_retain_mem->reboot_counter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (partition != NULL) {
|
||||
rtc_retain_mem->partition.offset = partition->offset;
|
||||
rtc_retain_mem->partition.size = partition->size;
|
||||
}
|
||||
|
||||
update_rtc_retain_mem_crc();
|
||||
}
|
||||
|
||||
rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void)
|
||||
{
|
||||
return rtc_retain_mem;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
// Copyright 2019 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 "bootloader_common.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
|
||||
uint8_t bootloader_common_get_chip_revision(void)
|
||||
{
|
||||
uint8_t eco_bit0, eco_bit1, eco_bit2;
|
||||
eco_bit0 = (REG_READ(EFUSE_BLK0_RDATA3_REG) & 0xF000) >> 15;
|
||||
eco_bit1 = (REG_READ(EFUSE_BLK0_RDATA5_REG) & 0x100000) >> 20;
|
||||
eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 0x80000000) >> 31;
|
||||
uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0;
|
||||
uint8_t chip_ver = 0;
|
||||
switch (combine_value) {
|
||||
case 0:
|
||||
chip_ver = 0;
|
||||
break;
|
||||
case 1:
|
||||
chip_ver = 1;
|
||||
break;
|
||||
case 3:
|
||||
chip_ver = 2;
|
||||
break;
|
||||
case 7:
|
||||
chip_ver = 3;
|
||||
break;
|
||||
default:
|
||||
chip_ver = 0;
|
||||
break;
|
||||
}
|
||||
return chip_ver;
|
||||
}
|
||||
|
||||
int bootloader_clock_get_rated_freq_mhz()
|
||||
{
|
||||
//Check if ESP32 is rated for a CPU frequency of 160MHz only
|
||||
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) &&
|
||||
REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) {
|
||||
return 160;
|
||||
}
|
||||
return 240;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// Copyright 2019 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 "sdkconfig.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
int bootloader_clock_get_rated_freq_mhz()
|
||||
{
|
||||
/* No known limitation: all chips are 240MHz rated */
|
||||
return 240;
|
||||
}
|
||||
|
||||
uint8_t bootloader_common_get_chip_revision(void)
|
||||
{
|
||||
/* No other revisions for ESP32-S2beta */
|
||||
return 0;
|
||||
}
|
||||
@@ -17,9 +17,6 @@
|
||||
#include <esp_log.h>
|
||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||
#include <esp_flash_encrypt.h>
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#endif
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
/* Normal app version maps to esp_spi_flash.h operations...
|
||||
@@ -28,7 +25,7 @@ static const char *TAG = "bootloader_mmap";
|
||||
|
||||
static spi_flash_mmap_handle_t map;
|
||||
|
||||
uint32_t bootloader_mmap_get_free_pages(void)
|
||||
uint32_t bootloader_mmap_get_free_pages()
|
||||
{
|
||||
return spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
|
||||
}
|
||||
@@ -40,7 +37,7 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
return NULL; /* existing mapping in use... */
|
||||
}
|
||||
const void *result = NULL;
|
||||
uint32_t src_page = src_addr & ~(SPI_FLASH_MMU_PAGE_SIZE - 1);
|
||||
uint32_t src_page = src_addr & ~(SPI_FLASH_MMU_PAGE_SIZE-1);
|
||||
size += (src_addr - src_page);
|
||||
esp_err_t err = spi_flash_mmap(src_page, size, SPI_FLASH_MMAP_DATA, &result, &map);
|
||||
if (err != ESP_OK) {
|
||||
@@ -52,7 +49,7 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
|
||||
void bootloader_munmap(const void *mapping)
|
||||
{
|
||||
if (mapping && map) {
|
||||
if(mapping && map) {
|
||||
spi_flash_munmap(map);
|
||||
}
|
||||
map = 0;
|
||||
@@ -70,11 +67,7 @@ esp_err_t bootloader_flash_read(size_t src, void *dest, size_t size, bool allow_
|
||||
esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted)
|
||||
{
|
||||
if (write_encrypted) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return spi_flash_write_encrypted(dest_addr, src, size);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
return SPI_Encrypt_Write(dest_addr, src, size);
|
||||
#endif
|
||||
} else {
|
||||
return spi_flash_write(dest_addr, src, size);
|
||||
}
|
||||
@@ -93,41 +86,24 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
#else
|
||||
/* Bootloader version, uses ROM functions only */
|
||||
#include <soc/dport_reg.h>
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include <esp32/rom/spi_flash.h>
|
||||
#include <esp32/rom/cache.h>
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include <esp32s2beta/rom/spi_flash.h>
|
||||
#include <esp32s2beta/rom/cache.h>
|
||||
#endif
|
||||
|
||||
static const char *TAG = "bootloader_flash";
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Use first 50 blocks in MMU for bootloader_mmap,
|
||||
50th block for bootloader_flash_read
|
||||
*/
|
||||
#define MMU_BLOCK0_VADDR SOC_DROM_LOW
|
||||
#define MMU_SIZE (0x320000)
|
||||
#define MMU_BLOCK50_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
|
||||
#define FLASH_READ_VADDR MMU_BLOCK50_VADDR
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
/* Use first 63 blocks in MMU for bootloader_mmap,
|
||||
63th block for bootloader_flash_read
|
||||
*/
|
||||
#define MMU_BLOCK0_VADDR SOC_DROM_LOW
|
||||
#define MMU_SIZE (0x3f0000)
|
||||
#define MMU_BLOCK63_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
|
||||
#define FLASH_READ_VADDR MMU_BLOCK63_VADDR
|
||||
#endif
|
||||
#define MMU_BLOCK0_VADDR 0x3f400000
|
||||
#define MMU_BLOCK50_VADDR 0x3f720000
|
||||
#define MMU_FREE_PAGES ((MMU_BLOCK50_VADDR - MMU_BLOCK0_VADDR) / FLASH_BLOCK_SIZE)
|
||||
|
||||
#define MMU_FREE_PAGES (MMU_SIZE / FLASH_BLOCK_SIZE)
|
||||
|
||||
static bool mapped;
|
||||
|
||||
// Current bootloader mapping (ab)used for bootloader_read()
|
||||
static uint32_t current_read_mapping = UINT32_MAX;
|
||||
|
||||
uint32_t bootloader_mmap_get_free_pages(void)
|
||||
uint32_t bootloader_mmap_get_free_pages()
|
||||
{
|
||||
/**
|
||||
* Allow mapping up to 50 of the 51 available MMU blocks (last one used for reads)
|
||||
@@ -142,41 +118,25 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
ESP_LOGE(TAG, "tried to bootloader_mmap twice");
|
||||
return NULL; /* can't map twice */
|
||||
}
|
||||
if (size > MMU_SIZE) {
|
||||
if (size > 0x320000) {
|
||||
/* Allow mapping up to 50 of the 51 available MMU blocks (last one used for reads) */
|
||||
ESP_LOGE(TAG, "bootloader_mmap excess size %x", size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t src_addr_aligned = src_addr & MMU_FLASH_MASK;
|
||||
uint32_t count = bootloader_cache_pages_to_map(size, src_addr);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
#endif
|
||||
ESP_LOGD(TAG, "mmu set paddr=%08x count=%d size=%x src_addr=%x src_addr_aligned=%x",
|
||||
src_addr & MMU_FLASH_MASK, count, size, src_addr, src_addr_aligned );
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
src_addr & MMU_FLASH_MASK, count, size, src_addr, src_addr_aligned );
|
||||
int e = cache_flash_mmu_set(0, 0, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
int e = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
|
||||
#endif
|
||||
if (e != 0) {
|
||||
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
|
||||
mapped = true;
|
||||
|
||||
@@ -186,17 +146,10 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
void bootloader_munmap(const void *mapping)
|
||||
{
|
||||
if (mapped) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Full MMU reset */
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
mmu_init(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
//TODO, save the autoload value.
|
||||
Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
Cache_MMU_Init();
|
||||
#endif
|
||||
mapped = false;
|
||||
current_read_mapping = UINT32_MAX;
|
||||
}
|
||||
@@ -204,7 +157,7 @@ void bootloader_munmap(const void *mapping)
|
||||
|
||||
static esp_err_t spi_to_esp_err(esp_rom_spiflash_result_t r)
|
||||
{
|
||||
switch (r) {
|
||||
switch(r) {
|
||||
case ESP_ROM_SPIFLASH_RESULT_OK:
|
||||
return ESP_OK;
|
||||
case ESP_ROM_SPIFLASH_RESULT_ERR:
|
||||
@@ -218,18 +171,10 @@ static esp_err_t spi_to_esp_err(esp_rom_spiflash_result_t r)
|
||||
|
||||
static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, size_t size)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
#endif
|
||||
esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
|
||||
return spi_to_esp_err(r);
|
||||
}
|
||||
@@ -238,42 +183,28 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
|
||||
{
|
||||
uint32_t *dest_words = (uint32_t *)dest;
|
||||
|
||||
/* Use the 51st MMU mapping to read from flash in 64KB blocks.
|
||||
(MMU will transparently decrypt if encryption is enabled.)
|
||||
*/
|
||||
for (int word = 0; word < size / 4; word++) {
|
||||
uint32_t word_src = src_addr + word * 4; /* Read this offset from flash */
|
||||
uint32_t map_at = word_src & MMU_FLASH_MASK; /* Map this 64KB block from flash */
|
||||
uint32_t *map_ptr;
|
||||
if (map_at != current_read_mapping) {
|
||||
/* Move the 64KB mmu mapping window to fit map_at */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
#endif
|
||||
ESP_LOGD(TAG, "mmu set block paddr=0x%08x (was 0x%08x)", map_at, current_read_mapping);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int e = cache_flash_mmu_set(0, 0, FLASH_READ_VADDR, map_at, 64, 1);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
int e = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, FLASH_READ_VADDR, map_at, 64, 1, 0);
|
||||
#endif
|
||||
int e = cache_flash_mmu_set(0, 0, MMU_BLOCK50_VADDR, map_at, 64, 1);
|
||||
if (e != 0) {
|
||||
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
return ESP_FAIL;
|
||||
}
|
||||
current_read_mapping = map_at;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
}
|
||||
map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at));
|
||||
map_ptr = (uint32_t *)(MMU_BLOCK50_VADDR + (word_src - map_at));
|
||||
dest_words[word] = *map_ptr;
|
||||
}
|
||||
return ESP_OK;
|
||||
@@ -324,12 +255,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
|
||||
}
|
||||
|
||||
if (write_encrypted) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return spi_to_esp_err(esp_rom_spiflash_write_encrypted(dest_addr, src, size));
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
// TODO: use the same ROM AP here
|
||||
return spi_to_esp_err(SPI_Encrypt_Write(dest_addr, src, size));
|
||||
#endif
|
||||
} else {
|
||||
return spi_to_esp_err(esp_rom_spiflash_write(dest_addr, src, size));
|
||||
}
|
||||
|
||||
@@ -27,12 +27,12 @@
|
||||
#include "flash_qio_mode.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
|
||||
void bootloader_flash_update_id(void)
|
||||
void bootloader_flash_update_id()
|
||||
{
|
||||
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_cs_timing_config(void)
|
||||
void IRAM_ATTR bootloader_flash_cs_timing_config()
|
||||
{
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_HOLD_TIME_V, 1, SPI_HOLD_TIME_S);
|
||||
@@ -1,118 +0,0 @@
|
||||
// Copyright 2019 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 <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include "string.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "soc/spi_caps.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
#define FLASH_IO_MATRIX_DUMMY_40M 0
|
||||
#define FLASH_IO_MATRIX_DUMMY_80M 0
|
||||
|
||||
#define FLASH_IO_DRIVE_GD_WITH_1V8PSRAM 3
|
||||
|
||||
void bootloader_flash_update_id()
|
||||
{
|
||||
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_cs_timing_config()
|
||||
{
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_CS_HOLD_TIME_V, 1, SPI_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_CS_SETUP_TIME_V, 0, SPI_CS_SETUP_TIME_S);
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(1), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_CS_HOLD_TIME_V, 1, SPI_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_CS_SETUP_TIME_V, 0, SPI_CS_SETUP_TIME_S);
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t* pfhdr)
|
||||
{
|
||||
uint32_t spi_clk_div = 0;
|
||||
switch (pfhdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
spi_clk_div = 1;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
spi_clk_div = 2;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_26M:
|
||||
spi_clk_div = 3;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_20M:
|
||||
spi_clk_div = 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
esp_rom_spiflash_config_clk(spi_clk_div, 0);
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_dummy_config(const esp_image_header_t* pfhdr)
|
||||
{
|
||||
int spi_cache_dummy = 0;
|
||||
int drv = 2;
|
||||
switch (pfhdr->spi_mode) {
|
||||
case ESP_IMAGE_SPI_MODE_QIO:
|
||||
spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_MODE_DIO:
|
||||
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //qio 3
|
||||
break;
|
||||
case ESP_IMAGE_SPI_MODE_QOUT:
|
||||
case ESP_IMAGE_SPI_MODE_DOUT:
|
||||
default:
|
||||
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
switch (pfhdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M;
|
||||
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M;
|
||||
SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M,
|
||||
SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
drv = 3;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M;
|
||||
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M;
|
||||
SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M,
|
||||
SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bootloader_configure_spi_pins(drv);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2018 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.
|
||||
@@ -13,54 +13,137 @@
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include <limits.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "hal/timer_ll.h"
|
||||
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/crc.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/secure_boot.h"
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/timer_periph.h"
|
||||
#include "soc/rtc_wdt.h"
|
||||
#include "soc/spi_periph.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_config.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
|
||||
#include "flash_qio_mode.h"
|
||||
|
||||
extern int _bss_start;
|
||||
extern int _bss_end;
|
||||
extern int _data_start;
|
||||
extern int _data_end;
|
||||
|
||||
static const char* TAG = "boot";
|
||||
|
||||
static esp_err_t bootloader_main();
|
||||
static void print_flash_info(const esp_image_header_t* pfhdr);
|
||||
static void update_flash_config(const esp_image_header_t* pfhdr);
|
||||
static void bootloader_init_flash_configure(const esp_image_header_t* pfhdr);
|
||||
static void uart_console_configure(void);
|
||||
static void wdt_reset_check(void);
|
||||
|
||||
|
||||
static const char *TAG = "boot";
|
||||
|
||||
esp_image_header_t bootloader_image_hdr;
|
||||
|
||||
void bootloader_clear_bss_section(void)
|
||||
esp_err_t bootloader_init()
|
||||
{
|
||||
cpu_configure_region_protection();
|
||||
cpu_init_memctl();
|
||||
|
||||
/* Sanity check that static RAM is after the stack */
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
int *sp = get_sp();
|
||||
assert(&_bss_start <= &_bss_end);
|
||||
assert(&_data_start <= &_data_end);
|
||||
assert(sp < &_bss_start);
|
||||
assert(sp < &_data_start);
|
||||
}
|
||||
#endif
|
||||
|
||||
//Clear bss
|
||||
memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
|
||||
}
|
||||
|
||||
esp_err_t bootloader_read_bootloader_header(void)
|
||||
{
|
||||
/* load bootloader image header */
|
||||
if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &bootloader_image_hdr, sizeof(esp_image_header_t), true) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed to load bootloader image header!");
|
||||
/* completely reset MMU for both CPUs
|
||||
(in case serial bootloader was running) */
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Read_Disable(1);
|
||||
Cache_Flush(0);
|
||||
Cache_Flush(1);
|
||||
mmu_init(0);
|
||||
DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
||||
mmu_init(1);
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
||||
/* (above steps probably unnecessary for most serial bootloader
|
||||
usage, all that's absolutely needed is that we unmask DROM0
|
||||
cache on the following two lines - normal ROM boot exits with
|
||||
DROM0 cache unmasked, but serial bootloader exits with it
|
||||
masked. However can't hurt to be thorough and reset
|
||||
everything.)
|
||||
|
||||
The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
|
||||
necessary to work around a hardware bug.
|
||||
*/
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
|
||||
|
||||
if(bootloader_main() != ESP_OK){
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t bootloader_check_bootloader_validity(void)
|
||||
static esp_err_t bootloader_main()
|
||||
{
|
||||
/* read chip revision from efuse */
|
||||
uint8_t revision = bootloader_common_get_chip_revision();
|
||||
ESP_LOGI(TAG, "chip revision: %d", revision);
|
||||
/* compare with the one set in bootloader image header */
|
||||
if (bootloader_common_check_chip_validity(&bootloader_image_hdr, ESP_IMAGE_BOOTLOADER) != ESP_OK) {
|
||||
bootloader_common_vddsdio_configure();
|
||||
/* Read and keep flash ID, for further use. */
|
||||
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||
esp_image_header_t fhdr;
|
||||
if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr, sizeof(esp_image_header_t), true) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed to load bootloader header!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
bootloader_init_flash_configure(&fhdr);
|
||||
#if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240)
|
||||
//Check if ESP32 is rated for a CPU frequency of 160MHz only
|
||||
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) &&
|
||||
REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) {
|
||||
ESP_LOGE(TAG, "Chip CPU frequency rated for 160MHz. Modify CPU frequency in menuconfig");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
bootloader_clock_configure();
|
||||
uart_console_configure();
|
||||
wdt_reset_check();
|
||||
ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER);
|
||||
|
||||
ESP_LOGI(TAG, "compile time " __TIME__ );
|
||||
ets_set_appcpu_boot_addr(0);
|
||||
|
||||
void bootloader_config_wdt(void)
|
||||
{
|
||||
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
ESP_LOGD(TAG, "Enabling RTCWDT(%d ms)", CONFIG_BOOTLOADER_WDT_TIME_MS);
|
||||
rtc_wdt_protect_off();
|
||||
@@ -71,28 +154,293 @@ void bootloader_config_wdt(void)
|
||||
rtc_wdt_set_time(RTC_WDT_STAGE0, CONFIG_BOOTLOADER_WDT_TIME_MS);
|
||||
rtc_wdt_enable();
|
||||
rtc_wdt_protect_on();
|
||||
#else /* disable watch dog */
|
||||
#else
|
||||
/* disable watch dog here */
|
||||
rtc_wdt_disable();
|
||||
#endif
|
||||
timer_ll_wdt_set_protect(&TIMERG0, false);
|
||||
timer_ll_wdt_flashboot_en(&TIMERG0, false);
|
||||
}
|
||||
REG_SET_FIELD(TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY, TIMG_WDT_WKEY_VALUE);
|
||||
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if(spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
|
||||
ESP_LOGE(TAG, "SPI flash pins are overridden. \"Enable SPI flash ROM driver patched functions\" must be enabled in menuconfig");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
|
||||
void bootloader_enable_random(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Enabling RNG early entropy source...");
|
||||
bootloader_random_enable();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
#endif
|
||||
|
||||
print_flash_info(&fhdr);
|
||||
|
||||
update_flash_config(&fhdr);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void bootloader_print_banner(void)
|
||||
static void update_flash_config(const esp_image_header_t* pfhdr)
|
||||
{
|
||||
ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER);
|
||||
ESP_LOGI(TAG, "compile time " __TIME__);
|
||||
uint32_t size;
|
||||
switch(pfhdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
size = 1;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
size = 2;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
size = 4;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
size = 8;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
size = 16;
|
||||
break;
|
||||
default:
|
||||
size = 2;
|
||||
}
|
||||
Cache_Read_Disable( 0 );
|
||||
// Set flash chip size
|
||||
esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
|
||||
// TODO: set mode
|
||||
// TODO: set frequency
|
||||
Cache_Flush(0);
|
||||
Cache_Read_Enable( 0 );
|
||||
}
|
||||
|
||||
static void print_flash_info(const esp_image_header_t* phdr)
|
||||
{
|
||||
#if (BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE)
|
||||
|
||||
ESP_LOGD(TAG, "magic %02x", phdr->magic );
|
||||
ESP_LOGD(TAG, "segments %02x", phdr->segment_count );
|
||||
ESP_LOGD(TAG, "spi_mode %02x", phdr->spi_mode );
|
||||
ESP_LOGD(TAG, "spi_speed %02x", phdr->spi_speed );
|
||||
ESP_LOGD(TAG, "spi_size %02x", phdr->spi_size );
|
||||
|
||||
const char* str;
|
||||
switch ( phdr->spi_speed ) {
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
str = "40MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_26M:
|
||||
str = "26.7MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_20M:
|
||||
str = "20MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
str = "80MHz";
|
||||
break;
|
||||
default:
|
||||
str = "20MHz";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Speed : %s", str );
|
||||
|
||||
/* SPI mode could have been set to QIO during boot already,
|
||||
so test the SPI registers not the flash header */
|
||||
uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
|
||||
if (spi_ctrl & SPI_FREAD_QIO) {
|
||||
str = "QIO";
|
||||
} else if (spi_ctrl & SPI_FREAD_QUAD) {
|
||||
str = "QOUT";
|
||||
} else if (spi_ctrl & SPI_FREAD_DIO) {
|
||||
str = "DIO";
|
||||
} else if (spi_ctrl & SPI_FREAD_DUAL) {
|
||||
str = "DOUT";
|
||||
} else if (spi_ctrl & SPI_FASTRD_MODE) {
|
||||
str = "FAST READ";
|
||||
} else {
|
||||
str = "SLOW READ";
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Mode : %s", str );
|
||||
|
||||
switch ( phdr->spi_size ) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
str = "1MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
str = "2MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
str = "4MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
str = "8MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
str = "16MB";
|
||||
break;
|
||||
default:
|
||||
str = "2MB";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Flash Size : %s", str );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Bootloader reads SPI configuration from bin header, so that
|
||||
* the burning configuration can be different with compiling configuration.
|
||||
*/
|
||||
static void IRAM_ATTR bootloader_init_flash_configure(const esp_image_header_t* pfhdr)
|
||||
{
|
||||
bootloader_flash_gpio_config(pfhdr);
|
||||
bootloader_flash_dummy_config(pfhdr);
|
||||
bootloader_flash_cs_timing_config();
|
||||
}
|
||||
|
||||
static void uart_console_configure(void)
|
||||
{
|
||||
#if CONFIG_ESP_CONSOLE_UART_NONE
|
||||
ets_install_putc1(NULL);
|
||||
ets_install_putc2(NULL);
|
||||
#else // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
const int uart_num = CONFIG_ESP_CONSOLE_UART_NUM;
|
||||
|
||||
uartAttach();
|
||||
ets_install_uart_printf();
|
||||
|
||||
// Wait for UART FIFO to be empty.
|
||||
uart_tx_wait_idle(0);
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
// Some constants to make the following code less upper-case
|
||||
const int uart_tx_gpio = CONFIG_ESP_CONSOLE_UART_TX_GPIO;
|
||||
const int uart_rx_gpio = CONFIG_ESP_CONSOLE_UART_RX_GPIO;
|
||||
// Switch to the new UART (this just changes UART number used for
|
||||
// ets_printf in ROM code).
|
||||
uart_tx_switch(uart_num);
|
||||
// If console is attached to UART1 or if non-default pins are used,
|
||||
// need to reconfigure pins using GPIO matrix
|
||||
if (uart_num != 0 || uart_tx_gpio != 1 || uart_rx_gpio != 3) {
|
||||
// Change pin mode for GPIO1/3 from UART to GPIO
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_GPIO3);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_GPIO1);
|
||||
// Route GPIO signals to/from pins
|
||||
// (arrays should be optimized away by the compiler)
|
||||
const uint32_t tx_idx_list[3] = { U0TXD_OUT_IDX, U1TXD_OUT_IDX, U2TXD_OUT_IDX };
|
||||
const uint32_t rx_idx_list[3] = { U0RXD_IN_IDX, U1RXD_IN_IDX, U2RXD_IN_IDX };
|
||||
const uint32_t uart_reset[3] = { DPORT_UART_RST, DPORT_UART1_RST, DPORT_UART2_RST };
|
||||
const uint32_t tx_idx = tx_idx_list[uart_num];
|
||||
const uint32_t rx_idx = rx_idx_list[uart_num];
|
||||
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
|
||||
gpio_pad_pullup(uart_rx_gpio);
|
||||
|
||||
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
|
||||
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
|
||||
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
}
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
|
||||
// Set configured UART console baud rate
|
||||
const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE;
|
||||
uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
|
||||
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
}
|
||||
|
||||
static void wdt_reset_cpu0_info_enable(void)
|
||||
{
|
||||
//We do not reset core1 info here because it didn't work before cpu1 was up. So we put it into call_start_cpu1.
|
||||
DPORT_REG_SET_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_PDEBUG_ENABLE | DPORT_PRO_CPU_RECORD_ENABLE);
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_RECORD_ENABLE);
|
||||
}
|
||||
|
||||
static void wdt_reset_info_dump(int cpu)
|
||||
{
|
||||
uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0,
|
||||
lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
|
||||
const char *cpu_name = cpu ? "APP" : "PRO";
|
||||
|
||||
if (cpu == 0) {
|
||||
stat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_STATUS_REG);
|
||||
pid = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PID_REG);
|
||||
inst = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGINST_REG);
|
||||
dstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG);
|
||||
data = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGDATA_REG);
|
||||
pc = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGPC_REG);
|
||||
lsstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0STAT_REG);
|
||||
lsaddr = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG);
|
||||
lsdata = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG);
|
||||
|
||||
} else {
|
||||
stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG);
|
||||
pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG);
|
||||
inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG);
|
||||
dstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGSTATUS_REG);
|
||||
data = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGDATA_REG);
|
||||
pc = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGPC_REG);
|
||||
lsstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG);
|
||||
lsaddr = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG);
|
||||
lsdata = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG);
|
||||
}
|
||||
if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 &&
|
||||
DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x", cpu_name, pc);
|
||||
}
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata);
|
||||
}
|
||||
|
||||
static void wdt_reset_check(void)
|
||||
{
|
||||
int wdt_rst = 0;
|
||||
RESET_REASON rst_reas[2];
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
rst_reas[1] = rtc_get_reset_reason(1);
|
||||
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
if (rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET || rst_reas[1] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "APP CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
if (wdt_rst) {
|
||||
// if reset by WDT dump info from trace port
|
||||
wdt_reset_info_dump(0);
|
||||
wdt_reset_info_dump(1);
|
||||
}
|
||||
wdt_reset_cpu0_info_enable();
|
||||
}
|
||||
|
||||
void __assert_func(const char *file, int line, const char *func, const char *expr)
|
||||
{
|
||||
ESP_LOGE(TAG, "Assert failed in %s, %s:%d (%s)", func, file, line, expr);
|
||||
while (1) {
|
||||
}
|
||||
while(1) {}
|
||||
}
|
||||
|
||||
void abort()
|
||||
{
|
||||
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
ets_printf("abort() was called at PC 0x%08x\r\n", (intptr_t)__builtin_return_address(0) - 3);
|
||||
#endif
|
||||
if (esp_cpu_in_ocd_debug_mode()) {
|
||||
__asm__ ("break 0,0");
|
||||
}
|
||||
while(1) {}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
#include "esp_system.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
|
||||
void bootloader_fill_random(void *buffer, size_t length)
|
||||
{
|
||||
@@ -35,9 +34,7 @@ void bootloader_fill_random(void *buffer, size_t length)
|
||||
{
|
||||
uint8_t *buffer_bytes = (uint8_t *)buffer;
|
||||
uint32_t random;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
uint32_t start, now;
|
||||
#endif
|
||||
|
||||
assert(buffer != NULL);
|
||||
|
||||
@@ -50,18 +47,14 @@ void bootloader_fill_random(void *buffer, size_t length)
|
||||
as-is, we repeatedly read the RNG register and XOR all
|
||||
values.
|
||||
*/
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
random = REG_READ(WDEV_RND_REG);
|
||||
RSR(CCOUNT, start);
|
||||
do {
|
||||
random ^= REG_READ(WDEV_RND_REG);
|
||||
RSR(CCOUNT, now);
|
||||
} while (now - start < 80 * 32 * 2); /* extra factor of 2 is precautionary */
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
// ToDo: Get random from register
|
||||
random = 12345678;
|
||||
#endif
|
||||
} while(now - start < 80*32*2); /* extra factor of 2 is precautionary */
|
||||
}
|
||||
|
||||
buffer_bytes[i] = random >> ((i % 4) * 8);
|
||||
}
|
||||
}
|
||||
@@ -72,11 +65,7 @@ void bootloader_random_enable(void)
|
||||
/* Ensure the hardware RNG is enabled following a soft reset. This should always be the case already (this clock is
|
||||
never disabled while the CPU is running), this is a "belts and braces" type check.
|
||||
*/
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_RNG_EN);
|
||||
#else
|
||||
periph_module_enable(PERIPH_RNG_MODULE);
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
/* Enable SAR ADC in test mode to feed ADC readings of the 1.1V
|
||||
reference via I2S into the RNG entropy input.
|
||||
@@ -86,23 +75,11 @@ void bootloader_random_enable(void)
|
||||
*/
|
||||
SET_PERI_REG_BITS(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_DTEST_RTC, 2, RTC_CNTL_DTEST_RTC_S);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_ENT_RTC);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_SAR2_EN_TEST);
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
#else
|
||||
periph_module_enable(PERIPH_I2S0_MODULE);
|
||||
#endif // BOOTLOADER_BUILD
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_ULP_CP_FORCE_START_TOP);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_ULP_CP_START_TOP);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SET_PERI_REG_MASK(SENS_SAR_MEAS2_CTRL1_REG, SENS_SAR2_EN_TEST);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_FORCE_START_TOP);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_START_TOP);
|
||||
#endif
|
||||
|
||||
// Test pattern configuration byte 0xAD:
|
||||
//--[7:4] channel_sel: 10-->en_test
|
||||
//--[3:2] bit_width : 3-->12bit
|
||||
@@ -111,31 +88,22 @@ void bootloader_random_enable(void)
|
||||
WRITE_PERI_REG(SYSCON_SARADC_SAR2_PATT_TAB2_REG, 0xADADADAD);
|
||||
WRITE_PERI_REG(SYSCON_SARADC_SAR2_PATT_TAB3_REG, 0xADADADAD);
|
||||
WRITE_PERI_REG(SYSCON_SARADC_SAR2_PATT_TAB4_REG, 0xADADADAD);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S);
|
||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DIG_FORCE);
|
||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SET_PERI_REG_BITS(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S);
|
||||
SET_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG, SENS_SAR1_DIG_FORCE);
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX);
|
||||
#endif
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_CLK_DIV, 4, SYSCON_SARADC_SAR_CLK_DIV_S);
|
||||
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_RSTB_WAIT, 8, SYSCON_SARADC_RSTB_WAIT_S); /* was 1 */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 10, SYSCON_SARADC_START_WAIT_S);
|
||||
#endif
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_WORK_MODE, 0, SYSCON_SARADC_WORK_MODE_S);
|
||||
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_SEL);
|
||||
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_DATA_SAR_SEL);
|
||||
|
||||
SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(0), I2S_RX_BCK_DIV_NUM, 20, I2S_RX_BCK_DIV_NUM_S);
|
||||
|
||||
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_DATA_TO_I2S);
|
||||
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG,SYSCON_SARADC_DATA_TO_I2S);
|
||||
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_CAMERA_EN);
|
||||
SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_LCD_EN);
|
||||
@@ -146,54 +114,32 @@ void bootloader_random_enable(void)
|
||||
|
||||
void bootloader_random_disable(void)
|
||||
{
|
||||
/* Disable i2s clock */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
|
||||
|
||||
/* Reset some i2s configuration (possibly redundant as we reset entire
|
||||
I2S peripheral further down). */
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_START);
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_RESET);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_CAMERA_EN);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_LCD_EN);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE_TEST_EN);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE);
|
||||
|
||||
/* Disable i2s clock */
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
#else
|
||||
periph_module_disable(PERIPH_I2S0_MODULE);
|
||||
#endif // BOOTLOADER_BUILD
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_START);
|
||||
|
||||
/* Restore SYSCON mode registers */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DIG_FORCE);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG, SENS_SAR1_DIG_FORCE);
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Restore SAR ADC mode */
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_SAR2_EN_TEST);
|
||||
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX
|
||||
| SYSCON_SARADC_SAR_SEL | SYSCON_SARADC_DATA_TO_I2S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS2_CTRL1_REG, SENS_SAR2_EN_TEST);
|
||||
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_SEL | SYSCON_SARADC_DATA_TO_I2S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 8, SYSCON_SARADC_START_WAIT_S);
|
||||
#endif
|
||||
|
||||
/* Reset i2s peripheral */
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
#else
|
||||
periph_module_reset(PERIPH_I2S0_MODULE);
|
||||
#endif
|
||||
|
||||
/* Disable pull supply voltage to SAR ADC */
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_ENT_RTC);
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
@@ -29,19 +28,6 @@
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/secure_boot.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/cache.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/crc.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#include "esp32s2beta/rom/uart.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#include "esp32s2beta/rom/secure_boot.h"
|
||||
#else
|
||||
#error "Unsupported IDF_TARGET"
|
||||
#endif
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/cpu.h"
|
||||
@@ -65,22 +51,22 @@
|
||||
#include "bootloader_sha.h"
|
||||
#include "esp_efuse.h"
|
||||
|
||||
static const char *TAG = "boot";
|
||||
static const char* TAG = "boot";
|
||||
|
||||
/* Reduce literal size for some generic string literals */
|
||||
#define MAP_ERR_MSG "Image contains multiple %s segments. Only the last one will be mapped."
|
||||
|
||||
static bool ota_has_initial_contents;
|
||||
|
||||
static void load_image(const esp_image_metadata_t *image_data);
|
||||
static void load_image(const esp_image_metadata_t* image_data);
|
||||
static void unpack_load_app(const esp_image_metadata_t *data);
|
||||
static void set_cache_and_start_app(uint32_t drom_addr,
|
||||
uint32_t drom_load_addr,
|
||||
uint32_t drom_size,
|
||||
uint32_t irom_addr,
|
||||
uint32_t irom_load_addr,
|
||||
uint32_t irom_size,
|
||||
uint32_t entry_addr);
|
||||
uint32_t drom_load_addr,
|
||||
uint32_t drom_size,
|
||||
uint32_t irom_addr,
|
||||
uint32_t irom_load_addr,
|
||||
uint32_t irom_size,
|
||||
uint32_t entry_addr);
|
||||
|
||||
// Read ota_info partition and fill array from two otadata structures.
|
||||
static esp_err_t read_otadata(const esp_partition_pos_t *ota_info, esp_ota_select_entry_t *two_otadata)
|
||||
@@ -110,7 +96,7 @@ static esp_err_t read_otadata(const esp_partition_pos_t *ota_info, esp_ota_selec
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
|
||||
bool bootloader_utility_load_partition_table(bootloader_state_t* bs)
|
||||
{
|
||||
const esp_partition_info_t *partitions;
|
||||
const char *partition_usage;
|
||||
@@ -133,16 +119,16 @@ bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
|
||||
ESP_LOGI(TAG, "Partition Table:");
|
||||
ESP_LOGI(TAG, "## Label Usage Type ST Offset Length");
|
||||
|
||||
for (int i = 0; i < num_partitions; i++) {
|
||||
for(int i = 0; i < num_partitions; i++) {
|
||||
const esp_partition_info_t *partition = &partitions[i];
|
||||
ESP_LOGD(TAG, "load partition table entry 0x%x", (intptr_t)partition);
|
||||
ESP_LOGD(TAG, "type=%x subtype=%x", partition->type, partition->subtype);
|
||||
partition_usage = "unknown";
|
||||
|
||||
/* valid partition table */
|
||||
switch (partition->type) {
|
||||
switch(partition->type) {
|
||||
case PART_TYPE_APP: /* app partition */
|
||||
switch (partition->subtype) {
|
||||
switch(partition->subtype) {
|
||||
case PART_SUBTYPE_FACTORY: /* factory binary */
|
||||
bs->factory = partition->pos;
|
||||
partition_usage = "factory app";
|
||||
@@ -157,14 +143,15 @@ bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
|
||||
bs->ota[partition->subtype & PART_SUBTYPE_OTA_MASK] = partition->pos;
|
||||
++bs->app_count;
|
||||
partition_usage = "OTA app";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
partition_usage = "Unknown app";
|
||||
}
|
||||
break;
|
||||
}
|
||||
break; /* PART_TYPE_APP */
|
||||
case PART_TYPE_DATA: /* data partition */
|
||||
switch (partition->subtype) {
|
||||
switch(partition->subtype) {
|
||||
case PART_SUBTYPE_DATA_OTA: /* ota data */
|
||||
bs->ota_info = partition->pos;
|
||||
partition_usage = "OTA data";
|
||||
@@ -201,7 +188,7 @@ bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
|
||||
|
||||
bootloader_munmap(partitions);
|
||||
|
||||
ESP_LOGI(TAG, "End of partition table");
|
||||
ESP_LOGI(TAG,"End of partition table");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -227,7 +214,7 @@ static esp_partition_pos_t index_to_partition(const bootloader_state_t *bs, int
|
||||
static void log_invalid_app_partition(int index)
|
||||
{
|
||||
const char *not_bootable = " is not bootable"; /* save a few string literal bytes */
|
||||
switch (index) {
|
||||
switch(index) {
|
||||
case FACTORY_INDEX:
|
||||
ESP_LOGE(TAG, "Factory app partition%s", not_bootable);
|
||||
break;
|
||||
@@ -330,8 +317,8 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
|
||||
|
||||
#ifndef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
if ((bootloader_common_ota_select_invalid(&otadata[0]) &&
|
||||
bootloader_common_ota_select_invalid(&otadata[1])) ||
|
||||
bs->app_count == 0) {
|
||||
bootloader_common_ota_select_invalid(&otadata[1])) ||
|
||||
bs->app_count == 0) {
|
||||
ESP_LOGD(TAG, "OTA sequence numbers both empty (all-0xFF) or partition table does not have bootable ota_apps (app_count=%d)", bs->app_count);
|
||||
if (bs->factory.offset != 0) {
|
||||
ESP_LOGI(TAG, "Defaulting to factory image");
|
||||
@@ -341,7 +328,7 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
|
||||
boot_index = 0;
|
||||
// Try to boot from ota_0.
|
||||
if ((otadata[0].ota_seq == UINT32_MAX || otadata[0].crc != bootloader_common_ota_select_crc(&otadata[0])) &&
|
||||
(otadata[1].ota_seq == UINT32_MAX || otadata[1].crc != bootloader_common_ota_select_crc(&otadata[1]))) {
|
||||
(otadata[1].ota_seq == UINT32_MAX || otadata[1].crc != bootloader_common_ota_select_crc(&otadata[1]))) {
|
||||
// Factory is not found and both otadata are initial(0xFFFFFFFF) or incorrect crc.
|
||||
// will set correct ota_seq.
|
||||
ota_has_initial_contents = true;
|
||||
@@ -354,7 +341,7 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs)
|
||||
ESP_LOGI(TAG, "Secure version (from eFuse) = %d", esp_efuse_read_secure_version());
|
||||
// When CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK is enabled factory partition should not be in partition table, only two ota_app are there.
|
||||
if ((otadata[0].ota_seq == UINT32_MAX || otadata[0].crc != bootloader_common_ota_select_crc(&otadata[0])) &&
|
||||
(otadata[1].ota_seq == UINT32_MAX || otadata[1].crc != bootloader_common_ota_select_crc(&otadata[1]))) {
|
||||
(otadata[1].ota_seq == UINT32_MAX || otadata[1].crc != bootloader_common_ota_select_crc(&otadata[1]))) {
|
||||
ESP_LOGI(TAG, "otadata[0..1] in initial state");
|
||||
// both otadata are initial(0xFFFFFFFF) or incorrect crc.
|
||||
// will set correct ota_seq.
|
||||
@@ -429,31 +416,8 @@ static void set_actual_ota_seq(const bootloader_state_t *bs, int index)
|
||||
update_anti_rollback(&bs->ota[index]);
|
||||
#endif
|
||||
}
|
||||
#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
|
||||
esp_partition_pos_t partition = index_to_partition(bs, index);
|
||||
bootloader_common_update_rtc_retain_mem(&partition, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
|
||||
void bootloader_utility_load_boot_image_from_deep_sleep(void)
|
||||
{
|
||||
if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) {
|
||||
esp_partition_pos_t* partition = bootloader_common_get_rtc_retain_mem_partition();
|
||||
if (partition != NULL) {
|
||||
esp_image_metadata_t image_data;
|
||||
if (bootloader_load_image_no_verify(partition, &image_data) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Fast booting app from partition at offset 0x%x", partition->offset);
|
||||
bootloader_common_update_rtc_retain_mem(NULL, true);
|
||||
load_image(&image_data);
|
||||
}
|
||||
}
|
||||
ESP_LOGE(TAG, "Fast booting is not successful");
|
||||
ESP_LOGI(TAG, "Try to load an app as usual with all validations");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define TRY_LOG_FORMAT "Trying partition index %d offs 0x%x size 0x%x"
|
||||
|
||||
void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index)
|
||||
@@ -462,7 +426,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
|
||||
esp_partition_pos_t part;
|
||||
esp_image_metadata_t image_data;
|
||||
|
||||
if (start_index == TEST_APP_INDEX) {
|
||||
if(start_index == TEST_APP_INDEX) {
|
||||
if (try_load_partition(&bs->test, &image_data)) {
|
||||
load_image(&image_data);
|
||||
} else {
|
||||
@@ -472,7 +436,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
|
||||
}
|
||||
|
||||
/* work backwards from start_index, down to the factory app */
|
||||
for (index = start_index; index >= FACTORY_INDEX; index--) {
|
||||
for(index = start_index; index >= FACTORY_INDEX; index--) {
|
||||
part = index_to_partition(bs, index);
|
||||
if (part.size == 0) {
|
||||
continue;
|
||||
@@ -486,7 +450,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
|
||||
}
|
||||
|
||||
/* failing that work forwards from start_index, try valid OTA slots */
|
||||
for (index = start_index + 1; index < bs->app_count; index++) {
|
||||
for(index = start_index + 1; index < bs->app_count; index++) {
|
||||
part = index_to_partition(bs, index);
|
||||
if (part.size == 0) {
|
||||
continue;
|
||||
@@ -510,7 +474,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
|
||||
}
|
||||
|
||||
// Copy loaded segments to RAM, set up caches for mapped segments, and start application.
|
||||
static void load_image(const esp_image_metadata_t *image_data)
|
||||
static void load_image(const esp_image_metadata_t* image_data)
|
||||
{
|
||||
/**
|
||||
* Rough steps for a first boot, when encryption and secure boot are both disabled:
|
||||
@@ -607,21 +571,18 @@ static void load_image(const esp_image_metadata_t *image_data)
|
||||
so issue a system reset to ensure flash encryption
|
||||
cache resets properly */
|
||||
ESP_LOGI(TAG, "Resetting with flash encryption enabled...");
|
||||
uart_tx_wait_idle(0);
|
||||
bootloader_reset();
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Disabling RNG early entropy source...");
|
||||
#if !CONFIG_IDF_ENV_FPGA
|
||||
bootloader_random_disable();
|
||||
#endif
|
||||
|
||||
// copy loaded segments to RAM, set up caches for mapped segments, and start application
|
||||
unpack_load_app(image_data);
|
||||
}
|
||||
|
||||
static void unpack_load_app(const esp_image_metadata_t *data)
|
||||
static void unpack_load_app(const esp_image_metadata_t* data)
|
||||
{
|
||||
uint32_t drom_addr = 0;
|
||||
uint32_t drom_load_addr = 0;
|
||||
@@ -657,12 +618,12 @@ static void unpack_load_app(const esp_image_metadata_t *data)
|
||||
|
||||
ESP_LOGD(TAG, "calling set_cache_and_start_app");
|
||||
set_cache_and_start_app(drom_addr,
|
||||
drom_load_addr,
|
||||
drom_size,
|
||||
irom_addr,
|
||||
irom_load_addr,
|
||||
irom_size,
|
||||
data->image.entry_addr);
|
||||
drom_load_addr,
|
||||
drom_size,
|
||||
irom_addr,
|
||||
irom_load_addr,
|
||||
irom_size,
|
||||
data->image.entry_addr);
|
||||
}
|
||||
|
||||
static void set_cache_and_start_app(
|
||||
@@ -676,13 +637,8 @@ static void set_cache_and_start_app(
|
||||
{
|
||||
int rc;
|
||||
ESP_LOGD(TAG, "configure drom and irom and start");
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
#endif
|
||||
Cache_Read_Disable( 0 );
|
||||
Cache_Flush( 0 );
|
||||
|
||||
/* Clear the MMU entries that are already set up,
|
||||
so the new app only has the mappings it creates.
|
||||
@@ -694,66 +650,33 @@ static void set_cache_and_start_app(
|
||||
uint32_t drom_load_addr_aligned = drom_load_addr & MMU_FLASH_MASK;
|
||||
uint32_t drom_page_count = bootloader_cache_pages_to_map(drom_size, drom_load_addr);
|
||||
ESP_LOGV(TAG, "d mmu set paddr=%08x vaddr=%08x size=%d n=%d",
|
||||
drom_addr & MMU_FLASH_MASK, drom_load_addr_aligned, drom_size, drom_page_count);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
drom_addr & MMU_FLASH_MASK, drom_load_addr_aligned, drom_size, drom_page_count);
|
||||
rc = cache_flash_mmu_set(0, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000,
|
||||
64, drom_page_count, 0);
|
||||
#endif
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
rc = cache_flash_mmu_set(1, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count);
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
#endif
|
||||
|
||||
uint32_t irom_load_addr_aligned = irom_load_addr & MMU_FLASH_MASK;
|
||||
uint32_t irom_page_count = bootloader_cache_pages_to_map(irom_size, irom_load_addr);
|
||||
ESP_LOGV(TAG, "i mmu set paddr=%08x vaddr=%08x size=%d n=%d",
|
||||
irom_addr & MMU_FLASH_MASK, irom_load_addr_aligned, irom_size, irom_page_count);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
irom_addr & MMU_FLASH_MASK, irom_load_addr_aligned, irom_size, irom_page_count);
|
||||
rc = cache_flash_mmu_set(0, 0, irom_load_addr_aligned, irom_addr & MMU_FLASH_MASK, 64, irom_page_count);
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t iram1_used = 0, irom0_used = 0;
|
||||
if (irom_load_addr + irom_size > IRAM1_ADDRESS_LOW) {
|
||||
iram1_used = 1;
|
||||
}
|
||||
if (irom_load_addr + irom_size > IROM0_ADDRESS_LOW) {
|
||||
irom0_used = 1;
|
||||
}
|
||||
if (iram1_used || irom0_used) {
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, IRAM0_ADDRESS_LOW, 0, 64, 64, 1);
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, IRAM1_ADDRESS_LOW, 0, 64, 64, 1);
|
||||
REG_SET_BIT(DPORT_CACHE_SOURCE_1_REG, DPORT_PRO_CACHE_I_SOURCE_PRO_IRAM1);
|
||||
REG_CLR_BIT(DPORT_PRO_ICACHE_CTRL1_REG, DPORT_PRO_ICACHE_MASK_IRAM1);
|
||||
if (irom0_used) {
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, IROM0_ADDRESS_LOW, 0, 64, 64, 1);
|
||||
REG_SET_BIT(DPORT_CACHE_SOURCE_1_REG, DPORT_PRO_CACHE_I_SOURCE_PRO_IROM0);
|
||||
REG_CLR_BIT(DPORT_PRO_ICACHE_CTRL1_REG, DPORT_PRO_ICACHE_MASK_IROM0);
|
||||
}
|
||||
}
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
|
||||
#endif
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
rc = cache_flash_mmu_set(1, 0, irom_load_addr_aligned, irom_addr & MMU_FLASH_MASK, 64, irom_page_count);
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
|
||||
DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG,
|
||||
(DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) |
|
||||
(DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 |
|
||||
DPORT_PRO_CACHE_MASK_DRAM1 );
|
||||
(DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) |
|
||||
(DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 |
|
||||
DPORT_PRO_CACHE_MASK_DRAM1 );
|
||||
|
||||
DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG,
|
||||
(DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) |
|
||||
(DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 |
|
||||
DPORT_APP_CACHE_MASK_DRAM1 );
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
DPORT_REG_CLR_BIT( DPORT_PRO_ICACHE_CTRL1_REG, (DPORT_PRO_ICACHE_MASK_IRAM0) | (DPORT_PRO_ICACHE_MASK_IRAM1 & 0) | (DPORT_PRO_ICACHE_MASK_IROM0 & 0) | DPORT_PRO_ICACHE_MASK_DROM0 );
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
(DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) |
|
||||
(DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 |
|
||||
DPORT_APP_CACHE_MASK_DRAM1 );
|
||||
|
||||
Cache_Read_Enable( 0 );
|
||||
|
||||
// Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
|
||||
|
||||
ESP_LOGD(TAG, "start: 0x%08x", entry_addr);
|
||||
@@ -765,6 +688,7 @@ static void set_cache_and_start_app(
|
||||
(*entry)();
|
||||
}
|
||||
|
||||
|
||||
void bootloader_reset(void)
|
||||
{
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
@@ -795,24 +719,3 @@ esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_he
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void bootloader_debug_buffer(const void *buffer, size_t length, const char *label)
|
||||
{
|
||||
#if BOOT_LOG_LEVEL >= LOG_LEVEL_DEBUG
|
||||
assert(length <= 128); // Avoid unbounded VLA size
|
||||
const uint8_t *bytes = (const uint8_t *)buffer;
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,480 +0,0 @@
|
||||
// Copyright 2019 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 "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "flash_qio_mode.h"
|
||||
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/spi_periph.h"
|
||||
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "esp32/rom/uart.h"
|
||||
|
||||
static const char *TAG = "boot.esp32";
|
||||
|
||||
#define FLASH_CLK_IO SPI_CLK_GPIO_NUM
|
||||
#define FLASH_CS_IO SPI_CS0_GPIO_NUM
|
||||
#define FLASH_SPIQ_IO SPI_Q_GPIO_NUM
|
||||
#define FLASH_SPID_IO SPI_D_GPIO_NUM
|
||||
#define FLASH_SPIWP_IO SPI_WP_GPIO_NUM
|
||||
#define FLASH_SPIHD_IO SPI_HD_GPIO_NUM
|
||||
|
||||
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) {
|
||||
// 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);
|
||||
} else {
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
|
||||
gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
|
||||
//select pin function gpio
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
|
||||
// flash clock signal should come from IO MUX.
|
||||
// set drive ability for clock
|
||||
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);
|
||||
|
||||
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 || CONFIG_SPIRAM_TYPE_ESPPSRAM64
|
||||
uint32_t flash_id = g_rom_flashchip.device_id;
|
||||
if (flash_id == FLASH_ID_GD25LQ32C) {
|
||||
// Set drive ability for 1.8v flash in 80Mhz.
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bootloader_reset_mmu(void)
|
||||
{
|
||||
/* completely reset MMU in case serial bootloader was running */
|
||||
Cache_Read_Disable(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
Cache_Read_Disable(1);
|
||||
#endif
|
||||
Cache_Flush(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
Cache_Flush(1);
|
||||
#endif
|
||||
mmu_init(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
/* The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
|
||||
necessary to work around a hardware bug. */
|
||||
DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
||||
mmu_init(1);
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
||||
#endif
|
||||
|
||||
/* normal ROM boot exits with DROM0 cache unmasked,
|
||||
but serial bootloader exits with it masked. */
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t bootloader_check_rated_cpu_clock(void)
|
||||
{
|
||||
int rated_freq = bootloader_clock_get_rated_freq_mhz();
|
||||
if (rated_freq < CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) {
|
||||
ESP_LOGE(TAG, "Chip CPU frequency rated for %dMHz, configured for %dMHz. Modify CPU frequency in menuconfig",
|
||||
rated_freq, CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void update_flash_config(const esp_image_header_t *bootloader_hdr)
|
||||
{
|
||||
uint32_t size;
|
||||
switch (bootloader_hdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
size = 1;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
size = 2;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
size = 4;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
size = 8;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
size = 16;
|
||||
break;
|
||||
default:
|
||||
size = 2;
|
||||
}
|
||||
Cache_Read_Disable(0);
|
||||
// Set flash chip size
|
||||
esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
|
||||
// TODO: set mode
|
||||
// TODO: set frequency
|
||||
Cache_Flush(0);
|
||||
Cache_Read_Enable(0);
|
||||
}
|
||||
|
||||
static void print_flash_info(const esp_image_header_t *bootloader_hdr)
|
||||
{
|
||||
ESP_LOGD(TAG, "magic %02x", bootloader_hdr->magic);
|
||||
ESP_LOGD(TAG, "segments %02x", bootloader_hdr->segment_count);
|
||||
ESP_LOGD(TAG, "spi_mode %02x", bootloader_hdr->spi_mode);
|
||||
ESP_LOGD(TAG, "spi_speed %02x", bootloader_hdr->spi_speed);
|
||||
ESP_LOGD(TAG, "spi_size %02x", bootloader_hdr->spi_size);
|
||||
|
||||
const char *str;
|
||||
switch (bootloader_hdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
str = "40MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_26M:
|
||||
str = "26.7MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_20M:
|
||||
str = "20MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
str = "80MHz";
|
||||
break;
|
||||
default:
|
||||
str = "20MHz";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Speed : %s", str);
|
||||
|
||||
/* SPI mode could have been set to QIO during boot already,
|
||||
so test the SPI registers not the flash header */
|
||||
uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
|
||||
if (spi_ctrl & SPI_FREAD_QIO) {
|
||||
str = "QIO";
|
||||
} else if (spi_ctrl & SPI_FREAD_QUAD) {
|
||||
str = "QOUT";
|
||||
} else if (spi_ctrl & SPI_FREAD_DIO) {
|
||||
str = "DIO";
|
||||
} else if (spi_ctrl & SPI_FREAD_DUAL) {
|
||||
str = "DOUT";
|
||||
} else if (spi_ctrl & SPI_FASTRD_MODE) {
|
||||
str = "FAST READ";
|
||||
} else {
|
||||
str = "SLOW READ";
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Mode : %s", str);
|
||||
|
||||
switch (bootloader_hdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
str = "1MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
str = "2MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
str = "4MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
str = "8MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
str = "16MB";
|
||||
break;
|
||||
default:
|
||||
str = "2MB";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Flash Size : %s", str);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR bootloader_init_flash_configure(void)
|
||||
{
|
||||
bootloader_flash_gpio_config(&bootloader_image_hdr);
|
||||
bootloader_flash_dummy_config(&bootloader_image_hdr);
|
||||
bootloader_flash_cs_timing_config();
|
||||
}
|
||||
|
||||
static esp_err_t bootloader_init_spi_flash(void)
|
||||
{
|
||||
bootloader_init_flash_configure();
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
|
||||
ESP_LOGE(TAG, "SPI flash pins are overridden. Enable CONFIG_SPI_FLASH_ROM_DRIVER_PATCH in menuconfig");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
#endif
|
||||
|
||||
print_flash_info(&bootloader_image_hdr);
|
||||
update_flash_config(&bootloader_image_hdr);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void bootloader_init_uart_console(void)
|
||||
{
|
||||
#if CONFIG_ESP_CONSOLE_UART_NONE
|
||||
ets_install_putc1(NULL);
|
||||
ets_install_putc2(NULL);
|
||||
#else // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
const int uart_num = CONFIG_ESP_CONSOLE_UART_NUM;
|
||||
|
||||
uartAttach();
|
||||
ets_install_uart_printf();
|
||||
|
||||
// Wait for UART FIFO to be empty.
|
||||
uart_tx_wait_idle(0);
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
// Some constants to make the following code less upper-case
|
||||
const int uart_tx_gpio = CONFIG_ESP_CONSOLE_UART_TX_GPIO;
|
||||
const int uart_rx_gpio = CONFIG_ESP_CONSOLE_UART_RX_GPIO;
|
||||
// Switch to the new UART (this just changes UART number used for
|
||||
// ets_printf in ROM code).
|
||||
uart_tx_switch(uart_num);
|
||||
// If console is attached to UART1 or if non-default pins are used,
|
||||
// need to reconfigure pins using GPIO matrix
|
||||
if (uart_num != 0 || uart_tx_gpio != 1 || uart_rx_gpio != 3) {
|
||||
// Change pin mode for GPIO1/3 from UART to GPIO
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_GPIO3);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_GPIO1);
|
||||
// Route GPIO signals to/from pins
|
||||
// (arrays should be optimized away by the compiler)
|
||||
const uint32_t tx_idx_list[3] = {U0TXD_OUT_IDX, U1TXD_OUT_IDX, U2TXD_OUT_IDX};
|
||||
const uint32_t rx_idx_list[3] = {U0RXD_IN_IDX, U1RXD_IN_IDX, U2RXD_IN_IDX};
|
||||
const uint32_t uart_reset[3] = {DPORT_UART_RST, DPORT_UART1_RST, DPORT_UART2_RST};
|
||||
const uint32_t tx_idx = tx_idx_list[uart_num];
|
||||
const uint32_t rx_idx = rx_idx_list[uart_num];
|
||||
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
|
||||
gpio_pad_pullup(uart_rx_gpio);
|
||||
|
||||
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
|
||||
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
|
||||
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
}
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
|
||||
// Set configured UART console baud rate
|
||||
const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE;
|
||||
uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
|
||||
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
}
|
||||
|
||||
static void wdt_reset_cpu0_info_enable(void)
|
||||
{
|
||||
//We do not reset core1 info here because it didn't work before cpu1 was up. So we put it into call_start_cpu1.
|
||||
DPORT_REG_SET_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_PDEBUG_ENABLE | DPORT_PRO_CPU_RECORD_ENABLE);
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_RECORD_ENABLE);
|
||||
}
|
||||
|
||||
static void wdt_reset_info_dump(int cpu)
|
||||
{
|
||||
uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0,
|
||||
lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
|
||||
const char *cpu_name = cpu ? "APP" : "PRO";
|
||||
|
||||
if (cpu == 0) {
|
||||
stat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_STATUS_REG);
|
||||
pid = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PID_REG);
|
||||
inst = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGINST_REG);
|
||||
dstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG);
|
||||
data = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGDATA_REG);
|
||||
pc = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGPC_REG);
|
||||
lsstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0STAT_REG);
|
||||
lsaddr = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG);
|
||||
lsdata = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG);
|
||||
} else {
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG);
|
||||
pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG);
|
||||
inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG);
|
||||
dstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGSTATUS_REG);
|
||||
data = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGDATA_REG);
|
||||
pc = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGPC_REG);
|
||||
lsstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG);
|
||||
lsaddr = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG);
|
||||
lsdata = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG);
|
||||
#else
|
||||
ESP_LOGE(TAG, "WDT reset info: &s CPU not support!\n", cpu_name);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 &&
|
||||
DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x", cpu_name, pc);
|
||||
}
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata);
|
||||
}
|
||||
|
||||
static void bootloader_check_wdt_reset(void)
|
||||
{
|
||||
int wdt_rst = 0;
|
||||
RESET_REASON rst_reas[2];
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
rst_reas[1] = rtc_get_reset_reason(1);
|
||||
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
if (rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET || rst_reas[1] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "APP CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
if (wdt_rst) {
|
||||
// if reset by WDT dump info from trace port
|
||||
wdt_reset_info_dump(0);
|
||||
wdt_reset_info_dump(1);
|
||||
}
|
||||
wdt_reset_cpu0_info_enable();
|
||||
}
|
||||
|
||||
void abort(void)
|
||||
{
|
||||
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
ets_printf("abort() was called at PC 0x%08x\r\n", (intptr_t)__builtin_return_address(0) - 3);
|
||||
#endif
|
||||
if (esp_cpu_in_ocd_debug_mode()) {
|
||||
__asm__("break 0,0");
|
||||
}
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t bootloader_init(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
// workaround for tensilica erratum572
|
||||
cpu_init_memctl();
|
||||
// protect memory region
|
||||
cpu_configure_region_protection();
|
||||
// check that static RAM is after the stack
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
assert(&_bss_start <= &_bss_end);
|
||||
assert(&_data_start <= &_data_end);
|
||||
int *sp = get_sp();
|
||||
assert(sp < &_bss_start);
|
||||
assert(sp < &_data_start);
|
||||
}
|
||||
#endif
|
||||
// clear bss section
|
||||
bootloader_clear_bss_section();
|
||||
// bootst up vddsdio
|
||||
bootloader_common_vddsdio_configure();
|
||||
// reset MMU
|
||||
bootloader_reset_mmu();
|
||||
// check rated CPU clock
|
||||
if ((ret = bootloader_check_rated_cpu_clock()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// config clock
|
||||
bootloader_clock_configure();
|
||||
// initialize uart console, from now on, we can use esp_log
|
||||
bootloader_init_uart_console();
|
||||
/* print 2nd bootloader banner */
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// read chip revision and check if it's compatible to bootloader
|
||||
if ((ret = bootloader_check_bootloader_validity()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// initialize spi flash
|
||||
if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// check whether a WDT reset happend
|
||||
bootloader_check_wdt_reset();
|
||||
// config WDT
|
||||
bootloader_config_wdt();
|
||||
// enable RNG early entropy source
|
||||
bootloader_enable_random();
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@@ -16,10 +16,9 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp32/rom/sha.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/hwcrypto_periph.h"
|
||||
#include "esp32/rom/ets_sys.h" // TO REMOVE
|
||||
|
||||
static uint32_t words_hashed;
|
||||
|
||||
@@ -28,7 +27,7 @@ static const size_t BLOCK_WORDS = (64 / sizeof(uint32_t));
|
||||
// Words in final SHA256 digest
|
||||
static const size_t DIGEST_WORDS = (32 / sizeof(uint32_t));
|
||||
|
||||
bootloader_sha256_handle_t bootloader_sha256_start(void)
|
||||
bootloader_sha256_handle_t bootloader_sha256_start()
|
||||
{
|
||||
// Enable SHA hardware
|
||||
ets_sha_enable();
|
||||
|
||||
@@ -37,8 +37,8 @@ static const char *TAG = "flash_encrypt";
|
||||
|
||||
/* Static functions for stages of flash encryption */
|
||||
static esp_err_t initialise_flash_encryption(void);
|
||||
static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis) __attribute__((unused));
|
||||
static esp_err_t encrypt_bootloader(void);
|
||||
static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis);
|
||||
static esp_err_t encrypt_bootloader();
|
||||
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions);
|
||||
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition);
|
||||
|
||||
@@ -60,14 +60,8 @@ esp_err_t esp_flash_encrypt_check_and_update(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
else {
|
||||
#ifndef CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
|
||||
/* Flash is not encrypted, so encrypt it! */
|
||||
return encrypt_flash_contents(flash_crypt_cnt, flash_crypt_wr_dis);
|
||||
#else
|
||||
ESP_LOGE(TAG, "flash encryption is not enabled, and SECURE_FLASH_REQUIRE_ALREADY_ENABLED "
|
||||
"is set, refusing to boot.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
#endif // CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +168,7 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry
|
||||
|
||||
/* If the last flash_crypt_cnt bit is burned or write-disabled, the
|
||||
device can't re-encrypt itself. */
|
||||
if (flash_crypt_wr_dis || flash_crypt_cnt == 0xFF) {
|
||||
if (flash_crypt_wr_dis) {
|
||||
ESP_LOGE(TAG, "Cannot re-encrypt data (FLASH_CRYPT_CNT 0x%02x write disabled %d", flash_crypt_cnt, flash_crypt_wr_dis);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -229,7 +223,7 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_bootloader(void)
|
||||
static esp_err_t encrypt_bootloader()
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t image_length;
|
||||
|
||||
@@ -95,7 +95,7 @@ static bool secure_boot_generate(uint32_t image_len){
|
||||
}
|
||||
|
||||
/* Burn values written to the efuse write registers */
|
||||
static inline void burn_efuses(void)
|
||||
static inline void burn_efuses()
|
||||
{
|
||||
esp_efuse_burn_new_values();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp32/rom/sha.h"
|
||||
#include "uECC.h"
|
||||
|
||||
|
||||
@@ -1,399 +0,0 @@
|
||||
// Copyright 2019 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 "sdkconfig.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
|
||||
#include "esp32s2beta/rom/cache.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#include "esp32s2beta/rom/uart.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "soc/assist_debug_reg.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/spi_periph.h"
|
||||
|
||||
static const char *TAG = "boot.esp32s2";
|
||||
|
||||
#define FLASH_CLK_IO SPI_CLK_GPIO_NUM
|
||||
#define FLASH_CS_IO SPI_CS0_GPIO_NUM
|
||||
#define FLASH_SPIQ_IO SPI_Q_GPIO_NUM
|
||||
#define FLASH_SPID_IO SPI_D_GPIO_NUM
|
||||
#define FLASH_SPIWP_IO SPI_WP_GPIO_NUM
|
||||
#define FLASH_SPIHD_IO SPI_HD_GPIO_NUM
|
||||
|
||||
void bootloader_configure_spi_pins(int drv)
|
||||
{
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
|
||||
gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
|
||||
//select pin function gpio
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIHD_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIWP_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPICS0_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIQ_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPID_U, PIN_FUNC_GPIO);
|
||||
// flash clock signal should come from IO MUX.
|
||||
// set drive ability for clock
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPICLK_U, FUNC_SPICLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
|
||||
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 || CONFIG_SPIRAM_TYPE_ESPPSRAM64
|
||||
uint32_t flash_id = g_rom_flashchip.device_id;
|
||||
if (flash_id == FLASH_ID_GD25LQ32C) {
|
||||
// Set drive ability for 1.8v flash in 80Mhz.
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIHD_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIWP_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICS0_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICLK_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIQ_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPID_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void bootloader_reset_mmu(void)
|
||||
{
|
||||
//ToDo: save the autoload value
|
||||
Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
Cache_MMU_Init();
|
||||
|
||||
/* normal ROM boot exits with DROM0 cache unmasked,
|
||||
but serial bootloader exits with it masked. */
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_ICACHE_CTRL1_REG, DPORT_PRO_ICACHE_MASK_DROM0);
|
||||
}
|
||||
|
||||
static void update_flash_config(const esp_image_header_t *bootloader_hdr)
|
||||
{
|
||||
uint32_t size;
|
||||
switch (bootloader_hdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
size = 1;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
size = 2;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
size = 4;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
size = 8;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
size = 16;
|
||||
break;
|
||||
default:
|
||||
size = 2;
|
||||
}
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
// Set flash chip size
|
||||
esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
|
||||
// TODO: set mode
|
||||
// TODO: set frequency
|
||||
Cache_Resume_ICache(autoload);
|
||||
}
|
||||
|
||||
static void print_flash_info(const esp_image_header_t *bootloader_hdr)
|
||||
{
|
||||
ESP_LOGD(TAG, "magic %02x", bootloader_hdr->magic);
|
||||
ESP_LOGD(TAG, "segments %02x", bootloader_hdr->segment_count);
|
||||
ESP_LOGD(TAG, "spi_mode %02x", bootloader_hdr->spi_mode);
|
||||
ESP_LOGD(TAG, "spi_speed %02x", bootloader_hdr->spi_speed);
|
||||
ESP_LOGD(TAG, "spi_size %02x", bootloader_hdr->spi_size);
|
||||
|
||||
const char *str;
|
||||
switch (bootloader_hdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
str = "40MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_26M:
|
||||
str = "26.7MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_20M:
|
||||
str = "20MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
str = "80MHz";
|
||||
break;
|
||||
default:
|
||||
str = "20MHz";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Speed : %s", str);
|
||||
|
||||
/* SPI mode could have been set to QIO during boot already,
|
||||
so test the SPI registers not the flash header */
|
||||
uint32_t spi_ctrl = REG_READ(SPI_MEM_CTRL_REG(0));
|
||||
if (spi_ctrl & SPI_MEM_FREAD_QIO) {
|
||||
str = "QIO";
|
||||
} else if (spi_ctrl & SPI_MEM_FREAD_QUAD) {
|
||||
str = "QOUT";
|
||||
} else if (spi_ctrl & SPI_MEM_FREAD_DIO) {
|
||||
str = "DIO";
|
||||
} else if (spi_ctrl & SPI_MEM_FREAD_DUAL) {
|
||||
str = "DOUT";
|
||||
} else if (spi_ctrl & SPI_MEM_FASTRD_MODE) {
|
||||
str = "FAST READ";
|
||||
} else {
|
||||
str = "SLOW READ";
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Mode : %s", str);
|
||||
|
||||
switch (bootloader_hdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
str = "1MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
str = "2MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
str = "4MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
str = "8MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
str = "16MB";
|
||||
break;
|
||||
default:
|
||||
str = "2MB";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Flash Size : %s", str);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR bootloader_init_flash_configure(void)
|
||||
{
|
||||
bootloader_flash_gpio_config(&bootloader_image_hdr);
|
||||
bootloader_flash_dummy_config(&bootloader_image_hdr);
|
||||
bootloader_flash_cs_timing_config();
|
||||
}
|
||||
|
||||
static esp_err_t bootloader_init_spi_flash(void)
|
||||
{
|
||||
bootloader_init_flash_configure();
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
|
||||
ESP_LOGE(TAG, "SPI flash pins are overridden. Enable CONFIG_SPI_FLASH_ROM_DRIVER_PATCH in menuconfig");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
#endif
|
||||
|
||||
print_flash_info(&bootloader_image_hdr);
|
||||
update_flash_config(&bootloader_image_hdr);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void bootloader_init_uart_console(void)
|
||||
{
|
||||
#if CONFIG_ESP_CONSOLE_UART_NONE
|
||||
ets_install_putc1(NULL);
|
||||
ets_install_putc2(NULL);
|
||||
#else // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
const int uart_num = CONFIG_ESP_CONSOLE_UART_NUM;
|
||||
|
||||
uartAttach();
|
||||
ets_install_uart_printf();
|
||||
|
||||
// Wait for UART FIFO to be empty.
|
||||
uart_tx_wait_idle(0);
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
// Some constants to make the following code less upper-case
|
||||
const int uart_tx_gpio = CONFIG_ESP_CONSOLE_UART_TX_GPIO;
|
||||
const int uart_rx_gpio = CONFIG_ESP_CONSOLE_UART_RX_GPIO;
|
||||
// Switch to the new UART (this just changes UART number used for
|
||||
// ets_printf in ROM code).
|
||||
uart_tx_switch(uart_num);
|
||||
// If console is attached to UART1 or if non-default pins are used,
|
||||
// need to reconfigure pins using GPIO matrix
|
||||
if (uart_num != 0 || uart_tx_gpio != 1 || uart_rx_gpio != 3) {
|
||||
// Change pin mode for GPIO1/3 from UART to GPIO
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_GPIO3);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_GPIO1);
|
||||
// Route GPIO signals to/from pins
|
||||
// (arrays should be optimized away by the compiler)
|
||||
const uint32_t tx_idx_list[3] = {U0TXD_OUT_IDX, U1TXD_OUT_IDX, U2TXD_OUT_IDX};
|
||||
const uint32_t rx_idx_list[3] = {U0RXD_IN_IDX, U1RXD_IN_IDX, U2RXD_IN_IDX};
|
||||
const uint32_t uart_reset[3] = {DPORT_UART_RST, DPORT_UART1_RST, DPORT_UART2_RST};
|
||||
const uint32_t tx_idx = tx_idx_list[uart_num];
|
||||
const uint32_t rx_idx = rx_idx_list[uart_num];
|
||||
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
|
||||
gpio_pad_pullup(uart_rx_gpio);
|
||||
|
||||
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
|
||||
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
|
||||
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
}
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
|
||||
// Set configured UART console baud rate
|
||||
const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE;
|
||||
uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
|
||||
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
}
|
||||
|
||||
static void wdt_reset_cpu0_info_enable(void)
|
||||
{
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_ASSIST_DEBUG);
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_ASSIST_DEBUG);
|
||||
REG_WRITE(ASSIST_DEBUG_PRO_PDEBUGENABLE, 1);
|
||||
REG_WRITE(ASSIST_DEBUG_PRO_RCD_RECORDING, 1);
|
||||
}
|
||||
|
||||
static void wdt_reset_info_dump(int cpu)
|
||||
{
|
||||
uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0,
|
||||
lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
|
||||
const char *cpu_name = cpu ? "APP" : "PRO";
|
||||
|
||||
stat = 0xdeadbeef;
|
||||
pid = 0;
|
||||
inst = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGINST);
|
||||
dstat = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGSTATUS);
|
||||
data = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGDATA);
|
||||
pc = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGPC);
|
||||
lsstat = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0STAT);
|
||||
lsaddr = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0ADDR);
|
||||
lsdata = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0DATA);
|
||||
|
||||
if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 &&
|
||||
DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x", cpu_name, pc);
|
||||
}
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata);
|
||||
}
|
||||
|
||||
static void bootloader_check_wdt_reset(void)
|
||||
{
|
||||
int wdt_rst = 0;
|
||||
RESET_REASON rst_reas[2];
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[0] == TG0WDT_CPU_RESET || rst_reas[0] == TG1WDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
if (wdt_rst) {
|
||||
// if reset by WDT dump info from trace port
|
||||
wdt_reset_info_dump(0);
|
||||
}
|
||||
wdt_reset_cpu0_info_enable();
|
||||
}
|
||||
|
||||
void abort(void)
|
||||
{
|
||||
#if !CONFIG_ESP32S2_PANIC_SILENT_REBOOT
|
||||
ets_printf("abort() was called at PC 0x%08x\r\n", (intptr_t)__builtin_return_address(0) - 3);
|
||||
#endif
|
||||
if (esp_cpu_in_ocd_debug_mode()) {
|
||||
__asm__("break 0,0");
|
||||
}
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t bootloader_init(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
// protect memory region
|
||||
cpu_configure_region_protection();
|
||||
/* check that static RAM is after the stack */
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
assert(&_bss_start <= &_bss_end);
|
||||
assert(&_data_start <= &_data_end);
|
||||
}
|
||||
#endif
|
||||
// clear bss section
|
||||
bootloader_clear_bss_section();
|
||||
// reset MMU
|
||||
bootloader_reset_mmu();
|
||||
// config clock
|
||||
bootloader_clock_configure();
|
||||
// initialize uart console, from now on, we can use esp_log
|
||||
bootloader_init_uart_console();
|
||||
/* print 2nd bootloader banner */
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// read chip revision and check if it's compatible to bootloader
|
||||
if ((ret = bootloader_check_bootloader_validity()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// initialize spi flash
|
||||
if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// check whether a WDT reset happend
|
||||
bootloader_check_wdt_reset();
|
||||
// config WDT
|
||||
bootloader_config_wdt();
|
||||
// enable RNG early entropy source
|
||||
bootloader_enable_random();
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
// Copyright 2017 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 "bootloader_sha.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp32s2beta/rom/sha.h"
|
||||
|
||||
static SHA_CTX ctx;
|
||||
|
||||
// Words per SHA256 block
|
||||
// static const size_t BLOCK_WORDS = (64/sizeof(uint32_t));
|
||||
// Words in final SHA256 digest
|
||||
// static const size_t DIGEST_WORDS = (32/sizeof(uint32_t));
|
||||
|
||||
bootloader_sha256_handle_t bootloader_sha256_start()
|
||||
{
|
||||
// Enable SHA hardware
|
||||
ets_sha_enable();
|
||||
ets_sha_init(&ctx, SHA2_256);
|
||||
return &ctx; // Meaningless non-NULL value
|
||||
}
|
||||
|
||||
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
assert(data_len % 4 == 0);
|
||||
ets_sha_update(&ctx, data, data_len, false);
|
||||
}
|
||||
|
||||
void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
|
||||
if (digest == NULL) {
|
||||
bzero(&ctx, sizeof(ctx));
|
||||
return;
|
||||
}
|
||||
ets_sha_finish(&ctx, digest);
|
||||
}
|
||||
@@ -1,303 +0,0 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// 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 <strings.h>
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32s2beta/rom/secure_boot.h"
|
||||
#include "esp32s2beta/rom/cache.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
|
||||
static const char *TAG = "flash_encrypt";
|
||||
|
||||
/* Static functions for stages of flash encryption */
|
||||
static esp_err_t initialise_flash_encryption(void);
|
||||
static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis);
|
||||
static esp_err_t encrypt_bootloader(void);
|
||||
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions);
|
||||
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition);
|
||||
|
||||
esp_err_t esp_flash_encrypt_check_and_update(void)
|
||||
{
|
||||
// TODO: not clear why this is read from DATA1 and written to PGM_DATA2
|
||||
uint32_t cnt = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG, EFUSE_SPI_BOOT_CRYPT_CNT);
|
||||
ESP_LOGV(TAG, "SPI_BOOT_CRYPT_CNT 0x%x", cnt);
|
||||
|
||||
bool flash_crypt_wr_dis = false; // TODO: check if CRYPT_CNT is write disabled
|
||||
|
||||
_Static_assert(EFUSE_SPI_BOOT_CRYPT_CNT == 0x7, "assuming CRYPT_CNT is only 3 bits wide");
|
||||
|
||||
if (cnt == 1 || cnt == 3 || cnt == 7) {
|
||||
/* Flash is already encrypted */
|
||||
int left;
|
||||
if (cnt == 7 /* || disabled */) {
|
||||
left = 0;
|
||||
} else if (cnt == 3) {
|
||||
left = 1;
|
||||
} else {
|
||||
left = 2;
|
||||
}
|
||||
ESP_LOGI(TAG, "flash encryption is enabled (%d plaintext flashes left)", left);
|
||||
return ESP_OK;
|
||||
}
|
||||
else {
|
||||
/* Flash is not encrypted, so encrypt it! */
|
||||
return encrypt_flash_contents(cnt, flash_crypt_wr_dis);
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t initialise_flash_encryption(void)
|
||||
{
|
||||
/* Before first flash encryption pass, need to initialise key & crypto config */
|
||||
|
||||
/* Find out if a key is already set */
|
||||
bool has_aes128 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, NULL);
|
||||
bool has_aes256_1 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, NULL);
|
||||
bool has_aes256_2 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, NULL);
|
||||
|
||||
bool has_key = has_aes128 || (has_aes256_1 && has_aes256_2);
|
||||
|
||||
if (!has_key && (has_aes256_1 || has_aes256_2)) {
|
||||
ESP_LOGE(TAG, "Invalid efuse key blocks: Both AES-256 key blocks must be set.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (has_key) {
|
||||
ESP_LOGI(TAG, "Using pre-existing key in efuse");
|
||||
|
||||
ESP_LOGE(TAG, "TODO: Check key is read & write protected"); // TODO
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Generating new flash encryption key...");
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_AES256
|
||||
const unsigned BLOCKS_NEEDED = 2;
|
||||
const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1;
|
||||
const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2;
|
||||
#else
|
||||
const unsigned BLOCKS_NEEDED = 1;
|
||||
const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY;
|
||||
const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY;
|
||||
#endif
|
||||
|
||||
if (ets_efuse_count_unused_key_blocks() < BLOCKS_NEEDED) {
|
||||
ESP_LOGE(TAG, "Not enough free efuse key blocks (need %d) to continue", BLOCKS_NEEDED);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
for(ets_efuse_purpose_t purpose = PURPOSE_START; purpose <= PURPOSE_END; purpose++) {
|
||||
uint32_t buf[8];
|
||||
bootloader_fill_random(buf, sizeof(buf));
|
||||
ets_efuse_block_t block = ets_efuse_find_unused_key_block();
|
||||
ESP_LOGD(TAG, "Writing ETS_EFUSE_BLOCK_KEY%d with purpose %d",
|
||||
block - ETS_EFUSE_BLOCK_KEY0, purpose);
|
||||
bootloader_debug_buffer(buf, sizeof(buf), "Key content");
|
||||
int r = ets_efuse_write_key(block, purpose, buf, sizeof(buf));
|
||||
bzero(buf, sizeof(buf));
|
||||
if (r != 0) {
|
||||
ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Key generation complete");
|
||||
}
|
||||
|
||||
ESP_LOGE(TAG, "TODO: burn remaining security protection bits"); // TODO
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Encrypt all flash data that should be encrypted */
|
||||
static esp_err_t encrypt_flash_contents(uint32_t spi_boot_crypt_cnt, bool flash_crypt_wr_dis)
|
||||
{
|
||||
esp_err_t err;
|
||||
esp_partition_info_t partition_table[ESP_PARTITION_TABLE_MAX_ENTRIES];
|
||||
int num_partitions;
|
||||
|
||||
/* If the last spi_boot_crypt_cnt bit is burned or write-disabled, the
|
||||
device can't re-encrypt itself. */
|
||||
if (flash_crypt_wr_dis || spi_boot_crypt_cnt == EFUSE_SPI_BOOT_CRYPT_CNT) {
|
||||
ESP_LOGE(TAG, "Cannot re-encrypt data (SPI_BOOT_CRYPT_CNT 0x%02x write disabled %d", spi_boot_crypt_cnt, flash_crypt_wr_dis);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (spi_boot_crypt_cnt == 0) {
|
||||
/* Very first flash of encrypted data: generate keys, etc. */
|
||||
err = initialise_flash_encryption();
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = encrypt_bootloader();
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = encrypt_and_load_partition_table(partition_table, &num_partitions);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Now iterate the just-loaded partition table, looking for entries to encrypt
|
||||
*/
|
||||
|
||||
/* Go through each partition and encrypt if necessary */
|
||||
for (int i = 0; i < num_partitions; i++) {
|
||||
err = encrypt_partition(i, &partition_table[i]);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "All flash regions checked for encryption pass");
|
||||
|
||||
/* Set least significant 0-bit in spi_boot_crypt_cnt */
|
||||
int ffs_inv = __builtin_ffs((~spi_boot_crypt_cnt) & 0x7);
|
||||
/* ffs_inv shouldn't be zero, as zero implies spi_boot_crypt_cnt == 0xFF */
|
||||
uint32_t new_spi_boot_crypt_cnt = spi_boot_crypt_cnt + (1 << (ffs_inv - 1));
|
||||
ESP_LOGD(TAG, "SPI_BOOT_CRYPT_CNT 0x%x -> 0x%x", spi_boot_crypt_cnt, new_spi_boot_crypt_cnt);
|
||||
|
||||
ets_efuse_clear_program_registers();
|
||||
REG_SET_FIELD(EFUSE_PGM_DATA2_REG, EFUSE_SPI_BOOT_CRYPT_CNT, new_spi_boot_crypt_cnt);
|
||||
ets_efuse_program(ETS_EFUSE_BLOCK0);
|
||||
|
||||
ESP_LOGI(TAG, "Flash encryption completed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_bootloader(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t image_length;
|
||||
/* 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...");
|
||||
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;
|
||||
}
|
||||
|
||||
if (esp_secure_boot_enabled()) {
|
||||
// TODO: anything different for secure boot?
|
||||
}
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG, "no valid bootloader was found");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions)
|
||||
{
|
||||
esp_err_t err;
|
||||
/* Check for plaintext partition table */
|
||||
err = bootloader_flash_read(ESP_PARTITION_TABLE_OFFSET, partition_table, ESP_PARTITION_TABLE_MAX_LEN, false);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to read partition table data");
|
||||
return err;
|
||||
}
|
||||
if (esp_partition_table_verify(partition_table, false, num_partitions) == ESP_OK) {
|
||||
ESP_LOGD(TAG, "partition table is plaintext. Encrypting...");
|
||||
esp_err_t err = esp_flash_encrypt_region(ESP_PARTITION_TABLE_OFFSET,
|
||||
FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt partition table in place. %x", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG, "Failed to read partition table data - not plaintext?");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* Valid partition table loded */
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition)
|
||||
{
|
||||
esp_err_t err;
|
||||
bool should_encrypt = (partition->flags & PART_FLAG_ENCRYPTED);
|
||||
|
||||
if (partition->type == PART_TYPE_APP) {
|
||||
/* check if the partition holds a valid unencrypted app */
|
||||
esp_image_metadata_t data_ignored;
|
||||
err = esp_image_verify(ESP_IMAGE_VERIFY,
|
||||
&partition->pos,
|
||||
&data_ignored);
|
||||
should_encrypt = (err == ESP_OK);
|
||||
} else if (partition->type == PART_TYPE_DATA && partition->subtype == PART_SUBTYPE_DATA_OTA) {
|
||||
/* check if we have ota data partition and the partition should be encrypted unconditionally */
|
||||
should_encrypt = true;
|
||||
}
|
||||
|
||||
if (!should_encrypt) {
|
||||
return ESP_OK;
|
||||
}
|
||||
else {
|
||||
/* should_encrypt */
|
||||
ESP_LOGI(TAG, "Encrypting partition %d at offset 0x%x (length 0x%x)...", index, partition->pos.offset, partition->pos.size);
|
||||
|
||||
err = esp_flash_encrypt_region(partition->pos.offset, partition->pos.size);
|
||||
ESP_LOGI(TAG, "Done encrypting");
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt partition %d", index);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t buf[FLASH_SECTOR_SIZE / sizeof(uint32_t)];
|
||||
|
||||
if (src_addr % FLASH_SECTOR_SIZE != 0) {
|
||||
ESP_LOGE(TAG, "esp_flash_encrypt_region bad src_addr 0x%x",src_addr);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < data_length; i += FLASH_SECTOR_SIZE) {
|
||||
uint32_t sec_start = i + src_addr;
|
||||
err = bootloader_flash_read(sec_start, buf, FLASH_SECTOR_SIZE, false);
|
||||
if (err != ESP_OK) {
|
||||
goto flash_failed;
|
||||
}
|
||||
err = bootloader_flash_erase_sector(sec_start / FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
goto flash_failed;
|
||||
}
|
||||
err = bootloader_flash_write(sec_start, buf, FLASH_SECTOR_SIZE, true);
|
||||
if (err != ESP_OK) {
|
||||
goto flash_failed;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
|
||||
flash_failed:
|
||||
ESP_LOGE(TAG, "flash operation failed: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
// Copyright 2015-2018 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 "esp_secure_boot.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32s2beta/rom/secure_boot.h"
|
||||
|
||||
#define TAG "secure_boot"
|
||||
|
||||
esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
{
|
||||
uint8_t hash[32];
|
||||
|
||||
if (ets_efuse_secure_boot_enabled())
|
||||
{
|
||||
ESP_LOGI(TAG, "secure boot is already enabled, continuing..");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Verifying bootloader signature...\n");
|
||||
int r = ets_secure_boot_verify_bootloader(hash, false);
|
||||
if (r != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to verify bootloader signature");
|
||||
return r;
|
||||
}
|
||||
|
||||
ets_efuse_clear_program_registers();
|
||||
REG_SET_BIT(EFUSE_PGM_DATA3_REG, EFUSE_SECURE_BOOT_EN);
|
||||
ets_efuse_program(ETS_EFUSE_BLOCK0);
|
||||
|
||||
assert(ets_efuse_secure_boot_enabled());
|
||||
ESP_LOGI(TAG, "Secure boot permanently enabled");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// 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 "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp32s2beta/rom/secure_boot.h"
|
||||
|
||||
static const char* TAG = "secure_boot";
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
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];
|
||||
const uint8_t *data;
|
||||
|
||||
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
|
||||
|
||||
if ((src_addr + length) % 4096 != 0) {
|
||||
ESP_LOGE(TAG, "addr 0x%x length 0x%x doesn't end on a sector boundary", src_addr, length);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
data = bootloader_mmap(src_addr, length + sizeof(struct ets_secure_boot_sig_block));
|
||||
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;
|
||||
}
|
||||
|
||||
// Calculate digest of main image
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
bootloader_sha256_handle_t handle = bootloader_sha256_start();
|
||||
bootloader_sha256_data(handle, data, length);
|
||||
bootloader_sha256_finish(handle, digest);
|
||||
#else
|
||||
/* Use thread-safe esp-idf SHA function */
|
||||
esp_sha(SHA2_256, data, length, digest);
|
||||
#endif
|
||||
|
||||
int r = ets_secure_boot_read_key_digests(&trusted_keys);
|
||||
|
||||
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);
|
||||
}
|
||||
bootloader_munmap(data);
|
||||
|
||||
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
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, image_digest, &trusted_keys);
|
||||
}
|
||||
|
||||
bootloader_munmap(sig);
|
||||
|
||||
return (r == 0) ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
@@ -13,6 +13,8 @@
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <esp32/rom/rtc.h>
|
||||
#include <soc/cpu.h>
|
||||
#include <bootloader_utility.h>
|
||||
#include <esp_secure_boot.h>
|
||||
@@ -22,14 +24,6 @@
|
||||
#include <bootloader_random.h>
|
||||
#include <bootloader_sha.h>
|
||||
#include "bootloader_util.h"
|
||||
#include "bootloader_common.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include <esp32/rom/rtc.h>
|
||||
#include <esp32/rom/secure_boot.h>
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include <esp32s2beta/rom/rtc.h>
|
||||
#include <esp32s2beta/rom/secure_boot.h>
|
||||
#endif
|
||||
|
||||
/* Checking signatures as part of verifying images is necessary:
|
||||
- Always if secure boot is enabled
|
||||
@@ -103,17 +97,14 @@ static esp_err_t __attribute__((unused)) verify_simple_hash(bootloader_sha256_ha
|
||||
static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data)
|
||||
{
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
bool do_load = (mode == ESP_IMAGE_LOAD) || (mode == ESP_IMAGE_LOAD_NO_VALIDATE);
|
||||
bool do_verify = (mode == ESP_IMAGE_LOAD) || (mode == ESP_IMAGE_VERIFY) || (mode == ESP_IMAGE_VERIFY_SILENT);
|
||||
bool do_load = (mode == ESP_IMAGE_LOAD);
|
||||
#else
|
||||
bool do_load = false; // Can't load the image in app mode
|
||||
bool do_verify = true; // In app mode is avalible only verify mode
|
||||
bool do_load = false; // Can't load the image in app mode
|
||||
#endif
|
||||
bool silent = (mode == ESP_IMAGE_VERIFY_SILENT);
|
||||
bool silent = (mode == ESP_IMAGE_VERIFY_SILENT);
|
||||
esp_err_t err = ESP_OK;
|
||||
// checksum the image a word at a time. This shaves 30-40ms per MB of image size
|
||||
uint32_t checksum_word = ESP_ROM_CHECKSUM_INITIAL;
|
||||
uint32_t *checksum = NULL;
|
||||
bootloader_sha256_handle_t sha_handle = NULL;
|
||||
|
||||
if (data == NULL || part == NULL) {
|
||||
@@ -134,45 +125,41 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (do_verify) {
|
||||
checksum = &checksum_word;
|
||||
|
||||
// Calculate SHA-256 of image if secure boot is on, or if image has a hash appended
|
||||
// Calculate SHA-256 of image if secure boot is on, or if image has a hash appended
|
||||
#ifdef SECURE_BOOT_CHECK_SIGNATURE
|
||||
if (1) {
|
||||
if (1) {
|
||||
#else
|
||||
if (data->image.hash_appended) {
|
||||
if (data->image.hash_appended) {
|
||||
#endif
|
||||
sha_handle = bootloader_sha256_start();
|
||||
if (sha_handle == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
bootloader_sha256_data(sha_handle, &data->image, sizeof(esp_image_header_t));
|
||||
sha_handle = bootloader_sha256_start();
|
||||
if (sha_handle == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
bootloader_sha256_data(sha_handle, &data->image, sizeof(esp_image_header_t));
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "image header: 0x%02x 0x%02x 0x%02x 0x%02x %08x",
|
||||
data->image.magic,
|
||||
data->image.segment_count,
|
||||
data->image.spi_mode,
|
||||
data->image.spi_size,
|
||||
data->image.entry_addr);
|
||||
ESP_LOGD(TAG, "image header: 0x%02x 0x%02x 0x%02x 0x%02x %08x",
|
||||
data->image.magic,
|
||||
data->image.segment_count,
|
||||
data->image.spi_mode,
|
||||
data->image.spi_size,
|
||||
data->image.entry_addr);
|
||||
|
||||
err = verify_image_header(data->start_addr, &data->image, silent);
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
err = verify_image_header(data->start_addr, &data->image, silent);
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (data->image.segment_count > ESP_IMAGE_MAX_SEGMENTS) {
|
||||
FAIL_LOAD("image at 0x%x segment count %d exceeds max %d",
|
||||
data->start_addr, data->image.segment_count, ESP_IMAGE_MAX_SEGMENTS);
|
||||
}
|
||||
} // if (do_verify)
|
||||
if (data->image.segment_count > ESP_IMAGE_MAX_SEGMENTS) {
|
||||
FAIL_LOAD("image at 0x%x segment count %d exceeds max %d",
|
||||
data->start_addr, data->image.segment_count, ESP_IMAGE_MAX_SEGMENTS);
|
||||
}
|
||||
|
||||
uint32_t next_addr = data->start_addr + sizeof(esp_image_header_t);
|
||||
for (int i = 0; i < data->image.segment_count; i++) {
|
||||
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);
|
||||
err = process_segment(i, next_addr, header, silent, do_load, sha_handle, &checksum_word);
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
@@ -181,81 +168,69 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
next_addr += header->data_len;
|
||||
}
|
||||
|
||||
if (do_verify) {
|
||||
// Segments all loaded, verify length
|
||||
uint32_t end_addr = next_addr;
|
||||
if (end_addr < data->start_addr) {
|
||||
FAIL_LOAD("image offset has wrapped");
|
||||
// Segments all loaded, verify length
|
||||
uint32_t end_addr = next_addr;
|
||||
if (end_addr < data->start_addr) {
|
||||
FAIL_LOAD("image offset has wrapped");
|
||||
}
|
||||
|
||||
data->image_len = end_addr - data->start_addr;
|
||||
ESP_LOGV(TAG, "image start 0x%08x end of last section 0x%08x", data->start_addr, end_addr);
|
||||
if (!esp_cpu_in_ocd_debug_mode()) {
|
||||
err = verify_checksum(sha_handle, checksum_word, data);
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (data->image_len > part->size) {
|
||||
FAIL_LOAD("Image length %d doesn't fit in partition length %d", data->image_len, part->size);
|
||||
}
|
||||
|
||||
data->image_len = end_addr - data->start_addr;
|
||||
ESP_LOGV(TAG, "image start 0x%08x end of last section 0x%08x", data->start_addr, end_addr);
|
||||
if (NULL != checksum && !esp_cpu_in_ocd_debug_mode()) {
|
||||
err = verify_checksum(sha_handle, checksum_word, data);
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 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);
|
||||
#endif
|
||||
|
||||
if (verify_sha) {
|
||||
if (data->image_len > part->size) {
|
||||
FAIL_LOAD("Image length %d doesn't fit in partition length %d", data->image_len, part->size);
|
||||
}
|
||||
bool is_bootloader = (data->start_addr == ESP_BOOTLOADER_OFFSET);
|
||||
/* For secure boot, we don't verify signature on bootloaders.
|
||||
|
||||
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.
|
||||
*/
|
||||
if (!is_bootloader) {
|
||||
#ifdef SECURE_BOOT_CHECK_SIGNATURE
|
||||
// secure boot images have a signature appended
|
||||
err = verify_secure_boot_signature(sha_handle, data);
|
||||
// secure boot images have a signature appended
|
||||
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);
|
||||
sha_handle = NULL; // calling verify_simple_hash finishes sha_handle
|
||||
}
|
||||
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||
} else { // verify_sha
|
||||
// bootloader may still have a sha256 digest handle open
|
||||
if (sha_handle != NULL) {
|
||||
bootloader_sha256_finish(sha_handle, NULL);
|
||||
}
|
||||
sha_handle = NULL;
|
||||
} //verify_sha
|
||||
|
||||
// Separately, if there's a hash appended to the image then copy it out to the data->image_digest field
|
||||
if (data->image.hash_appended) {
|
||||
const void *hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN);
|
||||
if (hash == NULL) {
|
||||
err = ESP_FAIL;
|
||||
goto err;
|
||||
}
|
||||
memcpy(data->image_digest, hash, HASH_LEN);
|
||||
bootloader_munmap(hash);
|
||||
// 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);
|
||||
}
|
||||
} // do_verify
|
||||
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||
} else { // is_bootloader
|
||||
// bootloader may still have a sha256 digest handle open
|
||||
if (sha_handle != NULL) {
|
||||
bootloader_sha256_finish(sha_handle, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (data->image.hash_appended) {
|
||||
const void *hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN);
|
||||
if (hash == NULL) {
|
||||
err = ESP_FAIL;
|
||||
goto err;
|
||||
}
|
||||
memcpy(data->image_digest, hash, HASH_LEN);
|
||||
bootloader_munmap(hash);
|
||||
}
|
||||
|
||||
sha_handle = NULL;
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
if (do_load && ram_obfs_value[0] != 0 && ram_obfs_value[1] != 0) { // Need to deobfuscate RAM
|
||||
if (do_load) { // 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)) {
|
||||
uint32_t *loaded = (uint32_t *)load_addr;
|
||||
for (int j = 0; j < data->segments[i].data_len / sizeof(uint32_t); j++) {
|
||||
for (int j = 0; j < data->segments[i].data_len/sizeof(uint32_t); j++) {
|
||||
loaded[j] ^= (j & 1) ? ram_obfs_value[0] : ram_obfs_value[1];
|
||||
}
|
||||
}
|
||||
@@ -266,9 +241,9 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
// Success!
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
err:
|
||||
if (err == ESP_OK) {
|
||||
err = ESP_ERR_IMAGE_INVALID;
|
||||
err = ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
if (sha_handle != NULL) {
|
||||
// Need to finish the hash process to free the handle
|
||||
@@ -277,7 +252,7 @@ err:
|
||||
// Prevent invalid/incomplete data leaking out
|
||||
bzero(data, sizeof(esp_image_metadata_t));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t bootloader_load_image(const esp_partition_pos_t *part, esp_image_metadata_t *data)
|
||||
{
|
||||
@@ -288,20 +263,13 @@ esp_err_t bootloader_load_image(const esp_partition_pos_t *part, esp_image_metad
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t bootloader_load_image_no_verify(const esp_partition_pos_t *part, esp_image_metadata_t *data)
|
||||
{
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
return image_load(ESP_IMAGE_LOAD_NO_VALIDATE, part, data);
|
||||
#else
|
||||
return ESP_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data)
|
||||
{
|
||||
return image_load(mode, part, data);
|
||||
}
|
||||
|
||||
esp_err_t esp_image_load(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data) __attribute__((alias("esp_image_verify")));
|
||||
|
||||
static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t *image, bool silent)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
@@ -323,16 +291,6 @@ static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t
|
||||
ESP_LOGW(TAG, "image at 0x%x has invalid SPI size %d", src_addr, image->spi_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (err == ESP_OK) {
|
||||
// Checking the chip revision header *will* print a bunch of other info
|
||||
// regardless of silent setting as this may be important, but don't bother checking it
|
||||
// if it looks like the app partition is erased or otherwise garbage
|
||||
if (bootloader_common_check_chip_validity(image, ESP_IMAGE_APPLICATION) != ESP_OK) {
|
||||
err = ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -372,7 +330,7 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
|
||||
ESP_LOGI(TAG, "segment %d: paddr=0x%08x vaddr=0x%08x size=0x%05x (%6d) %s",
|
||||
index, data_addr, load_addr,
|
||||
data_len, data_len,
|
||||
(do_load) ? "load" : (is_mapping) ? "map" : "");
|
||||
(do_load)?"load":(is_mapping)?"map":"");
|
||||
}
|
||||
|
||||
|
||||
@@ -380,7 +338,7 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
|
||||
/* Before loading segment, check it doesn't clobber bootloader RAM. */
|
||||
if (do_load) {
|
||||
const intptr_t load_end = load_addr + data_len;
|
||||
if (load_end < (intptr_t) SOC_DRAM_HIGH) {
|
||||
if (load_end <= (intptr_t) SOC_DIRAM_DRAM_HIGH) {
|
||||
/* Writing to DRAM */
|
||||
intptr_t sp = (intptr_t)get_sp();
|
||||
if (load_end > sp - STACK_LOAD_HEADROOM) {
|
||||
@@ -401,7 +359,7 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
|
||||
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)) {
|
||||
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;
|
||||
@@ -438,26 +396,13 @@ err:
|
||||
|
||||
static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, uint32_t data_len, bool do_load, bootloader_sha256_handle_t sha_handle, uint32_t *checksum)
|
||||
{
|
||||
// If we are not loading, and the checksum is empty, skip processing this
|
||||
// segment for data
|
||||
if(!do_load && checksum == NULL) {
|
||||
ESP_LOGD(TAG, "skipping checksum for segment");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
const uint32_t *data = (const uint32_t *)bootloader_mmap(data_addr, data_len);
|
||||
if (!data) {
|
||||
if(!data) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed",
|
||||
data_addr, data_len);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (checksum == NULL && sha_handle == NULL) {
|
||||
memcpy((void *)load_addr, data, data_len);
|
||||
bootloader_munmap(data);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
// Set up the obfuscation value to use for loading
|
||||
while (ram_obfs_value[0] == 0 || ram_obfs_value[1] == 0) {
|
||||
@@ -469,11 +414,9 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui
|
||||
const uint32_t *src = data;
|
||||
|
||||
for (int i = 0; i < data_len; i += 4) {
|
||||
int w_i = i / 4; // Word index
|
||||
int w_i = i/4; // Word index
|
||||
uint32_t w = src[w_i];
|
||||
if (checksum != NULL) {
|
||||
*checksum ^= w;
|
||||
}
|
||||
*checksum ^= w;
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
if (do_load) {
|
||||
dest[w_i] = w ^ ((w_i & 1) ? ram_obfs_value[0] : ram_obfs_value[1]);
|
||||
@@ -498,7 +441,7 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui
|
||||
static esp_err_t verify_segment_header(int index, const esp_image_segment_header_t *segment, uint32_t segment_data_offs, bool silent)
|
||||
{
|
||||
if ((segment->data_len & 3) != 0
|
||||
|| segment->data_len >= SIXTEEN_MB) {
|
||||
|| segment->data_len >= SIXTEEN_MB) {
|
||||
if (!silent) {
|
||||
ESP_LOGE(TAG, "invalid segment length 0x%x", segment->data_len);
|
||||
}
|
||||
@@ -514,7 +457,7 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
|
||||
ESP_LOGV(TAG, "segment %d map_segment %d segment_data_offs 0x%x load_addr 0x%x",
|
||||
index, map_segment, segment_data_offs, load_addr);
|
||||
if (map_segment
|
||||
&& ((segment_data_offs % SPI_FLASH_MMU_PAGE_SIZE) != (load_addr % SPI_FLASH_MMU_PAGE_SIZE))) {
|
||||
&& ((segment_data_offs % SPI_FLASH_MMU_PAGE_SIZE) != (load_addr % SPI_FLASH_MMU_PAGE_SIZE))) {
|
||||
if (!silent) {
|
||||
ESP_LOGE(TAG, "Segment %d load address 0x%08x, doesn't match data 0x%08x",
|
||||
index, load_addr, segment_data_offs);
|
||||
@@ -528,7 +471,7 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
|
||||
static bool should_map(uint32_t load_addr)
|
||||
{
|
||||
return (load_addr >= SOC_IROM_LOW && load_addr < SOC_IROM_HIGH)
|
||||
|| (load_addr >= SOC_DROM_LOW && load_addr < SOC_DROM_HIGH);
|
||||
|| (load_addr >= SOC_DROM_LOW && load_addr < SOC_DROM_HIGH);
|
||||
}
|
||||
|
||||
static bool should_load(uint32_t load_addr)
|
||||
@@ -551,15 +494,15 @@ static bool should_load(uint32_t load_addr)
|
||||
|
||||
if (!load_rtc_memory) {
|
||||
if (load_addr >= SOC_RTC_IRAM_LOW && load_addr < SOC_RTC_IRAM_HIGH) {
|
||||
ESP_LOGD(TAG, "Skipping RTC fast memory segment at 0x%08x", load_addr);
|
||||
ESP_LOGD(TAG, "Skipping RTC fast memory segment at 0x%08x\n", load_addr);
|
||||
return false;
|
||||
}
|
||||
if (load_addr >= SOC_RTC_DRAM_LOW && load_addr < SOC_RTC_DRAM_HIGH) {
|
||||
ESP_LOGD(TAG, "Skipping RTC fast memory segment at 0x%08x", load_addr);
|
||||
ESP_LOGD(TAG, "Skipping RTC fast memory segment at 0x%08x\n", load_addr);
|
||||
return false;
|
||||
}
|
||||
if (load_addr >= SOC_RTC_DATA_LOW && load_addr < SOC_RTC_DATA_HIGH) {
|
||||
ESP_LOGD(TAG, "Skipping RTC slow memory segment at 0x%08x", load_addr);
|
||||
ESP_LOGD(TAG, "Skipping RTC slow memory segment at 0x%08x\n", load_addr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -587,8 +530,8 @@ esp_err_t esp_image_verify_bootloader_data(esp_image_metadata_t *data)
|
||||
.size = ESP_PARTITION_TABLE_OFFSET - ESP_BOOTLOADER_OFFSET,
|
||||
};
|
||||
return esp_image_verify(ESP_IMAGE_VERIFY,
|
||||
&bootloader_part,
|
||||
data);
|
||||
&bootloader_part,
|
||||
data);
|
||||
}
|
||||
|
||||
|
||||
@@ -603,9 +546,9 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t
|
||||
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)
|
||||
^ (checksum_word >> 16)
|
||||
^ (checksum_word >> 8)
|
||||
^ (checksum_word >> 0);
|
||||
^ (checksum_word >> 16)
|
||||
^ (checksum_word >> 8)
|
||||
^ (checksum_word >> 0);
|
||||
if (err != ESP_OK || checksum != calc) {
|
||||
ESP_LOGE(TAG, "Checksum failed. Calculated 0x%x read 0x%x", checksum, calc);
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
@@ -623,36 +566,26 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void debug_log_hash(const uint8_t *image_hash, const char *caption);
|
||||
|
||||
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data)
|
||||
{
|
||||
uint8_t image_hash[HASH_LEN] = { 0 };
|
||||
uint32_t end = data->start_addr + data->image_len;
|
||||
|
||||
ESP_LOGI(TAG, "Verifying image signature...");
|
||||
|
||||
// For secure boot, we calculate the signature hash over the whole file, which includes any "simple" hash
|
||||
// appended to the image for corruption detection
|
||||
if (data->image.hash_appended) {
|
||||
const void *simple_hash = bootloader_mmap(end - HASH_LEN, HASH_LEN);
|
||||
const void *simple_hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN);
|
||||
bootloader_sha256_data(sha_handle, simple_hash, HASH_LEN);
|
||||
bootloader_munmap(simple_hash);
|
||||
}
|
||||
|
||||
#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 += pad_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
bootloader_sha256_finish(sha_handle, image_hash);
|
||||
|
||||
// Log the hash for debugging
|
||||
bootloader_debug_buffer(image_hash, HASH_LEN, "Calculated secure boot hash");
|
||||
debug_log_hash(image_hash, "Calculated secure boot hash");
|
||||
|
||||
// Use hash to verify signature block
|
||||
const esp_secure_boot_sig_block_t *sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t));
|
||||
@@ -677,11 +610,6 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -691,13 +619,13 @@ static esp_err_t verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_i
|
||||
bootloader_sha256_finish(sha_handle, image_hash);
|
||||
|
||||
// Log the hash for debugging
|
||||
bootloader_debug_buffer(image_hash, HASH_LEN, "Calculated hash");
|
||||
debug_log_hash(image_hash, "Calculated hash");
|
||||
|
||||
// Simple hash for verification only
|
||||
const void *hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN);
|
||||
if (memcmp(hash, image_hash, HASH_LEN) != 0) {
|
||||
ESP_LOGE(TAG, "Image hash failed - image is corrupt");
|
||||
bootloader_debug_buffer(hash, HASH_LEN, "Expected hash");
|
||||
debug_log_hash(hash, "Expected hash");
|
||||
bootloader_munmap(hash);
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
@@ -705,3 +633,14 @@ static esp_err_t verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_i
|
||||
bootloader_munmap(hash);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Log a hash as a hex string
|
||||
static void debug_log_hash(const uint8_t *image_hash, const char *label)
|
||||
{
|
||||
#if BOOT_LOG_LEVEL >= LOG_LEVEL_DEBUG
|
||||
char hash_print[HASH_LEN * 2 + 1];
|
||||
hash_print[HASH_LEN * 2] = 0;
|
||||
bootloader_sha256_hex_to_str(hash_print, image_hash, HASH_LEN);
|
||||
ESP_LOGD(TAG, "%s: %s", label, hash_print);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -13,53 +13,11 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <strings.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_efuse_table.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_secure_boot.h"
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
static const char *TAG = "flash_encrypt";
|
||||
|
||||
void esp_flash_encryption_init_checks()
|
||||
{
|
||||
esp_flash_enc_mode_t mode;
|
||||
|
||||
// First check is: if Release mode flash encryption & secure boot are enabled then
|
||||
// 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_ENABLED
|
||||
if (esp_secure_boot_enabled() && esp_flash_encryption_enabled()) {
|
||||
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_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_ENABLED
|
||||
#endif // CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
|
||||
// Second check is to print a warning or error if the current running flash encryption mode
|
||||
// doesn't match the expectation from project config (due to mismatched bootloader and app, probably)
|
||||
mode = esp_get_flash_encryption_mode();
|
||||
if (mode == ESP_FLASH_ENC_MODE_DEVELOPMENT) {
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
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_EARLY_LOGW(TAG, "Flash encryption mode is DEVELOPMENT (not secure)");
|
||||
#endif
|
||||
} else if (mode == ESP_FLASH_ENC_MODE_RELEASE) {
|
||||
ESP_EARLY_LOGI(TAG, "Flash encryption mode is RELEASE");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void esp_flash_write_protect_crypt_cnt(void)
|
||||
void esp_flash_write_protect_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);
|
||||
@@ -68,7 +26,7 @@ void esp_flash_write_protect_crypt_cnt(void)
|
||||
}
|
||||
}
|
||||
|
||||
esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
|
||||
esp_flash_enc_mode_t esp_get_flash_encryption_mode()
|
||||
{
|
||||
uint8_t efuse_flash_crypt_cnt_wr_protected = 0;
|
||||
uint8_t dis_dl_enc = 0, dis_dl_dec = 0, dis_dl_cache = 0;
|
||||
|
||||
@@ -16,26 +16,14 @@
|
||||
#include "flash_qio_mode.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#include "soc/spi_mem_struct.h"
|
||||
#endif
|
||||
#include "soc/spi_struct.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/spi_periph.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.
|
||||
@@ -51,11 +39,10 @@
|
||||
|
||||
static const char *TAG = "qio_mode";
|
||||
|
||||
typedef unsigned (*read_status_fn_t)(void);
|
||||
typedef unsigned (*read_status_fn_t)();
|
||||
typedef void (*write_status_fn_t)(unsigned);
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
typedef struct __attribute__((packed)) {
|
||||
const char *manufacturer;
|
||||
uint8_t mfg_id; /* 8-bit JEDEC manufacturer ID */
|
||||
uint16_t flash_id; /* 16-bit JEDEC flash chip ID */
|
||||
@@ -66,11 +53,11 @@ typedef struct __attribute__((packed))
|
||||
} qio_info_t;
|
||||
|
||||
/* Read 8 bit status using RDSR command */
|
||||
static unsigned read_status_8b_rdsr(void);
|
||||
static unsigned read_status_8b_rdsr();
|
||||
/* Read 8 bit status (second byte) using RDSR2 command */
|
||||
static unsigned read_status_8b_rdsr2(void);
|
||||
static unsigned read_status_8b_rdsr2();
|
||||
/* read 16 bit status using RDSR & RDSR2 (low and high bytes) */
|
||||
static unsigned read_status_16b_rdsr_rdsr2(void);
|
||||
static unsigned read_status_16b_rdsr_rdsr2();
|
||||
|
||||
/* Write 8 bit status using WRSR */
|
||||
static void write_status_8b_wrsr(unsigned new_status);
|
||||
@@ -80,7 +67,7 @@ static void write_status_8b_wrsr2(unsigned new_status);
|
||||
static void write_status_16b_wrsr(unsigned new_status);
|
||||
|
||||
/* Read 8 bit status of XM25QU64A */
|
||||
static unsigned read_status_8b_xmc25qu64a(void);
|
||||
static unsigned read_status_8b_xmc25qu64a();
|
||||
/* Write 8 bit status of XM25QU64A */
|
||||
static void write_status_8b_xmc25qu64a(unsigned new_status);
|
||||
|
||||
@@ -103,7 +90,7 @@ static void write_status_8b_xmc25qu64a(unsigned new_status);
|
||||
Searching of this table stops when the first match is found.
|
||||
*/
|
||||
const static qio_info_t chip_data[] = {
|
||||
/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
|
||||
/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
|
||||
{ "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 },
|
||||
{ "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */
|
||||
{ "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
|
||||
@@ -122,8 +109,8 @@ const static qio_info_t chip_data[] = {
|
||||
#define NUM_CHIPS (sizeof(chip_data) / sizeof(qio_info_t))
|
||||
|
||||
static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
write_status_fn_t write_status_fn,
|
||||
uint8_t status_qio_bit);
|
||||
write_status_fn_t write_status_fn,
|
||||
uint8_t status_qio_bit);
|
||||
|
||||
/* Generic function to use the "user command" SPI controller functionality
|
||||
to send commands to the SPI flash and read the respopnse.
|
||||
@@ -134,53 +121,13 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8
|
||||
|
||||
/* 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 bootloader_read_flash_id()
|
||||
{
|
||||
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)
|
||||
{
|
||||
uint32_t raw_flash_id;
|
||||
@@ -198,7 +145,7 @@ void bootloader_enable_qio_mode(void)
|
||||
flash_id = raw_flash_id & 0xFFFF;
|
||||
ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id);
|
||||
|
||||
for (i = 0; i < NUM_CHIPS - 1; i++) {
|
||||
for (i = 0; i < NUM_CHIPS-1; i++) {
|
||||
const qio_info_t *chip = &chip_data[i];
|
||||
if (mfg_id == chip->mfg_id && (flash_id & chip->id_mask) == (chip->flash_id & chip->id_mask)) {
|
||||
ESP_LOGI(TAG, "Enabling QIO for flash chip %s", chip_data[i].manufacturer);
|
||||
@@ -209,22 +156,19 @@ void bootloader_enable_qio_mode(void)
|
||||
if (i == NUM_CHIPS - 1) {
|
||||
ESP_LOGI(TAG, "Enabling default flash chip QIO");
|
||||
}
|
||||
|
||||
enable_qio_mode(chip_data[i].read_status_fn,
|
||||
chip_data[i].write_status_fn,
|
||||
chip_data[i].status_qio_bit);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
write_status_fn_t write_status_fn,
|
||||
uint8_t status_qio_bit)
|
||||
write_status_fn_t write_status_fn,
|
||||
uint8_t status_qio_bit)
|
||||
{
|
||||
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.
|
||||
@@ -234,28 +178,27 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
//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)) {
|
||||
(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) {
|
||||
if ((status & (1<<status_qio_bit)) == 0) {
|
||||
execute_flash_command(CMD_WREN, 0, 0, 0);
|
||||
write_status_fn(status | (1 << status_qio_bit));
|
||||
write_status_fn(status | (1<<status_qio_bit));
|
||||
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
|
||||
status = read_status_fn();
|
||||
ESP_LOGD(TAG, "Updated flash chip status 0x%x", status);
|
||||
if ((status & (1 << status_qio_bit)) == 0) {
|
||||
if ((status & (1<<status_qio_bit)) == 0) {
|
||||
ESP_LOGE(TAG, "Failed to set QIE bit, not enabling QIO mode");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -275,29 +218,22 @@ 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
|
||||
esp_rom_spiflash_select_qio_pins(CONFIG_BOOTLOADER_SPI_WP_PIN, spiconfig);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
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)
|
||||
static unsigned read_status_8b_rdsr()
|
||||
{
|
||||
return execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||
}
|
||||
|
||||
static unsigned read_status_8b_rdsr2(void)
|
||||
static unsigned read_status_8b_rdsr2()
|
||||
{
|
||||
return execute_flash_command(CMD_RDSR2, 0, 0, 8);
|
||||
}
|
||||
|
||||
static unsigned read_status_16b_rdsr_rdsr2(void)
|
||||
static unsigned read_status_16b_rdsr_rdsr2()
|
||||
{
|
||||
return execute_flash_command(CMD_RDSR, 0, 0, 8) | (execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
|
||||
}
|
||||
@@ -317,7 +253,7 @@ static void write_status_16b_wrsr(unsigned new_status)
|
||||
execute_flash_command(CMD_WRSR, new_status, 16, 0);
|
||||
}
|
||||
|
||||
static unsigned read_status_8b_xmc25qu64a(void)
|
||||
static unsigned read_status_8b_xmc25qu64a()
|
||||
{
|
||||
execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
@@ -338,11 +274,7 @@ static void write_status_8b_xmc25qu64a(unsigned new_status)
|
||||
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;
|
||||
@@ -350,17 +282,9 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8
|
||||
|
||||
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]) {
|
||||
@@ -375,8 +299,8 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8
|
||||
}
|
||||
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while (SPIFLASH.cmd.usr != 0) {
|
||||
}
|
||||
while(SPIFLASH.cmd.usr != 0)
|
||||
{ }
|
||||
|
||||
SPIFLASH.ctrl.val = old_ctrl_reg;
|
||||
return SPIFLASH.data_buf[0];
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
|
||||
bootloader_sha256_handle_t bootloader_sha256_start(void)
|
||||
bootloader_sha256_handle_t bootloader_sha256_start()
|
||||
{
|
||||
mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)malloc(sizeof(mbedtls_sha256_context));
|
||||
if (!ctx) {
|
||||
|
||||
@@ -56,10 +56,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)
|
||||
{
|
||||
#if !(defined(CONFIG_MBEDTLS_ECDSA_C) && defined(CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED))
|
||||
ESP_LOGE(TAG, "Signature verification requires ECDSA & SECP256R1 curve enabled");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#else
|
||||
ptrdiff_t keylen;
|
||||
|
||||
keylen = signature_verification_key_end - signature_verification_key_start;
|
||||
@@ -121,5 +117,4 @@ cleanup:
|
||||
mbedtls_mpi_free(&s);
|
||||
mbedtls_ecdsa_free(&ecdsa_context);
|
||||
return ret == 0 ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
#endif // CONFIG_MBEDTLS_ECDSA_C && CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#include "string.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@@ -33,7 +34,6 @@ TEST_CASE("Verify bootloader image in flash", "[bootloader_support]")
|
||||
TEST_ASSERT_EQUAL(data.image_len, bootloader_length);
|
||||
}
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2BETA)
|
||||
TEST_CASE("Verify unit test app image", "[bootloader_support]")
|
||||
{
|
||||
esp_image_metadata_t data = { 0 };
|
||||
@@ -48,7 +48,6 @@ TEST_CASE("Verify unit test app image", "[bootloader_support]")
|
||||
TEST_ASSERT_NOT_EQUAL(0, data.image_len);
|
||||
TEST_ASSERT_TRUE(data.image_len <= running->size);
|
||||
}
|
||||
#endif
|
||||
|
||||
void check_label_search (int num_test, const char *list, const char *t_label, bool result)
|
||||
{
|
||||
|
||||
@@ -33,7 +33,6 @@ if(CONFIG_BT_ENABLED)
|
||||
host/bluedroid/bta/av/include
|
||||
host/bluedroid/bta/dm/include
|
||||
host/bluedroid/bta/gatt/include
|
||||
host/bluedroid/bta/hf_ag/include
|
||||
host/bluedroid/bta/hf_client/include
|
||||
host/bluedroid/bta/hh/include
|
||||
host/bluedroid/bta/jv/include
|
||||
@@ -75,7 +74,6 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/api/esp_gatt_common_api.c"
|
||||
"host/bluedroid/api/esp_gattc_api.c"
|
||||
"host/bluedroid/api/esp_gatts_api.c"
|
||||
"host/bluedroid/api/esp_hf_ag_api.c"
|
||||
"host/bluedroid/api/esp_hf_client_api.c"
|
||||
"host/bluedroid/api/esp_spp_api.c"
|
||||
"host/bluedroid/bta/ar/bta_ar.c"
|
||||
@@ -118,15 +116,6 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/bta/jv/bta_jv_api.c"
|
||||
"host/bluedroid/bta/jv/bta_jv_cfg.c"
|
||||
"host/bluedroid/bta/jv/bta_jv_main.c"
|
||||
"host/bluedroid/bta/hf_ag/bta_ag_act.c"
|
||||
"host/bluedroid/bta/hf_ag/bta_ag_api.c"
|
||||
"host/bluedroid/bta/hf_ag/bta_ag_at.c"
|
||||
"host/bluedroid/bta/hf_ag/bta_ag_cfg.c"
|
||||
"host/bluedroid/bta/hf_ag/bta_ag_cmd.c"
|
||||
"host/bluedroid/bta/hf_ag/bta_ag_main.c"
|
||||
"host/bluedroid/bta/hf_ag/bta_ag_rfc.c"
|
||||
"host/bluedroid/bta/hf_ag/bta_ag_sco.c"
|
||||
"host/bluedroid/bta/hf_ag/bta_ag_sdp.c"
|
||||
"host/bluedroid/bta/hf_client/bta_hf_client_act.c"
|
||||
"host/bluedroid/bta/hf_client/bta_hf_client_api.c"
|
||||
"host/bluedroid/bta/hf_client/bta_hf_client_at.c"
|
||||
@@ -162,8 +151,6 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/btc/profile/std/a2dp/btc_av.c"
|
||||
"host/bluedroid/btc/profile/std/avrc/btc_avrc.c"
|
||||
"host/bluedroid/btc/profile/std/avrc/bta_avrc_co.c"
|
||||
"host/bluedroid/btc/profile/std/hf_ag/bta_ag_co.c"
|
||||
"host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c"
|
||||
"host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c"
|
||||
"host/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c"
|
||||
"host/bluedroid/btc/profile/std/gap/btc_gap_ble.c"
|
||||
@@ -302,23 +289,15 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/stack/smp/smp_l2c.c"
|
||||
"host/bluedroid/stack/smp/smp_main.c"
|
||||
"host/bluedroid/stack/smp/smp_utils.c")
|
||||
|
||||
if(CONFIG_BLE_MESH)
|
||||
list(APPEND srcs "esp_ble_mesh/mesh_core/bluedroid_host/mesh_bearer_adapt.c")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if(CONFIG_BLE_MESH)
|
||||
list(APPEND include_dirs
|
||||
"esp_ble_mesh/mesh_common/include"
|
||||
"esp_ble_mesh/mesh_core"
|
||||
"esp_ble_mesh/mesh_core/include"
|
||||
"esp_ble_mesh/mesh_core/storage"
|
||||
"esp_ble_mesh/mesh_core/settings"
|
||||
"esp_ble_mesh/btc/include"
|
||||
"esp_ble_mesh/mesh_models/common/include"
|
||||
"esp_ble_mesh/mesh_models/client/include"
|
||||
"esp_ble_mesh/mesh_models/server/include"
|
||||
"esp_ble_mesh/mesh_models/include"
|
||||
"esp_ble_mesh/api/core/include"
|
||||
"esp_ble_mesh/api/models/include"
|
||||
"esp_ble_mesh/api")
|
||||
@@ -342,13 +321,7 @@ 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/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_util.c"
|
||||
"esp_ble_mesh/mesh_core/storage/settings_nvs.c"
|
||||
"esp_ble_mesh/mesh_core/settings/settings_nvs.c"
|
||||
"esp_ble_mesh/mesh_core/access.c"
|
||||
"esp_ble_mesh/mesh_core/adv.c"
|
||||
"esp_ble_mesh/mesh_core/beacon.c"
|
||||
@@ -359,30 +332,30 @@ if(CONFIG_BT_ENABLED)
|
||||
"esp_ble_mesh/mesh_core/health_cli.c"
|
||||
"esp_ble_mesh/mesh_core/health_srv.c"
|
||||
"esp_ble_mesh/mesh_core/lpn.c"
|
||||
"esp_ble_mesh/mesh_core/main.c"
|
||||
"esp_ble_mesh/mesh_core/mesh_aes_encrypt.c"
|
||||
"esp_ble_mesh/mesh_core/mesh_atomic.c"
|
||||
"esp_ble_mesh/mesh_core/mesh_bearer_adapt.c"
|
||||
"esp_ble_mesh/mesh_core/mesh_buf.c"
|
||||
"esp_ble_mesh/mesh_core/mesh_hci.c"
|
||||
"esp_ble_mesh/mesh_core/mesh_kernel.c"
|
||||
"esp_ble_mesh/mesh_core/mesh_main.c"
|
||||
"esp_ble_mesh/mesh_core/mesh_util.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/provisioner_proxy.c"
|
||||
"esp_ble_mesh/mesh_core/proxy.c"
|
||||
"esp_ble_mesh/mesh_core/settings.c"
|
||||
"esp_ble_mesh/mesh_core/test.c"
|
||||
"esp_ble_mesh/mesh_core/transport.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"
|
||||
"esp_ble_mesh/mesh_models/server/server_common.c"
|
||||
"esp_ble_mesh/mesh_models/server/state_binding.c"
|
||||
"esp_ble_mesh/mesh_models/server/state_transition.c"
|
||||
"esp_ble_mesh/mesh_models/server/time_scene_server.c")
|
||||
"esp_ble_mesh/mesh_models/generic_client.c"
|
||||
"esp_ble_mesh/mesh_models/lighting_client.c"
|
||||
"esp_ble_mesh/mesh_models/mesh_common.c"
|
||||
"esp_ble_mesh/mesh_models/model_common.c"
|
||||
"esp_ble_mesh/mesh_models/sensor_client.c"
|
||||
"esp_ble_mesh/mesh_models/time_scene_client.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_NIMBLE_ENABLED)
|
||||
@@ -397,20 +370,15 @@ if(CONFIG_BT_ENABLED)
|
||||
host/nimble/nimble/nimble/host/services/gap/include
|
||||
host/nimble/nimble/nimble/host/services/gatt/include
|
||||
host/nimble/nimble/nimble/host/services/ias/include
|
||||
host/nimble/nimble/nimble/host/services/ipss/include
|
||||
host/nimble/nimble/nimble/host/services/lls/include
|
||||
host/nimble/nimble/nimble/host/services/tps/include
|
||||
host/nimble/nimble/nimble/host/util/include
|
||||
host/nimble/nimble/nimble/host/store/ram/include
|
||||
host/nimble/nimble/nimble/host/store/config/include
|
||||
host/nimble/nimble/porting/npl/freertos/include
|
||||
host/nimble/nimble/ext/tinycrypt/include
|
||||
host/nimble/esp-hci/include)
|
||||
|
||||
if(NOT CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS)
|
||||
|
||||
list(APPEND include_dirs
|
||||
host/nimble/nimble/ext/tinycrypt/include)
|
||||
|
||||
list(APPEND srcs "host/nimble/nimble/ext/tinycrypt/src/utils.c"
|
||||
"host/nimble/nimble/ext/tinycrypt/src/sha256.c"
|
||||
"host/nimble/nimble/ext/tinycrypt/src/ecc.c"
|
||||
@@ -425,14 +393,11 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/nimble/nimble/ext/tinycrypt/src/hmac_prng.c"
|
||||
"host/nimble/nimble/ext/tinycrypt/src/ecc_platform_specific.c"
|
||||
"host/nimble/nimble/ext/tinycrypt/src/hmac.c"
|
||||
"host/nimble/nimble/ext/tinycrypt/src/cbc_mode.c")
|
||||
endif()
|
||||
|
||||
list(APPEND srcs "host/nimble/nimble/nimble/host/util/src/addr.c"
|
||||
"host/nimble/nimble/ext/tinycrypt/src/cbc_mode.c"
|
||||
"host/nimble/nimble/nimble/host/util/src/addr.c"
|
||||
"host/nimble/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c"
|
||||
"host/nimble/nimble/nimble/host/services/tps/src/ble_svc_tps.c"
|
||||
"host/nimble/nimble/nimble/host/services/ias/src/ble_svc_ias.c"
|
||||
"host/nimble/nimble/nimble/host/services/ipss/src/ble_svc_ipss.c"
|
||||
"host/nimble/nimble/nimble/host/services/ans/src/ble_svc_ans.c"
|
||||
"host/nimble/nimble/nimble/host/services/gap/src/ble_svc_gap.c"
|
||||
"host/nimble/nimble/nimble/host/services/bas/src/ble_svc_bas.c"
|
||||
@@ -454,7 +419,6 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/nimble/nimble/nimble/host/src/ble_hs_hci_evt.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_hs_dbg.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_hs_mqueue.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_hs_periodic_sync.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_att.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_gattc.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_store.c"
|
||||
@@ -498,10 +462,6 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/nimble/nimble/porting/nimble/src/os_cputime.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")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_NIMBLE_MESH)
|
||||
|
||||
list(APPEND include_dirs
|
||||
@@ -541,7 +501,9 @@ idf_component_register(SRCS "${srcs}"
|
||||
REQUIRES nvs_flash soc)
|
||||
|
||||
if(CONFIG_BT_ENABLED)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-implicit-fallthrough -Wno-unused-const-variable)
|
||||
if(GCC_NOT_5_2_0)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-implicit-fallthrough -Wno-unused-const-variable)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-L${CMAKE_CURRENT_LIST_DIR}/controller/lib")
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
menu "Bluetooth"
|
||||
menu Bluetooth
|
||||
|
||||
config BT_ENABLED
|
||||
bool "Bluetooth"
|
||||
depends on IDF_TARGET_ESP32
|
||||
help
|
||||
Select this option to enable Bluetooth and show the submenu with Bluetooth configuration choices.
|
||||
|
||||
@@ -78,20 +77,6 @@ menu "Bluetooth"
|
||||
default 1 if BTDM_CTRL_BR_EDR_SCO_DATA_PATH_PCM
|
||||
default 0
|
||||
|
||||
config BTDM_CTRL_AUTO_LATENCY
|
||||
bool "Auto latency"
|
||||
depends on BTDM_CTRL_MODE_BTDM
|
||||
default n
|
||||
help
|
||||
BLE auto latency, used to enhance classic BT performance
|
||||
while classic BT and BLE are enabled at the same time.
|
||||
|
||||
config BTDM_CTRL_AUTO_LATENCY_EFF
|
||||
bool
|
||||
default BTDM_CTRL_AUTO_LATENCY if BTDM_CTRL_MODE_BTDM
|
||||
default n
|
||||
|
||||
|
||||
config BTDM_CTRL_BLE_MAX_CONN_EFF
|
||||
int
|
||||
default BTDM_CTRL_BLE_MAX_CONN if BTDM_CTRL_MODE_BLE_ONLY || BTDM_CTRL_MODE_BTDM
|
||||
@@ -333,8 +318,8 @@ menu "Bluetooth"
|
||||
|
||||
config BTDM_CTRL_FULL_SCAN_SUPPORTED
|
||||
bool "BLE full scan feature supported"
|
||||
depends on BTDM_CONTROLLER_MODE_BLE_ONLY || BTDM_CONTROLLER_MODE_BTDM
|
||||
default y
|
||||
depends on BTDM_CTRL_MODE_BLE_ONLY
|
||||
default n
|
||||
help
|
||||
The full scan function is mainly used to provide BLE scan performance.
|
||||
This is required for scenes with high scan performance requirements, such as BLE Mesh scenes.
|
||||
@@ -373,21 +358,6 @@ 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
|
||||
@@ -408,13 +378,6 @@ menu "Bluetooth"
|
||||
help
|
||||
This option is recommended for BLE only usecases to save on memory
|
||||
|
||||
config BT_CONTROLLER_ONLY
|
||||
bool "Controller Only"
|
||||
help
|
||||
This option is recommended when you want to communicate directly with the
|
||||
controller (without any host) or when you are using any other host stack
|
||||
not supported by Espressif (not mentioned here).
|
||||
|
||||
endchoice
|
||||
|
||||
menu "Bluedroid Options"
|
||||
@@ -432,6 +395,7 @@ endmenu
|
||||
|
||||
menuconfig BLE_MESH
|
||||
bool "ESP BLE Mesh Support"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
help
|
||||
This option enables ESP BLE Mesh support. The specific features that are
|
||||
available may depend on other features that have been enabled in the
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "esp_log.h"
|
||||
#include "bt_common.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "btc/btc_alarm.h"
|
||||
|
||||
#ifdef CONFIG_BT_BLUEDROID_ENABLED
|
||||
#include "common/bt_target.h"
|
||||
@@ -33,6 +32,7 @@
|
||||
#include "btc_blufi_prf.h"
|
||||
#include "blufi_int.h"
|
||||
#include "btc/btc_dm.h"
|
||||
#include "btc/btc_alarm.h"
|
||||
#include "bta/bta_gatt_api.h"
|
||||
#if CLASSIC_BT_INCLUDED
|
||||
#include "btc/btc_profile_queue.h"
|
||||
@@ -47,9 +47,6 @@
|
||||
#if (BTC_SPP_INCLUDED == TRUE)
|
||||
#include "btc_spp.h"
|
||||
#endif /* #if (BTC_SPP_INCLUDED == TRUE) */
|
||||
#if BTC_HF_INCLUDED
|
||||
#include "btc_hf_ag.h"
|
||||
#endif/* #if BTC_HF_INCLUDED */
|
||||
#if BTC_HF_CLIENT_INCLUDED
|
||||
#include "btc_hf_client.h"
|
||||
#endif /* #if BTC_HF_CLIENT_INCLUDED */
|
||||
@@ -97,9 +94,7 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
|
||||
[BTC_PID_BLUFI] = {btc_blufi_call_handler, btc_blufi_cb_handler },
|
||||
#endif ///GATTS_INCLUDED == TRUE
|
||||
[BTC_PID_DM_SEC] = {NULL, btc_dm_sec_cb_handler },
|
||||
#endif
|
||||
[BTC_PID_ALARM] = {btc_alarm_handler, NULL },
|
||||
#ifdef CONFIG_BT_BLUEDROID_ENABLED
|
||||
#if CLASSIC_BT_INCLUDED
|
||||
#if (BTC_GAP_BT_INCLUDED == TRUE)
|
||||
[BTC_PID_GAP_BT] = {btc_gap_bt_call_handler, btc_gap_bt_cb_handler },
|
||||
@@ -113,29 +108,22 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
|
||||
#if (BTC_SPP_INCLUDED == TRUE)
|
||||
[BTC_PID_SPP] = {btc_spp_call_handler, btc_spp_cb_handler },
|
||||
#endif /* #if (BTC_SPP_INCLUDED == TRUE) */
|
||||
#if BTC_HF_INCLUDED
|
||||
[BTC_PID_HF] = {btc_hf_call_handler, btc_hf_cb_handler},
|
||||
#endif /* #if BTC_HF_INCLUDED */
|
||||
#if BTC_HF_CLIENT_INCLUDED
|
||||
[BTC_PID_HF_CLIENT] = {btc_hf_client_call_handler, btc_hf_client_cb_handler},
|
||||
#endif /* #if BTC_HF_CLIENT_INCLUDED */
|
||||
#endif /* #if CLASSIC_BT_INCLUDED */
|
||||
#endif
|
||||
#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 },
|
||||
[BTC_PID_HEALTH_CLIENT] = {btc_ble_mesh_health_client_call_handler, btc_ble_mesh_health_client_cb_handler },
|
||||
[BTC_PID_HEALTH_SERVER] = {btc_ble_mesh_health_server_call_handler, btc_ble_mesh_health_server_cb_handler },
|
||||
[BTC_PID_CONFIG_CLIENT] = {btc_ble_mesh_config_client_call_handler, btc_ble_mesh_config_client_cb_handler },
|
||||
[BTC_PID_CONFIG_SERVER] = {NULL, btc_ble_mesh_config_server_cb_handler },
|
||||
[BTC_PID_GENERIC_CLIENT] = {btc_ble_mesh_generic_client_call_handler, btc_ble_mesh_generic_client_cb_handler },
|
||||
[BTC_PID_LIGHTING_CLIENT] = {btc_ble_mesh_lighting_client_call_handler, btc_ble_mesh_lighting_client_cb_handler },
|
||||
[BTC_PID_SENSOR_CLIENT] = {btc_ble_mesh_sensor_client_call_handler, btc_ble_mesh_sensor_client_cb_handler },
|
||||
[BTC_PID_TIME_SCENE_CLIENT] = {btc_ble_mesh_time_scene_client_call_handler, btc_ble_mesh_time_scene_client_cb_handler},
|
||||
[BTC_PID_GENERIC_SERVER] = {NULL, btc_ble_mesh_generic_server_cb_handler },
|
||||
[BTC_PID_LIGHTING_SERVER] = {NULL, btc_ble_mesh_lighting_server_cb_handler },
|
||||
[BTC_PID_SENSOR_SERVER] = {NULL, btc_ble_mesh_sensor_server_cb_handler },
|
||||
[BTC_PID_TIME_SCENE_SERVER] = {NULL, btc_ble_mesh_time_scene_server_cb_handler},
|
||||
[BTC_PID_PROV] = {btc_mesh_prov_call_handler, btc_mesh_prov_cb_handler},
|
||||
[BTC_PID_MODEL] = {btc_mesh_model_call_handler, btc_mesh_model_cb_handler},
|
||||
[BTC_PID_HEALTH_CLIENT] = {btc_mesh_health_client_call_handler, btc_mesh_health_client_cb_handler},
|
||||
[BTC_PID_HEALTH_SERVER] = {btc_mesh_health_server_call_handler, btc_mesh_health_server_cb_handler},
|
||||
[BTC_PID_CFG_CLIENT] = {btc_mesh_cfg_client_call_handler, btc_mesh_cfg_client_cb_handler},
|
||||
[BTC_PID_CFG_SERVER] = {NULL , btc_mesh_cfg_server_cb_handler},
|
||||
[BTC_PID_GENERIC_CLIENT] = {btc_mesh_generic_client_call_handler, btc_mesh_generic_client_cb_handler},
|
||||
[BTC_PID_LIGHT_CLIENT] = {btc_mesh_light_client_call_handler, btc_mesh_light_client_cb_handler},
|
||||
[BTC_PID_SENSOR_CLIENT] = {btc_mesh_sensor_client_call_handler, btc_mesh_sensor_client_cb_handler},
|
||||
[BTC_PID_TIME_SCENE_CLIENT] = {btc_mesh_time_scene_client_call_handler, btc_mesh_time_scene_client_cb_handler},
|
||||
#endif /* #if CONFIG_BLE_MESH */
|
||||
};
|
||||
|
||||
@@ -333,7 +321,7 @@ error_exit:;
|
||||
|
||||
int btc_init(void)
|
||||
{
|
||||
btc_thread = osi_thread_create("BTC_TASK", 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, 3);
|
||||
if (btc_thread == NULL) {
|
||||
return BT_STATUS_NOMEM;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
#ifndef __BTC_MANAGE_H__
|
||||
#define __BTC_MANAGE_H__
|
||||
|
||||
#include "bta/bta_api.h"
|
||||
#include "btc/btc_task.h"
|
||||
#include "esp_bt_defs.h"
|
||||
|
||||
#if BTC_DYNAMIC_MEMORY == FALSE
|
||||
extern void *btc_profile_cb_tab[BTC_PID_NUM];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user