diff --git a/cpu/esp8266/bin/bootloader.bin b/cpu/esp8266/bin/bootloader.bin deleted file mode 100644 index 3a61ab09a8..0000000000 Binary files a/cpu/esp8266/bin/bootloader.bin and /dev/null differ diff --git a/cpu/esp8266/bin/bootloader_colors.bin b/cpu/esp8266/bin/bootloader_colors.bin deleted file mode 100644 index e940caac15..0000000000 Binary files a/cpu/esp8266/bin/bootloader_colors.bin and /dev/null differ diff --git a/cpu/esp8266/bin/bootloader_colors_info.bin b/cpu/esp8266/bin/bootloader_colors_info.bin deleted file mode 100644 index 78e7b425f6..0000000000 Binary files a/cpu/esp8266/bin/bootloader_colors_info.bin and /dev/null differ diff --git a/cpu/esp8266/bin/bootloader_info.bin b/cpu/esp8266/bin/bootloader_info.bin deleted file mode 100644 index 28ec8805d2..0000000000 Binary files a/cpu/esp8266/bin/bootloader_info.bin and /dev/null differ diff --git a/makefiles/tools/esptool.inc.mk b/makefiles/tools/esptool.inc.mk index ef632d35db..ff9e66607b 100644 --- a/makefiles/tools/esptool.inc.mk +++ b/makefiles/tools/esptool.inc.mk @@ -1,19 +1,7 @@ -ifeq ($(CPU),esp8266) - ifneq (,$(filter esp_log_colored,$(USEMODULE))) - BOOTLOADER_COLOR = _colors - endif - ifneq (,$(filter esp_log_startup,$(USEMODULE))) - BOOTLOADER_INFO = _info - endif - # Full path to the bootloader binary. In the ESP32 case this is set by the - # esp_bootloader module. - BOOTLOADER_BIN ?= $(RIOTCPU)/$(CPU)/bin/bootloader$(BOOTLOADER_COLOR)$(BOOTLOADER_INFO).bin -else - # ESP-IDF uses dio as flash mode for esptool.py when qout or qio mode are - # configured to always boot in dual SPI mode - ifneq (,$(filter qout qio,$(FLASH_MODE))) - FLASH_MODE = dio - endif +# ESP-IDF uses dio as flash mode for esptool.py when qout or qio mode are +# configured to always boot in dual SPI mode +ifneq (,$(filter qout qio,$(FLASH_MODE))) + FLASH_MODE = dio endif ESPTOOL ?= $(RIOTTOOLS)/esptools/esptool.py diff --git a/pkg/esp8266_sdk/Makefile.dep b/pkg/esp8266_sdk/Makefile.dep index 1df099a72b..593be7b4dc 100644 --- a/pkg/esp8266_sdk/Makefile.dep +++ b/pkg/esp8266_sdk/Makefile.dep @@ -1,2 +1,5 @@ # This package can only be used with the ESP8266 CPU FEATURES_REQUIRED += arch_esp8266 + +# Always include the ESP8266 SDK bootloader. +USEMODULE += esp_bootloader diff --git a/pkg/esp8266_sdk/Makefile.include b/pkg/esp8266_sdk/Makefile.include index b8ca392e49..270153533f 100644 --- a/pkg/esp8266_sdk/Makefile.include +++ b/pkg/esp8266_sdk/Makefile.include @@ -1,3 +1,5 @@ +PSEUDOMODULES += esp8266_sdk + # Directory with the SDK source checkout. Some modules in the cpu/esp8266 use # internal parts of the SDK and for that they need access to the # ESP8266_RTOS_SDK_DIR path. @@ -19,5 +21,13 @@ INCLUDES += -I$(ESP8266_SDK_BUILD_DIR) # Modified binary libraries are built here in the Makefile. LINKFLAGS += -L$(ESP8266_SDK_BUILD_DIR) -# esp8266_sdk doesn't generate any .a -PSEUDOMODULES += esp8266_sdk +# Bootloader module built from the SDK. +DIRS += $(RIOTBASE)/pkg/esp8266_sdk/bootloader +PSEUDOMODULES += esp_bootloader + +ifneq (,$(filter esp_bootloader,$(USEMODULE))) + # Bootloader file used by esptool.inc.mk + BOOTLOADER_BIN ?= $(BINDIR)/esp_bootloader/bootloader.bin +endif + +$(BOOTLOADER_BIN): diff --git a/pkg/esp8266_sdk/bootloader/Makefile b/pkg/esp8266_sdk/bootloader/Makefile new file mode 100644 index 0000000000..5531cc6788 --- /dev/null +++ b/pkg/esp8266_sdk/bootloader/Makefile @@ -0,0 +1,113 @@ +# Bootloader binary blob +MODULE := esp_bootloader + +# We are compiling the bootloader from the ESP8266_RTOS_SDK_DIR sources, so we +# can't use the automatic module SRC discovery rules. Also, the compiled code +# would not be linked into the application, instead it is linked into its own +# binary file. +NO_AUTO_SRC = 1 + +include $(RIOTBASE)/Makefile.base + +# List of bootloader sources. +include $(CURDIR)/bootloader.inc.mk + +# Bootloader baudrate, set to the application defined one if any or the default +# in serial.inc.mk +BOOTLOADER_BAUD ?= $(BAUD) + +# Bootloader sdkconfig.h defined in CURDIR directory. +INCLUDES = \ + -I$(dir $(RIOTBUILD_CONFIG_HEADER_C)) \ + -I$(ESP8266_RTOS_SDK_DIR)/components/bootloader_support/include \ + -I$(ESP8266_RTOS_SDK_DIR)/components/bootloader_support/include_priv \ + -I$(ESP8266_RTOS_SDK_DIR)/components/esp8266/include \ + -I$(ESP8266_RTOS_SDK_DIR)/components/heap/include \ + -I$(ESP8266_RTOS_SDK_DIR)/components/heap/port/esp8266/include \ + -I$(ESP8266_RTOS_SDK_DIR)/components/log/include/ \ + -I$(ESP8266_RTOS_SDK_DIR)/components/spi_flash/include \ + -I$(ESP8266_RTOS_SDK_DIR)/components/util/include \ + -I$(ESP8266_RTOS_SDK_DIR)/build-libs \ + -I$(CURDIR) + # + +# BOOTLOADER_BUILD=1 signals to the SDK that's a bootloader build. +CFLAGS = \ + -DBOOTLOADER_BUILD=1 \ + -DESP_PLATFORM \ + -DRIOT_BOOTLOADER_BAUD=$(BOOTLOADER_BAUD) \ + -DRIOT_FLASH_SIZE=$(FLASH_SIZE) \ + -O2 \ + -ffunction-sections \ + -fdata-sections \ + -fstrict-volatile-bitfields \ + -mlongcalls \ + # + +# Bootloader link flags. We use the SDK source and linking files instead of the +# RIOT-OS ones to link the bootloader. Note that we also use the unmodified +# SDK libraries. +LINKFLAGS = \ + -nostdlib \ + -u call_user_start_cpu0 \ + -Wl,--gc-sections \ + -Wl,-static \ + -Wl,-EL \ + -Wl,--start-group \ + $(ESP_SDK_BOOTLOADER_OBJS) \ + -Wl,--end-group \ + -lgcc \ + -lstdc++ \ + -lgcov \ + -L$(ESP8266_RTOS_SDK_DIR)/components/esp8266/lib \ + -lcore \ + -T$(ESP8266_RTOS_SDK_DIR)/components/esp8266/ld/esp8266.rom.ld \ + -L$(ESP8266_RTOS_SDK_DIR)/components/bootloader/subproject/main \ + -Tesp8266.bootloader.ld \ + -Tesp8266.bootloader.rom.ld \ + +# Build the bootloader on the application directory as it depends on the current +# app settings from riotbuild.h. +ESP_SDK_BOOTLOADER_DIR = $(BINDIR)/$(MODULE) +ESP_SDK_BOOTLOADER_BIN = $(ESP_SDK_BOOTLOADER_DIR)/bootloader.bin +ESP_SDK_BOOTLOADER_ELF = $(ESP_SDK_BOOTLOADER_DIR)/bootloader.elf + +ESP_SDK_BOOTLOADER_OBJS = \ + $(addprefix $(ESP_SDK_BOOTLOADER_DIR)/,$(ESP_SDK_BOOTLOADER_SRCS:%.c=%.o)) + +DEPS := $(ESP_SDK_BOOTLOADER_OBJS:%.o=%.d) +-include $(DEPS) + +# Main module dependency. We only build the bootloader.bin from this module. +$(MODULE).module: $(ESP_SDK_BOOTLOADER_BIN) + +OBJ_DEPS += $(CURDIR)/sdkconfig.h + +$(ESP_SDK_BOOTLOADER_DIR)/%.o: $(ESP8266_RTOS_SDK_DIR)/%.c $(OBJ_DEPS) + $(Q)mkdir -p $(dir $@) + $(Q)$(CCACHE) $(CC) \ + $(CFLAGS) $(INCLUDES) -MQ '$@' -MD -MP -c -o $@ $(abspath $<) + +$(ESP_SDK_BOOTLOADER_DIR): + mkdir -p $@ + +$(ESP_SDK_BOOTLOADER_ELF): $(ESP_SDK_BOOTLOADER_OBJS) \ + | $(ESP_SDK_BOOTLOADER_DIR) + $(Q)$(CC) -o $@ $(LINKFLAGS) -Wl,-Map=$(@:%.elf=%.map) + +FLASH_CHIP = esp8266 +ESPTOOL ?= $(RIOTTOOLS)/esptools/esptool.py +# TODO: These should be exported/configurable from the app side. That would +# require to export these values. +FLASH_MODE ?= dout +FLASH_FREQ ?= 40m +FLASH_SIZE ?= 4 + +# We use esptool to extract a version 1 app from the bootloader.elf. This is +# like the regular objdump binary file but it contains a 16 byte header which +# specifies the flash size, mode and speed that the ROM bootloader uses to load +# this second-stage bootloader image. +$(ESP_SDK_BOOTLOADER_BIN): $(ESP_SDK_BOOTLOADER_ELF) + $(Q)$(ESPTOOL) --chip $(FLASH_CHIP) elf2image --flash_mode $(FLASH_MODE) \ + --flash_size $(FLASH_SIZE)MB --flash_freq $(FLASH_FREQ) --version 1 -o $@ $< + $(Q)mv $(@)0x00000.bin $@ diff --git a/pkg/esp8266_sdk/bootloader/bootloader.inc.mk b/pkg/esp8266_sdk/bootloader/bootloader.inc.mk new file mode 100644 index 0000000000..d0f358fe2f --- /dev/null +++ b/pkg/esp8266_sdk/bootloader/bootloader.inc.mk @@ -0,0 +1,26 @@ +# Generated by ./update_mk.sh, don't modify directly. + +ESP_SDK_BOOTLOADER_SRCS = \ + components/bootloader/subproject/main/bootloader_start.c \ + components/bootloader_support/src/bootloader_clock.c \ + components/bootloader_support/src/bootloader_common.c \ + components/bootloader_support/src/bootloader_flash.c \ + components/bootloader_support/src/bootloader_init.c \ + components/bootloader_support/src/bootloader_random.c \ + components/bootloader_support/src/bootloader_sha.c \ + components/bootloader_support/src/bootloader_utility.c \ + components/bootloader_support/src/efuse.c \ + components/bootloader_support/src/esp_image_format.c \ + components/bootloader_support/src/flash_encrypt.c \ + components/bootloader_support/src/flash_partitions.c \ + components/bootloader_support/src/flash_qio_mode.c \ + components/bootloader_support/src/secure_boot.c \ + components/bootloader_support/src/secure_boot_signatures.c \ + components/esp8266/source/ets_printf.c \ + components/log/log.c \ + components/spi_flash/port/port.c \ + components/spi_flash/src/spi_flash.c \ + components/spi_flash/src/spi_flash_raw.c \ + components/util/src/base64.c \ + components/util/src/crc.c \ + # diff --git a/pkg/esp8266_sdk/bootloader/sdkconfig.h b/pkg/esp8266_sdk/bootloader/sdkconfig.h new file mode 100644 index 0000000000..182f272a82 --- /dev/null +++ b/pkg/esp8266_sdk/bootloader/sdkconfig.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2021 iosabi + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup pkg_esp8266_sdk + * @{ + * + * @file + * @brief RIOT-OS modification of the bootloader SDK configuration + * + * The bootloader build of the ESP8266 SDK needs some settings from the SDK + * configuration. These are normally generated by the menuconfig in the vendor + * SDK. + * + * Some of these parameters are configurable by the application. For example, + * the UART baudrate used by the console and the verbose level of the + * bootloader. + * + * @author iosabi + */ + +#ifndef SDKCONFIG_H +#define SDKCONFIG_H + +#if !DOXYGEN + +#include "riotbuild.h" + +#include "esp8266_idf_version.h" +#include "sdkconfig_default.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if MODULE_ESP_LOG_COLORED +#define CONFIG_LOG_COLORS 1 +#endif + +#ifndef CONFIG_LOG_BOOTLOADER_LEVEL +/* + * SDK Log levels: + * + * 0 = NONE + * 1 = ERROR + * 2 = WARN + * 3 = INFO + * 4 = DEBUG + * 5 = VERBOSE + */ +#if MODULE_ESP_LOG_STARTUP +#define CONFIG_LOG_BOOTLOADER_LEVEL 3 /* INFO */ +#else +#define CONFIG_LOG_BOOTLOADER_LEVEL 0 /* NONE */ +#endif +#endif + +/* + * Bootloader output baudrate, defined by the app settings as BAUD or + * BOOTLOADER_BAUD. + */ +#ifndef CONFIG_CONSOLE_UART_BAUDRATE +#define CONFIG_CONSOLE_UART_BAUDRATE (RIOT_BOOTLOADER_BAUD) +#endif + +/* + * The makefile FLASH_SIZE value is set in MB, but set as bytes to + * CONFIG_SPI_FLASH_SIZE. + */ +#ifndef CONFIG_SPI_FLASH_SIZE +#define CONFIG_SPI_FLASH_SIZE ((RIOT_FLASH_SIZE) * 1024 * 1024) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* !DOXYGEN */ +#endif /* SDKCONFIG_H */ +/** @} */ diff --git a/pkg/esp8266_sdk/bootloader/sdkconfig_default.h b/pkg/esp8266_sdk/bootloader/sdkconfig_default.h new file mode 100644 index 0000000000..4e110bfaab --- /dev/null +++ b/pkg/esp8266_sdk/bootloader/sdkconfig_default.h @@ -0,0 +1,28 @@ +/* + * Generated by ./update_mk.sh, don't modify directly. + * Default CONFIG_ parameters from the SDK package. + */ + +#ifndef SDKCONFIG_DEFAULT_H +#define SDKCONFIG_DEFAULT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define CONFIG_BOOTLOADER_INIT_SPI_FLASH 1 +#define CONFIG_CONSOLE_UART_NUM 0 +#define CONFIG_CRYSTAL_USED_26MHZ 1 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 +#define CONFIG_SPI_FLASH_MODE 0x0 +#define CONFIG_SSL_USING_MBEDTLS 1 +#define CONFIG_TARGET_PLATFORM_ESP8266 1 +#define CONFIG_USING_NEW_ETS_VPRINTF 1 + +#ifdef __cplusplus +} +#endif + +#endif /* SDKCONFIG_DEFAULT_H */ diff --git a/pkg/esp8266_sdk/bootloader/update_mk.sh b/pkg/esp8266_sdk/bootloader/update_mk.sh new file mode 100755 index 0000000000..a16ce4f9c2 --- /dev/null +++ b/pkg/esp8266_sdk/bootloader/update_mk.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +# Script to update the bootloader.inc.mk file. +# +# bootloader.inc.mk contains the list of source files and config options that +# the vendor SDK uses while building the bootloader. This is generated and +# included in the RIOT-OS source repository since it requires to have both a +# native toolchain and esp8266 toolchain configured and it was in general tricky +# to get to work from RIOT-OS build system. + +SCRIPTDIR=$(dirname "$(realpath "$0")") + +set -eu + +main() { + if ! which xtensa-esp8266-elf-gcc >/dev/null; then + echo "Assuming xtensa-esp8266-elf-gcc from /opt/esp/xtensa-esp8266-elf/bin" + export PATH="/opt/esp/xtensa-esp8266-elf/bin:${PATH}" + fi + + local bldr_dir="${SCRIPTDIR}/bldr_build" + rm -rf "${bldr_dir}" + mkdir -p "${bldr_dir}" + cd "${bldr_dir}" + + local sdk_path + sdk_path=$(realpath "${SCRIPTDIR}/../../../build/pkg/esp8266_sdk") + if [[ ! -e "${sdk_path}/Kconfig" ]]; then + echo "Download the ESP8266 RTOS SDK to ${sdk_path} by building RIOT first" + exit 1 + fi + + # Builds the bootloader.bin with the default config into the bldr_build + PROJECT_NAME=bootloader PROJECT_PATH="${bldr_dir}" \ + make \ + -f "${sdk_path}/make/project.mk" IDF_PATH="${sdk_path}" \ + CONFIG_TOOLPREFIX=xtensa-esp8266-elf- \ + defconfig bootloader -j + + # List of all the sources and headers used by the build except the generated + # sdkconfig.h. + local bootloader_srcs + bootloader_srcs=( + $(find . -name '*.d' -print0 | xargs -0 cat | tr ' ' '\n' | + grep -E '^/[^ ]+\.[ch]$' -o | xargs -I {} realpath {} | + grep -v -F /sdkconfig.h | sort | uniq)) + + ( + echo "# Generated by ./update_mk.sh, don't modify directly." + echo + # List of source files (.c) + echo "ESP_SDK_BOOTLOADER_SRCS = \\" + local src + for src in "${bootloader_srcs[@]}"; do + if [[ "${src%.c}" != "${src}" ]]; then + echo " ${src#${sdk_path}/} \\" + fi + done + echo " #" + ) >"${SCRIPTDIR}/bootloader.inc.mk" + + # List of the relevant CONFIG_ settings used by those files. + local configs + configs=( + $(grep -h -o -E '\bCONFIG_[A-Z0-9_]+\b' "${bootloader_srcs[@]}" | + sort | uniq)) + + ( + echo "/*" + echo " * Generated by ./update_mk.sh, don't modify directly." + echo " * Default CONFIG_ parameters from the SDK package." + echo " */" + echo + echo "#ifndef SDKCONFIG_DEFAULT_H" + echo "#define SDKCONFIG_DEFAULT_H" + echo + echo "#ifdef __cplusplus" + echo "extern \"C\" {" + echo "#endif" + echo + # Only list those configs not in the bootloader sdkconfig.h included in + # RIOT-OS. + local conf + for conf in "${configs[@]}"; do + grep -F "#define ${conf} " "${SCRIPTDIR}/sdkconfig.h" >/dev/null || + grep -F "#define ${conf} " "${bldr_dir}/build/include/sdkconfig.h" || true + done + echo + echo "#ifdef __cplusplus" + echo "}" + echo "#endif" + echo + echo "#endif /* SDKCONFIG_DEFAULT_H */" + ) >"${SCRIPTDIR}/sdkconfig_default.h" + + echo "Done." +} + +main "$@"