mirror of
https://github.com/SuperBFG7/ympd
synced 2024-12-26 19:10:25 +00:00
Removed mongoose src
This commit is contained in:
parent
998d675b2c
commit
7a3103d035
@ -3,12 +3,13 @@ cmake_minimum_required(VERSION 2.6)
|
||||
project (mympd C)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "2")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "2")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "3")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "0")
|
||||
if(CMAKE_BUILD_TYPE MATCHES RELEASE)
|
||||
set(ASSETS_PATH "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}/htdocs")
|
||||
else()
|
||||
set(ASSETS_PATH "${PROJECT_SOURCE_DIR}/htdocs")
|
||||
set(DEBUG ON)
|
||||
endif()
|
||||
|
||||
option(WITH_IPV6 "enable IPv6 support" ON)
|
||||
@ -22,8 +23,9 @@ include_directories(${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR} ${LIBMPDCLIENT_I
|
||||
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -ggdb -pedantic -D_FORTIFY_SOURCE=2 -fstack-protector -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fsanitize=shift -fsanitize=integer-divide-by-zero -fsanitize=unreachable -fsanitize=vla-bound -fsanitize=null -fsanitize=return -fsanitize=signed-integer-overflow -fsanitize=bounds -fsanitize=bounds-strict -fsanitize=alignment -fsanitize=object-size -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fsanitize=nonnull-attribute -fsanitize=returns-nonnull-attribute -fsanitize=bool -fsanitize=enum -fsanitize=vptr -static-libasan")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb -pedantic")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -pedantic")
|
||||
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -pedantic -D_FORTIFY_SOURCE=2 -fstack-protector -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fsanitize=shift -fsanitize=integer-divide-by-zero -fsanitize=unreachable -fsanitize=vla-bound -fsanitize=null -fsanitize=return -fsanitize=signed-integer-overflow -fsanitize=bounds -fsanitize=bounds-strict -fsanitize=alignment -fsanitize=object-size -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fsanitize=nonnull-attribute -fsanitize=returns-nonnull-attribute -fsanitize=bool -fsanitize=enum -fsanitize=vptr -static-libasan")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb")
|
||||
if(WITH_IPV6)
|
||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS NS_ENABLE_IPV6)
|
||||
endif()
|
||||
|
@ -30,4 +30,5 @@
|
||||
#define MYMPD_VERSION_PATCH ${CPACK_PACKAGE_VERSION_PATCH}
|
||||
#define MYMPD_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}"
|
||||
#define SRC_PATH "${ASSETS_PATH}"
|
||||
#cmakedefine DEBUG
|
||||
#endif
|
||||
|
@ -1 +0,0 @@
|
||||
mongoose-6.11/
|
@ -1,9 +0,0 @@
|
||||
binary/
|
||||
deps/
|
||||
docker/
|
||||
docs/
|
||||
examples/
|
||||
platforms/
|
||||
src/
|
||||
test/
|
||||
multilingual/
|
@ -1,8 +0,0 @@
|
||||
People who have agreed to the
|
||||
[Cesanta CLA](https://docs.cesanta.com/contributors_la.shtml)
|
||||
can make contributions. Note that the CLA isn't a copyright
|
||||
_assigment_ but rather a copyright _license_.
|
||||
You retain the copyright on your contributions.
|
||||
|
||||
We follow the Google C/C++ style guide: https://google.github.io/styleguide/cppguide.html
|
||||
We'd appreciate if your contribution follows the same style guide.
|
@ -1,68 +0,0 @@
|
||||
# Mongoose - Embedded Web Server / Embedded Networking Library
|
||||
|
||||
![](https://img.shields.io/badge/license-GPL_2-green.svg "License")
|
||||
|
||||
Mongoose is ideal for embedded environments. It has been designed
|
||||
for connecting devices and bringing them online. On the market since 2004,
|
||||
used by vast number of open source and
|
||||
commercial products - it even runs on the International Space station!
|
||||
Mongoose makes embedded network programming fast, robust, and easy.
|
||||
|
||||
- [Download Mongoose Source Code here](https://www.cesanta.com/download.html)
|
||||
|
||||
Looking for a complete IoT firmware solution?
|
||||
|
||||
Check out [Mongoose OS](https://mongoose-os.com) - open source embedded operating system for low-power connected microcontrollers. Secure, designed for Internet of Things, complete environment for prototyping, development and managing.
|
||||
|
||||
# Support
|
||||
- [Study mongoose example code](https://github.com/cesanta/mongoose/tree/master/examples)
|
||||
- [Read User Guide and API reference](https://cesanta.com/docs/overview/intro.html)
|
||||
- [Support Forum - ask your technical questions here](https://forum.mongoose-os.com/categories/mongoose)
|
||||
- [Commercial licensing and support available](https://www.cesanta.com/licensing.html)
|
||||
- [Check our latest releases](https://github.com/cesanta/mongoose/releases)
|
||||
|
||||
# Features
|
||||
|
||||
* Cross-platform: works on Linux/UNIX, MacOS, QNX, eCos, Windows, Android,
|
||||
iPhone, FreeRTOS (TI CC3200, ESP8266), etc
|
||||
* Supported hardware platforms: TI CC3200, TI MSP432, NRF52, STM32, PIC32, ESP8266, ESP32 and more
|
||||
* Builtin protocols:
|
||||
- plain TCP, plain UDP, SSL/TLS (over TCP, one-way or two-way)
|
||||
- HTTP client, HTTP server
|
||||
- WebSocket client, WebSocket server
|
||||
- MQTT client, MQTT broker
|
||||
- CoAP client, CoAP server
|
||||
- DNS client, DNS server, async DNS resolver
|
||||
* Single-threaded, asynchronous, non-blocking core with simple event-based API
|
||||
* Native support for [PicoTCP embedded TCP/IP stack](http://www.picotcp.com),
|
||||
[LWIP embedded TCP/IP stack](https://en.wikipedia.org/wiki/LwIP)
|
||||
* Tiny static and run-time footprint
|
||||
* Source code is both ISO C and ISO C++ compliant
|
||||
* Very easy to integrate: just copy
|
||||
[mongoose.c](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.c) and
|
||||
[mongoose.h](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.h)
|
||||
files to your build tree
|
||||
|
||||
# Licensing
|
||||
|
||||
Mongoose is released under Commercial and [GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) open source licenses.
|
||||
|
||||
Commercial Projects: [Contact us for commercial license.](https://www.cesanta.com/contact.html)
|
||||
|
||||
# Dashboard Example
|
||||
|
||||
Mongoose is often used to implement device dashboards and real-time
|
||||
data exchange over Websocket. Here is a dashboard example that illustrates
|
||||
the functionality:
|
||||
|
||||
![](http://www.cesanta.com/images/dashboard.png)
|
||||
|
||||
[Developing a new product? Contact us today to discuss how Mongoose can help.](https://www.cesanta.com/contact.html)
|
||||
|
||||
# Contributions
|
||||
|
||||
To submit contributions, sign [Cesanta CLA](https://cesanta.com/cla.html)
|
||||
and send GitHub pull request. You retain the copyright on your contributions.
|
||||
|
||||
# Looking for a pre-compiled Mongoose web server Windows or Mac binary?
|
||||
- [Download pre-compiled Mongoose web server binary.](https://www.cesanta.com/binary.html)
|
@ -1,8 +0,0 @@
|
||||
LOCAL_PATH := $(call my-dir)/..
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_CFLAGS := -std=c99 -O2 -W -Wall -pthread -pipe $(COPT)
|
||||
LOCAL_MODULE := mongoose
|
||||
LOCAL_SRC_FILES := examples/simplest_web_server/simplest_web_server.c mongoose.c
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
@ -1 +0,0 @@
|
||||
exclude_files=sha1\.c
|
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include "common/cs_dbg.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/cs_time.h"
|
||||
#include "common/str_util.h"
|
||||
|
||||
enum cs_log_level cs_log_threshold WEAK =
|
||||
#if CS_ENABLE_DEBUG
|
||||
LL_VERBOSE_DEBUG;
|
||||
#else
|
||||
LL_ERROR;
|
||||
#endif
|
||||
|
||||
static char *s_filter_pattern = NULL;
|
||||
static size_t s_filter_pattern_len;
|
||||
|
||||
void cs_log_set_filter(const char *pattern) WEAK;
|
||||
|
||||
#if CS_ENABLE_STDIO
|
||||
|
||||
FILE *cs_log_file WEAK = NULL;
|
||||
|
||||
#if CS_LOG_ENABLE_TS_DIFF
|
||||
double cs_log_ts WEAK;
|
||||
#endif
|
||||
|
||||
enum cs_log_level cs_log_cur_msg_level WEAK = LL_NONE;
|
||||
|
||||
void cs_log_set_filter(const char *pattern) {
|
||||
free(s_filter_pattern);
|
||||
if (pattern != NULL) {
|
||||
s_filter_pattern = strdup(pattern);
|
||||
s_filter_pattern_len = strlen(pattern);
|
||||
} else {
|
||||
s_filter_pattern = NULL;
|
||||
s_filter_pattern_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int cs_log_print_prefix(enum cs_log_level, const char *, const char *) WEAK;
|
||||
int cs_log_print_prefix(enum cs_log_level level, const char *func,
|
||||
const char *filename) {
|
||||
char prefix[21];
|
||||
|
||||
if (level > cs_log_threshold) return 0;
|
||||
if (s_filter_pattern != NULL &&
|
||||
mg_match_prefix(s_filter_pattern, s_filter_pattern_len, func) == 0 &&
|
||||
mg_match_prefix(s_filter_pattern, s_filter_pattern_len, filename) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
strncpy(prefix, func, 20);
|
||||
prefix[20] = '\0';
|
||||
if (cs_log_file == NULL) cs_log_file = stderr;
|
||||
cs_log_cur_msg_level = level;
|
||||
fprintf(cs_log_file, "%-20s ", prefix);
|
||||
#if CS_LOG_ENABLE_TS_DIFF
|
||||
{
|
||||
double now = cs_time();
|
||||
fprintf(cs_log_file, "%7u ", (unsigned int) ((now - cs_log_ts) * 1000000));
|
||||
cs_log_ts = now;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cs_log_printf(const char *fmt, ...) WEAK;
|
||||
void cs_log_printf(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(cs_log_file, fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', cs_log_file);
|
||||
fflush(cs_log_file);
|
||||
cs_log_cur_msg_level = LL_NONE;
|
||||
}
|
||||
|
||||
void cs_log_set_file(FILE *file) WEAK;
|
||||
void cs_log_set_file(FILE *file) {
|
||||
cs_log_file = file;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void cs_log_set_filter(const char *pattern) {
|
||||
(void) pattern;
|
||||
}
|
||||
|
||||
#endif /* CS_ENABLE_STDIO */
|
||||
|
||||
void cs_log_set_level(enum cs_log_level level) WEAK;
|
||||
void cs_log_set_level(enum cs_log_level level) {
|
||||
cs_log_threshold = level;
|
||||
#if CS_LOG_ENABLE_TS_DIFF && CS_ENABLE_STDIO
|
||||
cs_log_ts = cs_time();
|
||||
#endif
|
||||
}
|
@ -1,149 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_CS_DBG_H_
|
||||
#define CS_COMMON_CS_DBG_H_
|
||||
|
||||
#include "common/platform.h"
|
||||
|
||||
#if CS_ENABLE_STDIO
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifndef CS_ENABLE_DEBUG
|
||||
#define CS_ENABLE_DEBUG 0
|
||||
#endif
|
||||
|
||||
#ifndef CS_LOG_ENABLE_TS_DIFF
|
||||
#define CS_LOG_ENABLE_TS_DIFF 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*
|
||||
* Log level; `LL_INFO` is the default. Use `cs_log_set_level()` to change it.
|
||||
*/
|
||||
enum cs_log_level {
|
||||
LL_NONE = -1,
|
||||
LL_ERROR = 0,
|
||||
LL_WARN = 1,
|
||||
LL_INFO = 2,
|
||||
LL_DEBUG = 3,
|
||||
LL_VERBOSE_DEBUG = 4,
|
||||
|
||||
_LL_MIN = -2,
|
||||
_LL_MAX = 5,
|
||||
};
|
||||
|
||||
/*
|
||||
* Set max log level to print; messages with the level above the given one will
|
||||
* not be printed.
|
||||
*/
|
||||
void cs_log_set_level(enum cs_log_level level);
|
||||
|
||||
/*
|
||||
* Set log filter. NULL (a default) logs everything.
|
||||
* Otherwise, function name and file name will be tested against the given
|
||||
* pattern, and only matching messages will be printed.
|
||||
*
|
||||
* For the pattern syntax, refer to `mg_match_prefix()` in `str_util.h`.
|
||||
*
|
||||
* Example:
|
||||
* ```c
|
||||
* void foo(void) {
|
||||
* LOG(LL_INFO, ("hello from foo"));
|
||||
* }
|
||||
*
|
||||
* void bar(void) {
|
||||
* LOG(LL_INFO, ("hello from bar"));
|
||||
* }
|
||||
*
|
||||
* void test(void) {
|
||||
* cs_log_set_filter(NULL);
|
||||
* foo();
|
||||
* bar();
|
||||
*
|
||||
* cs_log_set_filter("f*");
|
||||
* foo();
|
||||
* bar(); // Will NOT print anything
|
||||
*
|
||||
* cs_log_set_filter("bar");
|
||||
* foo(); // Will NOT print anything
|
||||
* bar();
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
void cs_log_set_filter(const char *pattern);
|
||||
|
||||
/*
|
||||
* Helper function which prints message prefix with the given `level`, function
|
||||
* name `func` and `filename`. If message should be printed (accordingly to the
|
||||
* current log level and filter), prints the prefix and returns 1, otherwise
|
||||
* returns 0.
|
||||
*
|
||||
* Clients should typically just use `LOG()` macro.
|
||||
*/
|
||||
int cs_log_print_prefix(enum cs_log_level level, const char *func,
|
||||
const char *filename);
|
||||
|
||||
extern enum cs_log_level cs_log_threshold;
|
||||
|
||||
#if CS_ENABLE_STDIO
|
||||
|
||||
/*
|
||||
* Set file to write logs into. If `NULL`, logs go to `stderr`.
|
||||
*/
|
||||
void cs_log_set_file(FILE *file);
|
||||
|
||||
/*
|
||||
* Prints log to the current log file, appends "\n" in the end and flushes the
|
||||
* stream.
|
||||
*/
|
||||
void cs_log_printf(const char *fmt, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 1, 2)))
|
||||
#endif
|
||||
;
|
||||
|
||||
/*
|
||||
* Format and print message `x` with the given level `l`. Example:
|
||||
*
|
||||
* ```c
|
||||
* LOG(LL_INFO, ("my info message: %d", 123));
|
||||
* LOG(LL_DEBUG, ("my debug message: %d", 123));
|
||||
* ```
|
||||
*/
|
||||
#define LOG(l, x) \
|
||||
do { \
|
||||
if (cs_log_print_prefix(l, __func__, __FILE__)) cs_log_printf x; \
|
||||
} while (0)
|
||||
|
||||
#ifndef CS_NDEBUG
|
||||
|
||||
/*
|
||||
* Shortcut for `LOG(LL_VERBOSE_DEBUG, (...))`
|
||||
*/
|
||||
#define DBG(x) LOG(LL_VERBOSE_DEBUG, x)
|
||||
|
||||
#else /* NDEBUG */
|
||||
|
||||
#define DBG(x)
|
||||
|
||||
#endif
|
||||
|
||||
#else /* CS_ENABLE_STDIO */
|
||||
|
||||
#define LOG(l, x)
|
||||
#define DBG(x)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* CS_COMMON_CS_DBG_H_ */
|
@ -1,211 +0,0 @@
|
||||
/*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*/
|
||||
|
||||
#include "common/cs_md5.h"
|
||||
#include "common/str_util.h"
|
||||
|
||||
#if !defined(EXCLUDE_COMMON)
|
||||
#if !CS_DISABLE_MD5
|
||||
|
||||
#include "common/cs_endian.h"
|
||||
|
||||
static void byteReverse(unsigned char *buf, unsigned longs) {
|
||||
/* Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN */
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
do {
|
||||
uint32_t t = (uint32_t)((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
||||
((unsigned) buf[1] << 8 | buf[0]);
|
||||
*(uint32_t *) buf = t;
|
||||
buf += 4;
|
||||
} while (--longs);
|
||||
#else
|
||||
(void) buf;
|
||||
(void) longs;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
(w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
void cs_md5_init(cs_md5_ctx *ctx) {
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bits[0] = 0;
|
||||
ctx->bits[1] = 0;
|
||||
}
|
||||
|
||||
static void cs_md5_transform(uint32_t buf[4], uint32_t const in[16]) {
|
||||
register uint32_t a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
void cs_md5_update(cs_md5_ctx *ctx, const unsigned char *buf, size_t len) {
|
||||
uint32_t t;
|
||||
|
||||
t = ctx->bits[0];
|
||||
if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++;
|
||||
ctx->bits[1] += (uint32_t) len >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f;
|
||||
|
||||
if (t) {
|
||||
unsigned char *p = (unsigned char *) ctx->in + t;
|
||||
|
||||
t = 64 - t;
|
||||
if (len < t) {
|
||||
memcpy(p, buf, len);
|
||||
return;
|
||||
}
|
||||
memcpy(p, buf, t);
|
||||
byteReverse(ctx->in, 16);
|
||||
cs_md5_transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
|
||||
while (len >= 64) {
|
||||
memcpy(ctx->in, buf, 64);
|
||||
byteReverse(ctx->in, 16);
|
||||
cs_md5_transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
memcpy(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
void cs_md5_final(unsigned char digest[16], cs_md5_ctx *ctx) {
|
||||
unsigned count;
|
||||
unsigned char *p;
|
||||
uint32_t *a;
|
||||
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
count = 64 - 1 - count;
|
||||
if (count < 8) {
|
||||
memset(p, 0, count);
|
||||
byteReverse(ctx->in, 16);
|
||||
cs_md5_transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
memset(ctx->in, 0, 56);
|
||||
} else {
|
||||
memset(p, 0, count - 8);
|
||||
}
|
||||
byteReverse(ctx->in, 14);
|
||||
|
||||
a = (uint32_t *) ctx->in;
|
||||
a[14] = ctx->bits[0];
|
||||
a[15] = ctx->bits[1];
|
||||
|
||||
cs_md5_transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
byteReverse((unsigned char *) ctx->buf, 4);
|
||||
memcpy(digest, ctx->buf, 16);
|
||||
memset((char *) ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
#endif /* CS_DISABLE_MD5 */
|
||||
#endif /* EXCLUDE_COMMON */
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_MD5_H_
|
||||
#define CS_COMMON_MD5_H_
|
||||
|
||||
#include "common/platform.h"
|
||||
|
||||
#ifndef CS_DISABLE_MD5
|
||||
#define CS_DISABLE_MD5 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct {
|
||||
uint32_t buf[4];
|
||||
uint32_t bits[2];
|
||||
unsigned char in[64];
|
||||
} cs_md5_ctx;
|
||||
|
||||
void cs_md5_init(cs_md5_ctx *c);
|
||||
void cs_md5_update(cs_md5_ctx *c, const unsigned char *data, size_t len);
|
||||
void cs_md5_final(unsigned char *md, cs_md5_ctx *c);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* CS_COMMON_MD5_H_ */
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include "common/cs_time.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <stddef.h>
|
||||
/*
|
||||
* There is no sys/time.h on ARMCC.
|
||||
*/
|
||||
#if !(defined(__ARMCC_VERSION) || defined(__ICCARM__)) && \
|
||||
!defined(__TI_COMPILER_VERSION__) && \
|
||||
(!defined(CS_PLATFORM) || CS_PLATFORM != CS_P_NXP_LPC)
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
double cs_time(void) WEAK;
|
||||
double cs_time(void) {
|
||||
double now;
|
||||
#ifndef _WIN32
|
||||
struct timeval tv;
|
||||
if (gettimeofday(&tv, NULL /* tz */) != 0) return 0;
|
||||
now = (double) tv.tv_sec + (((double) tv.tv_usec) / 1000000.0);
|
||||
#else
|
||||
SYSTEMTIME sysnow;
|
||||
FILETIME ftime;
|
||||
GetLocalTime(&sysnow);
|
||||
SystemTimeToFileTime(&sysnow, &ftime);
|
||||
/*
|
||||
* 1. VC 6.0 doesn't support conversion uint64 -> double, so, using int64
|
||||
* This should not cause a problems in this (21th) century
|
||||
* 2. Windows FILETIME is a number of 100-nanosecond intervals since January
|
||||
* 1, 1601 while time_t is a number of _seconds_ since January 1, 1970 UTC,
|
||||
* thus, we need to convert to seconds and adjust amount (subtract 11644473600
|
||||
* seconds)
|
||||
*/
|
||||
now = (double) (((int64_t) ftime.dwLowDateTime +
|
||||
((int64_t) ftime.dwHighDateTime << 32)) /
|
||||
10000000.0) -
|
||||
11644473600;
|
||||
#endif /* _WIN32 */
|
||||
return now;
|
||||
}
|
||||
|
||||
double cs_timegm(const struct tm *tm) {
|
||||
/* Month-to-day offset for non-leap-years. */
|
||||
static const int month_day[12] = {0, 31, 59, 90, 120, 151,
|
||||
181, 212, 243, 273, 304, 334};
|
||||
|
||||
/* Most of the calculation is easy; leap years are the main difficulty. */
|
||||
int month = tm->tm_mon % 12;
|
||||
int year = tm->tm_year + tm->tm_mon / 12;
|
||||
int year_for_leap;
|
||||
int64_t rt;
|
||||
|
||||
if (month < 0) { /* Negative values % 12 are still negative. */
|
||||
month += 12;
|
||||
--year;
|
||||
}
|
||||
|
||||
/* This is the number of Februaries since 1900. */
|
||||
year_for_leap = (month > 1) ? year + 1 : year;
|
||||
|
||||
rt =
|
||||
tm->tm_sec /* Seconds */
|
||||
+
|
||||
60 *
|
||||
(tm->tm_min /* Minute = 60 seconds */
|
||||
+
|
||||
60 * (tm->tm_hour /* Hour = 60 minutes */
|
||||
+
|
||||
24 * (month_day[month] + tm->tm_mday - 1 /* Day = 24 hours */
|
||||
+ 365 * (year - 70) /* Year = 365 days */
|
||||
+ (year_for_leap - 69) / 4 /* Every 4 years is leap... */
|
||||
- (year_for_leap - 1) / 100 /* Except centuries... */
|
||||
+ (year_for_leap + 299) / 400))); /* Except 400s. */
|
||||
return rt < 0 ? -1 : (double) rt;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_CS_TIME_H_
|
||||
#define CS_COMMON_CS_TIME_H_
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "common/platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Sub-second granularity time(). */
|
||||
double cs_time(void);
|
||||
|
||||
/*
|
||||
* Similar to (non-standard) timegm, converts broken-down time into the number
|
||||
* of seconds since Unix Epoch.
|
||||
*/
|
||||
double cs_timegm(const struct tm *tm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* CS_COMMON_CS_TIME_H_ */
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_MG_MEM_H_
|
||||
#define CS_COMMON_MG_MEM_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef MG_MALLOC
|
||||
#define MG_MALLOC malloc
|
||||
#endif
|
||||
|
||||
#ifndef MG_CALLOC
|
||||
#define MG_CALLOC calloc
|
||||
#endif
|
||||
|
||||
#ifndef MG_REALLOC
|
||||
#define MG_REALLOC realloc
|
||||
#endif
|
||||
|
||||
#ifndef MG_FREE
|
||||
#define MG_FREE free
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CS_COMMON_MG_MEM_H_ */
|
@ -1,121 +0,0 @@
|
||||
#ifndef CS_COMMON_PLATFORM_H_
|
||||
#define CS_COMMON_PLATFORM_H_
|
||||
|
||||
/*
|
||||
* For the "custom" platform, includes and dependencies can be
|
||||
* provided through mg_locals.h.
|
||||
*/
|
||||
#define CS_P_CUSTOM 0
|
||||
#define CS_P_UNIX 1
|
||||
#define CS_P_WINDOWS 2
|
||||
#define CS_P_ESP32 15
|
||||
#define CS_P_ESP8266 3
|
||||
#define CS_P_CC3100 6
|
||||
#define CS_P_CC3200 4
|
||||
#define CS_P_CC3220 17
|
||||
#define CS_P_MSP432 5
|
||||
#define CS_P_TM4C129 14
|
||||
#define CS_P_MBED 7
|
||||
#define CS_P_WINCE 8
|
||||
#define CS_P_NXP_LPC 13
|
||||
#define CS_P_NXP_KINETIS 9
|
||||
#define CS_P_NRF51 12
|
||||
#define CS_P_NRF52 10
|
||||
#define CS_P_PIC32 11
|
||||
#define CS_P_STM32 16
|
||||
/* Next id: 18 */
|
||||
|
||||
/* If not specified explicitly, we guess platform by defines. */
|
||||
#ifndef CS_PLATFORM
|
||||
|
||||
#if defined(TARGET_IS_MSP432P4XX) || defined(__MSP432P401R__)
|
||||
#define CS_PLATFORM CS_P_MSP432
|
||||
#elif defined(cc3200) || defined(TARGET_IS_CC3200)
|
||||
#define CS_PLATFORM CS_P_CC3200
|
||||
#elif defined(cc3220) || defined(TARGET_IS_CC3220)
|
||||
#define CS_PLATFORM CS_P_CC3220
|
||||
#elif defined(__unix__) || defined(__APPLE__)
|
||||
#define CS_PLATFORM CS_P_UNIX
|
||||
#elif defined(WINCE)
|
||||
#define CS_PLATFORM CS_P_WINCE
|
||||
#elif defined(_WIN32)
|
||||
#define CS_PLATFORM CS_P_WINDOWS
|
||||
#elif defined(__MBED__)
|
||||
#define CS_PLATFORM CS_P_MBED
|
||||
#elif defined(__USE_LPCOPEN)
|
||||
#define CS_PLATFORM CS_P_NXP_LPC
|
||||
#elif defined(FRDM_K64F) || defined(FREEDOM)
|
||||
#define CS_PLATFORM CS_P_NXP_KINETIS
|
||||
#elif defined(PIC32)
|
||||
#define CS_PLATFORM CS_P_PIC32
|
||||
#elif defined(ESP_PLATFORM)
|
||||
#define CS_PLATFORM CS_P_ESP32
|
||||
#elif defined(ICACHE_FLASH)
|
||||
#define CS_PLATFORM CS_P_ESP8266
|
||||
#elif defined(TARGET_IS_TM4C129_RA0) || defined(TARGET_IS_TM4C129_RA1) || \
|
||||
defined(TARGET_IS_TM4C129_RA2)
|
||||
#define CS_PLATFORM CS_P_TM4C129
|
||||
#elif defined(STM32)
|
||||
#define CS_PLATFORM CS_P_STM32
|
||||
#endif
|
||||
|
||||
#ifndef CS_PLATFORM
|
||||
#error "CS_PLATFORM is not specified and we couldn't guess it."
|
||||
#endif
|
||||
|
||||
#endif /* !defined(CS_PLATFORM) */
|
||||
|
||||
#define MG_NET_IF_SOCKET 1
|
||||
#define MG_NET_IF_SIMPLELINK 2
|
||||
#define MG_NET_IF_LWIP_LOW_LEVEL 3
|
||||
#define MG_NET_IF_PIC32 4
|
||||
|
||||
#define MG_SSL_IF_OPENSSL 1
|
||||
#define MG_SSL_IF_MBEDTLS 2
|
||||
#define MG_SSL_IF_SIMPLELINK 3
|
||||
|
||||
#include "common/platforms/platform_unix.h"
|
||||
#include "common/platforms/platform_windows.h"
|
||||
#include "common/platforms/platform_esp32.h"
|
||||
#include "common/platforms/platform_esp8266.h"
|
||||
#include "common/platforms/platform_cc3100.h"
|
||||
#include "common/platforms/platform_cc3200.h"
|
||||
#include "common/platforms/platform_cc3220.h"
|
||||
#include "common/platforms/platform_mbed.h"
|
||||
#include "common/platforms/platform_nrf51.h"
|
||||
#include "common/platforms/platform_nrf52.h"
|
||||
#include "common/platforms/platform_wince.h"
|
||||
#include "common/platforms/platform_nxp_lpc.h"
|
||||
#include "common/platforms/platform_nxp_kinetis.h"
|
||||
#include "common/platforms/platform_pic32.h"
|
||||
#include "common/platforms/platform_stm32.h"
|
||||
|
||||
/* Common stuff */
|
||||
|
||||
#if !defined(WEAK)
|
||||
#if (defined(__GNUC__) || defined(__TI_COMPILER_VERSION__)) && !defined(_WIN32)
|
||||
#define WEAK __attribute__((weak))
|
||||
#else
|
||||
#define WEAK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define NORETURN __attribute__((noreturn))
|
||||
#define NOINLINE __attribute__((noinline))
|
||||
#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#define NOINSTR __attribute__((no_instrument_function))
|
||||
#define DO_NOT_WARN_UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define NORETURN
|
||||
#define NOINLINE
|
||||
#define WARN_UNUSED_RESULT
|
||||
#define NOINSTR
|
||||
#define DO_NOT_WARN_UNUSED
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
||||
#endif
|
||||
|
||||
#endif /* CS_COMMON_PLATFORM_H_ */
|
@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2017 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
#include "common/platform.h"
|
||||
|
||||
#include "mgos_core_dump.h"
|
||||
#include "mgos_hal.h"
|
||||
|
||||
struct arm_exc_frame {
|
||||
uint32_t r0;
|
||||
uint32_t r1;
|
||||
uint32_t r2;
|
||||
uint32_t r3;
|
||||
uint32_t r12;
|
||||
uint32_t lr;
|
||||
uint32_t pc;
|
||||
uint32_t xpsr;
|
||||
#ifdef ARM_HAVE_FPU
|
||||
uint32_t s[16];
|
||||
uint32_t fpscr;
|
||||
uint32_t reserved;
|
||||
#endif
|
||||
} __attribute__((packed));
|
||||
|
||||
struct arm_gdb_reg_file {
|
||||
uint32_t r[13];
|
||||
uint32_t sp;
|
||||
uint32_t lr;
|
||||
uint32_t pc;
|
||||
uint32_t cpsr;
|
||||
uint64_t d[16];
|
||||
uint32_t fpscr;
|
||||
} __attribute__((packed));
|
||||
|
||||
#if ARM_HAVE_FPU
|
||||
static void save_s16_s31(uint32_t *dst) {
|
||||
__asm volatile(
|
||||
"\
|
||||
vmov r1, s16\n str r1, [%0, 0]\n\
|
||||
vmov r1, s17\n str r1, [%0, 4]\n\
|
||||
vmov r1, s18\n str r1, [%0, 8]\n\
|
||||
vmov r1, s19\n str r1, [%0, 12]\n\
|
||||
vmov r1, s20\n str r1, [%0, 16]\n\
|
||||
vmov r1, s21\n str r1, [%0, 20]\n\
|
||||
vmov r1, s22\n str r1, [%0, 24]\n\
|
||||
vmov r1, s23\n str r1, [%0, 28]\n\
|
||||
vmov r1, s24\n str r1, [%0, 32]\n\
|
||||
vmov r1, s25\n str r1, [%0, 36]\n\
|
||||
vmov r1, s26\n str r1, [%0, 40]\n\
|
||||
vmov r1, s27\n str r1, [%0, 44]\n\
|
||||
vmov r1, s28\n str r1, [%0, 48]\n\
|
||||
vmov r1, s29\n str r1, [%0, 52]\n\
|
||||
vmov r1, s30\n str r1, [%0, 56]\n\
|
||||
vmov r1, s31\n str r1, [%0, 60]\n\
|
||||
"
|
||||
:
|
||||
: "r"(dst)
|
||||
: "r1");
|
||||
}
|
||||
|
||||
static void print_fpu_regs(const uint32_t *regs, int off, int n) {
|
||||
for (int i = 0, j = off; i < n; i++, j++) {
|
||||
if (j % 4 == 0) mgos_cd_putc('\n');
|
||||
mgos_cd_printf(" S%d: %s0x%08lx", j, (j < 10 ? " " : ""), regs[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void arm_exc_handler_bottom(uint8_t isr_no, struct arm_exc_frame *ef,
|
||||
struct arm_gdb_reg_file *rf) {
|
||||
char buf[8];
|
||||
const char *name;
|
||||
portDISABLE_INTERRUPTS();
|
||||
switch (isr_no) {
|
||||
case 0:
|
||||
name = "ThreadMode";
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 13:
|
||||
name = "Reserved";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
name = "NMI";
|
||||
break;
|
||||
case 3:
|
||||
name = "HardFault";
|
||||
break;
|
||||
case 4:
|
||||
name = "MemManage";
|
||||
break;
|
||||
case 5:
|
||||
name = "BusFault";
|
||||
break;
|
||||
case 6:
|
||||
name = "UsageFault";
|
||||
break;
|
||||
case 11:
|
||||
name = "SVCall";
|
||||
break;
|
||||
case 12:
|
||||
name = "ReservedDebug";
|
||||
break;
|
||||
case 14:
|
||||
name = "PendSV";
|
||||
break;
|
||||
case 15:
|
||||
name = "SysTick";
|
||||
break;
|
||||
default: {
|
||||
sprintf(buf, "IRQ%u", isr_no - 16);
|
||||
name = buf;
|
||||
}
|
||||
}
|
||||
mgos_cd_printf("\n\n--- Exception %u (%s) ---\n", isr_no, name);
|
||||
if (rf != NULL) {
|
||||
mgos_cd_printf(" R0: 0x%08lx R1: 0x%08lx R2: 0x%08lx R3: 0x%08lx\n",
|
||||
rf->r[0], rf->r[1], rf->r[2], rf->r[3]);
|
||||
mgos_cd_printf(" R4: 0x%08lx R5: 0x%08lx R6: 0x%08lx R7: 0x%08lx\n",
|
||||
rf->r[4], rf->r[5], rf->r[6], rf->r[7]);
|
||||
mgos_cd_printf(" R8: 0x%08lx R9: 0x%08lx R10: 0x%08lx R11: 0x%08lx\n",
|
||||
rf->r[8], rf->r[9], rf->r[10], rf->r[11]);
|
||||
mgos_cd_printf(" R12: 0x%08lx SP: 0x%08lx LR: 0x%08lx PC: 0x%08lx\n",
|
||||
rf->r[12], rf->sp, rf->lr, rf->pc);
|
||||
mgos_cd_printf(" PSR: 0x%08lx\n", rf->cpsr);
|
||||
}
|
||||
memset(rf->d, 0, sizeof(rf->d));
|
||||
#if ARM_HAVE_FPU
|
||||
rf->fpscr = ef->fpscr;
|
||||
memcpy((uint8_t *) rf->d, ef->s, sizeof(ef->s));
|
||||
print_fpu_regs((uint32_t *) rf->d, 0, ARRAY_SIZE(ef->s));
|
||||
save_s16_s31(ef->s);
|
||||
memcpy(((uint8_t *) rf->d) + sizeof(ef->s), ef->s, sizeof(ef->s));
|
||||
print_fpu_regs((uint32_t *) (((uint8_t *) rf->d) + sizeof(ef->s)), 16,
|
||||
ARRAY_SIZE(ef->s));
|
||||
mgos_cd_putc('\n');
|
||||
mgos_cd_printf("FPSCR: 0x%08lx\n", rf->fpscr);
|
||||
#else
|
||||
rf->fpscr = 0;
|
||||
#endif
|
||||
mgos_cd_emit_header();
|
||||
mgos_cd_emit_section(MGOS_CORE_DUMP_SECTION_REGS, rf, sizeof(*rf));
|
||||
mgos_cd_emit_section("SRAM", (void *) SRAM_BASE_ADDR, SRAM_SIZE);
|
||||
mgos_cd_emit_footer();
|
||||
#ifdef MGOS_HALT_ON_EXCEPTION
|
||||
mgos_cd_printf("Halting\n");
|
||||
while (1) {
|
||||
mgos_wdt_feed();
|
||||
}
|
||||
#else
|
||||
mgos_cd_printf("Rebooting\n");
|
||||
mgos_dev_system_restart();
|
||||
#endif
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2017 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
.arch armv7e-m
|
||||
.syntax unified
|
||||
.thumb
|
||||
|
||||
/* These are required to satisfy TI linker. */
|
||||
.eabi_attribute Tag_ABI_align_needed, 1
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
|
||||
.global arm_exc_handler_top
|
||||
.global arm_exc_handler_bottom
|
||||
|
||||
/*
|
||||
* Determines the stack pointer, populates most of the GDB frame
|
||||
* and hands off to the C routine.
|
||||
*/
|
||||
.section .text.arm_exc_handler_top
|
||||
.type arm_exc_handler_top, %function
|
||||
.align 8
|
||||
|
||||
arm_exc_handler_top:
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r1, msp
|
||||
mrsne r1, psp
|
||||
// r1 -> arm_exc_frame prepared for us by the CPU
|
||||
#if ARM_HAVE_FPU
|
||||
add r0, r1, #104 // sizeof(arm_exc_frame)
|
||||
sub sp, #328 // sizeof(arm_gdb_reg_file)
|
||||
#else
|
||||
add r0, r1, #32 // sizeof(arm_exc_frame)
|
||||
sub sp, #328 // sizeof(arm_gdb_reg_file)
|
||||
#endif
|
||||
mov r2, sp
|
||||
// r0 -> original sp, r2 -> arm_gdb_reg_file to fill
|
||||
// r3 - scratch
|
||||
ldr r3, [r1, #0] // r0
|
||||
str r3, [r2, #0]
|
||||
ldr r3, [r1, #4] // r2
|
||||
str r3, [r2, #4]
|
||||
ldr r3, [r1, #8] // r1
|
||||
str r3, [r2, #8]
|
||||
ldr r3, [r1, #12] // r3
|
||||
str r3, [r2, #12]
|
||||
str r4, [r2, #16] // r4
|
||||
str r5, [r2, #20] // r5
|
||||
str r6, [r2, #24] // r6
|
||||
str r7, [r2, #28] // r7
|
||||
str r8, [r2, #32] // r8
|
||||
str r9, [r2, #36] // r9
|
||||
str r10, [r2, #40] // r10
|
||||
str r11, [r2, #44] // r11
|
||||
ldr r3, [r1, #16] // r12
|
||||
str r3, [r2, #48]
|
||||
str r0, [r2, #52] // sp
|
||||
ldr r3, [r1, #20] // lr
|
||||
str r3, [r2, #56]
|
||||
ldr r3, [r1, #24] // pc
|
||||
str r3, [r2, #60]
|
||||
ldr r3, [r1, #28] // xpsr
|
||||
str r3, [r2, #64]
|
||||
|
||||
mrs r0, ipsr
|
||||
b arm_exc_handler_bottom
|
||||
.size arm_exc_handler_top, . - arm_exc_handler_top
|
@ -1,92 +0,0 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* GCC Linker script for CC3200. Based on TI's example "blinky.ld".
|
||||
*
|
||||
* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* Neither the name of Texas Instruments Incorporated nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ORG = DEFINED(ORG) ? ORG : 0x20004000;
|
||||
RAM_SIZE = DEFINED(RAM_SIZE) ? RAM_SIZE : 0x3C000;
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* SRAM size of 240KB for cc3200 ES 1.33 device onward */
|
||||
SRAM (rwx) : ORIGIN = ORG, LENGTH = RAM_SIZE
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
_text = .;
|
||||
KEEP(*(.intvecs))
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
. = ALIGN(8);
|
||||
_etext = .;
|
||||
} > SRAM
|
||||
|
||||
.ARM : {
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
__exidx_end = .;
|
||||
} > SRAM
|
||||
|
||||
__init_data = .;
|
||||
|
||||
.data : AT(__init_data)
|
||||
{
|
||||
_data = .;
|
||||
*(.data*)
|
||||
. = ALIGN (8);
|
||||
_edata = .;
|
||||
} > SRAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
_bss = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
_ebss = .;
|
||||
} > SRAM
|
||||
|
||||
.heap :
|
||||
{
|
||||
_heap = .;
|
||||
. = . + (LENGTH(SRAM) - SIZEOF(.text) - SIZEOF(.ARM) - SIZEOF(.data) - SIZEOF(.bss));
|
||||
. = ALIGN(8);
|
||||
_eheap = .;
|
||||
|
||||
} > SRAM
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#if CS_PLATFORM == CS_P_CC3200
|
||||
|
||||
#include "common/mg_mem.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef __TI_COMPILER_VERSION__
|
||||
#include <reent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <inc/hw_types.h>
|
||||
#include <inc/hw_memmap.h>
|
||||
#include <driverlib/prcm.h>
|
||||
#include <driverlib/rom.h>
|
||||
#include <driverlib/rom_map.h>
|
||||
#include <driverlib/uart.h>
|
||||
#include <driverlib/utils.h>
|
||||
|
||||
#define CONSOLE_UART UARTA0_BASE
|
||||
|
||||
#ifdef __TI_COMPILER_VERSION__
|
||||
int asprintf(char **strp, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
int len;
|
||||
|
||||
*strp = MG_MALLOC(BUFSIZ);
|
||||
if (*strp == NULL) return -1;
|
||||
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(*strp, BUFSIZ, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len > 0) {
|
||||
*strp = MG_REALLOC(*strp, len + 1);
|
||||
if (*strp == NULL) return -1;
|
||||
}
|
||||
|
||||
if (len >= BUFSIZ) {
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(*strp, len + 1, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#if MG_TI_NO_HOST_INTERFACE
|
||||
time_t HOSTtime() {
|
||||
struct timeval tp;
|
||||
gettimeofday(&tp, NULL);
|
||||
return tp.tv_sec;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TI_COMPILER_VERSION__ */
|
||||
|
||||
void fprint_str(FILE *fp, const char *str) {
|
||||
while (*str != '\0') {
|
||||
if (*str == '\n') MAP_UARTCharPut(CONSOLE_UART, '\r');
|
||||
MAP_UARTCharPut(CONSOLE_UART, *str++);
|
||||
}
|
||||
}
|
||||
|
||||
void _exit(int status) {
|
||||
fprint_str(stderr, "_exit\n");
|
||||
/* cause an unaligned access exception, that will drop you into gdb */
|
||||
*(int *) 1 = status;
|
||||
while (1)
|
||||
; /* avoid gcc warning because stdlib abort() has noreturn attribute */
|
||||
}
|
||||
|
||||
void _not_implemented(const char *what) {
|
||||
fprint_str(stderr, what);
|
||||
fprint_str(stderr, " is not implemented\n");
|
||||
_exit(42);
|
||||
}
|
||||
|
||||
int _kill(int pid, int sig) {
|
||||
(void) pid;
|
||||
(void) sig;
|
||||
_not_implemented("_kill");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _getpid() {
|
||||
fprint_str(stderr, "_getpid is not implemented\n");
|
||||
return 42;
|
||||
}
|
||||
|
||||
int _isatty(int fd) {
|
||||
/* 0, 1 and 2 are TTYs. */
|
||||
return fd < 2;
|
||||
}
|
||||
|
||||
#endif /* CS_PLATFORM == CS_P_CC3200 */
|
@ -1,82 +0,0 @@
|
||||
//*****************************************************************************
|
||||
// cc3200v1p32.cmd
|
||||
//
|
||||
// CCS linker configuration file for cc3200 ES 1.32.
|
||||
//
|
||||
// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
|
||||
//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
//
|
||||
// Neither the name of Texas Instruments Incorporated nor the names of
|
||||
// its contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
--retain=g_pfnVectors
|
||||
|
||||
//*****************************************************************************
|
||||
// The following command line options are set as part of the CCS project.
|
||||
// If you are building using the command line, or for some reason want to
|
||||
// define them here, you can uncomment and modify these lines as needed.
|
||||
// If you are using CCS for building, it is probably better to make any such
|
||||
// modifications in your CCS project and leave this file alone.
|
||||
//*****************************************************************************
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
// The starting address of the application. Normally the interrupt vectors
|
||||
// must be located at the beginning of the application.
|
||||
//*****************************************************************************
|
||||
#define RAM_BASE 0x20004000
|
||||
|
||||
/* System memory map */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* Application uses internal RAM for program and data */
|
||||
SRAM_CODE (RWX) : origin = 0x20004000, length = 0x2F000
|
||||
SRAM_DATA (RWX) : origin = 0x20033000, length = 0xD000
|
||||
}
|
||||
|
||||
/* Section allocation in memory */
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.intvecs: > RAM_BASE
|
||||
.init_array : > SRAM_CODE
|
||||
.vtable : > SRAM_CODE
|
||||
.text : > SRAM_CODE
|
||||
.const : > SRAM_CODE
|
||||
.cinit : > SRAM_CODE
|
||||
.pinit : > SRAM_CODE
|
||||
.data : > SRAM_DATA
|
||||
.bss : > SRAM_DATA
|
||||
.sysmem : > SRAM_DATA
|
||||
.stack : > SRAM_DATA(HIGH)
|
||||
}
|
||||
|
@ -1,52 +0,0 @@
|
||||
APP_LDFLAGS ?=
|
||||
CC_WRAPPER ?=
|
||||
GENFILES_LIST ?=
|
||||
CC = arm-none-eabi-gcc
|
||||
CXX = arm-none-eabi-g++
|
||||
AR = arm-none-eabi-ar
|
||||
NM = arm-none-eabi-nm
|
||||
|
||||
IPATH += $(SDK_PATH)/third_party/FreeRTOS/source/portable/GCC/ARM_CM4
|
||||
VPATH += $(SDK_PATH)/third_party/FreeRTOS/source/portable/GCC/ARM_CM4
|
||||
|
||||
C_CXX_FLAGS = -mthumb -mcpu=cortex-m4 -ffunction-sections -fdata-sections \
|
||||
-MD -Os -ggdb -Wall -Werror -Dgcc
|
||||
CFLAGS += -std=c99 $(C_CXX_FLAGS)
|
||||
CXXFLAGS += -std=g++11 $(C_CXX_FLAGS)
|
||||
|
||||
AR = arm-none-eabi-ar
|
||||
LD = arm-none-eabi-ld
|
||||
OBJCOPY = arm-none-eabi-objcopy
|
||||
LIBGCC := ${shell ${CC} -mthumb ${CFLAGS} -print-libgcc-file-name}
|
||||
LIBC := ${shell ${CC} ${CFLAGS} -print-file-name=libc.a}
|
||||
LIBM := ${shell ${CC} ${CFLAGS} -print-file-name=libm.a}
|
||||
|
||||
# Disable certain warnings on SDK sources, we have no control over them anyway.
|
||||
# We also force-include platform.h which resolves some symbol conflicts
|
||||
# between system includes and simplelink.h
|
||||
$(SDK_OBJS): CFLAGS += -Wno-missing-braces -Wno-strict-aliasing -Wno-parentheses -Wno-unused-variable -Wno-builtin-macro-redefined
|
||||
$(SDK_OBJS): CFLAGS += -include common/platform.h
|
||||
|
||||
# cc flags,file
|
||||
define cc
|
||||
$(vecho) "GCC $2 -> $@"
|
||||
$(Q) $(CC_WRAPPER) $(CC) -c $1 -o $@ $2
|
||||
endef
|
||||
define cxx
|
||||
$(vecho) "G++ $2 -> $@"
|
||||
$(Q) $(CC_WRAPPER) $(CXX) -c $1 -o $@ $2
|
||||
endef
|
||||
|
||||
# ar files
|
||||
define ar
|
||||
$(vecho) "AR $@"
|
||||
$(Q) $(AR) cru $@ $1
|
||||
endef
|
||||
|
||||
# link script,flags,objs
|
||||
define link
|
||||
$(vecho) "LD $@"
|
||||
$(Q) $(CC_WRAPPER) $(LD) \
|
||||
--gc-sections -o $@ -T $1 $2 $3 \
|
||||
$(LIBM) $(LIBC) $(LIBGCC)
|
||||
endef
|
@ -1,52 +0,0 @@
|
||||
IPATH += $(SDK_PATH)/third_party/FreeRTOS/source/portable/CCS/ARM_CM3
|
||||
VPATH += $(SDK_PATH)/third_party/FreeRTOS/source/portable/CCS/ARM_CM3
|
||||
|
||||
CC_WRAPPER ?=
|
||||
CC = $(TOOLCHAIN)/bin/armcl
|
||||
AR = $(TOOLCHAIN)/bin/armar
|
||||
NM = nm
|
||||
GENFILES_LIST ?=
|
||||
|
||||
C_CXX_FLAGS = -Dccs -I$(TOOLCHAIN)/include
|
||||
TI_C_CXX_FLAGS = -mv7M4 --little_endian --code_state=16 --float_support=vfplib --abi=eabi \
|
||||
-O4 --opt_for_speed=0 --unaligned_access=on --small_enum \
|
||||
--gen_func_subsections=on --diag_wrap=off --display_error_number \
|
||||
--emit_warnings_as_errors
|
||||
CFLAGS += --c99 $(TI_C_CXX_FLAGS) $(C_CXX_FLAGS)
|
||||
CXXFLAGS += $(TI_C_CXX_FLAGS) $(C_CXX_FLAGS)
|
||||
|
||||
# cc flags,file
|
||||
define cc
|
||||
$(vecho) "TICC $2 -> $@"
|
||||
$(Q) $(CC_WRAPPER) $(CC) -c --preproc_with_compile -ppd=$@.d $1 --output_file=$@ $2
|
||||
endef
|
||||
define cxx
|
||||
$(vecho) "TICXX $2 -> $@"
|
||||
$(Q) $(CC_WRAPPER) $(CC) -c --preproc_with_compile -ppd=$@.d $1 --output_file=$@ $2
|
||||
endef
|
||||
|
||||
# asm flags,file
|
||||
define asm
|
||||
$(vecho) "TIASM $2 -> $@"
|
||||
$(Q) $(CC_WRAPPER) $(CC) -c $1 --output_file=$@ $2
|
||||
endef
|
||||
|
||||
# ar files
|
||||
define ar
|
||||
$(vecho) "TIAR $@"
|
||||
$(Q) $(AR) qru $@ $1
|
||||
endef
|
||||
|
||||
# link script,flags,objs
|
||||
define link
|
||||
$(vecho) "TILD $@"
|
||||
$(Q) $(CC_WRAPPER) $(CC) \
|
||||
-mv7M4 --code_state=16 --float_support=vfplib --abi=eabi --little_endian \
|
||||
--run_linker \
|
||||
--generate_dead_funcs_list=$@.garbage.xml \
|
||||
-i $(TOOLCHAIN)/lib \
|
||||
--reread_libs --warn_sections --display_error_number \
|
||||
--unused_section_elimination=on \
|
||||
-o $@ --map_file=$@.map --xml_link_info=$@.map.xml \
|
||||
$2 $1 $3
|
||||
endef
|
File diff suppressed because it is too large
Load Diff
@ -1,35 +0,0 @@
|
||||
#include "rom_functions.h"
|
||||
|
||||
void SLIP_send(uint8_t *pkt, uint32_t size) {
|
||||
send_packet(pkt, size);
|
||||
}
|
||||
|
||||
uint32_t SLIP_recv(void *pkt, uint32_t max_len) {
|
||||
uint8_t c;
|
||||
uint32_t len = 0;
|
||||
uint8_t *p = (uint8_t *) pkt;
|
||||
do {
|
||||
c = uart_rx_one_char_block();
|
||||
} while (c != '\xc0');
|
||||
while (len < max_len) {
|
||||
c = uart_rx_one_char_block();
|
||||
if (c == '\xc0') return len;
|
||||
if (c == '\xdb') {
|
||||
c = uart_rx_one_char_block();
|
||||
if (c == '\xdc') {
|
||||
c = '\xc0';
|
||||
} else if (c == '\xdd') {
|
||||
c = '\xdb';
|
||||
} else {
|
||||
len = 0;
|
||||
break; /* Bad esc sequence. */
|
||||
}
|
||||
}
|
||||
*p++ = c;
|
||||
len++;
|
||||
}
|
||||
do {
|
||||
c = uart_rx_one_char_block();
|
||||
} while (c != '\xc0');
|
||||
return len;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_STUBS_SLIP_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_STUBS_SLIP_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
void SLIP_send(const void *pkt, uint32_t size);
|
||||
uint32_t SLIP_recv(void *pkt, uint32_t max_len);
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_STUBS_SLIP_H_ */
|
@ -1,559 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* Spiffy flasher. Implements strong checksums (MD5) and can use higher
|
||||
* baud rates. Actual max baud rate will differe from device to device,
|
||||
* but 921K seems to be common.
|
||||
*
|
||||
* SLIP protocol is used for communication.
|
||||
* First packet is a single byte - command number.
|
||||
* After that, a packet with a variable number of 32-bit (LE) arguments,
|
||||
* depending on command.
|
||||
*
|
||||
* Then command produces variable number of packets of output, but first
|
||||
* packet of length 1 is the response code: 0 for success, non-zero - error.
|
||||
*
|
||||
* See individual command description below.
|
||||
*/
|
||||
|
||||
#include "stub_flasher.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rom_functions.h"
|
||||
|
||||
#if defined(ESP8266)
|
||||
#include "eagle_soc.h"
|
||||
#include "ets_sys.h"
|
||||
#include "../../../miniz.c"
|
||||
#elif defined(ESP32)
|
||||
#include "rom/efuse.h"
|
||||
#include "rom/miniz.h"
|
||||
#include "rom/spi_flash.h"
|
||||
#include "soc/uart_reg.h"
|
||||
#include "led.h"
|
||||
#endif
|
||||
|
||||
#include "slip.h"
|
||||
#include "uart.h"
|
||||
|
||||
/* Param: baud rate. */
|
||||
uint32_t params[1] __attribute__((section(".params")));
|
||||
|
||||
#define FLASH_BLOCK_SIZE 65536
|
||||
#define FLASH_SECTOR_SIZE 4096
|
||||
#define FLASH_PAGE_SIZE 256
|
||||
|
||||
/* These consts should be in sync with flasher_client.go */
|
||||
#define NUM_BUFS 4
|
||||
#define BUF_SIZE 4096
|
||||
#define FLASH_WRITE_SIZE BUF_SIZE
|
||||
|
||||
#define UART_RX_INTS (UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA)
|
||||
|
||||
extern uint32_t _bss_start, _bss_end;
|
||||
|
||||
#ifdef ESP8266
|
||||
#define REG_SPI_BASE(i) (0x60000200 - i * 0x100)
|
||||
|
||||
#define SPI_CMD_REG(i) (REG_SPI_BASE(i) + 0x0)
|
||||
#define SPI_FLASH_WREN (BIT(30))
|
||||
#define SPI_FLASH_RDID (BIT(28))
|
||||
#define SPI_FLASH_SE (BIT(24))
|
||||
#define SPI_FLASH_BE (BIT(23))
|
||||
|
||||
#define SPI_ADDR_REG(i) (REG_SPI_BASE(i) + 0x4)
|
||||
|
||||
#define SPI_USER_REG(i) (REG_SPI_BASE(i) + 0x1C)
|
||||
|
||||
#define SPI_W0_REG(i) (REG_SPI_BASE(i) + 0x40)
|
||||
#endif
|
||||
|
||||
enum read_state {
|
||||
READ_WAIT_START = 0,
|
||||
READ_FLAGS,
|
||||
READ_DATA,
|
||||
READ_UNESCAPE,
|
||||
READ_ERROR,
|
||||
};
|
||||
|
||||
struct data_buf {
|
||||
uint32_t len;
|
||||
uint8_t data[BUF_SIZE];
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
#define FLAG_COMPRESSED 1
|
||||
|
||||
struct uart_buf {
|
||||
enum read_state state;
|
||||
struct data_buf bufs[NUM_BUFS];
|
||||
uint32_t bri, bwi;
|
||||
uint32_t ps;
|
||||
};
|
||||
|
||||
static inline uint32_t ccount(void) {
|
||||
uint32_t r;
|
||||
__asm volatile("rsr.ccount %0" : "=a"(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
struct write_progress {
|
||||
uint32_t num_written;
|
||||
uint32_t buf_level;
|
||||
uint8_t digest[16];
|
||||
};
|
||||
|
||||
struct write_result {
|
||||
uint32_t wait_time;
|
||||
uint32_t decomp_time;
|
||||
uint32_t write_time;
|
||||
uint32_t erase_time;
|
||||
uint32_t total_time;
|
||||
uint8_t digest[16];
|
||||
};
|
||||
|
||||
static struct uart_buf ub;
|
||||
static uint32_t inflate_buf[TINFL_LZ_DICT_SIZE / sizeof(uint32_t)];
|
||||
|
||||
static void next_write_buf(void) {
|
||||
ub.bwi++;
|
||||
if (ub.bwi == NUM_BUFS) ub.bwi = 0;
|
||||
ub.bufs[ub.bwi].len = 0;
|
||||
ub.bufs[ub.bwi].flags = 0;
|
||||
}
|
||||
|
||||
static void add_byte(uint8_t byte) {
|
||||
struct data_buf *buf = &ub.bufs[ub.bwi];
|
||||
if (buf->len < BUF_SIZE) {
|
||||
buf->data[buf->len++] = byte;
|
||||
ub.ps++;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_isr(void *arg) {
|
||||
uint32_t int_st = READ_PERI_REG(UART_INT_ST_REG(0));
|
||||
uint8_t fifo_len, i;
|
||||
while ((fifo_len = READ_PERI_REG(UART_STATUS_REG(0))) > 0) {
|
||||
for (i = 0; i < fifo_len; i++) {
|
||||
uint8_t byte = READ_PERI_REG(UART_FIFO_REG(0));
|
||||
switch (ub.state) {
|
||||
case READ_WAIT_START: {
|
||||
if (byte == 0xc0) {
|
||||
ub.state = READ_FLAGS;
|
||||
ub.ps = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case READ_FLAGS:
|
||||
case READ_DATA: {
|
||||
struct data_buf *buf = &ub.bufs[ub.bwi];
|
||||
if (byte == 0xdb) {
|
||||
ub.state = READ_UNESCAPE;
|
||||
} else if (byte == 0xc0) {
|
||||
next_write_buf();
|
||||
if (ub.ps == 0) {
|
||||
/* Empty packet, sender aborted. */
|
||||
ub.state = READ_ERROR;
|
||||
SET_PERI_REG_MASK(UART_INT_ENA_REG(0), 0);
|
||||
goto out;
|
||||
} else {
|
||||
ub.state = READ_WAIT_START;
|
||||
}
|
||||
} else {
|
||||
if (ub.state == READ_FLAGS) {
|
||||
buf->flags = byte;
|
||||
ub.state = READ_DATA;
|
||||
} else {
|
||||
add_byte(byte);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case READ_UNESCAPE: {
|
||||
if (byte == 0xdc) {
|
||||
byte = 0xc0;
|
||||
} else if (byte == 0xdd) {
|
||||
byte = 0xdb;
|
||||
} else {
|
||||
ub.state = READ_ERROR;
|
||||
SET_PERI_REG_MASK(UART_INT_ENA_REG(0), 0);
|
||||
goto out;
|
||||
}
|
||||
add_byte(byte);
|
||||
ub.state = READ_DATA;
|
||||
break;
|
||||
}
|
||||
case READ_ERROR: {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
WRITE_PERI_REG(UART_INT_CLR_REG(0), int_st);
|
||||
(void) arg;
|
||||
}
|
||||
|
||||
size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
|
||||
const void *pSrc_buf, size_t src_buf_len,
|
||||
int flags);
|
||||
#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
|
||||
#define TINFL_FLAG_PARSE_ZLIB_HEADER 1
|
||||
|
||||
#if defined(ESP8266)
|
||||
int esp_rom_spiflash_erase_start(uint32_t addr, uint32_t cmd) {
|
||||
SPI_write_enable(flashchip);
|
||||
WRITE_PERI_REG(SPI_ADDR_REG(0), addr);
|
||||
WRITE_PERI_REG(SPI_CMD_REG(0), cmd);
|
||||
while (READ_PERI_REG(SPI_CMD_REG(0)) & cmd) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#elif defined(ESP32)
|
||||
extern esp_rom_spiflash_chip_t g_rom_spiflash_chip;
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_erase_start(uint32_t addr,
|
||||
uint32_t cmd) {
|
||||
esp_rom_spiflash_chip_t *spi = &g_rom_spiflash_chip;
|
||||
esp_rom_spiflash_wait_idle(spi);
|
||||
|
||||
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
|
||||
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN,
|
||||
ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN);
|
||||
|
||||
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_WREN);
|
||||
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0) {
|
||||
}
|
||||
|
||||
WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, addr);
|
||||
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, cmd);
|
||||
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
int do_flash_write(uint32_t addr, uint32_t len, uint32_t erase) {
|
||||
int ret = 0;
|
||||
uint32_t num_erased = 0;
|
||||
struct MD5Context ctx;
|
||||
MD5Init(&ctx);
|
||||
|
||||
if (addr % FLASH_SECTOR_SIZE != 0) return 0x32;
|
||||
if (len % FLASH_SECTOR_SIZE != 0) return 0x33;
|
||||
if (esp_rom_spiflash_unlock() != 0) return 0x34;
|
||||
|
||||
memset(&ub, 0, sizeof(ub));
|
||||
memset(&inflate_buf, 0, sizeof(inflate_buf));
|
||||
ets_isr_attach(ETS_UART0_INUM, uart_isr, &ub);
|
||||
uint32_t saved_conf1 = READ_PERI_REG(UART_CONF1_REG(0));
|
||||
/* Reduce frequency of UART interrupts */
|
||||
WRITE_PERI_REG(UART_CONF1_REG(0), UART_RX_TOUT_EN |
|
||||
(20 << UART_RX_TOUT_THRHD_S) |
|
||||
(100 << UART_RXFIFO_FULL_THRHD_S));
|
||||
SET_PERI_REG_MASK(UART_INT_ENA_REG(0), UART_RX_INTS);
|
||||
ets_isr_unmask(1 << ETS_UART0_INUM);
|
||||
|
||||
struct write_result wr;
|
||||
memset(&wr, 0, sizeof(wr));
|
||||
|
||||
struct write_progress wp = {.num_written = 0, .buf_level = 0};
|
||||
wp.buf_level = (uint32_t) &addr;
|
||||
SLIP_send(&wp, sizeof(wp));
|
||||
wr.total_time = ccount();
|
||||
while (wp.num_written < len) {
|
||||
/* Prepare the space ahead. */
|
||||
uint32_t start_count = ccount();
|
||||
while (erase && num_erased < wp.num_written + FLASH_WRITE_SIZE) {
|
||||
const uint32_t num_left = (len - num_erased);
|
||||
if (num_left >= FLASH_BLOCK_SIZE && addr % FLASH_BLOCK_SIZE == 0) {
|
||||
if (esp_rom_spiflash_erase_start(addr, SPI_FLASH_BE) != 0) {
|
||||
ret = 0x35;
|
||||
goto out;
|
||||
}
|
||||
num_erased += FLASH_BLOCK_SIZE;
|
||||
} else {
|
||||
/* len % FLASH_SECTOR_SIZE == 0 is enforced, no further checks needed */
|
||||
if (esp_rom_spiflash_erase_start(addr, SPI_FLASH_SE) != 0) {
|
||||
ret = 0x36;
|
||||
goto out;
|
||||
}
|
||||
num_erased += FLASH_SECTOR_SIZE;
|
||||
}
|
||||
}
|
||||
wr.erase_time += ccount() - start_count;
|
||||
start_count = ccount();
|
||||
/* Wait for data to arrive. */
|
||||
wp.buf_level = 0;
|
||||
for (int i = 0; i < NUM_BUFS; i++) wp.buf_level += ub.bufs[i].len;
|
||||
volatile uint32_t *bwi = &ub.bwi;
|
||||
while (*bwi == ub.bri && ub.state != READ_ERROR) {
|
||||
}
|
||||
struct data_buf *buf = &ub.bufs[ub.bri];
|
||||
if (ub.state == READ_ERROR) {
|
||||
ret = 0x37;
|
||||
goto out;
|
||||
}
|
||||
wr.wait_time += ccount() - start_count;
|
||||
start_count = ccount();
|
||||
uint32_t *data = (uint32_t *) buf->data;
|
||||
uint32_t write_len = buf->len;
|
||||
if (buf->flags & FLAG_COMPRESSED) {
|
||||
data = inflate_buf;
|
||||
write_len = tinfl_decompress_mem_to_mem(
|
||||
&inflate_buf[0], sizeof(inflate_buf), buf->data, write_len,
|
||||
TINFL_FLAG_PARSE_ZLIB_HEADER);
|
||||
if (write_len == TINFL_DECOMPRESS_MEM_TO_MEM_FAILED) {
|
||||
ret = 0x40;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
wr.decomp_time += ccount() - start_count;
|
||||
MD5Update(&ctx, (uint8_t *) data, write_len);
|
||||
start_count = ccount();
|
||||
wr.erase_time += ccount() - start_count;
|
||||
start_count = ccount();
|
||||
if (esp_rom_spiflash_write(addr, data, write_len) != 0) {
|
||||
ret = 0x38;
|
||||
goto out;
|
||||
}
|
||||
wr.write_time += ccount() - start_count;
|
||||
buf->len = 0;
|
||||
ub.bri++;
|
||||
if (ub.bri == NUM_BUFS) ub.bri = 0;
|
||||
addr += write_len;
|
||||
wp.num_written += write_len;
|
||||
struct MD5Context ctx2;
|
||||
memcpy(&ctx2, &ctx, sizeof(ctx));
|
||||
MD5Final(wp.digest, &ctx2);
|
||||
SLIP_send(&wp, sizeof(wp));
|
||||
}
|
||||
|
||||
MD5Final(wr.digest, &ctx);
|
||||
|
||||
wr.total_time = ccount() - wr.total_time;
|
||||
SLIP_send(&wr, sizeof(wr));
|
||||
|
||||
out:
|
||||
WRITE_PERI_REG(UART_CONF1_REG(0), saved_conf1);
|
||||
ets_isr_mask(1 << ETS_UART0_INUM);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_flash_read(uint32_t addr, uint32_t len, uint32_t block_size,
|
||||
uint32_t max_in_flight) {
|
||||
uint8_t buf[FLASH_SECTOR_SIZE];
|
||||
uint8_t digest[16];
|
||||
struct MD5Context ctx;
|
||||
uint32_t num_sent = 0, num_acked = 0;
|
||||
if (block_size > sizeof(buf)) return 0x52;
|
||||
MD5Init(&ctx);
|
||||
while (num_acked < len) {
|
||||
while (num_sent < len && num_sent - num_acked < max_in_flight) {
|
||||
uint32_t n = len - num_sent;
|
||||
if (n > block_size) n = block_size;
|
||||
if (esp_rom_spiflash_read(addr, (uint32_t *) buf, n) != 0) return 0x53;
|
||||
send_packet(buf, n);
|
||||
MD5Update(&ctx, buf, n);
|
||||
addr += n;
|
||||
num_sent += n;
|
||||
}
|
||||
{
|
||||
if (SLIP_recv(&num_acked, sizeof(num_acked)) != 4) return 0x54;
|
||||
if (num_acked > num_sent) return 0x55;
|
||||
}
|
||||
}
|
||||
MD5Final(digest, &ctx);
|
||||
send_packet(digest, sizeof(digest));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_flash_digest(uint32_t addr, uint32_t len, uint32_t digest_block_size) {
|
||||
uint8_t buf[FLASH_SECTOR_SIZE];
|
||||
uint8_t digest[16];
|
||||
uint32_t read_block_size =
|
||||
digest_block_size ? digest_block_size : sizeof(buf);
|
||||
struct MD5Context ctx;
|
||||
if (digest_block_size > sizeof(buf)) return 0x62;
|
||||
MD5Init(&ctx);
|
||||
while (len > 0) {
|
||||
uint32_t n = len;
|
||||
struct MD5Context block_ctx;
|
||||
MD5Init(&block_ctx);
|
||||
if (n > read_block_size) n = read_block_size;
|
||||
if (esp_rom_spiflash_read(addr, (uint32_t *) buf, n) != 0) return 0x63;
|
||||
MD5Update(&ctx, buf, n);
|
||||
if (digest_block_size > 0) {
|
||||
MD5Update(&block_ctx, buf, n);
|
||||
MD5Final(digest, &block_ctx);
|
||||
send_packet(digest, sizeof(digest));
|
||||
}
|
||||
addr += n;
|
||||
len -= n;
|
||||
}
|
||||
MD5Final(digest, &ctx);
|
||||
send_packet(digest, sizeof(digest));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_flash_read_chip_id(void) {
|
||||
uint32_t chip_id = 0;
|
||||
WRITE_PERI_REG(SPI_CMD_REG(0), SPI_FLASH_RDID);
|
||||
while (READ_PERI_REG(SPI_CMD_REG(0)) & SPI_FLASH_RDID) {
|
||||
}
|
||||
chip_id = READ_PERI_REG(SPI_W0_REG(0)) & 0xFFFFFF;
|
||||
send_packet((uint8_t *) &chip_id, sizeof(chip_id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t cmd_loop(void) {
|
||||
uint8_t cmd = 0x55;
|
||||
do {
|
||||
/* Reset FIFO to re-sync */
|
||||
SET_PERI_REG_MASK(UART_CONF0_REG(0), UART_RXFIFO_RST);
|
||||
CLEAR_PERI_REG_MASK(UART_CONF0_REG(0), UART_RXFIFO_RST);
|
||||
uint32_t args[4];
|
||||
uint32_t len = SLIP_recv(&cmd, 1);
|
||||
if (len != 1) {
|
||||
continue;
|
||||
}
|
||||
uint8_t resp = 0xff;
|
||||
switch (cmd) {
|
||||
case CMD_FLASH_WRITE: {
|
||||
len = SLIP_recv(args, sizeof(args));
|
||||
if (len == 12) {
|
||||
resp = do_flash_write(args[0] /* addr */, args[1] /* len */,
|
||||
args[2] /* erase */);
|
||||
} else {
|
||||
resp = 0x41;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CMD_FLASH_READ: {
|
||||
len = SLIP_recv(args, sizeof(args));
|
||||
if (len == 16) {
|
||||
resp = do_flash_read(args[0] /* addr */, args[1], /* len */
|
||||
args[2] /* block_size */,
|
||||
args[3] /* max_in_flight */);
|
||||
} else {
|
||||
resp = 0x51;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CMD_FLASH_DIGEST: {
|
||||
len = SLIP_recv(args, sizeof(args));
|
||||
if (len == 12) {
|
||||
resp = do_flash_digest(args[0] /* addr */, args[1], /* len */
|
||||
args[2] /* digest_block_size */);
|
||||
} else {
|
||||
resp = 0x61;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CMD_FLASH_READ_CHIP_ID: {
|
||||
resp = do_flash_read_chip_id();
|
||||
break;
|
||||
}
|
||||
case CMD_FLASH_ERASE_CHIP: {
|
||||
resp = esp_rom_spiflash_erase_chip();
|
||||
break;
|
||||
}
|
||||
case CMD_BOOT_FW:
|
||||
case CMD_REBOOT: {
|
||||
resp = 0;
|
||||
SLIP_send(&resp, 1);
|
||||
return cmd;
|
||||
}
|
||||
case CMD_ECHO: {
|
||||
len = SLIP_recv(args, sizeof(args));
|
||||
SLIP_send(args, len);
|
||||
resp = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SLIP_send(&resp, 1);
|
||||
} while (cmd != CMD_BOOT_FW && cmd != CMD_REBOOT);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void stub_main1(void) {
|
||||
uint32_t baud_rate = params[0];
|
||||
uint32_t greeting = 0x4941484f; /* OHAI */
|
||||
uint8_t last_cmd;
|
||||
|
||||
/* This points at us right now, reset for next boot. */
|
||||
ets_set_user_start(0);
|
||||
|
||||
/* Selects SPI functions for flash pins. */
|
||||
#if defined(ESP8266)
|
||||
SelectSpiFunction();
|
||||
SET_PERI_REG_MASK(0x3FF00014, 1); /* Switch to 160 MHz */
|
||||
#elif defined(ESP32)
|
||||
esp_rom_spiflash_attach(ets_efuse_get_spiconfig(), 0 /* legacy */);
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_config_param(
|
||||
0 /* deviceId */, 16 * 1024 * 1024 /* chip_size */, FLASH_BLOCK_SIZE,
|
||||
FLASH_SECTOR_SIZE, FLASH_PAGE_SIZE, 0xffff /* status_mask */);
|
||||
|
||||
if (baud_rate > 0) {
|
||||
ets_delay_us(10000);
|
||||
set_baud_rate(0, baud_rate);
|
||||
}
|
||||
|
||||
/* Give host time to get ready too. */
|
||||
ets_delay_us(50000);
|
||||
|
||||
#ifdef BAUD_TEST
|
||||
while (1) {
|
||||
WRITE_PERI_REG(UART_FIFO_REG(0), 0x55);
|
||||
}
|
||||
#else
|
||||
SLIP_send(&greeting, 4);
|
||||
#endif
|
||||
|
||||
last_cmd = cmd_loop();
|
||||
|
||||
ets_delay_us(10000);
|
||||
|
||||
if (last_cmd == CMD_BOOT_FW) {
|
||||
#if defined(ESP8266)
|
||||
/*
|
||||
* Find the return address in our own stack and change it.
|
||||
* "flash_finish" it gets to the same point, except it doesn't need to
|
||||
* patch up its RA: it returns from UartDwnLdProc, then from f_400011ac,
|
||||
* then jumps to 0x4000108a, then checks strapping bits again (which will
|
||||
* not have changed), and then proceeds to 0x400010a8.
|
||||
*/
|
||||
volatile uint32_t *sp = &baud_rate;
|
||||
while (*sp != (uint32_t) 0x40001100) sp++;
|
||||
*sp = 0x400010a8;
|
||||
/*
|
||||
* The following dummy asm fragment acts as a barrier, to make sure function
|
||||
* epilogue, including return address loading, is added after our stack
|
||||
* patching.
|
||||
*/
|
||||
__asm volatile("nop.n");
|
||||
return; /* To 0x400010a8 */
|
||||
#elif defined(ESP32)
|
||||
/* TODO(rojer) */
|
||||
#endif
|
||||
} else {
|
||||
software_reset();
|
||||
}
|
||||
/* Not reached */
|
||||
}
|
||||
|
||||
/* miniz requires at least 12K of stack */
|
||||
uint32_t stack[3071];
|
||||
uint32_t stack_end;
|
||||
|
||||
void stub_main(void) {
|
||||
memset(&_bss_start, 0, (&_bss_end - &_bss_start));
|
||||
__asm volatile("movi a1, stack_end\n");
|
||||
stub_main1();
|
||||
// Keep the stack vars alive.
|
||||
stack[0] = stack_end = 0xff;
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_STUBS_STUB_FLASHER_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_STUBS_STUB_FLASHER_H_
|
||||
|
||||
enum stub_cmd {
|
||||
/*
|
||||
* Write to the SPI flash.
|
||||
*
|
||||
* Args: addr, len, erase; addr and len must be SECTOR_SIZE-aligned.
|
||||
* If erase != 0, perform erase before writing.
|
||||
* Input: Stream of data to be written, note: no SLIP encapsulation here.
|
||||
* Output: SLIP packets with number of bytes written after every write.
|
||||
* This can (and should) be used for flow control. Flasher will
|
||||
* write in 1K chunks but will buffer up to 4K of data
|
||||
* Use this feedback to keep buffer above 1K but below 4K.
|
||||
* Final packet will contain MD5 digest of the data written.
|
||||
*/
|
||||
CMD_FLASH_WRITE = 1,
|
||||
|
||||
/*
|
||||
* Read from the SPI flash.
|
||||
*
|
||||
* Args: addr, len, block_size; no alignment requirements, block_size <= 4K.
|
||||
* Input: None.
|
||||
* Output: Packets of up to block_size with data. An acknowledgement is
|
||||
*expected
|
||||
* after every packet, in the form of a packet with total number of
|
||||
* bytes received so far.
|
||||
* Last packet is the MD5 digest of the data sent.
|
||||
*
|
||||
* Note: No flow control is performed, it is assumed that the host can cope
|
||||
* with the inbound stream.
|
||||
*/
|
||||
CMD_FLASH_READ = 2,
|
||||
|
||||
/*
|
||||
* Compute MD5 digest of the specified flash region.
|
||||
*
|
||||
* Args: addr, len, digest_block_size; no alignment requirements.
|
||||
* Input: None.
|
||||
* Output: If block digests are not enabled (digest_block_size == 0),
|
||||
* only overall digest is produced.
|
||||
* Otherwise, there will be a separate digest for each block,
|
||||
* the remainder (if any) and the overall digest at the end.
|
||||
*/
|
||||
CMD_FLASH_DIGEST = 3,
|
||||
|
||||
/*
|
||||
* Read flash chip ID.
|
||||
* This is the JEDEC ID, containinf manufactirer, SPI mode and capacity.
|
||||
*
|
||||
* Args: None.
|
||||
* Input: None.
|
||||
* Output: 32 bit chip id (only 24 bits are meaningful).
|
||||
*/
|
||||
CMD_FLASH_READ_CHIP_ID = 4,
|
||||
|
||||
/*
|
||||
* Zap the whole chip at once.
|
||||
*
|
||||
* Args: None.
|
||||
* Input: None.
|
||||
* Output: None.
|
||||
*/
|
||||
CMD_FLASH_ERASE_CHIP = 5,
|
||||
|
||||
/*
|
||||
* Boots the firmware from flash.
|
||||
*
|
||||
* Args: None.
|
||||
* Input: None.
|
||||
* Output: None.
|
||||
*/
|
||||
CMD_BOOT_FW = 6,
|
||||
|
||||
/*
|
||||
* Reboot the CPU.
|
||||
* Since strapping settings are not reset, this will reboot into whatever mode
|
||||
* got us here, most likely UART loader.
|
||||
*
|
||||
* Args: None.
|
||||
* Input: None.
|
||||
* Output: None.
|
||||
*/
|
||||
CMD_REBOOT = 7,
|
||||
|
||||
/*
|
||||
* Echo the arguments back to the host.
|
||||
*
|
||||
* Args: variable.
|
||||
* Input: None.
|
||||
* Output: arguments.
|
||||
*/
|
||||
CMD_ECHO = 8,
|
||||
};
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_STUBS_STUB_FLASHER_H_ */
|
@ -1 +0,0 @@
|
||||
rom.bin -nodiff
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
xtensa-esp108-elf-gcc -Wl,-N,-Ttext,0x40000000 -nostdlib rom.S -o rom.elf && \
|
||||
xtensa-esp108-elf-objdump -d rom.elf > ESP31B_ROM.txt
|
@ -1,163 +0,0 @@
|
||||
/* Just some notes scribbled while disassembling */
|
||||
|
||||
/*
|
||||
* RTC = 0x60008000
|
||||
* RTC+0x18: ??c????? ???????? ???????? ????????
|
||||
* RTC+0x34: ???????? ??bbbbbb bbbb???? ??aaaaaa
|
||||
*/
|
||||
int _X_get_rst_cause(void) {
|
||||
int ret;
|
||||
int a = GET_PERI_REG_BITS(RTC_STATE1, 6, 0);
|
||||
if (a == 5) {
|
||||
int b = (RTC_STATE1 >> 12) && 0xfff;
|
||||
if (b != 1) {
|
||||
ret = (b == 8 ? a : 0);
|
||||
} else {
|
||||
ret = 20;
|
||||
}
|
||||
} else {
|
||||
ret = a;
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(RTC_STATE0, RTC_CNTL_SLP_WAKEUP);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* RTC = 0x60008000
|
||||
* RTC+0x38: ???????? ???????? ???????? ??cccccc
|
||||
* RTC+0x74: ???????? ???????? ???????? dddddddd
|
||||
* RTC+0x80: ???????? ??????a? ???b???? ????????
|
||||
*/
|
||||
void main(void) {
|
||||
uint32_t rst_cause = _X_get_rst_cause();
|
||||
CLEAR_PERI_REG_MASK(RTC+0x80, BIT(17)); // a
|
||||
SET_PERI_REG_MASK(RTC+0x80, BIT(12)); // b
|
||||
uint32_t boot_mode = GET_PERI_REG_BITS(GPIO_STRAP, 6, 0); // c
|
||||
if (boot_mode & (BIT(5) | BIT(4)) == (BIT(5) | BIT(4)) || boot_mode == 24 || boot_mode == 26) {
|
||||
CLEAR_PERI_REG_MASK(RTC+0x74, 0xff);
|
||||
}
|
||||
if (boot_mode & (BIT(5) | BIT(4)) == BIT(5)) {
|
||||
CLEAR_PERI_REG_MASK(RTC+0x94, BIT(31));
|
||||
CLEAR_PERI_REG_MASK(RTC+0x98, BIT(31));
|
||||
CLEAR_PERI_REG_MASK(RTC+0x9c, BIT(31));
|
||||
CLEAR_PERI_REG_MASK(RTC+0xa0, BIT(31));
|
||||
CLEAR_PERI_REG_MASK(RTC+0xa4, BIT(31));
|
||||
CLEAR_PERI_REG_MASK(RTC+0xa8, BIT(31));
|
||||
CLEAR_PERI_REG_MASK(RTC+0xac, BIT(31));
|
||||
}
|
||||
if (boot_mode & (BIT(5) | BIT(3)) == 0) {
|
||||
// ... 1405
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(RTC+0x74, 0xff);
|
||||
_X_uart_attach();
|
||||
_X_uart_init(0);
|
||||
// GPIO_STRAP ...
|
||||
ets_printf(boot_banner, fw_build, rst_cause, boot_mode);
|
||||
// rst_cause
|
||||
if (rst_cause == 1 || rst_cause == 2) {
|
||||
|
||||
} else {
|
||||
// ...
|
||||
}
|
||||
ets_printf("%s %u", "ets_main.c", 305);
|
||||
while(1) {}
|
||||
}
|
||||
|
||||
/*
|
||||
* GPIO strap mapping:
|
||||
*
|
||||
* 0011 1111 1011 0011
|
||||
* || |||| |||| ||||
|
||||
* || |||| |||| |||`- IO5
|
||||
* || |||| |||| ||`-- IO15
|
||||
* || |||| |||| |`--- IO4
|
||||
* || |||| |||| `---- IO2
|
||||
* || |||| |||`------ ?
|
||||
* || |||| ||`------- IO0
|
||||
* || |||| |`-------- IO12
|
||||
* || |||| `--------- ?
|
||||
* || |||`----------- CLK
|
||||
* || ||`------------ ?
|
||||
* || |`------------- SD0
|
||||
* || `-------------- SD1
|
||||
* |`---------------- ? SD2
|
||||
* `----------------- SD3
|
||||
*/
|
||||
|
||||
struct uartdev {
|
||||
uint32_t baud_rate; // 0
|
||||
uint32_t ud4;
|
||||
uint32_t ud8;
|
||||
uint32_t ud12;
|
||||
uint32_t ud16;
|
||||
uint32_t ud20;
|
||||
uint8_t ud24;
|
||||
uint8_t ud25;
|
||||
uint32_t ud28;
|
||||
uint32_t ud32;
|
||||
uint32_t ud36;
|
||||
uint8_t ud40;
|
||||
uint32_t ud48;
|
||||
uint32_t ud52;
|
||||
};
|
||||
|
||||
void _X_uart_attach(void) {
|
||||
// zero uartdev
|
||||
uartdev.baud_rate = 115200;
|
||||
_X_xtos_ints_off(1 << ETS_UART_INUM);
|
||||
// INTR_MAP_REG_C
|
||||
// 11111111 11111111 11111100 00011111 &
|
||||
// 00000000 00000000 00000000 10100000 |
|
||||
// PRODPORT_INTR_MAP_13 -> 5 = ETS_UART_INUM
|
||||
// 11111111 11111111 10000011 11111111 &
|
||||
// 00000000 00000000 00010100 11111111 |
|
||||
// PRODPORT_INTR_MAP_14 -> 5 = ETS_UART_INUM
|
||||
_xtos_set_interrupt_handler_arg(ETS_UART_INUM, uart_int_handler, _c_0x3fffdb2c_uart_int_handler_arg);
|
||||
}
|
||||
|
||||
void _X_uart_init(uint32_t a) {
|
||||
// GPIO_FUNC_IN_SEL3
|
||||
// xx999999 88888877 77776666 66555555
|
||||
// 11111111 11111100 00001111 11111111 = 0xfffc0fff
|
||||
// 00000000 00000000 10010000 00000000 = 0x00009000
|
||||
// GPIO17 func => 9
|
||||
// 00000000 00000010 00000000 00000000
|
||||
uart_div_modify(13000000 / uartdev.baud_rate);
|
||||
// ...
|
||||
}
|
||||
|
||||
struct _st_0x3fffdc90 {
|
||||
};
|
||||
|
||||
struct _st_0x3fffdf70 {
|
||||
void *fp1; // 20
|
||||
void *fp2; // 24
|
||||
uint32_t d28;
|
||||
uint32_t d32;
|
||||
uint32_t d36;
|
||||
struct _st_0x3fffdc90 *st; // 44
|
||||
} stdf70;
|
||||
|
||||
void _X_slc_init_attach(void *fp1, void *fp2, struct _st_0x3fffdc90 *st, uint32_t gpio_mode) {
|
||||
stdf70.fp1 = fp1;
|
||||
stdf70.fp2 = fp2;
|
||||
stdf70.st = st;
|
||||
d28 = d32 = d36 = 0;
|
||||
SET_PERI_REG_MASK(WIFI_RST_EN, PRODPORT_SDIO_RST);
|
||||
CLEAR_PERI_REG_MASK(WIFI_RST_EN, PRODPORT_SDIO_RST);
|
||||
if (gpio_mode == 4) {
|
||||
SET_PERI_REG((READ_PERI_REG(PERIPHS_HINF_BASEADDR+4) & 0xf0000000) | 0x01110013);
|
||||
} else {
|
||||
SET_PERI_REG((READ_PERI_REG(PERIPHS_HINF_BASEADDR+4) & 0xf0000000) | 0x02320017);
|
||||
}
|
||||
SET_PERI_REG(PERIPHS_HINF_BASEADDR, 0x11116666);
|
||||
_X_slc_set_host_io_max_window();
|
||||
...
|
||||
}
|
||||
|
||||
#define SLC_TOKEN1 (PERIPHS_SLC_BASEADDR + 0x54)
|
||||
#define SLC_BRIDGE_CONF (PERIPHS_SLC_BASEADDR + 0x74)
|
||||
|
||||
void _X_slc_set_host_io_max_window(void) {
|
||||
SET_PERI_REG(SLC_BRIDGE_CONF, (READ_PERI_REG(SLC_BRIDGE_CONF) & 0xfffff0c0) | 0x720);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
.text
|
||||
.org 0
|
||||
.globl _start
|
||||
|
||||
// xtensa-esp108-elf-gcc -Wl,-N,-Ttext,0x40000000 -nostdlib rom.S -o rom.elf
|
||||
|
||||
here = .
|
||||
#define PROVIDE(name, addr) name = here + addr - 0x40000000
|
||||
|
||||
#include "rom_functions.S"
|
||||
|
||||
.text
|
||||
|
||||
_start:
|
||||
.incbin "rom.bin"
|
||||
_end:
|
Binary file not shown.
@ -1,294 +0,0 @@
|
||||
// These come from linker script
|
||||
|
||||
PROVIDE ( Cache_Read_Disable , 0x4000444c );
|
||||
PROVIDE ( Cache_Read_Enable , 0x4000438c );
|
||||
|
||||
PROVIDE ( ets_delay_us , 0x40002db4 );
|
||||
|
||||
PROVIDE ( bzero , 0x40002a54 );
|
||||
|
||||
PROVIDE ( memcmp , 0x400068ec );
|
||||
PROVIDE ( memcpy , 0x40006974 );
|
||||
PROVIDE ( memmove , 0x40006a6c );
|
||||
PROVIDE ( memset , 0x40006be4 );
|
||||
|
||||
PROVIDE ( strcmp , 0x40005bb8 );
|
||||
PROVIDE ( strcpy , 0x40005cdc );
|
||||
PROVIDE ( strlen , 0x40005d6c );
|
||||
PROVIDE ( strncmp , 0x40005dd0 );
|
||||
PROVIDE ( strncpy , 0x40005e90 );
|
||||
PROVIDE ( strstr , 0x40005f6c );
|
||||
|
||||
PROVIDE ( ets_install_putc1 , 0x40002774 );
|
||||
PROVIDE ( ets_printf , 0x40002804 );
|
||||
PROVIDE ( ets_putc , 0x40002b14 );
|
||||
|
||||
PROVIDE ( ets_str2macaddr , 0x40002a64 );
|
||||
|
||||
PROVIDE ( gpio_output_set , 0x400049d8 );
|
||||
PROVIDE ( gpio_output_set_high , 0x400049f8 );
|
||||
|
||||
PROVIDE ( ets_get_cpu_frequency , 0x40002de8 );
|
||||
PROVIDE ( ets_update_cpu_frequency , 0x40002ddc );
|
||||
|
||||
PROVIDE ( lldesc_build_chain , 0x40004c8c );
|
||||
|
||||
PROVIDE ( multofup , 0x400068a0 );
|
||||
PROVIDE ( roundup2 , 0x40006890 );
|
||||
|
||||
PROVIDE (software_reset_cpu , 0x40002998 );
|
||||
|
||||
PROVIDE ( SPIEraseSector , 0x40004708 );
|
||||
PROVIDE ( SPIRead , 0x40004898 );
|
||||
PROVIDE ( SPIWrite , 0x40004738 );
|
||||
|
||||
PROVIDE ( uart_div_modify , 0x400034e8 );
|
||||
PROVIDE ( uart_tx_one_char , 0x4000362c );
|
||||
|
||||
PROVIDE ( __divsi3 , 0x40006888 );
|
||||
PROVIDE ( __udivdi3 , 0x40006c30 );
|
||||
PROVIDE ( __umoddi3 , 0x40006e64 );
|
||||
|
||||
PROVIDE ( _xtos_set_intlevel , 0x40006670 );
|
||||
|
||||
// These have been reverse-engineered.
|
||||
|
||||
PROVIDE(_XX_Vec40, 0x40000040)
|
||||
PROVIDE(_XX_ExcVec50, 0x40000050)
|
||||
PROVIDE(_XX_ExcVec80, 0x40000080)
|
||||
|
||||
PROVIDE(_XX_Vec400, 0x40000300)
|
||||
|
||||
PROVIDE(_WindowOverflowHandler, 0x40000100)
|
||||
PROVIDE(_WindowUnderflowHandler, 0x40000140)
|
||||
|
||||
PROVIDE(_X_ResetVector, 0x40000500)
|
||||
|
||||
PROVIDE(_c_stack, 0x40000700)
|
||||
PROVIDE(_c_bss_start, 0x40000708)
|
||||
PROVIDE(_c_bss_end, 0x4000070c)
|
||||
PROVIDE(_c_0x3fffc210, 0x40000734)
|
||||
PROVIDE(_c_0x80000000, 0x40000738)
|
||||
PROVIDE(_c_0x40000000, 0x40000760)
|
||||
PROVIDE(_c_0x7fffffff, 0x40000780)
|
||||
PROVIDE(_c_0x00ff0000, 0x40000798)
|
||||
|
||||
PROVIDE(_X_start, 0x400007ac)
|
||||
|
||||
PROVIDE(_c_0x3fffd820, 0x40000f50)
|
||||
PROVIDE(_X_ets_task, 0x40000f54)
|
||||
PROVIDE(_XX_unk0f84, 0x40000f84)
|
||||
PROVIDE(_XX_unk0f96, 0x40000f98)
|
||||
|
||||
PROVIDE(_c_ets_critical_level, 0x400010a4)
|
||||
PROVIDE(_X_ets_enter_critical, 0x400010a8)
|
||||
PROVIDE(_X_ets_exit_critical, 0x400010bc)
|
||||
PROVIDE(_X_ets_exit_critical_and_wait_int, 0x400010d4)
|
||||
PROVIDE(_X_ets_isr_attach, 0x400010e8) // 3 args
|
||||
PROVIDE(_X_ets_isr_mask, 0x400010f8) // 1 arg
|
||||
PROVIDE(_X_ets_isr_unmask, 0x40001104) // 1 arg
|
||||
|
||||
PROVIDE(_c_0x3fffda30, 0x40001110)
|
||||
PROVIDE(_XX_set_0x3fffda30_0, 0x40001114)
|
||||
PROVIDE(_XX_set_0x3fffda30_4, 0x40001120)
|
||||
PROVIDE(_c_0xfffdffff, 0x4000112c)
|
||||
PROVIDE(_c_0x60003e00, 0x40001130)
|
||||
PROVIDE(_c_0x60008200, 0x40001134)
|
||||
PROVIDE(_c_0x60007e00, 0x40001138)
|
||||
PROVIDE(_c_0x1000, 0x4000113c)
|
||||
PROVIDE(_s_fw_build, 0x40001140)
|
||||
PROVIDE(_s_boot_banner, 0x40001144)
|
||||
PROVIDE(_s_pct_s_pct_u, 0x40001148)
|
||||
PROVIDE(_s_ets_main_c, 0x4000114c)
|
||||
PROVIDE(_X_main, 0x4000115c)
|
||||
|
||||
PROVIDE(_l_strap_0x0xxx, 0x4000125a)
|
||||
PROVIDE(_l_strap_init_uart0, 0x40001269)
|
||||
PROVIDE(_l_strap_0x0x00, 0x400012e2)
|
||||
PROVIDE(_l_boot, 0x400012ea)
|
||||
PROVIDE(_l_rst_cause_345, 0x40001336)
|
||||
PROVIDE(_l_rst_cause_12, 0x40001342)
|
||||
PROVIDE(_l_strap_NxNxxx, 0x40001405)
|
||||
PROVIDE(_l_strap_0010xx, 0x4000144c)
|
||||
PROVIDE(_l_strap_001000_0x110x, 0x400014b0)
|
||||
PROVIDE(_l_strap_0x0x11_loader, 0x400014c9) // loader
|
||||
PROVIDE(_l_strap_0x0x01, 0x400014d4)
|
||||
PROVIDE(_l_strap_0x0x10, 0x400014e6)
|
||||
PROVIDE(_c_0xffff8fff, 0x400014f0)
|
||||
PROVIDE(_c_0x60008e00, 0x400014f4)
|
||||
|
||||
PROVIDE(_s_waiting_for_host, 0x4000152c)
|
||||
PROVIDE(_s_mem_banner, 0x40001cdc)
|
||||
PROVIDE(_c_stack_sentry, 0x40001ce0)
|
||||
PROVIDE(_XX_unk153c, 0x4000153c)
|
||||
|
||||
PROVIDE(_c_data_end, 0x40001cd8)
|
||||
PROVIDE(_c_data_start, 0x40001ce4)
|
||||
PROVIDE(_X_print_mem_banner, 0x40001ce8)
|
||||
|
||||
PROVIDE(_s_exc_sp_fmt, 0x40001d0c)
|
||||
PROVIDE(_s_exc_sf_dump_fmt, 0x40001d10)
|
||||
PROVIDE(_s_exc_regs_fmt, 0x40001d14)
|
||||
PROVIDE(_X_exc_handler, 0x40001d18)
|
||||
|
||||
PROVIDE(_XX_unk1d90, 0x40001d90)
|
||||
|
||||
PROVIDE(_X_ets_memset, 0x40001db4)
|
||||
PROVIDE(_X_ets_memcpy, 0x40001dc4)
|
||||
PROVIDE(_X_ets_memmove, 0x40001dd4)
|
||||
PROVIDE(_X_ets_memcmp, 0x40001de4)
|
||||
|
||||
PROVIDE(_st_0x3fffda9c, 0x40002150) // struct
|
||||
|
||||
PROVIDE(_X_ets_uart_putc, 0x4000223c)
|
||||
PROVIDE(_X_ets_unk225c, 0x4000225c)
|
||||
|
||||
PROVIDE(_c_0x4000223c_ets_uart_putc, 0x40002780)
|
||||
PROVIDE(_X_ets_install_uart_printf, 0x40002784)
|
||||
PROVIDE(_c_0x400027dc, 0x40002790)
|
||||
PROVIDE(_X_ets_install_external_printf, 0x40002794)
|
||||
PROVIDE(_X_ets_install_putc2, 0x400027b4)
|
||||
PROVIDE(_X_ets_get_printf_buf_remain_len, 0x400027c0)
|
||||
PROVIDE(_X_ets_reset_printf_buf_len, 0x400027cc)
|
||||
PROVIDE(_X_ets_putc, 0x400027dc)
|
||||
|
||||
PROVIDE(_c_0xdfffffff, 0x400028d4)
|
||||
PROVIDE(_X_get_rst_cause, 0x400028d8)
|
||||
PROVIDE(_XX_unk2948, 0x40002948)
|
||||
PROVIDE(_l_2970, 0x40002970)
|
||||
PROVIDE(_X_sw_sys_rst, 0x4000297c)
|
||||
PROVIDE(_c_0x00400000, 0x400029b4)
|
||||
PROVIDE(_c_0xffbfffff, 0x400029b8)
|
||||
PROVIDE(_XX_apb_bridge_toggle, 0x400029bc) // turns RTC_CNTL_APB2RTC_BRIDGE_SEL on and off
|
||||
PROVIDE(_X_ets_strcpy, 0x400029ec)
|
||||
PROVIDE(_X_ets_strncpy, 0x40002a00)
|
||||
PROVIDE(_X_ets_strcmp, 0x40002a10)
|
||||
PROVIDE(_X_ets_strncmp, 0x40002a24)
|
||||
PROVIDE(_X_ets_strlen, 0x40002a34)
|
||||
PROVIDE(_X_ets_strstr, 0x40002a40)
|
||||
|
||||
PROVIDE(_st_0x3fffdb10_uartdev, 0x40002e4c) // some struct - uartdev?
|
||||
|
||||
PROVIDE(_c_0x3fffdb00, 0x40002e50)
|
||||
PROVIDE(_c_0x3fffdb04, 0x40002f64)
|
||||
PROVIDE(_XX_unk2e58, 0x40002e58)
|
||||
PROVIDE(_X_UartDwnLdProc, 0x40002f6c)
|
||||
PROVIDE(_c_0x00001800, 0x400030ec)
|
||||
PROVIDE(_X_FlashDwnLdStartMsgProc, 0x400030f0)
|
||||
PROVIDE(_XX_unk313c, 0x4000313c)
|
||||
PROVIDE(_XX_unk31bc, 0x400031bc)
|
||||
PROVIDE(_XX_unk31e4, 0x400031e4)
|
||||
PROVIDE(_XX_unk3210, 0x40003210)
|
||||
PROVIDE(_XX_unk3240, 0x40003240)
|
||||
PROVIDE(_X_MemDwnLdStopReqMsgProc, 0x4000329c)
|
||||
PROVIDE(_X_UartConnectProc, 0x400032c4)
|
||||
PROVIDE(_X_UartRegWriteProc, 0x400032d4)
|
||||
PROVIDE(_X_UartRegReadProc, 0x40003318)
|
||||
|
||||
PROVIDE(_c_115200, 0x4000332c)
|
||||
PROVIDE(_c_0x3feffe00, 0x40003330)
|
||||
PROVIDE(_c_0xffff83ff, 0x40003334)
|
||||
PROVIDE(_c_0x00001400, 0x40003338)
|
||||
PROVIDE(_c_0x40003728_uart_int_handler, 0x4000333c)
|
||||
PROVIDE(_c_0x3fffdb2c_uart_int_handler_arg, 0x40003340)
|
||||
PROVIDE(_X_uart_attach, 0x40003344)
|
||||
PROVIDE(_XX_uart_set_unk33c0, 0x400033c0)
|
||||
PROVIDE(_c_0x5ffffe00, 0x400033cc)
|
||||
PROVIDE(_c_0x0000ffff, 0x400033d0)
|
||||
PROVIDE(_c_0x000fffff, 0x40003448)
|
||||
PROVIDE(_c_0x00060000, 0x400034e0)
|
||||
PROVIDE(_c_0xfff9ffff, 0x400034e4)
|
||||
|
||||
PROVIDE(_c_0xfffc0fff, 0x40003520)
|
||||
PROVIDE(_c_0x00009000, 0x40003524)
|
||||
PROVIDE(_c_0x00020000, 0x40003528)
|
||||
PROVIDE(_c_13000000, 0x4000352c)
|
||||
PROVIDE(_c_0x08000000, 0x40003530)
|
||||
PROVIDE(_X_uart_init, 0x40003534)
|
||||
PROVIDE(_l_35f4, 0x400035f4)
|
||||
PROVIDE(_X_uart_wait_tx_empty, 0x4000369c)
|
||||
|
||||
PROVIDE(_X_uart_int_handler, 0x40003728)
|
||||
|
||||
PROVIDE(_X_uart_tx_one_char2, 0x40003664)
|
||||
|
||||
PROVIDE(_X_send_packet, 0x400037d4)
|
||||
PROVIDE(_X_SendMsg, 0x40003828)
|
||||
PROVIDE(_X_recv_packet, 0x4000383c)
|
||||
PROVIDE(_X_RcvMsg, 0x40003988)
|
||||
PROVIDE(_X_uart_rx_readbuff, 0x400039a0)
|
||||
|
||||
PROVIDE(_c_0x60004e00, 0x40003a18)
|
||||
PROVIDE(_X_SelectSpiFunction, 0x40003a1c) // 1 arg - SPI number
|
||||
PROVIDE(_c_0x60002e00, 0x40003c78)
|
||||
PROVIDE(_X_SPI_chip_erase, 0x40003c7c)
|
||||
PROVIDE(_c_0x00ffffff, 0x40003cb4)
|
||||
PROVIDE(_c_0x01000000, 0x40003cb8)
|
||||
PROVIDE(_XX_unk3cbc, 0x40003cbc)
|
||||
PROVIDE(_c_0x00800000, 0x40003d00)
|
||||
PROVIDE(_c_0x02000000, 0x40003d4c)
|
||||
PROVIDE(_XX_unk3e24, 0x40003e24)
|
||||
PROVIDE(_X_SPI_read_status, 0x40003efc)
|
||||
PROVIDE(_c_0x90000000, 0x40003f48)
|
||||
PROVIDE(_c_0x70000035, 0x40003f4c)
|
||||
PROVIDE(_c_0x00040000, 0x40003f50)
|
||||
PROVIDE(_XX_unk3f54, 0x40003f54)
|
||||
PROVIDE(_c_0x04000000, 0x40003fcc)
|
||||
PROVIDE(_XX_unk4010, 0x40004010)
|
||||
PROVIDE(_X_SPI_write_enable, 0x400041bc)
|
||||
PROVIDE(_X_Wait_SPI_Idle, 0x40004208)
|
||||
PROVIDE(_l_4228, 0x40004228)
|
||||
PROVIDE(_l_4234, 0x40004234)
|
||||
PROVIDE(_XX_unk4238, 0x40004238)
|
||||
PROVIDE(_X_SPIFlashModeConfig, 0x400042d8)
|
||||
PROVIDE(_X_spi_flash_attach, 0x40004370) // 2 args: SPI num, ???
|
||||
PROVIDE(_X_SPIReadModeConfig, 0x40004538)
|
||||
|
||||
PROVIDE(_X_SPIEraseArea, 0x400048b4)
|
||||
PROVIDE(_XX_unk4940, 0x40004940)
|
||||
|
||||
PROVIDE(_st_0x3fffdc90, 0x40004d80)
|
||||
PROVIDE(_XX_unk4d88, 0x40004d88)
|
||||
PROVIDE(_XX_unk4f6c, 0x40004f6c)
|
||||
PROVIDE(_XX_unk4fc8, 0x40004fc8)
|
||||
|
||||
PROVIDE(_c_0xbfffffff, 0x40004c80)
|
||||
PROVIDE(_c_0xff000fff, 0x40004c88)
|
||||
PROVIDE(_XX_unk4f14, 0x40004f14)
|
||||
PROVIDE(_s_no_rds, 0x40005008)
|
||||
PROVIDE(_XX_unk500c, 0x4000500c)
|
||||
|
||||
PROVIDE(_fp_0x40004f6c, 0x40005164)
|
||||
PROVIDE(_fp_0x40004fc8, 0x40005168)
|
||||
PROVIDE(_X_sip_init_attach, 0x40005170) // 1 arg, boot_mode?
|
||||
PROVIDE(_XX_unk51ac, 0x400051ac)
|
||||
PROVIDE(_c_0x60017e00, 0x40005478)
|
||||
PROVIDE(_st_0x3fffdf70, 0x400054a4)
|
||||
PROVIDE(_c_0x6000ae00, 0x400054b8)
|
||||
PROVIDE(_c_0xf0000000, 0x400054bc)
|
||||
PROVIDE(_c_0x02320017, 0x400054c0)
|
||||
PROVIDE(_c_0x11116666, 0x400054c4)
|
||||
PROVIDE(_c_0x01110013, 0x400054e4)
|
||||
PROVIDE(_X_slc_init_attach, 0x400054e8) // 4 args - fp, fp, st, boot_mode; PRODPORT_SDIO_RST
|
||||
PROVIDE(_l_slc_boot_mode_4, 0x40005654)
|
||||
PROVIDE(_X_slc_enable, 0x40005678)
|
||||
PROVIDE(_X_slc_select_tohost_gpio_mode, 0x400056fc)
|
||||
PROVIDE(_X_slc_select_tohost_gpio, 0x40005708)
|
||||
PROVIDE(_c_0xff300000, 0x40005730)
|
||||
PROVIDE(_XX_unk5734, 0x40005734)
|
||||
PROVIDE(_XX_unk57b8, 0x400057b8)
|
||||
PROVIDE(_XX_unk57f4, 0x400057f4)
|
||||
PROVIDE(_XX_unk5848, 0x40005848)
|
||||
|
||||
PROVIDE(_c_0xfffff0c0, 0x40005988)
|
||||
PROVIDE(_X_slc_set_host_io_max_window, 0x4000598c)
|
||||
PROVIDE(_X_slc_init_credit, 0x400059ac)
|
||||
PROVIDE(_X_slc_add_credits, 0x400059c4)
|
||||
|
||||
PROVIDE(_X_xtos_set_interrupt_handler_arg, 0x400059d8)
|
||||
PROVIDE(_X_xtos_set_interrupt_handler, 0x40005a24)
|
||||
PROVIDE(_X_xtos_ints_on, 0x40005a34)
|
||||
PROVIDE(_X_xtos_ints_off, 0x40005a58)
|
||||
|
||||
PROVIDE(_XX_xtos_exc_unk5a80, 0x40005a80)
|
||||
PROVIDE(_XX_xtos_exc_unk5b94, 0x40005b94)
|
@ -1,2 +0,0 @@
|
||||
rom.bin -nodiff
|
||||
rom.elf -nodiff
|
@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
xtensa-esp32-elf-gcc -Wl,-N,-Ttext,0x40000000 -nostdlib rom.S -o rom.elf && \
|
||||
xtensa-esp32-elf-objdump -d rom.elf > ESP32_ROM.txt
|
@ -1,28 +0,0 @@
|
||||
.text
|
||||
.org 0
|
||||
.globl _start
|
||||
|
||||
// xtensa-esp32-elf-gcc -Wl,-N,-Ttext,0x40000000 -nostdlib rom.S -o rom.elf
|
||||
|
||||
here = .
|
||||
#define PROVIDE(name, addr) name = here + addr - 0x40000000
|
||||
|
||||
#include "rom_functions.S"
|
||||
|
||||
PROVIDE ( _x_unk_40061b88, 0x40061b88 )
|
||||
PROVIDE ( _x_unk_spi_400622c0, 0x400622c0 )
|
||||
PROVIDE ( _c_3ff000c8, 0x40062df0 )
|
||||
PROVIDE ( _c_3ff5b024, 0x40062e0c )
|
||||
PROVIDE ( _c_3ff5b000, 0x40062e10 )
|
||||
PROVIDE ( _c_3ff5b020, 0x40062e14 )
|
||||
PROVIDE ( _c_3ff5b028, 0x40062e18 )
|
||||
PROVIDE ( _l_40062e90, 0x40062e90 )
|
||||
PROVIDE ( _l_SPI_Prepare_Encrypt_Data_loop, 0x40062e34 )
|
||||
PROVIDE ( _l_SPI_Prepare_Encrypt_Data_wait, 0x40062e54 )
|
||||
PROVIDE ( _l_SPI_Prepare_Encrypt_Data_out, 0x40062e5e )
|
||||
|
||||
.text
|
||||
|
||||
_start:
|
||||
.incbin "rom.bin"
|
||||
_end:
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,51 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2015 Cesanta Software Limited
|
||||
# All rights reserved
|
||||
#
|
||||
|
||||
STUB = stub_hello.c
|
||||
LIBS =
|
||||
PARAMS =
|
||||
PORT = /dev/ttyUSB0
|
||||
|
||||
BUILD_DIR = .build
|
||||
COMMON_STUB_DIR = ../../esp
|
||||
STUB_ELF = $(BUILD_DIR)/$(patsubst %.c,%.elf,$(notdir $(STUB)))
|
||||
STUB_JSON ?= $(BUILD_DIR)/$(patsubst %.c,%.json,$(notdir $(STUB)))
|
||||
SDK = $(shell cat ../../../../fw/platforms/esp32/sdk.version)
|
||||
XT_CC = xtensa-esp32-elf-gcc
|
||||
|
||||
.PHONY: all clean run wrap
|
||||
|
||||
all: $(STUB_ELF)
|
||||
|
||||
$(STUB_ELF): $(STUB) $(LIBS)
|
||||
@echo " CC $^ -> $@"
|
||||
@[ -d $(BUILD_DIR) ] || mkdir $(BUILD_DIR)
|
||||
@docker run --rm -i -v $(CURDIR)/../../../..:/src $(SDK) //bin/bash -c \
|
||||
"cd /src/common/platforms/esp32/stubs && \
|
||||
$(XT_CC) -std=c99 -Wall -Werror -Os -DESP32 \
|
||||
-mtext-section-literals -mlongcalls -nostdlib -fno-builtin \
|
||||
-I. -I/src/common/platforms/esp \
|
||||
-I/opt/Espressif/esp-idf/components/esp32/include \
|
||||
-I/opt/Espressif/esp-idf/components/soc/esp32/include \
|
||||
-L/opt/Espressif/esp-idf -Wl,-static \
|
||||
-ffunction-sections -Wl,--gc-sections \
|
||||
-Tstub.ld -o $@ $^"
|
||||
|
||||
wrap: $(STUB_JSON)
|
||||
|
||||
$(STUB_JSON): $(STUB_ELF) $(COMMON_STUB_DIR)/esptool.py
|
||||
@echo " WRAP $< -> $@"
|
||||
@docker run --rm -i -v $(CURDIR)/../../../..:/src $(SDK) //bin/bash -c \
|
||||
"cd /src/common/platforms/esp32/stubs && \
|
||||
$(COMMON_STUB_DIR)/esptool.py wrap_stub $<" > $@
|
||||
|
||||
run: $(STUB_JSON)
|
||||
@echo " RUN $< $(PARAMS) -> $(PORT)"
|
||||
@docker run --rm -i --privileged -v $(CURDIR)/../../../..:/src $(SDK) //bin/bash -c \
|
||||
"cd /src/common/platforms/esp32/stubs && \
|
||||
$(COMMON_STUB_DIR)/esptool.py --port $(PORT) run_stub $< $(PARAMS)"
|
||||
|
||||
clean:
|
||||
@rm -rf $(BUILD_DIR)
|
@ -1,13 +0,0 @@
|
||||
This is a ESP boot loader stub development environment.
|
||||
|
||||
Code produced in this environment can be loaded and executed
|
||||
in the bootloader environment. Usually it is used to implement
|
||||
functionality not found in the bootloader.
|
||||
|
||||
Stubs can be executed using the `run_stub` command of the modified esptool.py provided.
|
||||
`wrap_stub` produces a JSON represenattion of the stub that can later be reused
|
||||
or built into other tools.
|
||||
|
||||
Example usage:
|
||||
$ make run STUB=stub_flash_size.c PORT=/dev/ttyUSB0
|
||||
$ make run STUB=stub_md5.c PORT=/dev/ttyUSB0 PARAMS="0x11000 10000 1"
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2017 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include "soc/gpio_reg.h"
|
||||
|
||||
void led_setup(int io) {
|
||||
if (io < 32) {
|
||||
WRITE_PERI_REG(GPIO_ENABLE_W1TS_REG, 1 << io);
|
||||
} else {
|
||||
WRITE_PERI_REG(GPIO_ENABLE1_W1TS_REG, 1 << (io - 32));
|
||||
}
|
||||
}
|
||||
|
||||
void led_on(int io) {
|
||||
if (io < 32) {
|
||||
WRITE_PERI_REG(GPIO_OUT_W1TS_REG, 1 << io);
|
||||
} else {
|
||||
WRITE_PERI_REG(GPIO_OUT1_W1TS_REG, 1 << (io - 32));
|
||||
}
|
||||
}
|
||||
|
||||
void led_off(int io) {
|
||||
if (io < 32) {
|
||||
WRITE_PERI_REG(GPIO_OUT_W1TC_REG, 1 << io);
|
||||
} else {
|
||||
WRITE_PERI_REG(GPIO_OUT1_W1TC_REG, 1 << (io - 32));
|
||||
}
|
||||
}
|
||||
|
||||
void led_toggle(int io) {
|
||||
if (READ_PERI_REG(GPIO_OUT_REG & (1 << io))) {
|
||||
WRITE_PERI_REG(GPIO_OUT_W1TC_REG, 1 << io);
|
||||
} else {
|
||||
WRITE_PERI_REG(GPIO_OUT_W1TS_REG, 1 << io);
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2017 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
void led_setup(int io);
|
||||
void led_on(int io);
|
||||
void led_off(int io);
|
||||
void led_toggle(int io);
|
@ -1,10 +0,0 @@
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP32_STUBS_ROM_FUNCTIONS_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP32_STUBS_ROM_FUNCTIONS_H_
|
||||
|
||||
#include "rom/ets_sys.h"
|
||||
#include "rom/spi_flash.h"
|
||||
#include "rom/md5_hash.h"
|
||||
#include "rom/uart.h"
|
||||
#include "rom/rtc.h"
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP32_STUBS_ROM_FUNCTIONS_H_ */
|
@ -1 +0,0 @@
|
||||
#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
MEMORY {
|
||||
iram : org = 0x40090000, len = 0x10000
|
||||
/* DRAM startin at 0x3FFC0000 gets stomped by something before mem_finish
|
||||
* and is thus not suitable for initialized data, but works fine for BSS. */
|
||||
dram_bss : org = 0x3FFC0000, len = 0x10000
|
||||
dram : org = 0x3FFD0000, len = 0x10000
|
||||
}
|
||||
|
||||
ENTRY(stub_main)
|
||||
|
||||
SECTIONS {
|
||||
.params 0x40090000 : {
|
||||
_params_start = ABSOLUTE(.);
|
||||
*(.params)
|
||||
_params_end = ABSOLUTE(.);
|
||||
} > iram
|
||||
|
||||
.text : ALIGN(4) {
|
||||
_code_start = ABSOLUTE(.);
|
||||
*(.literal)
|
||||
*(.text .text.*)
|
||||
} > iram
|
||||
|
||||
.bss : ALIGN(4) {
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.bss)
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} > dram
|
||||
|
||||
.data : ALIGN(4) {
|
||||
_data_start = ABSOLUTE(.);
|
||||
*(.data)
|
||||
*(.rodata .rodata.*)
|
||||
} > dram
|
||||
}
|
||||
|
||||
INCLUDE "components/esp32/ld/esp32.rom.ld"
|
||||
INCLUDE "components/esp32/ld/esp32.rom.spiram_incompatible_fns.ld"
|
||||
|
||||
PROVIDE(esp_rom_spiflash_attach = 0x40062a6c);
|
||||
PROVIDE(esp_rom_spiflash_config_clk = 0x40062bc8);
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*
|
||||
*
|
||||
* Stub template.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include "slip.h"
|
||||
|
||||
/* Define the args vector and put it into the ".params" section. */
|
||||
uint32_t params[3] __attribute__((section(".params")));
|
||||
|
||||
/* Define a function called stub_main. Do not return or reboot.
|
||||
* Use send_packet to communicate to the host. */
|
||||
|
||||
const char *hello = "Hello";
|
||||
|
||||
static char buf[1024];
|
||||
extern uint32_t _bss_start, _bss_end;
|
||||
|
||||
void stub_main(void) {
|
||||
uint32_t greeting = 0x4941484f;
|
||||
SLIP_send(&greeting, 4);
|
||||
memset(&_bss_start, 0, (&_bss_end - &_bss_start));
|
||||
buf[1] = 123;
|
||||
SLIP_send(hello, 5);
|
||||
while (1) {
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include "uart.h"
|
||||
|
||||
#include "rom_functions.h"
|
||||
|
||||
void set_baud_rate(uint32_t uart_no, uint32_t baud_rate) {
|
||||
uint32_t master_freq = ets_get_detected_xtal_freq() << 4;
|
||||
master_freq += (baud_rate / 2);
|
||||
uint32_t div = master_freq / baud_rate;
|
||||
uart_div_modify(uart_no, div);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP32_STUBS_UART_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP32_STUBS_UART_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void set_baud_rate(uint32_t uart_no, uint32_t baud_rate);
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP32_STUBS_UART_H_ */
|
@ -1,76 +0,0 @@
|
||||
CFLAGS_EXTRA ?=
|
||||
|
||||
XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin
|
||||
SDK_PATH ?= /opt/Espressif/ESP8266_SDK
|
||||
ESPTOOL ?= esptool.py
|
||||
ESPPORT ?= /dev/ttyACM0
|
||||
ESPSPEED ?= 230400
|
||||
# For flash = > 16Mbit
|
||||
ESPFLASHARGS = --flash_mode dio --flash_size 32m
|
||||
|
||||
VERBOSE ?= 0
|
||||
|
||||
CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc
|
||||
CXX := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-g++
|
||||
AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar
|
||||
LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc
|
||||
OBJCOPY := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-objcopy
|
||||
NM := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-nm
|
||||
CC_WRAPPER ?=
|
||||
|
||||
define link
|
||||
$(vecho) "LD $@"
|
||||
$(Q) $(CC_WRAPPER) $(LD) $(LIBDIRS) -T$(LD_SCRIPT) $(LDFLAGS) -o $@ \
|
||||
-Wl,-Map=$@.map -Wl,--start-group $1 -Wl,--end-group
|
||||
endef
|
||||
|
||||
define compile_params
|
||||
$(vecho) "$5 $1 -> $2"
|
||||
$(Q) $(CC_WRAPPER) $3 -MD -MP $(INCDIRS) $4 -c $1 -o $2
|
||||
endef
|
||||
|
||||
define compile
|
||||
$(call compile_params,$<,$@, $(CC), $(CFLAGS),"CC")
|
||||
endef
|
||||
|
||||
define compile_cxx
|
||||
$(call compile_params,$<,$@, $(CXX), $(CXXFLAGS),"CXX")
|
||||
endef
|
||||
|
||||
# some of these flags works around for gdb 7.5.x stacktrace issue
|
||||
# while still allowing -Os to remove padding between data in .rodata
|
||||
# section, allowing us to gain about 1k of ram.
|
||||
# text section is 4k bigger, but we care more about ram at the moment.
|
||||
# TODO(mkm): figure out which flag(s).
|
||||
NO_Os_FLAGS= -fno-expensive-optimizations -fno-thread-jumps \
|
||||
-fno-align-functions -fno-align-jumps \
|
||||
-fno-align-loops -fno-align-labels -fno-caller-saves \
|
||||
-fno-crossjumping -fno-cse-follow-jumps -fno-cse-skip-blocks \
|
||||
-fno-delete-null-pointer-checks -fno-devirtualize \
|
||||
-fno-gcse -fno-gcse-lm -fno-hoist-adjacent-loads \
|
||||
-fno-inline-small-functions -fno-indirect-inlining -fno-partial-inlining \
|
||||
-fno-ipa-cp -fno-ipa-sra -fno-peephole2 -fno-optimize-sibling-calls -fno-optimize-strlen \
|
||||
-fno-reorder-blocks -fno-reorder-blocks-and-partition -fno-reorder-functions \
|
||||
-fno-sched-interblock -fno-sched-spec -fno-rerun-cse-after-loop \
|
||||
-fno-schedule-insns -fno-schedule-insns2 -fno-strict-aliasing -fno-strict-overflow \
|
||||
-fno-tree-builtin-call-dce -fno-tree-switch-conversion -fno-tree-tail-merge \
|
||||
-fno-tree-pre -fno-tree-vrp
|
||||
|
||||
C_CXX_FLAGS = -W -Wall -Werror -Wundef -Wno-comment -Wno-variadic-macros -Wpointer-arith \
|
||||
-Os $(NO_Os_FLAGS) -g3 \
|
||||
-Wl,-EL -fno-inline-functions \
|
||||
-D_XOPEN_SOURCE=500 \
|
||||
-nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DSTATIC=static \
|
||||
-Wno-parentheses \
|
||||
-DIRAM='__attribute__((section(".fast.text")))' \
|
||||
-DICACHE_RAM_ATTR=IRAM \
|
||||
-DNOINSTR='__attribute__((no_instrument_function))' \
|
||||
-DCS_PLATFORM=3 \
|
||||
-ffunction-sections -fdata-sections
|
||||
|
||||
CFLAGS = -std=c99 $(C_CXX_FLAGS)
|
||||
CXXFLAGS = -std=gnu++11 -fno-exceptions $(C_CXX_FLAGS)
|
||||
|
||||
# linker flags used to generate the main object file
|
||||
LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start \
|
||||
-Wl,-static -Wl,--gc-sections
|
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mongoose/mongoose.h"
|
||||
|
||||
#ifdef RTOS_SDK
|
||||
#include "esp_libc.h"
|
||||
#else
|
||||
#include "osapi.h"
|
||||
#endif
|
||||
|
||||
extern int sha1_vector(size_t num_msgs, const uint8_t *msgs[],
|
||||
const size_t *msg_lens, uint8_t *digest);
|
||||
|
||||
extern int md5_vector(size_t num_msgs, const uint8_t *msgs[],
|
||||
const size_t *msg_lens, uint8_t *digest);
|
||||
|
||||
/* For digest auth. */
|
||||
void mg_hash_md5_v(size_t num_msgs, const uint8_t *msgs[],
|
||||
const size_t *msg_lens, uint8_t *digest) {
|
||||
(void) md5_vector(num_msgs, msgs, msg_lens, digest);
|
||||
}
|
||||
|
||||
/* For WebSocket handshake. */
|
||||
void mg_hash_sha1_v(size_t num_msgs, const uint8_t *msgs[],
|
||||
const size_t *msg_lens, uint8_t *digest) {
|
||||
(void) sha1_vector(num_msgs, msgs, msg_lens, digest);
|
||||
}
|
||||
|
||||
#if MG_ENABLE_SSL
|
||||
|
||||
#include "mbedtls/aes.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
|
||||
#define AES_PRIV_NR_POS (4 * 15)
|
||||
|
||||
/*
|
||||
* Crypto functions in ROM/SDK.
|
||||
* They come from wpa_supplicant, you can find them here https://w1.fi/cgit/
|
||||
*
|
||||
* Note that ROM version of the key setup function is older, does not take the
|
||||
* number of bits argument and only supports AES-128. This prototype doesn't
|
||||
* suit it, but since the difference is in the last aegument, it doesn't matter.
|
||||
*/
|
||||
|
||||
extern void rijndaelKeySetupDec(void *ctx, const uint8_t *key, int bits);
|
||||
extern int rijndaelKeySetupEnc(void *ctx, const uint8_t *key, int bits);
|
||||
void aes_encrypt(void *ctx, const uint8_t *plain, uint8_t *crypt);
|
||||
void aes_decrypt(void *ctx, const uint8_t *crypt, uint8_t *plain);
|
||||
|
||||
/*
|
||||
* AES that comes with wpa_supplicant allocates its own AES context in
|
||||
* aes_{encrypt,decrypt}_init. Ideally, we'd take that pointer and store it in
|
||||
* our mbedtls_aes_context, but then a lot of space would be wasted.
|
||||
* We do not call _init and go directly to key setup functions and poke number
|
||||
* of rounds into the right place too. This is a bit hacky, but works fine.
|
||||
* There is also a difference between older function in ROM and the one coming
|
||||
* with SDK which is newer: the older one actually takes two arguments, not 3.
|
||||
* But it doesn't matter, extra argument doesn't hurt and this works with both.
|
||||
*/
|
||||
int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits) {
|
||||
if (keybits != 128) return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
((uint32_t *) ctx)[AES_PRIV_NR_POS] = 10;
|
||||
rijndaelKeySetupEnc(ctx, key, 128);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits) {
|
||||
if (keybits != 128) return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
((uint32_t *) ctx)[AES_PRIV_NR_POS] = 10;
|
||||
rijndaelKeySetupDec(ctx, key, 128);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16]) {
|
||||
aes_encrypt(ctx, input, output);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16]) {
|
||||
aes_decrypt(ctx, input, output);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* os_get_random uses hardware RNG, so it's cool. */
|
||||
int mg_ssl_if_mbed_random(void *ctx, unsigned char *buf, size_t len) {
|
||||
os_get_random(buf, len);
|
||||
(void) ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For CryptoAuthLib host crypto. */
|
||||
int atcac_sw_sha2_256(const uint8_t *data, size_t data_size,
|
||||
uint8_t digest[32]) {
|
||||
mbedtls_sha256(data, data_size, digest, false /* is_224 */);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* MG_ENABLE_SSL */
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2017 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_ESP_HW_WDT_REGISTER_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_ESP_HW_WDT_REGISTER_H_
|
||||
|
||||
#ifdef RTOS_SDK
|
||||
#include <esp_common.h>
|
||||
#else
|
||||
#include <user_interface.h>
|
||||
#endif
|
||||
|
||||
#define REG_WDT_BASE 0x60000900
|
||||
|
||||
#define WDT_CTL (REG_WDT_BASE + 0x0)
|
||||
#define WDT_CTL_ENABLE (BIT(0))
|
||||
#define WDT_CTL_STAGE1_NO_RESET (BIT(1))
|
||||
#define WDT_CTL_STAGE1_DISABLE (BIT(2))
|
||||
#define WDT_CTL_UNK3 (BIT(3))
|
||||
#define WDT_CTL_UNK4 (BIT(4))
|
||||
#define WDT_CTL_UNK5 (BIT(5))
|
||||
|
||||
/* Bits 3, 4, 5 - ???; set to 1 by ROM. */
|
||||
|
||||
#define WDT_RELOAD_STAGE0 (REG_WDT_BASE + 0x4)
|
||||
#define WDT_RELOAD_STAGE0_V (0xf)
|
||||
#define WDT_RELOAD_STAGE0_S (0)
|
||||
|
||||
#define WDT_RELOAD_STAGE1 (REG_WDT_BASE + 0x8)
|
||||
#define WDT_RELOAD_STAGE1_V (0xf)
|
||||
#define WDT_RELOAD_STAGE1_S (0)
|
||||
|
||||
#define WDT_COUNT (REG_WDT_BASE + 0xc) /* Counts at CPU_CLK (80 MHz) */
|
||||
#define WDT_COUNT_V (0xffffffff)
|
||||
#define WDT_COUNT_S (0)
|
||||
|
||||
#define WDT_STAGE (REG_WDT_BASE + 0x10)
|
||||
#define WDT_STAGE_V (1)
|
||||
#define WDT_STAGE_S (0)
|
||||
|
||||
#define WDT_RESET (REG_WDT_BASE + 0x14)
|
||||
#define WDT_RESET_V (0xff)
|
||||
#define WDT_RESET_S (0)
|
||||
|
||||
#define WDT_RESET_STAGE (REG_WDT_BASE + 0x18)
|
||||
#define WDT_RESET_STAGE_V (0xff)
|
||||
#define WDT_RESET_STAGE_S (0)
|
||||
|
||||
#define WDT_RESET_VALUE 0x73
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_ESP_HW_WDT_REGISTER_H_ */
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_ESP_MISSING_INCLUDES_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_ESP_MISSING_INCLUDES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void pp_soft_wdt_init(void);
|
||||
void pp_soft_wdt_stop(void);
|
||||
void pp_soft_wdt_feed(void);
|
||||
void pp_soft_wdt_restart(void);
|
||||
void system_soft_wdt_stop(void); /* Alias for pp_soft_wdt_stop */
|
||||
|
||||
void Cache_Read_Disable(void);
|
||||
void Cache_Read_Enable(uint32_t, uint32_t, uint32_t);
|
||||
void Cache_Read_Disable_2(void);
|
||||
void Cache_Read_Enable_2(void);
|
||||
void Cache_Read_Enable_New(void);
|
||||
|
||||
int SPIEraseBlock(uint32_t block);
|
||||
uint32_t SPIRead(uint32_t addr, void *dst, uint32_t size);
|
||||
|
||||
#ifndef RTOS_SDK
|
||||
|
||||
#include <ets_sys.h>
|
||||
|
||||
/* There are no declarations for these anywhere in the SDK (as of 1.2.0). */
|
||||
void ets_isr_mask(unsigned intr);
|
||||
void ets_isr_unmask(unsigned intr);
|
||||
void system_restart_local(void);
|
||||
int os_printf_plus(const char *format, ...);
|
||||
|
||||
void ets_wdt_init(void);
|
||||
void ets_wdt_enable(uint32_t mode, uint32_t arg1, uint32_t arg2);
|
||||
void ets_wdt_disable(void);
|
||||
void ets_wdt_restore(uint32_t mode);
|
||||
uint32_t ets_wdt_get_mode(void);
|
||||
|
||||
void _xtos_l1int_handler(void);
|
||||
void _xtos_set_exception_handler();
|
||||
void xthal_set_intenable(unsigned);
|
||||
|
||||
/* These are present in mem.h but are commented out. */
|
||||
void *pvPortMalloc(size_t xWantedSize, const char *file, int line);
|
||||
void vPortFree(void *pv, const char *file, int line);
|
||||
void *pvPortZalloc(size_t size, const char *file, int line);
|
||||
void *pvPortRealloc(void *pv, size_t size, const char *file, int line);
|
||||
|
||||
#else /* !RTOS_SDK */
|
||||
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
void system_soft_wdt_feed(void);
|
||||
void system_soft_wdt_restart(void);
|
||||
void ets_putc(char c);
|
||||
|
||||
#endif /* RTOS_SDK */
|
||||
|
||||
void _ResetVector(void);
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_ESP_MISSING_INCLUDES_H_ */
|
@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_ESP_SSL_KRYPTON_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_ESP_SSL_KRYPTON_H_
|
||||
|
||||
#include "krypton/krypton.h"
|
||||
|
||||
struct mg_connection;
|
||||
|
||||
void mg_lwip_ssl_do_hs(struct mg_connection *nc);
|
||||
void mg_lwip_ssl_send(struct mg_connection *nc);
|
||||
void mg_lwip_ssl_recv(struct mg_connection *nc);
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_ESP_SSL_KRYPTON_H_ */
|
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "common/umm_malloc/umm_malloc.h"
|
||||
#include "esp_umm_malloc.h"
|
||||
|
||||
#if ESP_UMM_ENABLE
|
||||
|
||||
/*
|
||||
* ESP-specific glue for the `umm_malloc`.
|
||||
*
|
||||
* In SDK (https://github.com/cesanta/esp-open-sdk), there is an archive
|
||||
* `sdk/lib/libmain.a` which contains some files, including `mem_manager.o`.
|
||||
*
|
||||
* The `mem_manager.o` contains all the heap-related functions: `pvPortMalloc`,
|
||||
* etc. We have weaken all symbols from `mem_manager.o` by
|
||||
* `xtensa-lx106-elf-objcopy` (see exact commands in Dockerfile:
|
||||
* `docker/esp8266/Dockerfile-esp8266-build-oss`), and provide our own
|
||||
* implementations in this file.
|
||||
*
|
||||
* ------------------------------------
|
||||
*
|
||||
* NOTE that not all public functions from `mem_manager.o` need to be replaced:
|
||||
* some of them are used only internally:
|
||||
*
|
||||
* - system_show_malloc()
|
||||
* - pvShowMalloc()
|
||||
* - prvInsertBlockIntoUsedList()
|
||||
* - prvRemoveBlockFromUsedList()
|
||||
* - check_memleak_debug_enable()
|
||||
* - vPortInitialiseBlocks()
|
||||
*
|
||||
* So when we replace all the rest (`pvPortMalloc`, etc), we can check with
|
||||
* `objdump` that resulting binary (for SJ, it's `fw.out`) doesn't contain
|
||||
* any of the "internal" functions.
|
||||
*
|
||||
* ------------------------------------
|
||||
*
|
||||
* NOTE that to make linker actually consider implementations in this file,
|
||||
* you should explicitly reference some function from it. This is what
|
||||
* `esp_umm_init()` is for: it is a dummy no-op function that must be called
|
||||
* from somewhere outside.
|
||||
*
|
||||
* If you don't do this, linker will merely garbage-collect this file, and
|
||||
* will use heap implementation from SDK.
|
||||
*/
|
||||
|
||||
void *pvPortMalloc(size_t size, const char *file, unsigned line) {
|
||||
(void) file;
|
||||
(void) line;
|
||||
|
||||
return umm_malloc(size);
|
||||
}
|
||||
|
||||
void *pvPortCalloc(size_t num, size_t size, const char *file, unsigned line) {
|
||||
(void) file;
|
||||
(void) line;
|
||||
|
||||
return umm_calloc(num, size);
|
||||
}
|
||||
|
||||
void *pvPortZalloc(size_t size, const char *file, unsigned line) {
|
||||
void *ret;
|
||||
|
||||
(void) file;
|
||||
(void) line;
|
||||
|
||||
ret = umm_malloc(size);
|
||||
if (ret != NULL) memset(ret, 0, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *pvPortRealloc(void *ptr, size_t size, const char *file, unsigned line) {
|
||||
(void) file;
|
||||
(void) line;
|
||||
|
||||
return umm_realloc(ptr, size);
|
||||
}
|
||||
|
||||
void vPortFree(void *ptr, const char *file, unsigned line) {
|
||||
(void) file;
|
||||
(void) line;
|
||||
|
||||
umm_free(ptr);
|
||||
}
|
||||
|
||||
size_t xPortGetFreeHeapSize(void) {
|
||||
return umm_free_heap_size();
|
||||
}
|
||||
|
||||
size_t xPortWantedSizeAlign(void) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
void esp_umm_init(void) {
|
||||
/* Nothing to do, see header for details */
|
||||
}
|
||||
|
||||
void esp_umm_oom_cb(size_t size, size_t blocks_cnt) {
|
||||
fprintf(stderr, "E:M %u (%u blocks)\n", (unsigned int) size,
|
||||
(unsigned int) blocks_cnt);
|
||||
}
|
||||
|
||||
#endif /* ESP_UMM_ENABLE */
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#if ESP_UMM_ENABLE
|
||||
|
||||
/*
|
||||
* This is a no-op dummy function that is merely needed because we have to
|
||||
* reference any function from the file `esp_umm_malloc.c`, so that linker
|
||||
* won't garbage-collect the whole compilation unit.
|
||||
*/
|
||||
void esp_umm_init(void);
|
||||
|
||||
/*
|
||||
* Callback that gets called by umm_malloc in case of Out-of-memory error.
|
||||
*
|
||||
* `size` is the size requested by user, and `block_cnt` is a number of heap
|
||||
* blocks that umm_malloc failed to allocate
|
||||
*/
|
||||
void esp_umm_oom_cb(size_t size, size_t blocks_cnt);
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_ESP_UMM_MALLOC_H_ */
|
@ -1,26 +0,0 @@
|
||||
#
|
||||
# Makefile for esptool2
|
||||
# https://github.com/raburton/esp8266
|
||||
#
|
||||
|
||||
CFLAGS = -O2 -Wall
|
||||
CC = gcc
|
||||
LD = gcc
|
||||
BUILD_DIR = ../../build
|
||||
|
||||
all: $(BUILD_DIR) $(BUILD_DIR)/esptool2
|
||||
|
||||
$(BUILD_DIR):
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
|
||||
$(BUILD_DIR)/esptool2.o: esptool2.c esptool2.h esptool2_elf.h elf.h
|
||||
@echo "CC $<"
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/esptool2_elf.o: esptool2_elf.c esptool2.h esptool2_elf.h elf.h
|
||||
@echo "CC $<"
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/esptool2: $(BUILD_DIR)/esptool2.o $(BUILD_DIR)/esptool2_elf.o
|
||||
@echo "LD $@"
|
||||
$(LD) -o $@ $^
|
@ -1,76 +0,0 @@
|
||||
// Based on a small portion of ELF.h from LLVM
|
||||
|
||||
//===-- llvm/Support/ELF.h - ELF constants and data structures --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This header contains common, non-processor-specific data structures and
|
||||
// constants for the ELF file format.
|
||||
//
|
||||
// The details of the ELF32 bits in this file are largely based on the Tool
|
||||
// Interface Standard (TIS) Executable and Linking Format (ELF) Specification
|
||||
// Version 1.2, May 1995. The ELF64 stuff is based on ELF-64 Object File Format
|
||||
// Version 1.5, Draft 2, May 1998 as well as OpenBSD header files.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_RBOOT_ESPTOOL2_ELF_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_RBOOT_ESPTOOL2_ELF_H_
|
||||
|
||||
typedef uint32_t Elf32_Addr; // Program address
|
||||
typedef uint32_t Elf32_Off; // File offset
|
||||
typedef uint16_t Elf32_Half;
|
||||
typedef uint32_t Elf32_Word;
|
||||
typedef int32_t Elf32_Sword;
|
||||
|
||||
// e_ident size and indices
|
||||
enum {
|
||||
EI_MAG0 = 0, // File identification index.
|
||||
EI_MAG1 = 1, // File identification index.
|
||||
EI_MAG2 = 2, // File identification index.
|
||||
EI_MAG3 = 3, // File identification index.
|
||||
EI_CLASS = 4, // File class.
|
||||
EI_DATA = 5, // Data encoding.
|
||||
EI_VERSION = 6, // File version.
|
||||
EI_OSABI = 7, // OS/ABI identification.
|
||||
EI_ABIVERSION = 8, // ABI version.
|
||||
EI_PAD = 9, // Start of padding bytes.
|
||||
EI_NIDENT = 16 // Number of bytes in e_ident.
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned char e_ident[EI_NIDENT]; // ELF Identification bytes
|
||||
Elf32_Half e_type; // Type of file (see ET_* below)
|
||||
Elf32_Half e_machine; // Required architecture for this file (see EM_*)
|
||||
Elf32_Word e_version; // Must be equal to 1
|
||||
Elf32_Addr e_entry; // Address to jump to in order to start program
|
||||
Elf32_Off e_phoff; // Program header table's file offset, in bytes
|
||||
Elf32_Off e_shoff; // Section header table's file offset, in bytes
|
||||
Elf32_Word e_flags; // Processor-specific flags
|
||||
Elf32_Half e_ehsize; // Size of ELF header, in bytes
|
||||
Elf32_Half e_phentsize; // Size of an entry in the program header table
|
||||
Elf32_Half e_phnum; // Number of entries in the program header table
|
||||
Elf32_Half e_shentsize; // Size of an entry in the section header table
|
||||
Elf32_Half e_shnum; // Number of entries in the section header table
|
||||
Elf32_Half e_shstrndx; // Sect hdr table index of sect name string table
|
||||
} Elf32_Ehdr;
|
||||
|
||||
typedef struct {
|
||||
Elf32_Word sh_name; // Section name (index into string table)
|
||||
Elf32_Word sh_type; // Section type (SHT_*)
|
||||
Elf32_Word sh_flags; // Section flags (SHF_*)
|
||||
Elf32_Addr sh_addr; // Address where section is to be loaded
|
||||
Elf32_Off sh_offset; // File offset of section data, in bytes
|
||||
Elf32_Word sh_size; // Size of section, in bytes
|
||||
Elf32_Word sh_link; // Section type-specific header table index link
|
||||
Elf32_Word sh_info; // Section type-specific extra information
|
||||
Elf32_Word sh_addralign; // Section address alignment
|
||||
Elf32_Word sh_entsize; // Size of records contained within the section
|
||||
} Elf32_Shdr;
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_RBOOT_ESPTOOL2_ELF_H_ */
|
@ -1,561 +0,0 @@
|
||||
/**********************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015 Richard A Burton <richardaburton@gmail.com>
|
||||
*
|
||||
* This file is part of esptool2.
|
||||
*
|
||||
* esptool2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* esptool2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with esptool2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
**********************************************************************************/
|
||||
/* clang-format off */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "esptool2.h"
|
||||
#include "esptool2_elf.h"
|
||||
|
||||
#define IMAGE_PADDING 16
|
||||
#define SECTION_PADDING 4
|
||||
#define IROM_SECTION_PADDING 4096
|
||||
#define CHECKSUM_INIT 0xEF
|
||||
#define BIN_MAGIC_IROM 0xEA
|
||||
#define BIN_MAGIC_FLASH 0xE9
|
||||
|
||||
typedef struct {
|
||||
Elf32_Addr addr;
|
||||
Elf32_Word size;
|
||||
} Section_Header;
|
||||
|
||||
typedef struct {
|
||||
unsigned char magic;
|
||||
unsigned char count;
|
||||
unsigned char byte2;
|
||||
unsigned char byte3;
|
||||
Elf32_Addr entry;
|
||||
} Image_Header;
|
||||
|
||||
static const char PADDING[IROM_SECTION_PADDING] = {0};
|
||||
|
||||
static bool debugon = false;
|
||||
static bool quieton = false;
|
||||
|
||||
// Print a standard info message (unless quiet mode)
|
||||
void print(const char* format, ...) {
|
||||
va_list args;
|
||||
|
||||
if (!quieton) {
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
// Print a debug message (if debug mode)
|
||||
void debug(const char* format, ...) {
|
||||
va_list args;
|
||||
|
||||
if (debugon) {
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
// Print an error message (always)
|
||||
void error(const char* format, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// Write an elf section (by name) to an existing file.
|
||||
// Parameters:
|
||||
// headed - add a header to the output
|
||||
// zeroaddr - force zero entry point in header (default is the real entry point)
|
||||
// padded - output will be padded to multiple of SECTION_PADDING bytes
|
||||
// chksum - pointer to existing checksum to add this data to (zero if not needed)
|
||||
// Produces error message on failure (so caller doesn't need to).
|
||||
bool WriteElfSection(MyElf_File *elf, FILE *outfile, char* name, bool headed,
|
||||
bool zeroaddr, int padto, unsigned char *chksum) {
|
||||
|
||||
int i, pad = 0;
|
||||
bool ret = false;
|
||||
unsigned char *bindata = 0;
|
||||
Section_Header sechead;
|
||||
MyElf_Section *sect;
|
||||
|
||||
// get elf section header
|
||||
sect = GetElfSection(elf, name);
|
||||
if(!sect) {
|
||||
error("Error: Section '%s' not found in elf file.\r\n", name);
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// create image section header
|
||||
sechead.addr = (zeroaddr ? 0 : sect->address);
|
||||
sechead.size = sect->size;
|
||||
|
||||
// do we need to pad the section?
|
||||
if (padto) {
|
||||
pad = sechead.size % padto;
|
||||
if (pad > 0) {
|
||||
pad = padto - pad;
|
||||
sechead.size += pad;
|
||||
}
|
||||
}
|
||||
|
||||
debug("Adding section '%s', addr: 0x%08x, size: %d (+%d bytes(s) padding).\r\n",
|
||||
name, sect->address, sect->size, pad);
|
||||
|
||||
// get elf section binary data
|
||||
bindata = GetElfSectionData(elf, sect);
|
||||
if (!bindata) {
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// write section (and pad if required)
|
||||
if((headed && fwrite(&sechead, 1, sizeof(sechead), outfile) != sizeof(sechead))
|
||||
|| fwrite(bindata, 1, sect->size, outfile) != sect->size
|
||||
|| (pad > 0 && fwrite(PADDING, 1, pad, outfile) != pad)) {
|
||||
error("Error: Failed to write section '%s' to image file.\r\n", name);
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// include section data in the checksum
|
||||
if(chksum) {
|
||||
for(i = 0; i < (int)sect->size; i++) {
|
||||
*chksum ^= bindata[i];
|
||||
}
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
end_function:
|
||||
if (bindata) free(bindata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Load an elf file and export a section of it to a new file, without
|
||||
// header, padding or checksum. For exporting the .irom0.text library.
|
||||
// Produces error message on failure (so caller doesn't need to).
|
||||
bool ExportElfSection(char *infile, char *outfile, char *name) {
|
||||
|
||||
bool ret = false;
|
||||
FILE *fd = 0;
|
||||
MyElf_File *elf = 0;
|
||||
|
||||
// load elf file
|
||||
elf = LoadElf(infile);
|
||||
if (!elf) {
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// open output file
|
||||
fd = fopen(outfile, "wb");
|
||||
if(!fd) {
|
||||
error("Error: Can't open output file '%s' for writing.\r\n", outfile);
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// actually do the export
|
||||
ret = WriteElfSection(elf, fd, name, false, false, false, 0);
|
||||
|
||||
end_function:
|
||||
// clean up
|
||||
if (fd) fclose(fd);
|
||||
UnloadElf(elf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Create the main binary firmware image, from specified elf sections.
|
||||
// Can produce for standard standalone app (separate .irom0.text)
|
||||
// or sdk bootloaded apps (integrated .irom0.text).
|
||||
// Choice of type requires appropriately linked elf file.
|
||||
// Produces error message on failure (so caller doesn't need to).
|
||||
bool CreateHeaderFile(char *elffile, char *imagefile, char *sections[], int numsec) {
|
||||
|
||||
bool ret = false;
|
||||
int i;
|
||||
unsigned int j, len;
|
||||
FILE *outfile = 0;
|
||||
MyElf_File *elf = 0;
|
||||
MyElf_Section *sect;
|
||||
unsigned char *bindata = 0;
|
||||
char name[31];
|
||||
|
||||
// load elf file
|
||||
elf = LoadElf(elffile);
|
||||
if (!elf) {
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// open output file
|
||||
outfile = fopen(imagefile, "wb");
|
||||
if(outfile == NULL) {
|
||||
error("Error: Failed to open output file '%s' for writing.\r\n", imagefile);
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// add entry point
|
||||
fprintf(outfile, "const uint32 entry_addr = 0x%08x;\r\n", elf->header.e_entry);
|
||||
|
||||
// add sections
|
||||
for (i = 0; i < numsec; i++) {
|
||||
// get elf section header
|
||||
sect = GetElfSection(elf, sections[i]);
|
||||
if(!sect) {
|
||||
error("Error: Section '%s' not found in elf file.\r\n", sections[i]);
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// simple name fix name
|
||||
strncpy(name, sect->name, 31);
|
||||
len = strlen(name);
|
||||
for (j = 0; j < len; j++) {
|
||||
if (name[j] == '.') name[j] = '_';
|
||||
}
|
||||
|
||||
// add address, length and start the data block
|
||||
debug("Adding section '%s', addr: 0x%08x, size: %d.\r\n", sections[i], sect->address, sect->size);
|
||||
fprintf(outfile, "\r\nconst uint32 %s_addr = 0x%08x;\r\nconst uint32 %s_len = %d;\r\nconst uint8 %s_data[] = {",
|
||||
name, sect->address, name, sect->size, name);
|
||||
|
||||
// get elf section binary data
|
||||
bindata = GetElfSectionData(elf, sect);
|
||||
if (!bindata) {
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// add the data and finish off the block
|
||||
for (j = 0; j < sect->size; j++) {
|
||||
if (j % 16 == 0) fprintf(outfile, "\r\n 0x%02x,", bindata[j]);
|
||||
else fprintf(outfile, " 0x%02x,", bindata[j]);
|
||||
}
|
||||
fprintf(outfile, "\r\n};\r\n");
|
||||
free(bindata);
|
||||
bindata = 0;
|
||||
}
|
||||
|
||||
// if we got this far everything worked!
|
||||
ret = true;
|
||||
|
||||
end_function:
|
||||
// clean up
|
||||
if (outfile) fclose(outfile);
|
||||
if (elf) UnloadElf(elf);
|
||||
if (bindata) free(bindata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Create the main binary firmware image, from specified elf sections.
|
||||
// Can produce for standard standalone app (separate .irom0.text)
|
||||
// or sdk bootloaded apps (integrated .irom0.text).
|
||||
// Choice of type requires appropriately linked elf file.
|
||||
// Produces error message on failure (so caller doesn't need to).
|
||||
bool CreateBinFile(char *elffile, char *imagefile, int bootver, unsigned char mode,
|
||||
unsigned char clock, unsigned char size, bool iromchksum, char *sections[], int numsec) {
|
||||
|
||||
bool ret = false;
|
||||
int i, pad, len;
|
||||
unsigned char chksum = CHECKSUM_INIT;
|
||||
unsigned char *data = 0;
|
||||
FILE *outfile = 0;
|
||||
MyElf_File *elf = 0;
|
||||
Image_Header imghead;
|
||||
|
||||
// load elf file
|
||||
elf = LoadElf(elffile);
|
||||
if (!elf) {
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// open output file
|
||||
outfile = fopen(imagefile, "wb");
|
||||
if(outfile == NULL) {
|
||||
error("Error: Failed to open output file '%s' for writing.\r\n", imagefile);
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// set options common to standard and boot v1.2+ headers
|
||||
imghead.byte2 = mode;
|
||||
//imghead.byte3 = (int)((int)size << 4 | clock) && 0xff;
|
||||
imghead.byte3 = ((size << 4) | clock) & 0xff;
|
||||
imghead.entry = elf->header.e_entry;
|
||||
debug("Size = %02x\r\n", size);
|
||||
debug("Byte2 = %02x\r\n", imghead.byte2);
|
||||
debug("Byte3 = %02x\r\n", imghead.byte3);
|
||||
debug("Entry = %08x\r\n", imghead.entry);
|
||||
|
||||
// boot v1.2+ header
|
||||
if (bootver == 2) {
|
||||
// extra header
|
||||
imghead.magic = BIN_MAGIC_IROM;
|
||||
imghead.count = 4; // probably a version number here, not a count
|
||||
if(fwrite(&imghead, 1, sizeof(imghead), outfile) != sizeof(imghead)) {
|
||||
error("Error: Failed to write header to image file.\r\n");
|
||||
goto end_function;
|
||||
}
|
||||
if(!WriteElfSection(elf, outfile, ".irom0.text", true, true, IROM_SECTION_PADDING, (iromchksum ? &chksum : 0))) {
|
||||
goto end_function;
|
||||
}
|
||||
}
|
||||
|
||||
// standard header
|
||||
imghead.magic = BIN_MAGIC_FLASH;
|
||||
imghead.count = numsec;
|
||||
// write header
|
||||
if(fwrite(&imghead, 1, sizeof(imghead), outfile) != sizeof(imghead)) {
|
||||
error("Error: Failed to write header to image file.\r\n");
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// add sections
|
||||
for (i = 0; i < numsec; i++) {
|
||||
if(!WriteElfSection(elf, outfile, sections[i], true, false, SECTION_PADDING, &chksum)) {
|
||||
goto end_function;
|
||||
}
|
||||
}
|
||||
|
||||
// get image length (plus a byte for the checksum)
|
||||
len = ftell(outfile) + 1;
|
||||
|
||||
// do we need to pad the image?
|
||||
pad = len % IMAGE_PADDING;
|
||||
if (pad > 0) {
|
||||
pad = IMAGE_PADDING - pad;
|
||||
debug("Padding image with %d byte(s).\r\n", pad);
|
||||
if(fwrite(PADDING, 1, pad, outfile) != pad) {
|
||||
error("Error: Failed to write padding to image file.\r\n");
|
||||
goto end_function;
|
||||
}
|
||||
}
|
||||
|
||||
// write checksum
|
||||
if(fwrite(&chksum, 1, 1, outfile) != 1) {
|
||||
error("Error: Failed to write checksum to image file.\r\n");
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// boot v1.1
|
||||
if(bootver == 1) {
|
||||
// write 'ff' padding up to the position of the library
|
||||
len = 0x10000 - ftell(outfile);
|
||||
debug("Adding boot v1.1 padding, %d bytes of '0xff'.\r\n", len);
|
||||
data = (unsigned char*)malloc(len);
|
||||
memset(data, 0xff, len);
|
||||
if(fwrite(data, 1, len, outfile) != len) {
|
||||
error("Error: Failed to write boot v1.1 spacer.\r\n");
|
||||
goto end_function;
|
||||
}
|
||||
|
||||
// write the library
|
||||
if(!WriteElfSection(elf, outfile, ".irom0.text", false, false, 0, 0)) {
|
||||
goto end_function;
|
||||
}
|
||||
}
|
||||
|
||||
// if we got this far everything worked!
|
||||
ret = true;
|
||||
|
||||
end_function:
|
||||
// clean up
|
||||
if (outfile) fclose(outfile);
|
||||
if (data) free(data);
|
||||
if (elf) UnloadElf(elf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
int i;
|
||||
char *infile;
|
||||
char *outfile;
|
||||
int numstr;
|
||||
bool binfile = false;
|
||||
bool libfile = false;
|
||||
bool headerfile = false;
|
||||
bool paramerror = false;
|
||||
bool iromchksum = false;
|
||||
int bootver = 0;
|
||||
/* Overwrite-friendly by default */
|
||||
unsigned char mode = 0xff;
|
||||
unsigned char size = 0xff;
|
||||
unsigned char clock = 0;
|
||||
int opts = 0;
|
||||
|
||||
// parse options
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-bin")) {
|
||||
binfile = true;
|
||||
opts++;
|
||||
} else if (!strcmp(argv[i], "-lib")) {
|
||||
libfile = true;
|
||||
opts++;
|
||||
} else if (!strcmp(argv[i], "-header")) {
|
||||
headerfile = true;
|
||||
opts++;
|
||||
} else if (!strcmp(argv[i], "-quiet")) {
|
||||
quieton = true;
|
||||
} else if (!strcmp(argv[i], "-debug")) {
|
||||
debugon = true;
|
||||
} else if (!strcmp(argv[i], "-boot0")) {
|
||||
bootver = 0;
|
||||
} else if (!strcmp(argv[i], "-boot1")) {
|
||||
bootver = 1;
|
||||
} else if (!strcmp(argv[i], "-boot2")) {
|
||||
bootver = 2;
|
||||
} else if (!strcmp(argv[i], "-qio")) {
|
||||
mode = 0;
|
||||
} else if (!strcmp(argv[i], "-qout")) {
|
||||
mode = 1;
|
||||
} else if (!strcmp(argv[i], "-dio")) {
|
||||
mode = 2;
|
||||
} else if (!strcmp(argv[i], "-dout")) {
|
||||
mode = 3;
|
||||
} else if (!strcmp(argv[i], "-256")) {
|
||||
size = 1;
|
||||
} else if (!strcmp(argv[i], "-512")) {
|
||||
size = 0;
|
||||
} else if (!strcmp(argv[i], "-1024")) {
|
||||
size = 2;
|
||||
} else if (!strcmp(argv[i], "-2048")) {
|
||||
size = 3;
|
||||
} else if (!strcmp(argv[i], "-4096")) {
|
||||
size = 4;
|
||||
} else if (!strcmp(argv[i], "-20")) {
|
||||
clock = 2;
|
||||
} else if (!strcmp(argv[i], "-26.7")) {
|
||||
clock = 1;
|
||||
} else if (!strcmp(argv[i], "-40")) {
|
||||
clock = 0;
|
||||
} else if (!strcmp(argv[i], "-80")) {
|
||||
clock = 15;
|
||||
} else if (!strcmp(argv[i], "-iromchksum")) {
|
||||
iromchksum = true;
|
||||
} else if (!strcmp(argv[i], "--")) {
|
||||
i++;
|
||||
break;
|
||||
} else if (argv[i][0] == '-') {
|
||||
paramerror = true;
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
print("esptool2 v2.0.0 - (c) 2015 Richard A Burton <richardaburton@gmail.com>\r\n");
|
||||
print("This program is licensed under the GPL v3.\r\n");
|
||||
print("See the file LICENSE for details.\r\n\r\n");
|
||||
|
||||
if (paramerror) {
|
||||
error("Error: Unrecognised option '%s'.\r\n", argv[i]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
print("Usage:\r\n");
|
||||
print("esptool2 -lib [options] <input_file> <output_file>\r\n");
|
||||
print("esptool2 -bin [options] <input_file> <output_file> <elf_section>...\r\n");
|
||||
print("esptool2 -header [options] <input_file> <output_file> <elf_section>...\r\n");
|
||||
print("\r\n");
|
||||
print(" -lib\r\n");
|
||||
print(" Export the sdk library (.irom0.text), for a standalone app.\r\n");
|
||||
print(" e.g. esptool2 -elf esp8266_iot.out out.bin\r\n");
|
||||
print("\r\n");
|
||||
print(" -header\r\n");
|
||||
print(" Export elf sections as bytes to a C header file.\r\n");
|
||||
print(" e.g. esptool2 -elf esp8266_iot.out out.h .text .data .rodata\r\n");
|
||||
print("\r\n");
|
||||
print(" -bin\r\n");
|
||||
print(" Create binary program image, for standalone and bootloaded apps, with\r\n");
|
||||
print(" specified elf sections. Includes sdk library for bootloaded apps.\r\n");
|
||||
print(" e.g. esptool2 -bin esp8266_iot.out out.bin .text .data .rodata\r\n");
|
||||
print(" Options:\r\n");
|
||||
print(" bootloader: -boot0 -boot1 -boot2 (default -boot0)\r\n");
|
||||
print(" -boot0 = standalone app, not built for bootloader use\r\n");
|
||||
print(" -boot1 = built for bootloader v1.1\r\n");
|
||||
print(" -boot2 = built for bootloader v1.2+ (use for rBoot roms)\r\n");
|
||||
print(" (elf file must have been linked appropriately for chosen option)\r\n");
|
||||
print(" spi size (kb): -256 -512 -1024 -2048 -4096 (default -512)\r\n");
|
||||
print(" spi mode: -qio -qout -dio -dout (default -qio)\r\n");
|
||||
print(" spi speed: -20 -26.7 -40 -80 (default -40)\r\n");
|
||||
print(" include irom in checksum: -iromchksum (also needs enabling in rBoot)\r\n");
|
||||
print("\r\n");
|
||||
print("General options:\r\n");
|
||||
print(" -quiet prints only error messages\r\n");
|
||||
print(" -debug print extra debug information\r\n");
|
||||
print(" -- no more options follow (needed if your elf file starts with a '-')\r\n");
|
||||
print("\r\n");
|
||||
print("Returns:\r\n");
|
||||
print(" 0 on success\r\n");
|
||||
print(" -1 on failure\r\n");
|
||||
print("\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// validate command line options
|
||||
if (opts != 1) {
|
||||
error("Error: You must specify -bin OR -lib OR -header for build type.\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (quieton && debugon) {
|
||||
error("Error: You cannot specify -quiet and -debug.\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check enough parameters
|
||||
if ((libfile && i + 2 > argc) || ((binfile | headerfile) && i + 3 > argc)) {
|
||||
error("Error: Not enough arguments supplied.\r\n");
|
||||
return -1;
|
||||
} else if (libfile && i + 2 < argc) {
|
||||
error("Error: Too many arguments supplied.\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get parameters
|
||||
infile = argv[i++];
|
||||
outfile = argv[i++];
|
||||
numstr = argc - i;
|
||||
|
||||
// do it
|
||||
if (binfile) {
|
||||
if (!CreateBinFile(infile, outfile, bootver, mode, clock, size, iromchksum, &argv[i], numstr)) {
|
||||
remove(outfile);
|
||||
return -1;
|
||||
}
|
||||
} else if (headerfile) {
|
||||
if (!CreateHeaderFile(infile, outfile, &argv[i], numstr)) {
|
||||
remove(outfile);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (!ExportElfSection(infile, outfile, ".irom0.text")) {
|
||||
remove(outfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
print("Successfully created '%s'.\r\n", outfile);
|
||||
return 0;
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/**********************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015 Richard A Burton <richardaburton@gmail.com>
|
||||
*
|
||||
* This file is part of esptool2.
|
||||
*
|
||||
* esptool2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* esptool2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with esptool2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
**********************************************************************************/
|
||||
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_RBOOT_ESPTOOL2_ESPTOOL2_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_RBOOT_ESPTOOL2_ESPTOOL2_H_
|
||||
|
||||
#ifdef WIN32
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define bool char
|
||||
|
||||
void debug( const char* format, ... );
|
||||
void print( const char* format, ... );
|
||||
void error( const char* format, ... );
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_RBOOT_ESPTOOL2_ESPTOOL2_H_ */
|
@ -1,183 +0,0 @@
|
||||
/**********************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015 Richard A Burton <richardaburton@gmail.com>
|
||||
*
|
||||
* This file is part of esptool2.
|
||||
*
|
||||
* esptool2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* esptool2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with esptool2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
**********************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "esptool2.h"
|
||||
#include "esptool2_elf.h"
|
||||
|
||||
// Find a section in an elf file by name.
|
||||
// Returns pointer to section if found, else returns zero.
|
||||
// Does not produce any messages.
|
||||
MyElf_Section* GetElfSection(MyElf_File *elf, char *name) {
|
||||
|
||||
int i;
|
||||
|
||||
for(i = 0; i < elf->header.e_shnum - 1; i++) {
|
||||
if(!strcmp(name, elf->sections[i].name)) {
|
||||
debug("Found section '%s'.\r\n", name);
|
||||
return &elf->sections[i];
|
||||
}
|
||||
}
|
||||
|
||||
debug("Could not find section '%s'.\r\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reads an elf section (actual data) from the elf file.
|
||||
// Returns a pointer to newly allocated memory (or zero on error),
|
||||
// which should be freed by the caller when finished with.
|
||||
// Produces error message on failure (so caller doesn't need to).
|
||||
unsigned char* GetElfSectionData(MyElf_File *elf, MyElf_Section *section) {
|
||||
|
||||
unsigned char *data = 0;
|
||||
|
||||
if (section->size && section->offset) {
|
||||
|
||||
data = (unsigned char*)malloc(section->size);
|
||||
if(!data) {
|
||||
error("Error: Out of memory!\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(fseek(elf->fd, section->offset, SEEK_SET) ||
|
||||
fread(data, 1, section->size, elf->fd) != section->size) {
|
||||
error("Error: Can't read section '%s' data from elf file.\r\n", section->name);
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
error("Error: Section '%s' has no data to read.\r\n", section->name);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Opens an elf file and reads the string table and file & section headers.
|
||||
// Returns a pointer to a MyElf_File structure (or zero on error).
|
||||
// UnloadElf should be called to dispose of the MyElf_File structure.
|
||||
// Produces error message on failure (so caller doesn't need to).
|
||||
MyElf_File* LoadElf(char *infile) {
|
||||
|
||||
int i;
|
||||
MyElf_File *elf;
|
||||
Elf32_Shdr temp;
|
||||
|
||||
// allocate the elf structure
|
||||
elf = (MyElf_File*)malloc(sizeof(MyElf_File));
|
||||
if(!elf) {
|
||||
error("Error: Out of memory!\r\n");
|
||||
goto error_exit;
|
||||
}
|
||||
memset(elf, 0, sizeof(MyElf_File));
|
||||
|
||||
// open the file
|
||||
elf->fd = fopen(infile, "rb");
|
||||
if(!elf->fd) {
|
||||
error("Error: Can't open elf file '%s'.\r\n", infile);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
// read the header
|
||||
if(fread(&elf->header, 1, sizeof(Elf32_Ehdr), elf->fd) != sizeof(Elf32_Ehdr)) {
|
||||
error("Error: Can't read elf file header.\r\n");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
// check the file header
|
||||
if (memcmp(elf->header.e_ident, "\x7f" "ELF", 4)) {
|
||||
error("Error: Input files doesn't look like an elf file (bad header).\r\n");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
// is there a string table section (we need one)
|
||||
if(!elf->header.e_shstrndx) {
|
||||
error("Error: Elf file does not contain a string table.\r\n");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
// get the string table section header
|
||||
if(fseek(elf->fd, elf->header.e_shoff + (elf->header.e_shentsize * elf->header.e_shstrndx), SEEK_SET) ||
|
||||
fread(&temp, 1, sizeof(Elf32_Shdr), elf->fd) != sizeof(Elf32_Shdr)) {
|
||||
|
||||
error("Error: Can't read string table section from elf file.\r\n");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
// read the actual string table
|
||||
if(!temp.sh_size) {
|
||||
error("Error: Elf file contains an empty string table.\r\n");
|
||||
goto error_exit;
|
||||
}
|
||||
elf->strings = (char*)malloc(temp.sh_size);
|
||||
if(!elf->strings) {
|
||||
error("Error: Out of memory!\r\n");
|
||||
goto error_exit;
|
||||
}
|
||||
if(fseek(elf->fd, temp.sh_offset, SEEK_SET) ||
|
||||
fread(elf->strings, 1, temp.sh_size, elf->fd) != temp.sh_size) {
|
||||
error("Error: Failed to read string stable from elf file.\r\n");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
// read section headers
|
||||
elf->sections = (MyElf_Section*)malloc(sizeof(MyElf_Section) * elf->header.e_shnum);
|
||||
if(!elf->sections) {
|
||||
error("Error: Out of memory!\r\n");
|
||||
goto error_exit;
|
||||
}
|
||||
for(i = 1; i < elf->header.e_shnum; i++) {
|
||||
if(fseek(elf->fd, elf->header.e_shoff + (elf->header.e_shentsize * i), SEEK_SET)
|
||||
|| fread(&temp, 1, sizeof(Elf32_Shdr), elf->fd) != sizeof(Elf32_Shdr)) {
|
||||
error("Error: Can't read section %d from elf file.\r\n", i);
|
||||
break;
|
||||
}
|
||||
debug("Read section %d '%s'.\r\n", i, elf->strings + temp.sh_name);
|
||||
elf->sections[i-1].address = temp.sh_addr;
|
||||
elf->sections[i-1].offset = temp.sh_offset;
|
||||
elf->sections[i-1].size = temp.sh_size;
|
||||
elf->sections[i-1].name = elf->strings + temp.sh_name;
|
||||
}
|
||||
|
||||
return elf;
|
||||
|
||||
error_exit:
|
||||
if (elf) {
|
||||
if (elf->fd) fclose(elf->fd);
|
||||
if (elf->strings) free(elf->strings);
|
||||
free(elf);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
// Close an elf file and dispose of the MyElf_File structure.
|
||||
void UnloadElf(MyElf_File *elf) {
|
||||
if (elf) {
|
||||
debug("Unloading elf file.\r\n");
|
||||
if(elf->fd) fclose(elf->fd);
|
||||
if(elf->strings) free(elf->strings);
|
||||
if(elf->sections) free(elf->sections);
|
||||
free(elf);
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/**********************************************************************************
|
||||
*
|
||||
* Copyright (c) 2015 Richard A Burton <richardaburton@gmail.com>
|
||||
*
|
||||
* This file is part of esptool2.
|
||||
*
|
||||
* esptool2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* esptool2 is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with esptool2. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
**********************************************************************************/
|
||||
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_RBOOT_ESPTOOL2_ESPTOOL2_ELF_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_RBOOT_ESPTOOL2_ESPTOOL2_ELF_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "elf.h"
|
||||
|
||||
typedef struct {
|
||||
Elf32_Off offset;
|
||||
Elf32_Addr address;
|
||||
Elf32_Word size;
|
||||
char *name;
|
||||
} MyElf_Section;
|
||||
|
||||
typedef struct {
|
||||
FILE *fd;
|
||||
Elf32_Ehdr header;
|
||||
char *strings;
|
||||
MyElf_Section *sections;
|
||||
} MyElf_File;
|
||||
|
||||
MyElf_File* LoadElf(char *infile);
|
||||
void UnloadElf(MyElf_File *e_object);
|
||||
MyElf_Section* GetElfSection(MyElf_File *e_object, char *name);
|
||||
unsigned char* GetElfSectionData(MyElf_File *e_object, MyElf_Section *section);
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_RBOOT_ESPTOOL2_ESPTOOL2_ELF_H_ */
|
@ -1,674 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
@ -1,19 +0,0 @@
|
||||
Esptool2
|
||||
richardaburton@gmail.com
|
||||
http://richard.burtons.org/
|
||||
|
||||
Esptool2 is a tool for creating rom images for the ESP8266. It is an alternative
|
||||
to using the SDK supplied shell script/Makefile/python script combo, which is a
|
||||
mess. It was inspired by the windows esptool v0.0.2 by mamalala and found on
|
||||
www.esp8266.com but made somewhat simpler in code and usage. It also adds
|
||||
support for boot loader v1.2+ rom types, which was the main reason I wrote it.
|
||||
|
||||
It was written for my own use and the name was simply to distinguish it for the
|
||||
other version on my system. The 2 is not intended to imply it is better than the
|
||||
original. The original has since been updated to v0.0.3 which can write to the
|
||||
flash, but I currently have no intention to add that to esptool2, it is purely a
|
||||
rom creating utility. It has become an integral part of my build process now and
|
||||
has added functionality needed for building the rBoot boot loader. Since I have
|
||||
released rBoot I needed to release this as well.
|
||||
|
||||
Run tool for full usage instructions, or look at the code.
|
@ -1,152 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// rBoot OTA and config API for ESP8266.
|
||||
// Copyright 2015 Richard A Burton
|
||||
// richardaburton@gmail.com
|
||||
// See license.txt for license terms.
|
||||
// OTA code based on SDK sample from Espressif.
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
#ifdef RBOOT_INTEGRATION
|
||||
#include <rboot-integration.h>
|
||||
#endif
|
||||
|
||||
#include <c_types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef RTOS_SDK
|
||||
#include "spi_flash.h"
|
||||
#else
|
||||
#include <user_interface.h>
|
||||
#endif
|
||||
|
||||
#include "rboot-api.h"
|
||||
#include "../rboot-private.h"
|
||||
#include "esp_missing_includes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// get the rboot config
|
||||
rboot_config ICACHE_FLASH_ATTR rboot_get_config(void) {
|
||||
rboot_config conf;
|
||||
spi_flash_read(BOOT_CONFIG_SECTOR * SECTOR_SIZE, (uint32*)&conf, sizeof(rboot_config));
|
||||
return conf;
|
||||
}
|
||||
|
||||
// write the rboot config
|
||||
// preserves the contents of the rest of the sector,
|
||||
// so the rest of the sector can be used to store user data
|
||||
// updates checksum automatically (if enabled)
|
||||
bool ICACHE_FLASH_ATTR rboot_set_config(rboot_config *conf) {
|
||||
uint32_t buffer[sizeof(*conf) / sizeof(uint32_t) + 1];
|
||||
#ifdef BOOT_CONFIG_CHKSUM
|
||||
uint8 chksum;
|
||||
uint8 *ptr;
|
||||
#endif
|
||||
|
||||
#ifdef BOOT_CONFIG_CHKSUM
|
||||
chksum = CHKSUM_INIT;
|
||||
for (ptr = (uint8*)conf; ptr < &conf->chksum; ptr++) {
|
||||
chksum ^= *ptr;
|
||||
}
|
||||
conf->chksum = chksum;
|
||||
#endif
|
||||
|
||||
memset(buffer, 0xff, sizeof(buffer));
|
||||
memcpy(buffer, conf, sizeof(*conf));
|
||||
if (spi_flash_erase_sector(BOOT_CONFIG_SECTOR) != SPI_FLASH_RESULT_OK ||
|
||||
spi_flash_write(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, sizeof(buffer)) != SPI_FLASH_RESULT_OK) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// get current boot rom
|
||||
uint8 ICACHE_FLASH_ATTR rboot_get_current_rom(void) {
|
||||
rboot_config conf;
|
||||
conf = rboot_get_config();
|
||||
return conf.current_rom;
|
||||
}
|
||||
|
||||
// set current boot rom
|
||||
bool ICACHE_FLASH_ATTR rboot_set_current_rom(uint8 rom) {
|
||||
rboot_config conf;
|
||||
conf = rboot_get_config();
|
||||
if (rom >= conf.count) return false;
|
||||
conf.current_rom = rom;
|
||||
return rboot_set_config(&conf);
|
||||
}
|
||||
|
||||
// create the write status struct, based on supplied start address
|
||||
rboot_write_status ICACHE_FLASH_ATTR rboot_write_init(uint32 start_addr) {
|
||||
rboot_write_status status = {0};
|
||||
status.start_addr = start_addr;
|
||||
status.start_sector = start_addr / SECTOR_SIZE;
|
||||
//status.max_sector_count = 200;
|
||||
//os_printf("init addr: 0x%08x\r\n", start_addr);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// function to do the actual writing to flash
|
||||
// call repeatedly with more data (max len per write is the flash sector size (4k))
|
||||
bool ICACHE_FLASH_ATTR rboot_write_flash(rboot_write_status *status, uint8 *data, uint16 len) {
|
||||
|
||||
bool ret = false;
|
||||
uint8 *buffer;
|
||||
|
||||
if (data == NULL || len == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// get a buffer
|
||||
buffer = (uint8 *) calloc(1, len + status->extra_count);
|
||||
if (!buffer) {
|
||||
//os_printf("No ram!\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// copy in any remaining bytes from last chunk
|
||||
memcpy(buffer, status->extra_bytes, status->extra_count);
|
||||
// copy in new data
|
||||
memcpy(buffer + status->extra_count, data, len);
|
||||
|
||||
// calculate length, must be multiple of 4
|
||||
// save any remaining bytes for next go
|
||||
len += status->extra_count;
|
||||
status->extra_count = len % 4;
|
||||
len -= status->extra_count;
|
||||
memcpy(status->extra_bytes, buffer + len, status->extra_count);
|
||||
|
||||
// check data will fit
|
||||
//if (status->start_addr + len < (status->start_sector + status->max_sector_count) * SECTOR_SIZE) {
|
||||
|
||||
if (len > SECTOR_SIZE) {
|
||||
// to support larger writes we would need to erase current
|
||||
// (if not already done), next and possibly later sectors too
|
||||
} else {
|
||||
// check if the sector the write finishes in has been erased yet,
|
||||
// this is fine as long as data len < sector size
|
||||
if (status->last_sector_erased != (status->start_addr + len) / SECTOR_SIZE) {
|
||||
status->last_sector_erased = (status->start_addr + len) / SECTOR_SIZE;
|
||||
spi_flash_erase_sector(status->last_sector_erased);
|
||||
}
|
||||
}
|
||||
|
||||
// write current chunk
|
||||
//os_printf("write addr: 0x%08x, len: 0x%04x\r\n", status->start_addr, len);
|
||||
if (spi_flash_write(status->start_addr, (uint32 *)buffer, len) == SPI_FLASH_RESULT_OK) {
|
||||
ret = true;
|
||||
status->start_addr += len;
|
||||
}
|
||||
//}
|
||||
|
||||
free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,38 +0,0 @@
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_RBOOT_RBOOT_APPCODE_RBOOT_API_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_RBOOT_RBOOT_APPCODE_RBOOT_API_H_
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// rBoot OTA and config API for ESP8266.
|
||||
// Copyright 2015 Richard A Burton
|
||||
// richardaburton@gmail.com
|
||||
// See license.txt for license terms.
|
||||
// OTA code based on SDK sample from Espressif.
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
#include "../rboot.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32 start_addr;
|
||||
uint32 start_sector;
|
||||
//uint32 max_sector_count;
|
||||
uint32 last_sector_erased;
|
||||
uint8 extra_count;
|
||||
uint8 extra_bytes[4];
|
||||
} rboot_write_status;
|
||||
|
||||
rboot_config ICACHE_FLASH_ATTR rboot_get_config(void);
|
||||
bool ICACHE_FLASH_ATTR rboot_set_config(rboot_config *conf);
|
||||
uint8 ICACHE_FLASH_ATTR rboot_get_current_rom(void);
|
||||
bool ICACHE_FLASH_ATTR rboot_set_current_rom(uint8 rom);
|
||||
rboot_write_status ICACHE_FLASH_ATTR rboot_write_init(uint32 start_addr);
|
||||
bool ICACHE_FLASH_ATTR rboot_write_flash(rboot_write_status *status, uint8 *data, uint16 len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_RBOOT_RBOOT_APPCODE_RBOOT_API_H_ */
|
@ -1,61 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// rBoot open source boot loader for ESP8266.
|
||||
// Copyright 2015 Richard A Burton
|
||||
// richardaburton@gmail.com
|
||||
// See license.txt for license terms.
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#ifdef RBOOT_INTEGRATION
|
||||
#include <rboot-integration.h>
|
||||
#endif
|
||||
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned char uint8;
|
||||
|
||||
#include <rboot.h>
|
||||
|
||||
#if 0 //def BOOT_BIG_FLASH
|
||||
|
||||
// plain sdk defaults to iram
|
||||
#ifndef IRAM_ATTR
|
||||
#define IRAM_ATTR
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void Cache_Read_Disable();
|
||||
extern uint32 SPIRead(uint32, void*, uint32);
|
||||
extern void Cache_Read_Enable(uint32, uint32, uint32);
|
||||
|
||||
uint8 rBoot_mmap_1 = 0xff;
|
||||
uint8 rBoot_mmap_2 = 0xff;
|
||||
|
||||
// this function must remain in iram
|
||||
IRAM NOINSTR void __wrap_Cache_Read_Enable_New(void) {
|
||||
if (rBoot_mmap_1 == 0xff) {
|
||||
uint32 addr;
|
||||
rboot_config conf;
|
||||
|
||||
Cache_Read_Disable();
|
||||
|
||||
SPIRead(BOOT_CONFIG_SECTOR * SECTOR_SIZE, &conf, sizeof(rboot_config));
|
||||
|
||||
addr = conf.roms[conf.current_rom];
|
||||
addr /= 0x100000;
|
||||
|
||||
rBoot_mmap_2 = addr / 2;
|
||||
rBoot_mmap_1 = addr % 2;
|
||||
}
|
||||
|
||||
Cache_Read_Enable(rBoot_mmap_1, rBoot_mmap_2, 1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Binary file not shown.
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Richard A Burton (richardaburton@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
@ -1,74 +0,0 @@
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_RBOOT_RBOOT_RBOOT_PRIVATE_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_RBOOT_RBOOT_RBOOT_PRIVATE_H_
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// rBoot open source boot loader for ESP8266.
|
||||
// Copyright 2015 Richard A Burton
|
||||
// richardaburton@gmail.com
|
||||
// See license.txt for license terms.
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
typedef int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned char uint8;
|
||||
|
||||
#include "rboot.h"
|
||||
|
||||
#define NOINLINE __attribute__ ((noinline))
|
||||
|
||||
#define ROM_MAGIC 0xe9
|
||||
#define ROM_MAGIC_NEW1 0xea
|
||||
#define ROM_MAGIC_NEW2 0x04
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
// buffer size, must be at least 0x10 (size of rom_header_new structure)
|
||||
#define BUFFER_SIZE 0x100
|
||||
|
||||
// esp8266 built in rom functions
|
||||
extern void ets_printf(const char*, ...);
|
||||
extern uint32 SPIRead(uint32 addr, void *outptr, uint32 len);
|
||||
extern uint32 SPIEraseSector(int);
|
||||
extern uint32 SPIWrite(uint32 addr, void *inptr, uint32 len);
|
||||
|
||||
// functions we'll call by address
|
||||
typedef void stage2a(uint32);
|
||||
typedef void usercode(void);
|
||||
|
||||
// standard rom header
|
||||
typedef struct {
|
||||
// general rom header
|
||||
uint8 magic;
|
||||
uint8 count;
|
||||
uint8 flags1;
|
||||
uint8 flags2;
|
||||
usercode* entry;
|
||||
} rom_header;
|
||||
|
||||
typedef struct {
|
||||
uint8* address;
|
||||
uint32 length;
|
||||
} section_header;
|
||||
|
||||
// new rom header (irom section first) there is
|
||||
// another 8 byte header straight afterward the
|
||||
// standard header
|
||||
typedef struct {
|
||||
// general rom header
|
||||
uint8 magic;
|
||||
uint8 count; // second magic for new header
|
||||
uint8 flags1;
|
||||
uint8 flags2;
|
||||
uint32 entry;
|
||||
// new type rom, lib header
|
||||
uint32 add; // zero
|
||||
uint32 len; // length of irom section
|
||||
} rom_header_new;
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_RBOOT_RBOOT_RBOOT_PRIVATE_H_ */
|
@ -1,80 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// rBoot open source boot loader for ESP8266.
|
||||
// Copyright 2015 Richard A Burton
|
||||
// richardaburton@gmail.com
|
||||
// See license.txt for license terms.
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
#ifdef RBOOT_INTEGRATION
|
||||
#include <rboot-integration.h>
|
||||
#endif
|
||||
|
||||
#include "rboot-private.h"
|
||||
|
||||
usercode* NOINLINE load_rom(uint32 readpos) {
|
||||
|
||||
uint8 buffer[BUFFER_SIZE];
|
||||
uint8 sectcount;
|
||||
uint8 *writepos;
|
||||
uint32 remaining;
|
||||
usercode* usercode;
|
||||
|
||||
rom_header *header = (rom_header*)buffer;
|
||||
section_header *section = (section_header*)buffer;
|
||||
|
||||
// read rom header
|
||||
SPIRead(readpos, header, sizeof(rom_header));
|
||||
readpos += sizeof(rom_header);
|
||||
|
||||
// create function pointer for entry point
|
||||
usercode = header->entry;
|
||||
|
||||
// copy all the sections
|
||||
for (sectcount = header->count; sectcount > 0; sectcount--) {
|
||||
|
||||
// read section header
|
||||
SPIRead(readpos, section, sizeof(section_header));
|
||||
readpos += sizeof(section_header);
|
||||
|
||||
// get section address and length
|
||||
writepos = section->address;
|
||||
remaining = section->length;
|
||||
|
||||
while (remaining > 0) {
|
||||
// work out how much to read, up to 16 bytes at a time
|
||||
uint32 readlen = (remaining < BUFFER_SIZE) ? remaining : BUFFER_SIZE;
|
||||
// read the block
|
||||
SPIRead(readpos, buffer, readlen);
|
||||
readpos += readlen;
|
||||
// copy the block
|
||||
ets_memcpy(writepos, buffer, readlen);
|
||||
// increment next write position
|
||||
writepos += readlen;
|
||||
// decrement remaining count
|
||||
remaining -= readlen;
|
||||
}
|
||||
}
|
||||
|
||||
return usercode;
|
||||
}
|
||||
|
||||
#ifdef BOOT_NO_ASM
|
||||
|
||||
void call_user_start(uint32 readpos) {
|
||||
usercode* user;
|
||||
user = load_rom(readpos);
|
||||
user();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void call_user_start(uint32 readpos) {
|
||||
__asm volatile (
|
||||
"mov a15, a0\n" // store return addr, we already splatted a15!
|
||||
"call0 load_rom\n" // load the rom
|
||||
"mov a0, a15\n" // restore return addr
|
||||
"jx a2\n" // now jump to the rom code
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,211 +0,0 @@
|
||||
/* This linker script generated from xt-genldscripts.tpp for LSP . */
|
||||
/* Linker Script for ld -N */
|
||||
MEMORY
|
||||
{
|
||||
dport0_0_seg : org = 0x3FF00000, len = 0x10
|
||||
dram0_0_seg : org = 0x3FFE8000, len = 0x14000
|
||||
iram1_0_seg : org = 0x4010FC00, len = 0x400
|
||||
irom0_0_seg : org = 0x40240000, len = 0x3C000
|
||||
}
|
||||
|
||||
PHDRS
|
||||
{
|
||||
dport0_0_phdr PT_LOAD;
|
||||
dram0_0_phdr PT_LOAD;
|
||||
dram0_0_bss_phdr PT_LOAD;
|
||||
iram1_0_phdr PT_LOAD;
|
||||
irom0_0_phdr PT_LOAD;
|
||||
}
|
||||
|
||||
|
||||
/* Default entry point: */
|
||||
ENTRY(call_user_start)
|
||||
EXTERN(_DebugExceptionVector)
|
||||
EXTERN(_DoubleExceptionVector)
|
||||
EXTERN(_KernelExceptionVector)
|
||||
EXTERN(_NMIExceptionVector)
|
||||
EXTERN(_UserExceptionVector)
|
||||
PROVIDE(_memmap_vecbase_reset = 0x40000000);
|
||||
/* Various memory-map dependent cache attribute settings: */
|
||||
_memmap_cacheattr_wb_base = 0x00000110;
|
||||
_memmap_cacheattr_wt_base = 0x00000110;
|
||||
_memmap_cacheattr_bp_base = 0x00000220;
|
||||
_memmap_cacheattr_unused_mask = 0xFFFFF00F;
|
||||
_memmap_cacheattr_wb_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wba_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wbna_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wt_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_bp_trapnull = 0x2222222F;
|
||||
_memmap_cacheattr_wb_strict = 0xFFFFF11F;
|
||||
_memmap_cacheattr_wt_strict = 0xFFFFF11F;
|
||||
_memmap_cacheattr_bp_strict = 0xFFFFF22F;
|
||||
_memmap_cacheattr_wb_allvalid = 0x22222112;
|
||||
_memmap_cacheattr_wt_allvalid = 0x22222112;
|
||||
_memmap_cacheattr_bp_allvalid = 0x22222222;
|
||||
PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.dport0.rodata : ALIGN(4)
|
||||
{
|
||||
_dport0_rodata_start = ABSOLUTE(.);
|
||||
*(.dport0.rodata)
|
||||
*(.dport.rodata)
|
||||
_dport0_rodata_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.dport0.literal : ALIGN(4)
|
||||
{
|
||||
_dport0_literal_start = ABSOLUTE(.);
|
||||
*(.dport0.literal)
|
||||
*(.dport.literal)
|
||||
_dport0_literal_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.dport0.data : ALIGN(4)
|
||||
{
|
||||
_dport0_data_start = ABSOLUTE(.);
|
||||
*(.dport0.data)
|
||||
*(.dport.data)
|
||||
_dport0_data_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.data : ALIGN(4)
|
||||
{
|
||||
_data_start = ABSOLUTE(.);
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
*(.jcr)
|
||||
_data_end = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_phdr
|
||||
|
||||
.rodata : ALIGN(4)
|
||||
{
|
||||
_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)
|
||||
/* C++ constructor and destructor tables, properly ordered: */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .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)
|
||||
. = ALIGN(4); /* this table MUST be 4-byte aligned */
|
||||
_bss_table_start = ABSOLUTE(.);
|
||||
LONG(_bss_start)
|
||||
LONG(_bss_end)
|
||||
_bss_table_end = ABSOLUTE(.);
|
||||
_rodata_end = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_phdr
|
||||
|
||||
.bss ALIGN(8) (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
. = 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(.);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
/* _stack_sentry = ALIGN(0x8); */
|
||||
} >dram0_0_seg :dram0_0_bss_phdr
|
||||
/* __stack = 0x3ffc8000; */
|
||||
|
||||
.text : ALIGN(4)
|
||||
{
|
||||
_stext = .;
|
||||
_text_start = ABSOLUTE(.);
|
||||
*(.UserEnter.text)
|
||||
. = ALIGN(16);
|
||||
*(.DebugExceptionVector.text)
|
||||
. = ALIGN(16);
|
||||
*(.NMIExceptionVector.text)
|
||||
. = ALIGN(16);
|
||||
*(.KernelExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN(16);
|
||||
*(.UserExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN(16);
|
||||
*(.DoubleExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN (16);
|
||||
*(.entry.text)
|
||||
*(.init.literal)
|
||||
*(.init)
|
||||
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} >iram1_0_seg :iram1_0_phdr
|
||||
|
||||
.lit4 : ALIGN(4)
|
||||
{
|
||||
_lit4_start = ABSOLUTE(.);
|
||||
*(*.lit4)
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
} >iram1_0_seg :iram1_0_phdr
|
||||
|
||||
.irom0.text : ALIGN(4)
|
||||
{
|
||||
_irom0_text_start = ABSOLUTE(.);
|
||||
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
|
||||
_irom0_text_end = ABSOLUTE(.);
|
||||
} >irom0_0_seg :irom0_0_phdr
|
||||
|
||||
}
|
||||
|
||||
/* get ROM code address */
|
||||
INCLUDE "rboot_rom.ld"
|
@ -1,414 +0,0 @@
|
||||
//////////////////////////////////////////////////
|
||||
// rBoot open source boot loader for ESP8266.
|
||||
// Copyright 2015 Richard A Burton
|
||||
// richardaburton@gmail.com
|
||||
// See license.txt for license terms.
|
||||
//////////////////////////////////////////////////
|
||||
/* clang-format off */
|
||||
|
||||
#ifdef RBOOT_INTEGRATION
|
||||
#include <rboot-integration.h>
|
||||
#endif
|
||||
|
||||
#include "rboot-private.h"
|
||||
#include <rboot-hex2a.h>
|
||||
|
||||
static uint32 check_image(uint32 readpos) {
|
||||
|
||||
uint8 buffer[BUFFER_SIZE];
|
||||
uint8 sectcount;
|
||||
uint8 sectcurrent;
|
||||
uint8 *writepos;
|
||||
uint8 chksum = CHKSUM_INIT;
|
||||
uint32 loop;
|
||||
uint32 remaining;
|
||||
uint32 romaddr;
|
||||
|
||||
rom_header_new *header = (rom_header_new*)buffer;
|
||||
section_header *section = (section_header*)buffer;
|
||||
|
||||
if (readpos == 0 || readpos == 0xffffffff) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read rom header
|
||||
if (SPIRead(readpos, header, sizeof(rom_header_new)) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check header type
|
||||
if (header->magic == ROM_MAGIC) {
|
||||
// old type, no extra header or irom section to skip over
|
||||
romaddr = readpos;
|
||||
readpos += sizeof(rom_header);
|
||||
sectcount = header->count;
|
||||
} else if (header->magic == ROM_MAGIC_NEW1 && header->count == ROM_MAGIC_NEW2) {
|
||||
// new type, has extra header and irom section first
|
||||
romaddr = readpos + header->len + sizeof(rom_header_new);
|
||||
#ifdef BOOT_IROM_CHKSUM
|
||||
// we will set the real section count later, when we read the header
|
||||
sectcount = 0xff;
|
||||
// just skip the first part of the header
|
||||
// rest is processed for the chksum
|
||||
readpos += sizeof(rom_header);
|
||||
#else
|
||||
// skip the extra header and irom section
|
||||
readpos = romaddr;
|
||||
// read the normal header that follows
|
||||
if (SPIRead(readpos, header, sizeof(rom_header)) != 0) {
|
||||
return 0;
|
||||
}
|
||||
sectcount = header->count;
|
||||
readpos += sizeof(rom_header);
|
||||
#endif
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// test each section
|
||||
for (sectcurrent = 0; sectcurrent < sectcount; sectcurrent++) {
|
||||
|
||||
// read section header
|
||||
if (SPIRead(readpos, section, sizeof(section_header)) != 0) {
|
||||
return 0;
|
||||
}
|
||||
readpos += sizeof(section_header);
|
||||
|
||||
// get section address and length
|
||||
writepos = section->address;
|
||||
remaining = section->length;
|
||||
|
||||
while (remaining > 0) {
|
||||
// work out how much to read, up to BUFFER_SIZE
|
||||
uint32 readlen = (remaining < BUFFER_SIZE) ? remaining : BUFFER_SIZE;
|
||||
// read the block
|
||||
if (SPIRead(readpos, buffer, readlen) != 0) {
|
||||
return 0;
|
||||
}
|
||||
// increment next read and write positions
|
||||
readpos += readlen;
|
||||
writepos += readlen;
|
||||
// decrement remaining count
|
||||
remaining -= readlen;
|
||||
// add to chksum
|
||||
for (loop = 0; loop < readlen; loop++) {
|
||||
chksum ^= buffer[loop];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BOOT_IROM_CHKSUM
|
||||
if (sectcount == 0xff) {
|
||||
// just processed the irom section, now
|
||||
// read the normal header that follows
|
||||
if (SPIRead(readpos, header, sizeof(rom_header)) != 0) {
|
||||
return 0;
|
||||
}
|
||||
sectcount = header->count + 1;
|
||||
readpos += sizeof(rom_header);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// round up to next 16 and get checksum
|
||||
readpos = readpos | 0x0f;
|
||||
if (SPIRead(readpos, buffer, 1) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// compare calculated and stored checksums
|
||||
if (buffer[0] != chksum) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return romaddr;
|
||||
}
|
||||
|
||||
#define ETS_UNCACHED_ADDR(addr) (addr)
|
||||
#define READ_PERI_REG(addr) (*((volatile uint32 *)ETS_UNCACHED_ADDR(addr)))
|
||||
#define WRITE_PERI_REG(addr, val) (*((volatile uint32 *)ETS_UNCACHED_ADDR(addr))) = (uint32)(val)
|
||||
#define PERIPHS_RTC_BASEADDR 0x60000700
|
||||
#define REG_RTC_BASE PERIPHS_RTC_BASEADDR
|
||||
#define RTC_GPIO_OUT (REG_RTC_BASE + 0x068)
|
||||
#define RTC_GPIO_ENABLE (REG_RTC_BASE + 0x074)
|
||||
#define RTC_GPIO_IN_DATA (REG_RTC_BASE + 0x08C)
|
||||
#define RTC_GPIO_CONF (REG_RTC_BASE + 0x090)
|
||||
#define PAD_XPD_DCDC_CONF (REG_RTC_BASE + 0x0A0)
|
||||
static uint32 get_gpio16(void) {
|
||||
// set output level to 1
|
||||
WRITE_PERI_REG(RTC_GPIO_OUT, (READ_PERI_REG(RTC_GPIO_OUT) & (uint32)0xfffffffe) | (uint32)(1));
|
||||
|
||||
// read level
|
||||
WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | (uint32)0x1); // mux configuration for XPD_DCDC and rtc_gpio0 connection
|
||||
WRITE_PERI_REG(RTC_GPIO_CONF, (READ_PERI_REG(RTC_GPIO_CONF) & (uint32)0xfffffffe) | (uint32)0x0); //mux configuration for out enable
|
||||
WRITE_PERI_REG(RTC_GPIO_ENABLE, READ_PERI_REG(RTC_GPIO_ENABLE) & (uint32)0xfffffffe); //out disable
|
||||
|
||||
uint32 x = (READ_PERI_REG(RTC_GPIO_IN_DATA) & 1);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
#ifdef BOOT_CONFIG_CHKSUM
|
||||
// calculate checksum for block of data
|
||||
// from start up to (but excluding) end
|
||||
static uint8 calc_chksum(uint8 *start, uint8 *end) {
|
||||
uint8 chksum = CHKSUM_INIT;
|
||||
while(start < end) {
|
||||
chksum ^= *start;
|
||||
start++;
|
||||
}
|
||||
return chksum;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define UART_CLKDIV_26MHZ(B) (52000000 + B / 2) / B
|
||||
|
||||
// prevent this function being placed inline with main
|
||||
// to keep main's stack size as small as possible
|
||||
// don't mark as static or it'll be optimised out when
|
||||
// using the assembler stub
|
||||
uint32 NOINLINE find_image(void) {
|
||||
|
||||
uint8 flag;
|
||||
uint32 runAddr;
|
||||
uint32 flashsize;
|
||||
int32 romToBoot;
|
||||
uint8 gpio_boot = FALSE;
|
||||
uint8 updateConfig = FALSE;
|
||||
uint8 buffer[SECTOR_SIZE];
|
||||
|
||||
rboot_config *romconf = (rboot_config*)buffer;
|
||||
rom_header *header = (rom_header*)buffer;
|
||||
|
||||
// delay to slow boot (help see messages when debugging)
|
||||
//ets_delay_us(2000000);
|
||||
|
||||
uart_div_modify(0, UART_CLKDIV_26MHZ(115200));
|
||||
ets_delay_us(1000);
|
||||
|
||||
ets_printf("\r\nrBoot v1.2.1 - richardaburton@gmail.com\r\n");
|
||||
|
||||
// read rom header
|
||||
SPIRead(0, header, sizeof(rom_header));
|
||||
|
||||
// print and get flash size
|
||||
ets_printf("Flash Size: ");
|
||||
flag = header->flags2 >> 4;
|
||||
if (flag == 0) {
|
||||
ets_printf("4 Mbit\r\n");
|
||||
flashsize = 0x80000;
|
||||
} else if (flag == 1) {
|
||||
ets_printf("2 Mbit\r\n");
|
||||
flashsize = 0x40000;
|
||||
} else if (flag == 2) {
|
||||
ets_printf("8 Mbit\r\n");
|
||||
flashsize = 0x100000;
|
||||
} else {
|
||||
#ifdef BOOT_BIG_FLASH
|
||||
if (flag == 3) {
|
||||
ets_printf("16 Mbit\r\n");
|
||||
flashsize = 0x200000;
|
||||
} else if (flag == 4) {
|
||||
ets_printf("32 Mbit\r\n");
|
||||
flashsize = 0x400000;
|
||||
} else if (flag == 8) {
|
||||
ets_printf("64 Mbit\r\n");
|
||||
flashsize = 0x800000;
|
||||
} else if (flag == 9) {
|
||||
ets_printf("128 Mbit\r\n");
|
||||
flashsize = 0x1000000;
|
||||
} else {
|
||||
ets_printf("unknown\r\n");
|
||||
flashsize = 0x100000; // assume 8Mbit
|
||||
}
|
||||
#else
|
||||
ets_printf("8 Mbit\r\n");
|
||||
flashsize = 0x100000; // limit to 8Mbit
|
||||
#endif
|
||||
}
|
||||
|
||||
// print spi mode
|
||||
ets_printf("Flash Mode: ");
|
||||
if (header->flags1 == 0) {
|
||||
ets_printf("QIO\r\n");
|
||||
} else if (header->flags1 == 1) {
|
||||
ets_printf("QOUT\r\n");
|
||||
} else if (header->flags1 == 2) {
|
||||
ets_printf("DIO\r\n");
|
||||
} else if (header->flags1 == 3) {
|
||||
ets_printf("DOUT\r\n");
|
||||
} else {
|
||||
ets_printf("unknown\r\n");
|
||||
}
|
||||
|
||||
// print spi speed
|
||||
ets_printf("Flash Speed: ");
|
||||
flag = header->flags2 & 0x0f;
|
||||
if (flag == 0) ets_printf("40 MHz\r\n");
|
||||
else if (flag == 1) ets_printf("26.7 MHz\r\n");
|
||||
else if (flag == 2) ets_printf("20 MHz\r\n");
|
||||
else if (flag == 0x0f) ets_printf("80 MHz\r\n");
|
||||
else ets_printf("unknown\r\n");
|
||||
|
||||
// print enabled options
|
||||
#ifdef BOOT_BIG_FLASH
|
||||
ets_printf("rBoot Option: Big flash\r\n");
|
||||
#endif
|
||||
#ifdef BOOT_CONFIG_CHKSUM
|
||||
ets_printf("rBoot Option: Config chksum\r\n");
|
||||
#endif
|
||||
#ifdef BOOT_IROM_CHKSUM
|
||||
ets_printf("rBoot Option: irom chksum\r\n");
|
||||
#endif
|
||||
|
||||
ets_printf("\r\n");
|
||||
|
||||
// read boot config
|
||||
SPIRead(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE);
|
||||
// fresh install or old version?
|
||||
if (romconf->magic != BOOT_CONFIG_MAGIC || romconf->version != BOOT_CONFIG_VERSION
|
||||
#ifdef BOOT_CONFIG_CHKSUM
|
||||
|| romconf->chksum != calc_chksum((uint8*)romconf, (uint8*)&romconf->chksum)
|
||||
#endif
|
||||
) {
|
||||
/* Modified by Cesanta */
|
||||
ets_printf("Writing default boot config @ 0x%x.\r\n", BOOT_CONFIG_SECTOR * SECTOR_SIZE);
|
||||
ets_memset(romconf, 0x00, sizeof(rboot_config));
|
||||
romconf->magic = BOOT_CONFIG_MAGIC;
|
||||
romconf->version = BOOT_CONFIG_VERSION;
|
||||
romconf->count = 2;
|
||||
romconf->mode = MODE_STANDARD;
|
||||
/* FWx_ADDR, FWx_FS_ADDR and FS_SIZE, FW_SIZE must be defined by -D */
|
||||
romconf->roms[0] = FW1_ADDR;
|
||||
romconf->roms[1] = FW2_ADDR;
|
||||
romconf->fs_addresses[0] = FW1_FS_ADDR;
|
||||
romconf->fs_addresses[1] = FW2_FS_ADDR;
|
||||
romconf->fs_sizes[0] = romconf->fs_sizes[1] = FS_SIZE;
|
||||
romconf->roms_sizes[0] = romconf->roms_sizes[1] = FW_SIZE;
|
||||
#ifdef BOOT_CONFIG_CHKSUM
|
||||
romconf->chksum = calc_chksum((uint8*)romconf, (uint8*)&romconf->chksum);
|
||||
#endif
|
||||
// write new config sector
|
||||
SPIEraseSector(BOOT_CONFIG_SECTOR);
|
||||
SPIWrite(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE);
|
||||
}
|
||||
|
||||
// if gpio mode enabled check status of the gpio
|
||||
if ((romconf->mode & MODE_GPIO_ROM) && (get_gpio16() == 0)) {
|
||||
ets_printf("Booting GPIO-selected.\r\n");
|
||||
romToBoot = romconf->previous_rom;
|
||||
/*
|
||||
* Modified by Cesanta
|
||||
* Make FD current
|
||||
*/
|
||||
updateConfig = TRUE;
|
||||
romconf->fw_updated = 0;
|
||||
romconf->is_first_boot = 0;
|
||||
gpio_boot = TRUE;
|
||||
} else if (romconf->current_rom >= romconf->count) {
|
||||
// if invalid rom selected try rom 0
|
||||
ets_printf("Invalid rom selected, defaulting.\r\n");
|
||||
romToBoot = 0;
|
||||
romconf->current_rom = 0;
|
||||
romconf->fw_updated = 0;
|
||||
romconf->is_first_boot = 0;
|
||||
updateConfig = TRUE;
|
||||
} else {
|
||||
/* Modified by Cesanta */
|
||||
if (romconf->is_first_boot != 0) {
|
||||
ets_printf("First boot, attempt %d\n", romconf->boot_attempts);
|
||||
/* boot is unconfirmed */
|
||||
if (romconf->boot_attempts == 0) {
|
||||
/* haven't try to load yes */
|
||||
ets_printf("Boot is unconfirmed\r\n");
|
||||
romconf->boot_attempts++;
|
||||
} else {
|
||||
ets_printf("Boot failed, fallback to fw #%d\r\n",
|
||||
romconf->previous_rom);
|
||||
romconf->current_rom = romconf->previous_rom;
|
||||
/* clear fw update flag, to avoid post-update acttions */
|
||||
romconf->fw_updated = 0;
|
||||
romconf->boot_attempts = 0;
|
||||
}
|
||||
|
||||
updateConfig = TRUE;
|
||||
}
|
||||
/* End of Cesanta modifications */
|
||||
// try rom selected in the config
|
||||
romToBoot = romconf->current_rom;
|
||||
}
|
||||
|
||||
// try to find a good rom
|
||||
do {
|
||||
runAddr = check_image(romconf->roms[romToBoot]);
|
||||
if (runAddr == 0) {
|
||||
ets_printf("Rom %d is bad.\r\n", romToBoot);
|
||||
if (gpio_boot) {
|
||||
// don't switch to backup for gpio-selected rom
|
||||
ets_printf("GPIO boot failed.\r\n");
|
||||
return 0;
|
||||
} else {
|
||||
// for normal mode try each previous rom
|
||||
// until we find a good one or run out
|
||||
updateConfig = TRUE;
|
||||
romToBoot--;
|
||||
if (romToBoot < 0) romToBoot = romconf->count - 1;
|
||||
if (romToBoot == romconf->current_rom) {
|
||||
// tried them all and all are bad!
|
||||
ets_printf("No good rom available.\r\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (runAddr == 0);
|
||||
|
||||
// re-write config, if required
|
||||
if (updateConfig) {
|
||||
romconf->current_rom = romToBoot;
|
||||
#ifdef BOOT_CONFIG_CHKSUM
|
||||
romconf->chksum = calc_chksum((uint8*)romconf, (uint8*)&romconf->chksum);
|
||||
#endif
|
||||
SPIEraseSector(BOOT_CONFIG_SECTOR);
|
||||
SPIWrite(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE);
|
||||
}
|
||||
|
||||
ets_printf("Booting rom %d (0x%x).\r\n", romToBoot, romconf->roms[romToBoot]);
|
||||
// copy the loader to top of iram
|
||||
ets_memcpy((void*)_text_addr, _text_data, _text_len);
|
||||
// return address to load from
|
||||
return runAddr;
|
||||
|
||||
}
|
||||
|
||||
#ifdef BOOT_NO_ASM
|
||||
|
||||
// small stub method to ensure minimum stack space used
|
||||
void call_user_start(void) {
|
||||
uint32 addr;
|
||||
stage2a *loader;
|
||||
|
||||
addr = find_image();
|
||||
if (addr != 0) {
|
||||
loader = (stage2a*)entry_addr;
|
||||
loader(addr);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// assembler stub uses no stack space
|
||||
// works with gcc
|
||||
void call_user_start(void) {
|
||||
__asm volatile (
|
||||
"mov a15, a0\n" // store return addr, hope nobody wanted a15!
|
||||
"call0 find_image\n" // find a good rom to boot
|
||||
"mov a0, a15\n" // restore return addr
|
||||
"bnez a2, 1f\n" // ?success
|
||||
"ret\n" // no, return
|
||||
"1:\n" // yes...
|
||||
"movi a3, entry_addr\n" // actually gives us a pointer to entry_addr
|
||||
"l32i a3, a3, 0\n" // now really load entry_addr
|
||||
"jx a3\n" // now jump to it
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,82 +0,0 @@
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_RBOOT_RBOOT_RBOOT_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_RBOOT_RBOOT_RBOOT_H_
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// rBoot open source boot loader for ESP8266.
|
||||
// Copyright 2015 Richard A Burton
|
||||
// richardaburton@gmail.com
|
||||
// See license.txt for license terms.
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// uncomment to use only c code
|
||||
// if you aren't using gcc you may need to do this
|
||||
//#define BOOT_NO_ASM
|
||||
|
||||
// uncomment to have a checksum on the boot config
|
||||
//#define BOOT_CONFIG_CHKSUM
|
||||
|
||||
// uncomment to enable big flash support (>1MB)
|
||||
//#define BOOT_BIG_FLASH
|
||||
|
||||
// uncomment to include .irom0.text section in the checksum
|
||||
// roms must be built with esptool2 using -iromchksum option
|
||||
//#define BOOT_IROM_CHKSUM
|
||||
|
||||
// increase if required
|
||||
#define MAX_ROMS 4
|
||||
|
||||
#define CHKSUM_INIT 0xef
|
||||
|
||||
#define SECTOR_SIZE 0x1000
|
||||
|
||||
#ifndef BOOT_CONFIG_ADDR
|
||||
#define BOOT_CONFIG_ADDR 0x1000
|
||||
#endif
|
||||
|
||||
#define BOOT_CONFIG_SECTOR (BOOT_CONFIG_ADDR / SECTOR_SIZE)
|
||||
|
||||
#define BOOT_CONFIG_MAGIC 0xe1
|
||||
#define BOOT_CONFIG_VERSION 0x01
|
||||
|
||||
#define MODE_STANDARD 0x00
|
||||
#define MODE_GPIO_ROM 0x01
|
||||
|
||||
// boot config structure
|
||||
// rom addresses must be multiples of 0x1000 (flash sector aligned)
|
||||
// without BOOT_BIG_FLASH only the first 8Mbit of the chip will be memory mapped
|
||||
// so rom slots containing .irom0.text sections must remain below 0x100000
|
||||
// slots beyond this will only be accessible via spi read calls, so
|
||||
// use these for stored resources, not code
|
||||
// with BOOT_BIG_FLASH the flash will be mapped in chunks of 8MBit, so roms can
|
||||
// be anywhere, but must not straddle two 8MBit blocks
|
||||
typedef struct {
|
||||
uint8 magic; // our magic
|
||||
uint8 version; // config struct version
|
||||
uint8 mode; // boot loader mode
|
||||
uint8 current_rom; // currently selected rom
|
||||
uint8 gpio_rom; // rom to use for gpio boot
|
||||
uint8 count; // number of roms in use
|
||||
uint8 previous_rom; // previously selected rom
|
||||
uint8 is_first_boot;
|
||||
uint8 boot_attempts;
|
||||
uint8 fw_updated;
|
||||
uint8 padding[2];
|
||||
uint32 roms[MAX_ROMS]; // flash addresses of the roms
|
||||
uint32 roms_sizes[MAX_ROMS]; // sizes of the roms
|
||||
uint32 fs_addresses[MAX_ROMS]; // file system addresses
|
||||
uint32 fs_sizes[MAX_ROMS]; // file system sizes
|
||||
uint32 user_flags;
|
||||
#ifdef BOOT_CONFIG_CHKSUM
|
||||
uint8 chksum; // config chksum
|
||||
#endif
|
||||
} rboot_config;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_RBOOT_RBOOT_RBOOT_H_ */
|
@ -1,2 +0,0 @@
|
||||
INCLUDE "eagle.app.v6.ld"
|
||||
INCLUDE "rboot_rom.ld"
|
@ -1,89 +0,0 @@
|
||||
#
|
||||
# Makefile for rBoot
|
||||
# https://github.com/raburton/esp8266
|
||||
#
|
||||
|
||||
ESPTOOL2 ?= ../../build/esptool2
|
||||
SDK_BASE ?= /opt/Espressif/ESP8266_SDK
|
||||
SPI_SIZE ?=
|
||||
RBOOT_INTEGRATION ?=
|
||||
RBOOT_EXTRA_INCDIR ?=
|
||||
|
||||
# RBOOT_BUILD_BASE and RBOOT_GEN_BASE should be provided via makefile parameters
|
||||
RBOOT_BUILD_BASE ?=
|
||||
# RBOOT_GEN_BASE is the directory for generated inputs
|
||||
RBOOT_GEN_BASE ?=
|
||||
|
||||
ifndef XTENSA_BINDIR
|
||||
CC := xtensa-lx106-elf-gcc
|
||||
LD := xtensa-lx106-elf-gcc
|
||||
else
|
||||
CC := $(addprefix $(XTENSA_BINDIR)/,xtensa-lx106-elf-gcc)
|
||||
LD := $(addprefix $(XTENSA_BINDIR)/,xtensa-lx106-elf-gcc)
|
||||
endif
|
||||
CC_WRAPPER ?=
|
||||
|
||||
CFLAGS = -Os -O3 -Wpointer-arith -Wundef -Werror -Wl,-EL \
|
||||
-fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals \
|
||||
-D__ets__ -DIRAM='__attribute__((section(".fast.text")))' \
|
||||
-DNOINSTR='__attribute__((no_instrument_function))' \
|
||||
-DICACHE_FLASH $(CFLAGS_EXTRA)
|
||||
|
||||
LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -L $(SDK_BASE)/ld/
|
||||
|
||||
LD_SCRIPT = rboot.ld
|
||||
|
||||
E2_OPTS = -quiet -bin -boot0
|
||||
|
||||
ifeq ($(RBOOT_BIG_FLASH),1)
|
||||
CFLAGS += -DBOOT_BIG_FLASH
|
||||
endif
|
||||
ifeq ($(RBOOT_INTEGRATION),1)
|
||||
CFLAGS += -DRBOOT_INTEGRATION
|
||||
endif
|
||||
ifeq ($(SPI_SIZE), 256K)
|
||||
E2_OPTS += -256
|
||||
else ifeq ($(SPI_SIZE), 512K)
|
||||
E2_OPTS += -512
|
||||
else ifeq ($(SPI_SIZE), 1M)
|
||||
E2_OPTS += -1024
|
||||
else ifeq ($(SPI_SIZE), 2M)
|
||||
E2_OPTS += -2048
|
||||
else ifeq ($(SPI_SIZE), 4M)
|
||||
E2_OPTS += -4096
|
||||
endif
|
||||
|
||||
RBOOT_EXTRA_INCDIR := $(addprefix -I,$(RBOOT_EXTRA_INCDIR))
|
||||
|
||||
.SECONDARY:
|
||||
|
||||
all: $(RBOOT_BUILD_BASE)/rboot.bin
|
||||
|
||||
$(RBOOT_BUILD_BASE)/rboot-stage2a.o: rboot-stage2a.c rboot-private.h rboot.h
|
||||
@echo "CC $<"
|
||||
@$(CC_WRAPPER) $(CC) $(CFLAGS) $(RBOOT_EXTRA_INCDIR) -c $< -o $@
|
||||
|
||||
$(RBOOT_BUILD_BASE)/rboot-stage2a.elf: $(RBOOT_BUILD_BASE)/rboot-stage2a.o
|
||||
@echo "LD $@"
|
||||
@$(CC_WRAPPER) $(LD) -Trboot-stage2a.ld $(LDFLAGS) -Wl,--start-group $^ -Wl,--end-group -o $@
|
||||
|
||||
$(RBOOT_GEN_BASE)/rboot-hex2a.h: $(RBOOT_BUILD_BASE)/rboot-stage2a.elf
|
||||
@echo "E2 $@"
|
||||
@$(ESPTOOL2) -quiet -header $< $@ .text
|
||||
|
||||
$(RBOOT_BUILD_BASE)/rboot.o: rboot.c rboot-private.h rboot.h $(RBOOT_GEN_BASE)/rboot-hex2a.h
|
||||
@echo "CC $<"
|
||||
@$(CC) $(CFLAGS) -I$(RBOOT_GEN_BASE) $(RBOOT_EXTRA_INCDIR) -c $< -o $@
|
||||
|
||||
$(RBOOT_BUILD_BASE)/%.o: %.c %.h
|
||||
@echo "CC $<"
|
||||
@$(CC) $(CFLAGS) $(RBOOT_EXTRA_INCDIR) -c $< -o $@
|
||||
|
||||
$(RBOOT_BUILD_BASE)/%.elf: $(RBOOT_BUILD_BASE)/%.o
|
||||
@echo "LD $@"
|
||||
@$(LD) -T$(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $^ -Wl,--end-group -o $@
|
||||
|
||||
$(RBOOT_BUILD_BASE)/%.bin: $(RBOOT_BUILD_BASE)/%.elf
|
||||
@echo "E2 $@"
|
||||
@$(ESPTOOL2) $(E2_OPTS) $< $@ .text .rodata
|
||||
|
@ -1,8 +0,0 @@
|
||||
PROVIDE ( ets_delay_us = 0x40002ecc );
|
||||
PROVIDE ( ets_memcpy = 0x400018b4 );
|
||||
PROVIDE ( ets_memset = 0x400018a4 );
|
||||
PROVIDE ( ets_printf = 0x400024cc );
|
||||
PROVIDE ( SPIEraseSector = 0x40004a00 );
|
||||
PROVIDE ( SPIRead = 0x40004b1c );
|
||||
PROVIDE ( SPIWrite = 0x40004a4c );
|
||||
PROVIDE ( uart_div_modify = 0x400039d8 );
|
@ -1,40 +0,0 @@
|
||||
rBoot - User API for rBoot on the ESP8266
|
||||
------------------------------------------
|
||||
by Richard A Burton, richardaburton@gmail.com
|
||||
http://richard.burtons.org/
|
||||
|
||||
This provides a few simple APIs for getting & setting rBoot config and for
|
||||
writing data from OTA updates. API source files are in the appcode directory.
|
||||
|
||||
Actual OTA network code is implementation specific and no longer included in
|
||||
rBoot itself, see the rBoot sample projects for this code (which you can then
|
||||
use in your own projects).
|
||||
|
||||
rboot_config rboot_get_config();
|
||||
Returns rboot_config (defined in rboot.h) allowing you to modify any values
|
||||
in it, including the rom layout.
|
||||
|
||||
bool rboot_set_config(rboot_config *conf);
|
||||
Saves the rboot_config structure back to sector 2 of the flash, while
|
||||
maintaining the contents of the rest of the sector. You can use the rest of
|
||||
this sector for your app settings, as long as you protect this structure
|
||||
when you do so.
|
||||
|
||||
uint8 rboot_get_current_rom();
|
||||
Get the currently selected boot rom (the currently running rom, as long as
|
||||
you haven't changed it since boot).
|
||||
|
||||
bool rboot_set_current_rom(uint8 rom);
|
||||
Set the current boot rom, which will be used when next restarted.
|
||||
|
||||
rboot_write_status rboot_write_init(uint32 start_addr);
|
||||
Call once before starting to pass data to write to the flash. start_addr is
|
||||
the address on the SPI flash to write from. Returns a status structure which
|
||||
must be passed back on each write. The contents of the structure should not
|
||||
be modified by the calling code.
|
||||
|
||||
bool rboot_write_flash(rboot_write_status *status, uint8 *data, uint16 len);
|
||||
Call repeatedly to write data to the flash, starting at the address
|
||||
specified on the prior call to rboot_write_init. Current write position is
|
||||
tracked automatically. This method is likely to be called each time a packet
|
||||
of OTA data is received over the network.
|
@ -1,218 +0,0 @@
|
||||
rBoot - An open source boot loader for the ESP8266
|
||||
--------------------------------------------------
|
||||
by Richard A Burton, richardaburton@gmail.com
|
||||
http://richard.burtons.org/
|
||||
|
||||
|
||||
rBoot is designed to be a flexible open source boot loader, a replacement for
|
||||
the binary blob supplied with the SDK. It has the following advantages over the
|
||||
Espressif loader:
|
||||
|
||||
- Open source (written in C).
|
||||
- Supports up to 256 roms.
|
||||
- Roms can be variable size.
|
||||
- Able to test multiple roms to find a valid backup (without resetting).
|
||||
- Flash layout can be changed on the fly (with care and appropriately linked
|
||||
rom images).
|
||||
- GPIO support for rom selection.
|
||||
- Wastes no stack space (SDK boot loader uses 144 bytes).
|
||||
- Documented config structure to allow easy editing from user code.
|
||||
- Can validate .irom0.text section with checksum.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
The ESP8266 can only map 8Mbits (1MB) of flash to memory, but which 8Mbits to
|
||||
map is selectable. This allows individual roms to be up to 1MB in size, so long
|
||||
as they do not straddle an 8Mbit boundary on the flash. This means you could
|
||||
have four 1MB roms or 8 512KB roms on a 32Mbit flash (such as on the ESP-12), or
|
||||
a combination. Note, however, that you could not have, for example, a 512KB rom
|
||||
followed immediately by a 1MB rom because the 2nd rom would then straddle an
|
||||
8MBit boundary. By default support for using more than the first 8Mbit of the
|
||||
flash is disabled, because it requires several steps to get it working. See
|
||||
below for instructions.
|
||||
|
||||
Building
|
||||
--------
|
||||
A Makefile is included, which should work with the gcc xtensa cross compiler.
|
||||
There are two source files, the first is compiled and included as data in the
|
||||
second. When run this code is copied to memory and executed (there is a good
|
||||
reason for this, see my blog for an explanation). The make file will handle this
|
||||
for you, but you'll need my esptool2 (see github).
|
||||
|
||||
To use the Makefile set SDK_BASE to point to the root of the Espressif SDK and
|
||||
either set XTENSA_BINDIR to the gcc xtensa bin directory or include it in your
|
||||
PATH. These can be set as environment variables or by editing the Makefile.
|
||||
|
||||
Two small assembler stub functions allow the bootloader to launch the user code
|
||||
without reserving any space on the stack (while the SDK boot loader uses 144
|
||||
bytes). This compiles fine with GCC, but if you use another compiler and it
|
||||
will not compile/work for you then uncomment the #define BOOT_NO_ASM in rboot.h
|
||||
to use a C version of these functions (this uses 32 bytes).
|
||||
|
||||
Tested with SDK v1.3 and GCC v4.8.2.
|
||||
|
||||
Installation
|
||||
------------
|
||||
Simply write rboot.bin to the first sector of the flash. Remember to set your
|
||||
flash size correctly with your chosen flash tool (e.g. for esptool.py use the
|
||||
-fs option). When run rBoot will create it's own config at the start of sector
|
||||
two for a simple two rom system. You can can then write your two roms to flash
|
||||
addresses 0x2000 and (half chip size + 0x2000). E.g. for 8Mbit flash:
|
||||
esptool.py -fs 8m 0x0000 rboot.bin 0x2000 user1.bin 0x82000 user2.bin
|
||||
|
||||
Note: your device may need other options specified. E.g. The nodemcu devkit v1.0
|
||||
(commonly, but incorrectly, sold as v2) also needs the "-fm dio" option.
|
||||
|
||||
For more interesting rom layouts you'll need to write an rBoot config sector
|
||||
manually, see next step.
|
||||
|
||||
The two testload bin files can be flashed in place of normal user roms for
|
||||
testing rBoot. You do not need these for normal use.
|
||||
|
||||
rBoot Config
|
||||
------------
|
||||
typedef struct {
|
||||
uint8 magic; // our magic
|
||||
uint8 version; // config struct version
|
||||
uint8 mode; // boot loader mode
|
||||
uint8 current_rom; // currently selected rom
|
||||
uint8 gpio_rom; // rom to use for gpio boot
|
||||
uint8 count; // number of roms in use
|
||||
uint8 unused[2]; // padding
|
||||
uint32 roms[MAX_ROMS]; // flash addresses of the roms
|
||||
#ifdef BOOT_CONFIG_CHKSUM
|
||||
uint8 chksum; // boot config chksum
|
||||
#endif
|
||||
} rboot_config;
|
||||
|
||||
Write a config structure as above to address 0x1000 on the flash. If you want
|
||||
more than 4 roms (default) just increase MAX_ROMS when you compile rBoot.
|
||||
Think about how you intend to layout your flash before you start!
|
||||
Rom addresses must be sector aligned i.e start on a multiple of 4096.
|
||||
|
||||
- magic should have value 0xe1 (defined as BOOT_CONFIG_MAGIC).
|
||||
- version is used in case the config structure changes after deployment. It is
|
||||
defined as 0x01 (BOOT_CONFIG_VERSION). I don't intend to increase this, but
|
||||
you should if you choose to reflash the bootloader after deployment and
|
||||
the config structure has changed.
|
||||
- mode can be 0x00 (MODE_STANDARD) or 0x01 (MODE_GPIO_ROM). If you set GPIO
|
||||
you will need to set gpio_rom as well. The sample GPIO code uses GPIO 16 on
|
||||
a nodemcu dev board, if you want to use a different GPIO you'll need to
|
||||
adapt the code in rBoot slightly.
|
||||
- current_rom is the rom to boot, numbered 0 to count-1.
|
||||
- gpio_rom is the rom to boot when the GPIO is triggered at boot.
|
||||
- count is the number of roms available (may be less than MAX_ROMS, but not
|
||||
more).
|
||||
- unused[2] is padding so the uint32 rom addresses are 4 bytes aligned.
|
||||
- roms is the array of flash address for the roms. The default generated
|
||||
config will contain two entries: 0x00002000 and 0x00082000.
|
||||
- chksum (if enabled, not by deafult) should be the xor of 0xef followed by
|
||||
each of the bytes of the config structure up to (but obviously not
|
||||
including) the chksum byte itself.
|
||||
|
||||
Linking user code
|
||||
-----------------
|
||||
Each rom will need to be linked with an appropriate linker file, specifying
|
||||
where it will reside on the flash. If you are only flashing one rom to multiple
|
||||
places on the flash it must be linked multiple times to produce the set of rom
|
||||
images. This is the same as with the SDK loader.
|
||||
|
||||
Because there are endless possibilities for layout with this loader I don't
|
||||
supply sample linker files. Instead I'll tell you how to make them.
|
||||
|
||||
For each rom slot on the flash take a copy of the eagle.app.v6.ld linker script
|
||||
from the sdk. You then need to modify just one line in it for each rom:
|
||||
irom0_0_seg : org = 0x40240000, len = 0x3C000
|
||||
|
||||
Change the org address to be 0x40200000 (base memory mapped location of the
|
||||
flash) + flash address + 0x10 (offset of data after the header).
|
||||
The logical place for your first rom is the third sector, address 0x2000.
|
||||
0x40200000 + 0x2000 + 0x10 = 0x40202010
|
||||
If you use the default generated config the loader will expect to find the
|
||||
second rom at flash address half-chip-size + 0x2000 (e.g. 0x82000 on an 8MBit
|
||||
flash) so the irom0_0_seg should be:
|
||||
0x40200000 + 0x82000 + 0x10 = 0x40282010
|
||||
Due to the limitation of mapped flash (max 8MBit) if you use a larger chip and
|
||||
do not have big flash support enabled the second rom in the default config will
|
||||
still be placed at 0x082000, not truly half-chip-size + 0x2000.
|
||||
Ideally you should also adjust the len to help detect over sized sections at
|
||||
link time, but more important is the overall size of the rom which you need to
|
||||
ensure fits in the space you have allocated for it in your flash layout plan.
|
||||
|
||||
Then simply compile and link as you would normally for OTA updates with the SDK
|
||||
boot loader, except using the linker scripts you've just prepared rather than
|
||||
the ones supplied with the SDK. Remember when building roms to create them as
|
||||
'new' type roms (for use with SDK boot loader v1.2+). Or if using my esptool2
|
||||
use the -boot2 option. Note: the test loads included with rBoot are built with
|
||||
-boot0 because they do not contain a .irom0.text section (and so the value of
|
||||
irom0_0_seg in the linker file is irrelevant to them) but 'normal' user apps
|
||||
always do.
|
||||
|
||||
irom checksum
|
||||
-------------
|
||||
The SDK boot loader checksum only covers sections loaded into ram (data and some
|
||||
code). Most of the SDK and user code remains on the flash and that is not
|
||||
included in the checksum. This means you could attempt to boot a corrupt rom
|
||||
and, because it looks ok to the boot loader, there will be no attempt to switch
|
||||
to a backup rom. rBoot improves on this by allowing the .irom0.text section to
|
||||
be included in the checksum. To enable this uncomment #define BOOT_IROM_CHKSUM
|
||||
in rboot.h and build your roms with esptool2 using the -iromchksum option.
|
||||
|
||||
Big flash support
|
||||
-----------------
|
||||
This only needs to be enabled if you wish to be able to memory map more than the
|
||||
first 8MBit of the flash. Note you can still only map 8Mbit at a time. Use this
|
||||
if you want to have multiple 1MB roms, or more smaller roms than will fit in
|
||||
8Mbits. If you have a large flash but only need, for example, two 512KB roms you
|
||||
do not need to enable this mode.
|
||||
|
||||
Support in rBoot is enabled by uncommenting the #define BOOT_BIG_FLASH in
|
||||
rboot.h.
|
||||
|
||||
Thinking about your linker files is either simpler or more complicated,
|
||||
depending on your usage of the flash. If you intend to use multiple 1MB roms you
|
||||
will only need one linker file and you only need to link once for OTA updates.
|
||||
Although when you perform an OTA update the rom will be written to a different
|
||||
position on the flash, each 8Mbit of flash is mapped (separately) to 0x40200000.
|
||||
So when any given rom is run the code will appear at the same place in memory
|
||||
regardless of where it is on the flash. Your base address for the linker would
|
||||
be 0x40202010. (Actually all but the first rom could base at 0x40200010 (because
|
||||
they don't need to leave space for rBoot and config) but then you're just making
|
||||
it more complicated again!)
|
||||
If you wanted eight 512KB roms you would need two linker files - one for the
|
||||
first half of any given 8Mbits of flash and another for the second half. Just
|
||||
remember you are really laying out within a single 8MBit area, which can then be
|
||||
replicated multiple times on the flash.
|
||||
|
||||
Now the clever bit - rBoot needs to hijack the memory mapping code to select
|
||||
which 8Mbits gets mapped. There is no API for this, but we can override the SDK
|
||||
function. First we need to slightly modify the SDK library libmain.a, like so:
|
||||
|
||||
xtensa-lx106-elf-objcopy -W Cache_Read_Enable_New libmain.a libmain2.a
|
||||
|
||||
This produces a version of libmain with a 'weakened' Cache_Read_Enable_New
|
||||
function, which we can then override with our own. Modify your Makefile to link
|
||||
against the library main2 instead of main.
|
||||
Next add rboot-bigflash.c (from the appcode directory) & rboot.h to your project
|
||||
- this adds the replacement Cache_Read_Enable_New to your code.
|
||||
|
||||
Getting gcc to apply the override correctly can be slightly tricky (I'm not sure
|
||||
why, it shouldn't be). One option is to add "-u Cache_Read_Enable_New" to your
|
||||
LD_FLAGS and change the order of objects on the LD command so your objects/.a
|
||||
file is before the libraries. Another way that seems easier was to #include
|
||||
rboot-bigflash.c into the main .c file, rather than compiling it to a separate
|
||||
object file. I can't make any sense of that, but I suggest you uncomment the
|
||||
message in the Cache_Read_Enable_New function when you first build with it, to
|
||||
make sure you are getting your version into the rom.
|
||||
|
||||
Now when rBoot starts your rom, the SDK code linked in it that normally performs
|
||||
the memory mapping will delegate part of that task to rBoot code (linked in your
|
||||
rom, not in rBoot itself) to choose which part of the flash to map.
|
||||
|
||||
Integration into other frameworks
|
||||
---------------------------------
|
||||
If you wish to integrate rBoot into a development framework (e.g. Sming) you
|
||||
can set the define RBOOT_INTEGRATION and at compile time the file
|
||||
rboot-integration.h will be included into the source. This should allow you to
|
||||
set some platform specific options without having to modify the source of rBoot
|
||||
which makes it easier to integrate and maintain.
|
@ -1,2 +0,0 @@
|
||||
rom.bin -nodiff
|
||||
rom.elf -nodiff
|
@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
xtensa-lx106-elf-gcc -Wl,-N,-Ttext,0x40000000 -nostdlib rom.S -o rom.elf && \
|
||||
xtensa-lx106-elf-objdump -d rom.elf > ESP8266_ROM.txt
|
@ -1,101 +0,0 @@
|
||||
.text
|
||||
.org 0
|
||||
.globl _start
|
||||
|
||||
// xtensa-esp108-elf-gcc -Wl,-N,-Ttext,0x40000000 -nostdlib rom.S -o rom.elf
|
||||
|
||||
here = .
|
||||
#define PROVIDE(name, addr) name = here + addr - 0x40000000
|
||||
|
||||
#include "rom_functions.S"
|
||||
|
||||
PROVIDE(SPI_chip_erase, 0x40004080)
|
||||
PROVIDE(SPIFlashModeConfig, 0x40004568)
|
||||
|
||||
PROVIDE(_c_0x80000000, 0x400003a4)
|
||||
PROVIDE(_c_0x00400000, 0x40000414)
|
||||
PROVIDE(_c_0x00ffffff, 0x40000418)
|
||||
PROVIDE(_p_user_start, 0x40000fb8) // 0x3fffdcd0
|
||||
PROVIDE(_c_0x60000200, 0x40000fc4)
|
||||
PROVIDE(_s_ets_build, 0x40000fc8) // Jan 8 2013
|
||||
PROVIDE(_s_ets_banner, 0x40000fcc) // ets %s,rst cause:%d, boot mode:(%d,%d)
|
||||
PROVIDE(_s_format_s_s, 0x40000fd0) // %s %s
|
||||
PROVIDE(_s_ets_main_c, 0x40000fd4) // ets_main.c
|
||||
PROVIDE(_s_user_code_done, 0x40000fe0) // user code done
|
||||
PROVIDE(_s_wdt_reset, 0x40000fe4) // wdt reset
|
||||
PROVIDE(_s_unk_reset, 0x40000fe8) // unknown reset
|
||||
PROVIDE(_l_boot_mode_6, 0x40001044)
|
||||
PROVIDE(_l_boot_mode_0_1_2_3, 0x4000104a)
|
||||
PROVIDE(_l_rst_cause_ge_3, 0x40001075)
|
||||
PROVIDE(_l_rst_cause_ge_3_lt_7, 0x40001084)
|
||||
PROVIDE(_l_rst_cause_3_soft_wdt, 0x4000108a)
|
||||
PROVIDE(_l_load_from_flash, 0x400010a8)
|
||||
PROVIDE(_l_run_user_code, 0x400010be)
|
||||
PROVIDE(_l_wdt_reset, 0x40001118)
|
||||
PROVIDE(_l_rst_cause_1_2, 0x40001121)
|
||||
PROVIDE(_l_rst_cause_unknown, 0x40001130)
|
||||
PROVIDE(_l_boot_mode_7, 0x40001148)
|
||||
PROVIDE(_l_boot_mode_4, 0x40001150)
|
||||
PROVIDE(_c_0x60000600, 0x4000115c)
|
||||
PROVIDE(_s_waiting_for_host, 0x4000119c) // waiting for host
|
||||
PROVIDE(_x_unk1160, 0x40001160)
|
||||
PROVIDE(_c_0x3fffa000_uart_buf, 0x400011a0)
|
||||
PROVIDE(_c_0x2000, 0x400011a4)
|
||||
PROVIDE(_c_0x40100000, 0x400011a8) // default user_start
|
||||
PROVIDE(_x_boot2, 0x400011ac) // arg: 0x3fffdcd0 (&user_start)
|
||||
PROVIDE(_l_strapping_2_eq_0, 0x400011d2)
|
||||
PROVIDE(_l_124d, 0x4000124d)
|
||||
PROVIDE(_l_boot_mode2_eq_2, 0x40001265)
|
||||
PROVIDE(_l_boot_mode_eq_2, 0x40001268)
|
||||
PROVIDE(_l_boot_mode_eq_1, 0x4000127a)
|
||||
PROVIDE(_l_setup_uart, 0x40001291)
|
||||
PROVIDE(_l_boot_mode_eq_3, 0x400012b0)
|
||||
PROVIDE(_x_load_from_flash, 0x40001308)
|
||||
PROVIDE(_c_0x00001000, 0x40001994)
|
||||
PROVIDE(_c_0xffdfffff, 0x400025dc)
|
||||
PROVIDE(_l_rr_not_dsleep, 0x40002624)
|
||||
PROVIDE(_c_100000, 0x40002664)
|
||||
PROVIDE(_c_0x3feffe00, 0x40002e5c)
|
||||
PROVIDE(_p_cpu_freq, 0x40002ec8)
|
||||
PROVIDE(_x_wdt_interval, 0x40002f14) // arg: 3 -> 11, 6 -> 12, 12 -> 13
|
||||
PROVIDE(_p_wdt_cfg, 0x40002f30)
|
||||
PROVIDE(_wdt_soft_timer_fn2, 0x40002f3c)
|
||||
PROVIDE(_l_wdt_soft_timer_fn2_exit, 0x40002f59)
|
||||
PROVIDE(_l_wdt_soft_timer_fn2_feed, 0x40002f60)
|
||||
PROVIDE(_l_wdt_soft_timer_fn2_mode2_stage1_feed, 0x40002f74)
|
||||
PROVIDE(_wdt_soft_timer_fn, 0x40002f88)
|
||||
PROVIDE(_p_wdt_soft_timer_fn, 0x40002f98)
|
||||
PROVIDE(_p_wdt_soft_timer, 0x40002f9c) // 0x3fffdde0
|
||||
PROVIDE(_l_skip_wdt_imask, 0x40002fc4)
|
||||
PROVIDE(_l_wdt_enable_and_exit, 0x40002fea)
|
||||
PROVIDE(_l_wdt_mode_1, 0x4000309c)
|
||||
PROVIDE(_l_wdt_mode_2_4, 0x4000300a)
|
||||
PROVIDE(_l_wdt_mode_3, 0x40003060)
|
||||
PROVIDE(_l_recv_req, 0x400033a1)
|
||||
PROVIDE(_l_send_response, 0x400033be)
|
||||
PROVIDE(_l_send_resp_pkt, 0x400033da)
|
||||
PROVIDE(_l_process_req, 0x40003424)
|
||||
PROVIDE(_l_34a3, 0x400034a3)
|
||||
PROVIDE(_l_34b9, 0x400034b9)
|
||||
PROVIDE(_c_0x00001800, 0x40003534)
|
||||
PROVIDE(_c_0x60000a00, 0x40003f54)
|
||||
PROVIDE(_c_0x01000000, 0x400040bc)
|
||||
PROVIDE(_x_SPI_erase_sector, 0x400040c0)
|
||||
PROVIDE(_l_SPI_erase_sector_align_ok, 0x400040dc)
|
||||
PROVIDE(_c_0x00800000, 0x4000411c)
|
||||
PROVIDE(_x_SPI_erase_block, 0x40004120)
|
||||
PROVIDE(_c_0x20000000, 0x4000416c)
|
||||
PROVIDE(_c_0x08000000, 0x400043c4)
|
||||
PROVIDE(_c_0x04000000, 0x400043fc)
|
||||
PROVIDE(_c_0x40000000, 0x40004438)
|
||||
PROVIDE(_p_flashchip, 0x40004874)
|
||||
PROVIDE(_s_bootup, 0x400054cc) // bootup , addr 0x%08x
|
||||
PROVIDE(_p_sip_ctx, 0x40005130)
|
||||
PROVIDE(_l_sip_cmd_out, 0x4000550a)
|
||||
PROVIDE(_c_0x00010000, 0x40005de0)
|
||||
|
||||
.text
|
||||
|
||||
_start:
|
||||
.incbin "rom.bin"
|
||||
_end:
|
Binary file not shown.
Binary file not shown.
@ -1,347 +0,0 @@
|
||||
PROVIDE ( Cache_Read_Disable , 0x400047f0 );
|
||||
PROVIDE ( Cache_Read_Enable , 0x40004678 );
|
||||
PROVIDE ( FilePacketSendReqMsgProc , 0x400035a0 );
|
||||
PROVIDE ( FlashDwnLdParamCfgMsgProc , 0x4000368c );
|
||||
PROVIDE ( FlashDwnLdStartMsgProc , 0x40003538 );
|
||||
PROVIDE ( FlashDwnLdStopReqMsgProc , 0x40003658 );
|
||||
PROVIDE ( GetUartDevice , 0x40003f4c );
|
||||
PROVIDE ( MD5Final , 0x40009900 );
|
||||
PROVIDE ( MD5Init , 0x40009818 );
|
||||
PROVIDE ( MD5Update , 0x40009834 );
|
||||
PROVIDE ( MemDwnLdStartMsgProc , 0x400036c4 );
|
||||
PROVIDE ( MemDwnLdStopReqMsgProc , 0x4000377c );
|
||||
PROVIDE ( MemPacketSendReqMsgProc , 0x400036f0 );
|
||||
PROVIDE ( RcvMsg , 0x40003eac );
|
||||
PROVIDE ( SHA1Final , 0x4000b648 );
|
||||
PROVIDE ( SHA1Init , 0x4000b584 );
|
||||
PROVIDE ( SHA1Transform , 0x4000a364 );
|
||||
PROVIDE ( SHA1Update , 0x4000b5a8 );
|
||||
PROVIDE ( SPI_read_status , 0x400043c8 );
|
||||
PROVIDE ( SPI_write_status , 0x40004400 );
|
||||
PROVIDE ( SPI_write_enable , 0x4000443c );
|
||||
PROVIDE ( Wait_SPI_Idle , 0x4000448c );
|
||||
PROVIDE ( SPIEraseArea , 0x40004b44 );
|
||||
PROVIDE ( SPIEraseBlock , 0x400049b4 );
|
||||
PROVIDE ( SPIEraseChip , 0x40004984 );
|
||||
PROVIDE ( SPIEraseSector , 0x40004a00 );
|
||||
PROVIDE ( SPILock , 0x400048a8 );
|
||||
PROVIDE ( SPIParamCfg , 0x40004c2c );
|
||||
PROVIDE ( SPIRead , 0x40004b1c );
|
||||
PROVIDE ( SPIReadModeCnfig , 0x400048ec );
|
||||
PROVIDE ( SPIUnlock , 0x40004878 );
|
||||
PROVIDE ( SPIWrite , 0x40004a4c );
|
||||
PROVIDE ( SelectSpiFunction , 0x40003f58 );
|
||||
PROVIDE ( SendMsg , 0x40003cf4 );
|
||||
PROVIDE ( UartConnCheck , 0x40003230 );
|
||||
PROVIDE ( UartConnectProc , 0x400037a0 );
|
||||
PROVIDE ( UartDwnLdProc , 0x40003368 );
|
||||
PROVIDE ( UartGetCmdLn , 0x40003ef4 );
|
||||
PROVIDE ( UartRegReadProc , 0x4000381c );
|
||||
PROVIDE ( UartRegWriteProc , 0x400037ac );
|
||||
PROVIDE ( UartRxString , 0x40003c30 );
|
||||
PROVIDE ( Uart_Init , 0x40003a14 );
|
||||
PROVIDE ( _DebugExceptionVector , 0x40000010 );
|
||||
PROVIDE ( _DoubleExceptionVector , 0x40000070 );
|
||||
PROVIDE ( _KernelExceptionVector , 0x40000030 );
|
||||
PROVIDE ( _NMIExceptionVector , 0x40000020 );
|
||||
PROVIDE ( _ResetHandler , 0x400000a4 );
|
||||
PROVIDE ( _ResetVector , 0x40000080 );
|
||||
PROVIDE ( _UserExceptionVector , 0x40000050 );
|
||||
PROVIDE ( __adddf3 , 0x4000c538 );
|
||||
PROVIDE ( __addsf3 , 0x4000c180 );
|
||||
PROVIDE ( __divdf3 , 0x4000cb94 );
|
||||
PROVIDE ( __divdi3 , 0x4000ce60 );
|
||||
PROVIDE ( __divsi3 , 0x4000dc88 );
|
||||
PROVIDE ( __extendsfdf2 , 0x4000cdfc );
|
||||
PROVIDE ( __fixdfsi , 0x4000ccb8 );
|
||||
PROVIDE ( __fixunsdfsi , 0x4000cd00 );
|
||||
PROVIDE ( __fixunssfsi , 0x4000c4c4 );
|
||||
PROVIDE ( __floatsidf , 0x4000e2f0 );
|
||||
PROVIDE ( __floatsisf , 0x4000e2ac );
|
||||
PROVIDE ( __floatunsidf , 0x4000e2e8 );
|
||||
PROVIDE ( __floatunsisf , 0x4000e2a4 );
|
||||
PROVIDE ( __muldf3 , 0x4000c8f0 );
|
||||
PROVIDE ( __muldi3 , 0x40000650 );
|
||||
PROVIDE ( __mulsf3 , 0x4000c3dc );
|
||||
PROVIDE ( __subdf3 , 0x4000c688 );
|
||||
PROVIDE ( __subsf3 , 0x4000c268 );
|
||||
PROVIDE ( __truncdfsf2 , 0x4000cd5c );
|
||||
PROVIDE ( __udivdi3 , 0x4000d310 );
|
||||
PROVIDE ( __udivsi3 , 0x4000e21c );
|
||||
PROVIDE ( __umoddi3 , 0x4000d770 );
|
||||
PROVIDE ( __umodsi3 , 0x4000e268 );
|
||||
PROVIDE ( __umulsidi3 , 0x4000dcf0 );
|
||||
PROVIDE ( _rom_store , 0x4000e388 );
|
||||
PROVIDE ( _rom_store_table , 0x4000e328 );
|
||||
PROVIDE ( _start , 0x4000042c );
|
||||
PROVIDE ( _xtos_alloca_handler , 0x4000dbe0 );
|
||||
PROVIDE ( _xtos_c_wrapper_handler , 0x40000598 );
|
||||
PROVIDE ( _xtos_cause3_handler , 0x40000590 );
|
||||
PROVIDE ( _xtos_ints_off , 0x4000bda4 );
|
||||
PROVIDE ( _xtos_ints_on , 0x4000bd84 );
|
||||
PROVIDE ( _xtos_l1int_handler , 0x4000048c );
|
||||
PROVIDE ( _xtos_p_none , 0x4000dbf8 );
|
||||
PROVIDE ( _xtos_restore_intlevel , 0x4000056c );
|
||||
PROVIDE ( _xtos_return_from_exc , 0x4000dc54 );
|
||||
PROVIDE ( _xtos_set_exception_handler , 0x40000454 );
|
||||
PROVIDE ( _xtos_set_interrupt_handler , 0x4000bd70 );
|
||||
PROVIDE ( _xtos_set_interrupt_handler_arg , 0x4000bd28 );
|
||||
PROVIDE ( _xtos_set_intlevel , 0x4000dbfc );
|
||||
PROVIDE ( _xtos_set_min_intlevel , 0x4000dc18 );
|
||||
PROVIDE ( _xtos_set_vpri , 0x40000574 );
|
||||
PROVIDE ( _xtos_syscall_handler , 0x4000dbe4 );
|
||||
PROVIDE ( _xtos_unhandled_exception , 0x4000dc44 );
|
||||
PROVIDE ( _xtos_unhandled_interrupt , 0x4000dc3c );
|
||||
PROVIDE ( aes_decrypt , 0x400092d4 );
|
||||
PROVIDE ( aes_decrypt_deinit , 0x400092e4 );
|
||||
PROVIDE ( aes_decrypt_init , 0x40008ea4 );
|
||||
PROVIDE ( aes_unwrap , 0x40009410 );
|
||||
PROVIDE ( base64_decode , 0x40009648 );
|
||||
PROVIDE ( base64_encode , 0x400094fc );
|
||||
PROVIDE ( bzero , 0x4000de84 );
|
||||
PROVIDE ( cmd_parse , 0x40000814 );
|
||||
PROVIDE ( conv_str_decimal , 0x40000b24 );
|
||||
PROVIDE ( conv_str_hex , 0x40000cb8 );
|
||||
PROVIDE ( convert_para_str , 0x40000a60 );
|
||||
PROVIDE ( dtm_get_intr_mask , 0x400026d0 );
|
||||
PROVIDE ( dtm_params_init , 0x4000269c );
|
||||
PROVIDE ( dtm_set_intr_mask , 0x400026c8 );
|
||||
PROVIDE ( dtm_set_params , 0x400026dc );
|
||||
PROVIDE ( eprintf , 0x40001d14 );
|
||||
PROVIDE ( eprintf_init_buf , 0x40001cb8 );
|
||||
PROVIDE ( eprintf_to_host , 0x40001d48 );
|
||||
PROVIDE ( est_get_printf_buf_remain_len , 0x40002494 );
|
||||
PROVIDE ( est_reset_printf_buf_len , 0x4000249c );
|
||||
PROVIDE ( ets_bzero , 0x40002ae8 );
|
||||
PROVIDE ( ets_char2xdigit , 0x40002b74 );
|
||||
PROVIDE ( ets_delay_us , 0x40002ecc );
|
||||
PROVIDE ( ets_enter_sleep , 0x400027b8 );
|
||||
PROVIDE ( ets_external_printf , 0x40002578 );
|
||||
PROVIDE ( ets_get_cpu_frequency , 0x40002f0c );
|
||||
PROVIDE ( ets_getc , 0x40002bcc );
|
||||
PROVIDE ( ets_install_external_printf , 0x40002450 );
|
||||
PROVIDE ( ets_install_putc1 , 0x4000242c );
|
||||
PROVIDE ( ets_install_putc2 , 0x4000248c );
|
||||
PROVIDE ( ets_install_uart_printf , 0x40002438 );
|
||||
PROVIDE ( ets_intr_lock , 0x40000f74 );
|
||||
PROVIDE ( ets_intr_unlock , 0x40000f80 );
|
||||
PROVIDE ( ets_isr_attach , 0x40000f88 );
|
||||
PROVIDE ( ets_isr_mask , 0x40000f98 );
|
||||
PROVIDE ( ets_isr_unmask , 0x40000fa8 );
|
||||
PROVIDE ( ets_memcmp , 0x400018d4 );
|
||||
PROVIDE ( ets_memcpy , 0x400018b4 );
|
||||
PROVIDE ( ets_memmove , 0x400018c4 );
|
||||
PROVIDE ( ets_memset , 0x400018a4 );
|
||||
PROVIDE ( ets_post , 0x40000e24 );
|
||||
PROVIDE ( ets_printf , 0x400024cc );
|
||||
PROVIDE ( ets_putc , 0x40002be8 );
|
||||
PROVIDE ( ets_rtc_int_register , 0x40002a40 );
|
||||
PROVIDE ( ets_run , 0x40000e04 );
|
||||
PROVIDE ( ets_set_idle_cb , 0x40000dc0 );
|
||||
PROVIDE ( ets_set_user_start , 0x40000fbc );
|
||||
PROVIDE ( ets_str2macaddr , 0x40002af8 );
|
||||
PROVIDE ( ets_strcmp , 0x40002aa8 );
|
||||
PROVIDE ( ets_strcpy , 0x40002a88 );
|
||||
PROVIDE ( ets_strlen , 0x40002ac8 );
|
||||
PROVIDE ( ets_strncmp , 0x40002ab8 );
|
||||
PROVIDE ( ets_strncpy , 0x40002a98 );
|
||||
PROVIDE ( ets_strstr , 0x40002ad8 );
|
||||
PROVIDE ( ets_task , 0x40000dd0 );
|
||||
PROVIDE ( ets_timer_arm , 0x40002cc4 );
|
||||
PROVIDE ( ets_timer_disarm , 0x40002d40 );
|
||||
PROVIDE ( ets_timer_done , 0x40002d80 );
|
||||
PROVIDE ( ets_timer_handler_isr , 0x40002da8 );
|
||||
PROVIDE ( ets_timer_init , 0x40002e68 );
|
||||
PROVIDE ( ets_timer_setfn , 0x40002c48 );
|
||||
PROVIDE ( ets_uart_printf , 0x40002544 );
|
||||
PROVIDE ( ets_update_cpu_frequency , 0x40002f04 );
|
||||
PROVIDE ( ets_vprintf , 0x40001f00 );
|
||||
PROVIDE ( ets_wdt_disable , 0x400030f0 );
|
||||
PROVIDE ( ets_wdt_enable , 0x40002fa0 );
|
||||
PROVIDE ( ets_wdt_get_mode , 0x40002f34 );
|
||||
PROVIDE ( ets_wdt_init , 0x40003170 );
|
||||
PROVIDE ( ets_wdt_restore , 0x40003158 );
|
||||
PROVIDE ( ets_write_char , 0x40001da0 );
|
||||
PROVIDE ( get_first_seg , 0x4000091c );
|
||||
PROVIDE ( gpio_init , 0x40004c50 );
|
||||
PROVIDE ( gpio_input_get , 0x40004cf0 );
|
||||
PROVIDE ( gpio_intr_ack , 0x40004dcc );
|
||||
PROVIDE ( gpio_intr_handler_register , 0x40004e28 );
|
||||
PROVIDE ( gpio_intr_pending , 0x40004d88 );
|
||||
PROVIDE ( gpio_intr_test , 0x40004efc );
|
||||
PROVIDE ( gpio_output_set , 0x40004cd0 );
|
||||
PROVIDE ( gpio_pin_intr_state_set , 0x40004d90 );
|
||||
PROVIDE ( gpio_pin_wakeup_disable , 0x40004ed4 );
|
||||
PROVIDE ( gpio_pin_wakeup_enable , 0x40004e90 );
|
||||
PROVIDE ( gpio_register_get , 0x40004d5c );
|
||||
PROVIDE ( gpio_register_set , 0x40004d04 );
|
||||
PROVIDE ( hmac_md5 , 0x4000a2cc );
|
||||
PROVIDE ( hmac_md5_vector , 0x4000a160 );
|
||||
PROVIDE ( hmac_sha1 , 0x4000ba28 );
|
||||
PROVIDE ( hmac_sha1_vector , 0x4000b8b4 );
|
||||
PROVIDE ( lldesc_build_chain , 0x40004f40 );
|
||||
PROVIDE ( lldesc_num2link , 0x40005050 );
|
||||
PROVIDE ( lldesc_set_owner , 0x4000507c );
|
||||
PROVIDE ( main , 0x40000fec );
|
||||
PROVIDE ( md5_vector , 0x400097ac );
|
||||
PROVIDE ( mem_calloc , 0x40001c2c );
|
||||
PROVIDE ( mem_free , 0x400019e0 );
|
||||
PROVIDE ( mem_init , 0x40001998 );
|
||||
PROVIDE ( mem_malloc , 0x40001b40 );
|
||||
PROVIDE ( mem_realloc , 0x40001c6c );
|
||||
PROVIDE ( mem_trim , 0x40001a14 );
|
||||
PROVIDE ( mem_zalloc , 0x40001c58 );
|
||||
PROVIDE ( memcmp , 0x4000dea8 );
|
||||
PROVIDE ( memcpy , 0x4000df48 );
|
||||
PROVIDE ( memmove , 0x4000e04c );
|
||||
PROVIDE ( memset , 0x4000e190 );
|
||||
PROVIDE ( multofup , 0x400031c0 );
|
||||
PROVIDE ( pbkdf2_sha1 , 0x4000b840 );
|
||||
PROVIDE ( phy_get_romfuncs , 0x40006b08 );
|
||||
PROVIDE ( rand , 0x40000600 );
|
||||
PROVIDE ( rc4_skip , 0x4000dd68 );
|
||||
PROVIDE ( recv_packet , 0x40003d08 );
|
||||
PROVIDE ( remove_head_space , 0x40000a04 );
|
||||
PROVIDE ( rijndaelKeySetupDec , 0x40008dd0 );
|
||||
PROVIDE ( rijndaelKeySetupEnc , 0x40009300 );
|
||||
PROVIDE ( rom_abs_temp , 0x400060c0 );
|
||||
PROVIDE ( rom_ana_inf_gating_en , 0x40006b10 );
|
||||
PROVIDE ( rom_cal_tos_v50 , 0x40007a28 );
|
||||
PROVIDE ( rom_chip_50_set_channel , 0x40006f84 );
|
||||
PROVIDE ( rom_chip_v5_disable_cca , 0x400060d0 );
|
||||
PROVIDE ( rom_chip_v5_enable_cca , 0x400060ec );
|
||||
PROVIDE ( rom_chip_v5_rx_init , 0x4000711c );
|
||||
PROVIDE ( rom_chip_v5_sense_backoff , 0x4000610c );
|
||||
PROVIDE ( rom_chip_v5_tx_init , 0x4000718c );
|
||||
PROVIDE ( rom_dc_iq_est , 0x4000615c );
|
||||
PROVIDE ( rom_en_pwdet , 0x400061b8 );
|
||||
PROVIDE ( rom_get_bb_atten , 0x40006238 );
|
||||
PROVIDE ( rom_get_corr_power , 0x40006260 );
|
||||
PROVIDE ( rom_get_fm_sar_dout , 0x400062dc );
|
||||
PROVIDE ( rom_get_noisefloor , 0x40006394 );
|
||||
PROVIDE ( rom_get_power_db , 0x400063b0 );
|
||||
PROVIDE ( rom_i2c_readReg , 0x40007268 );
|
||||
PROVIDE ( rom_i2c_readReg_Mask , 0x4000729c );
|
||||
PROVIDE ( rom_i2c_writeReg , 0x400072d8 );
|
||||
PROVIDE ( rom_i2c_writeReg_Mask , 0x4000730c );
|
||||
PROVIDE ( rom_iq_est_disable , 0x40006400 );
|
||||
PROVIDE ( rom_iq_est_enable , 0x40006430 );
|
||||
PROVIDE ( rom_linear_to_db , 0x40006484 );
|
||||
PROVIDE ( rom_mhz2ieee , 0x400065a4 );
|
||||
PROVIDE ( rom_pbus_dco___SA2 , 0x40007bf0 );
|
||||
PROVIDE ( rom_pbus_debugmode , 0x4000737c );
|
||||
PROVIDE ( rom_pbus_enter_debugmode , 0x40007410 );
|
||||
PROVIDE ( rom_pbus_exit_debugmode , 0x40007448 );
|
||||
PROVIDE ( rom_pbus_force_test , 0x4000747c );
|
||||
PROVIDE ( rom_pbus_rd , 0x400074d8 );
|
||||
PROVIDE ( rom_pbus_set_rxgain , 0x4000754c );
|
||||
PROVIDE ( rom_pbus_set_txgain , 0x40007610 );
|
||||
PROVIDE ( rom_pbus_workmode , 0x40007648 );
|
||||
PROVIDE ( rom_pbus_xpd_rx_off , 0x40007688 );
|
||||
PROVIDE ( rom_pbus_xpd_rx_on , 0x400076cc );
|
||||
PROVIDE ( rom_pbus_xpd_tx_off , 0x400076fc );
|
||||
PROVIDE ( rom_pbus_xpd_tx_on , 0x40007740 );
|
||||
PROVIDE ( rom_pbus_xpd_tx_on__low_gain , 0x400077a0 );
|
||||
PROVIDE ( rom_phy_reset_req , 0x40007804 );
|
||||
PROVIDE ( rom_restart_cal , 0x4000781c );
|
||||
PROVIDE ( rom_rfcal_pwrctrl , 0x40007eb4 );
|
||||
PROVIDE ( rom_rfcal_rxiq , 0x4000804c );
|
||||
PROVIDE ( rom_rfcal_rxiq_set_reg , 0x40008264 );
|
||||
PROVIDE ( rom_rfcal_txcap , 0x40008388 );
|
||||
PROVIDE ( rom_rfcal_txiq , 0x40008610 );
|
||||
PROVIDE ( rom_rfcal_txiq_cover , 0x400088b8 );
|
||||
PROVIDE ( rom_rfcal_txiq_set_reg , 0x40008a70 );
|
||||
PROVIDE ( rom_rfpll_reset , 0x40007868 );
|
||||
PROVIDE ( rom_rfpll_set_freq , 0x40007968 );
|
||||
PROVIDE ( rom_rxiq_cover_mg_mp , 0x40008b6c );
|
||||
PROVIDE ( rom_rxiq_get_mis , 0x40006628 );
|
||||
PROVIDE ( rom_sar_init , 0x40006738 );
|
||||
PROVIDE ( rom_set_ana_inf_tx_scale , 0x4000678c );
|
||||
PROVIDE ( rom_set_channel_freq , 0x40006c50 );
|
||||
PROVIDE ( rom_set_loopback_gain , 0x400067c8 );
|
||||
PROVIDE ( rom_set_noise_floor , 0x40006830 );
|
||||
PROVIDE ( rom_set_rxclk_en , 0x40006550 );
|
||||
PROVIDE ( rom_set_txbb_atten , 0x40008c6c );
|
||||
PROVIDE ( rom_set_txclk_en , 0x4000650c );
|
||||
PROVIDE ( rom_set_txiq_cal , 0x40008d34 );
|
||||
PROVIDE ( rom_start_noisefloor , 0x40006874 );
|
||||
PROVIDE ( rom_start_tx_tone , 0x400068b4 );
|
||||
PROVIDE ( rom_stop_tx_tone , 0x4000698c );
|
||||
PROVIDE ( rom_tx_mac_disable , 0x40006a98 );
|
||||
PROVIDE ( rom_tx_mac_enable , 0x40006ad4 );
|
||||
PROVIDE ( rom_txtone_linear_pwr , 0x40006a1c );
|
||||
PROVIDE ( rom_write_rfpll_sdm , 0x400078dc );
|
||||
PROVIDE ( roundup2 , 0x400031b4 );
|
||||
PROVIDE ( rtc_enter_sleep , 0x40002870 );
|
||||
PROVIDE ( rtc_get_reset_reason , 0x400025e0 );
|
||||
PROVIDE ( rtc_intr_handler , 0x400029ec );
|
||||
PROVIDE ( rtc_set_sleep_mode , 0x40002668 );
|
||||
PROVIDE ( save_rxbcn_mactime , 0x400027a4 );
|
||||
PROVIDE ( save_tsf_us , 0x400027ac );
|
||||
PROVIDE ( send_packet , 0x40003c80 );
|
||||
PROVIDE ( sha1_prf , 0x4000ba48 );
|
||||
PROVIDE ( sha1_vector , 0x4000a2ec );
|
||||
PROVIDE ( sip_alloc_to_host_evt , 0x40005180 );
|
||||
PROVIDE ( sip_get_ptr , 0x400058a8 );
|
||||
PROVIDE ( sip_get_state , 0x40005668 );
|
||||
PROVIDE ( sip_init_attach , 0x4000567c );
|
||||
PROVIDE ( sip_install_rx_ctrl_cb , 0x4000544c );
|
||||
PROVIDE ( sip_install_rx_data_cb , 0x4000545c );
|
||||
PROVIDE ( sip_post , 0x400050fc );
|
||||
PROVIDE ( sip_post_init , 0x400056c4 );
|
||||
PROVIDE ( sip_reclaim_from_host_cmd , 0x4000534c );
|
||||
PROVIDE ( sip_reclaim_tx_data_pkt , 0x400052c0 );
|
||||
PROVIDE ( sip_send , 0x40005808 );
|
||||
PROVIDE ( sip_to_host_chain_append , 0x40005864 );
|
||||
PROVIDE ( sip_to_host_evt_send_done , 0x40005234 );
|
||||
PROVIDE ( slc_add_credits , 0x400060ac );
|
||||
PROVIDE ( slc_enable , 0x40005d90 );
|
||||
PROVIDE ( slc_from_host_chain_fetch , 0x40005f24 );
|
||||
PROVIDE ( slc_from_host_chain_recycle , 0x40005e94 );
|
||||
PROVIDE ( slc_init_attach , 0x40005c50 );
|
||||
PROVIDE ( slc_init_credit , 0x4000608c );
|
||||
PROVIDE ( slc_pause_from_host , 0x40006014 );
|
||||
PROVIDE ( slc_reattach , 0x40005c1c );
|
||||
PROVIDE ( slc_resume_from_host , 0x4000603c );
|
||||
PROVIDE ( slc_select_tohost_gpio , 0x40005dc0 );
|
||||
PROVIDE ( slc_select_tohost_gpio_mode , 0x40005db8 );
|
||||
PROVIDE ( slc_send_to_host_chain , 0x40005de4 );
|
||||
PROVIDE ( slc_set_host_io_max_window , 0x40006068 );
|
||||
PROVIDE ( slc_to_host_chain_recycle , 0x40005f10 );
|
||||
PROVIDE ( software_reset , 0x4000264c );
|
||||
PROVIDE ( spi_flash_attach , 0x40004644 );
|
||||
PROVIDE ( srand , 0x400005f0 );
|
||||
PROVIDE ( strcmp , 0x4000bdc8 );
|
||||
PROVIDE ( strcpy , 0x4000bec8 );
|
||||
PROVIDE ( strlen , 0x4000bf4c );
|
||||
PROVIDE ( strncmp , 0x4000bfa8 );
|
||||
PROVIDE ( strncpy , 0x4000c0a0 );
|
||||
PROVIDE ( strstr , 0x4000e1e0 );
|
||||
PROVIDE ( timer_insert , 0x40002c64 );
|
||||
PROVIDE ( uartAttach , 0x4000383c );
|
||||
PROVIDE ( uart_baudrate_detect , 0x40003924 );
|
||||
PROVIDE ( uart_buff_switch , 0x400038a4 );
|
||||
PROVIDE ( uart_div_modify , 0x400039d8 );
|
||||
PROVIDE ( uart_rx_intr_handler , 0x40003bbc );
|
||||
PROVIDE ( uart_rx_one_char , 0x40003b8c );
|
||||
PROVIDE ( uart_rx_one_char_block , 0x40003b64 );
|
||||
PROVIDE ( uart_rx_readbuff , 0x40003ec8 );
|
||||
PROVIDE ( uart_tx_one_char , 0x40003b30 );
|
||||
PROVIDE ( wepkey_128 , 0x4000bc40 );
|
||||
PROVIDE ( wepkey_64 , 0x4000bb3c );
|
||||
PROVIDE ( xthal_bcopy , 0x40000688 );
|
||||
PROVIDE ( xthal_copy123 , 0x4000074c );
|
||||
PROVIDE ( xthal_get_ccompare , 0x4000dd4c );
|
||||
PROVIDE ( xthal_get_ccount , 0x4000dd38 );
|
||||
PROVIDE ( xthal_get_interrupt , 0x4000dd58 );
|
||||
PROVIDE ( xthal_get_intread , 0x4000dd58 );
|
||||
PROVIDE ( xthal_memcpy , 0x400006c4 );
|
||||
PROVIDE ( xthal_set_ccompare , 0x4000dd40 );
|
||||
PROVIDE ( xthal_set_intclear , 0x4000dd60 );
|
||||
PROVIDE ( xthal_spill_registers_into_stack_nw , 0x4000e320 );
|
||||
PROVIDE ( xthal_window_spill , 0x4000e324 );
|
||||
PROVIDE ( xthal_window_spill_nw , 0x4000e320 );
|
||||
|
||||
PROVIDE ( Te0 , 0x3fffccf0 );
|
||||
PROVIDE ( UartDev , 0x3fffde10 );
|
||||
PROVIDE ( flashchip , 0x3fffc714);
|
@ -1,50 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2015 Cesanta Software Limited
|
||||
# All rights reserved
|
||||
#
|
||||
|
||||
STUB = stub_hello.c
|
||||
LIBS =
|
||||
PARAMS =
|
||||
CFLAGS =
|
||||
PORT = /dev/ttyUSB0
|
||||
|
||||
BUILD_DIR = .build
|
||||
COMMON_STUB_DIR = ../../esp
|
||||
STUB_ELF = $(BUILD_DIR)/$(patsubst %.c,%.elf,$(notdir $(STUB)))
|
||||
STUB_JSON ?= $(BUILD_DIR)/$(patsubst %.c,%.json,$(notdir $(STUB)))
|
||||
SDK = $(shell cat ../../../../fw/platforms/esp8266/sdk.version)
|
||||
XT_CC = xtensa-lx106-elf-gcc
|
||||
|
||||
.PHONY: all clean run wrap
|
||||
|
||||
all: $(STUB_ELF)
|
||||
|
||||
$(STUB_ELF): $(STUB) $(LIBS)
|
||||
@echo " CC $^ -> $@"
|
||||
@[ -d $(BUILD_DIR) ] || mkdir $(BUILD_DIR)
|
||||
@docker run --rm -i -v $(CURDIR)/../../../..:/src $(SDK) //bin/bash -c \
|
||||
"cd /src/common/platforms/esp8266/stubs && \
|
||||
$(XT_CC) -std=c99 -Wall -Werror -Os -DESP8266 \
|
||||
-mtext-section-literals -mlongcalls -nostdlib -fno-builtin \
|
||||
-I. -I/src/common/platforms/esp \
|
||||
-I/opt/Espressif/ESP8266_SDK \
|
||||
-Wl,-static -ffunction-sections -Wl,--gc-sections \
|
||||
-Tstub.ld $(CFLAGS) -o $@ $^"
|
||||
|
||||
wrap: $(STUB_JSON)
|
||||
|
||||
$(STUB_JSON): $(STUB_ELF) $(COMMON_STUB_DIR)/esptool.py
|
||||
@echo " WRAP $< -> $@"
|
||||
@docker run --rm -i -v $(CURDIR)/../../../..:/src $(SDK) //bin/bash -c \
|
||||
"cd /src/common/platforms/esp8266/stubs && \
|
||||
$(COMMON_STUB_DIR)/esptool.py wrap_stub $<" > $@
|
||||
|
||||
run: $(STUB_JSON)
|
||||
@echo " RUN $< $(PARAMS) -> $(PORT)"
|
||||
@docker run --rm -i --privileged -v $(CURDIR)/../../../..:/src $(SDK) //bin/bash -c \
|
||||
"cd /src/common/platforms/esp8266/stubs && \
|
||||
$(COMMON_STUB_DIR)/esptool.py --port $(PORT) run_stub $< $(PARAMS)"
|
||||
|
||||
clean:
|
||||
@rm -rf $(BUILD_DIR)
|
@ -1,13 +0,0 @@
|
||||
This is a ESP boot loader stub development environment.
|
||||
|
||||
Code produced in this environment can be loaded and executed
|
||||
in the bootloader environment. Usually it is used to implement
|
||||
functionality not found in the bootloader.
|
||||
|
||||
Stubs can be executed using the `run_stub` command of the modified esptool.py provided.
|
||||
`wrap_stub` produces a JSON represenattion of the stub that can later be reused
|
||||
or built into other tools.
|
||||
|
||||
Example usage:
|
||||
$ make run STUB=stub_flash_size.c PORT=/dev/ttyUSB0
|
||||
$ make run STUB=stub_md5.c PORT=/dev/ttyUSB0 PARAMS="0x11000 10000 1"
|
@ -1,14 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
|
||||
for line in open(sys.argv[1]):
|
||||
i = 0
|
||||
while i < len(line):
|
||||
n = len(line) - i
|
||||
if n > 80: n = 80
|
||||
l = line[i:i+n]
|
||||
if n == 80:
|
||||
l += '\\'
|
||||
print l
|
||||
i += n
|
@ -1,91 +0,0 @@
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_STUBS_ROM_FUNCTIONS_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_STUBS_ROM_FUNCTIONS_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "/opt/Espressif/ESP8266_NONOS_SDK/include/c_types.h"
|
||||
#include "/opt/Espressif/ESP8266_NONOS_SDK/include/spi_flash.h"
|
||||
|
||||
int uart_rx_one_char(uint8_t *ch);
|
||||
uint8_t uart_rx_one_char_block();
|
||||
int uart_tx_one_char(char ch);
|
||||
void uart_div_modify(uint32_t uart_no, uint32_t baud_div);
|
||||
|
||||
int SendMsg(uint8_t *msg, uint8_t size);
|
||||
int send_packet(uint8_t *packet, uint32_t size);
|
||||
// recv_packet depends on global UartDev, better to avoid it.
|
||||
// uint32_t recv_packet(void *packet, uint32_t len, uint8_t no_sync);
|
||||
|
||||
void _putc1(char *ch);
|
||||
|
||||
void ets_delay_us(uint32_t us);
|
||||
|
||||
uint32_t SPILock();
|
||||
uint32_t SPIUnlock();
|
||||
uint32_t SPIRead(uint32_t addr, void *dst, uint32_t size);
|
||||
uint32_t SPIWrite(uint32_t addr, const uint32_t *src, uint32_t size);
|
||||
uint32_t SPIEraseChip();
|
||||
uint32_t SPIEraseBlock(uint32_t block_num);
|
||||
uint32_t SPIEraseSector(uint32_t sector_num);
|
||||
|
||||
extern SpiFlashChip *flashchip;
|
||||
uint32_t Wait_SPI_Idle(SpiFlashChip *spi);
|
||||
uint32_t SPI_chip_erase(SpiFlashChip *spi);
|
||||
uint32_t SPI_read_status(SpiFlashChip *spi);
|
||||
uint32_t SPI_write_enable(SpiFlashChip *spi);
|
||||
|
||||
void spi_flash_attach();
|
||||
|
||||
/* ESP32 API compatibility */
|
||||
#define esp_rom_spiflash_unlock SPIUnlock
|
||||
#define esp_rom_spiflash_erase_sector SPIEraseSector
|
||||
#define esp_rom_spiflash_erase_block SPIEraseBlock
|
||||
#define esp_rom_spiflash_erase_chip SPIEraseChip
|
||||
#define esp_rom_spiflash_read SPIRead
|
||||
#define esp_rom_spiflash_write SPIWrite
|
||||
#define esp_rom_spiflash_config_param SPIParamCfg
|
||||
|
||||
void SelectSpiFunction();
|
||||
void SPIFlashModeConfig(uint32_t a, uint32_t b);
|
||||
void SPIReadModeCnfig(uint32_t a);
|
||||
uint32_t SPIParamCfg(uint32_t deviceId, uint32_t chip_size, uint32_t block_size,
|
||||
uint32_t sector_size, uint32_t page_size,
|
||||
uint32_t status_mask);
|
||||
|
||||
void Cache_Read_Disable();
|
||||
|
||||
void ets_delay_us(uint32_t delay_micros);
|
||||
|
||||
void ets_isr_mask(uint32_t ints);
|
||||
void ets_isr_unmask(uint32_t ints);
|
||||
typedef void (*int_handler_t)(void *arg);
|
||||
|
||||
void ets_intr_lock();
|
||||
void ets_intr_unlock();
|
||||
void ets_set_user_start(void (*user_start_fn)());
|
||||
|
||||
uint32_t rtc_get_reset_reason();
|
||||
void software_reset();
|
||||
void rom_phy_reset_req();
|
||||
|
||||
void uart_rx_intr_handler(void *arg);
|
||||
|
||||
void _ResetVector();
|
||||
|
||||
/* Crypto functions are from wpa_supplicant. */
|
||||
int md5_vector(uint32_t num_msgs, const uint8_t *msgs[],
|
||||
const uint32_t *msg_lens, uint8_t *digest);
|
||||
int sha1_vector(uint32_t num_msgs, const uint8_t *msgs[],
|
||||
const uint32_t *msg_lens, uint8_t *digest);
|
||||
|
||||
struct MD5Context {
|
||||
uint32_t buf[4];
|
||||
uint32_t bits[2];
|
||||
uint8_t in[64];
|
||||
};
|
||||
|
||||
void MD5Init(struct MD5Context *ctx);
|
||||
void MD5Update(struct MD5Context *ctx, void *buf, uint32_t len);
|
||||
void MD5Final(uint8_t digest[16], struct MD5Context *ctx);
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_STUBS_ROM_FUNCTIONS_H_ */
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
MEMORY {
|
||||
iram : org = 0x40100000, len = 0x8000
|
||||
dram : org = 0x3FFE8000, len = 0x14000
|
||||
}
|
||||
|
||||
ENTRY(stub_main)
|
||||
|
||||
SECTIONS {
|
||||
.params 0x40100000 : {
|
||||
_params_start = ABSOLUTE(.);
|
||||
*(.params)
|
||||
_params_end = ABSOLUTE(.);
|
||||
} > iram
|
||||
|
||||
.text : ALIGN(4) {
|
||||
_code_start = ABSOLUTE(.);
|
||||
*(.literal)
|
||||
*(.text .text.*)
|
||||
} > iram
|
||||
|
||||
.bss : ALIGN(4) {
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.bss)
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} > dram
|
||||
|
||||
.data : ALIGN(4) {
|
||||
_data_start = ABSOLUTE(.);
|
||||
*(.data)
|
||||
*(.rodata .rodata.*)
|
||||
} > dram
|
||||
}
|
||||
|
||||
INCLUDE "eagle.rom.addr.v6.ld"
|
||||
|
||||
PROVIDE(SPIFlashModeConfig = 0x40004568);
|
||||
PROVIDE(SPI_erase_sector = 0x400040c0);
|
||||
PROVIDE(SPI_erase_block = 0x40004120);
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*
|
||||
*
|
||||
* Stub template.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "rom_functions.h"
|
||||
|
||||
/* Define the args vector and put it into the ".params" section. */
|
||||
uint32_t params[3] __attribute__((section(".params")));
|
||||
|
||||
/* Define a function called stub_main. Do not return or reboot.
|
||||
* Use send_packet to communicate to the host. */
|
||||
|
||||
const char *hello = "Hello";
|
||||
|
||||
void stub_main(void) {
|
||||
send_packet(hello, 5);
|
||||
_ResetVector();
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include "uart.h"
|
||||
#include "ets_sys.h"
|
||||
|
||||
#define UART_CLKDIV_26MHZ(B) (52000000 + B / 2) / B
|
||||
|
||||
void set_baud_rate(uint32_t uart_no, uint32_t baud_rate) {
|
||||
uint32_t div = UART_CLKDIV_26MHZ(baud_rate);
|
||||
WRITE_PERI_REG(UART_CLKDIV_REG(uart_no), div & 0xfffff);
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_STUBS_UART_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_STUBS_UART_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void set_baud_rate(uint32_t uart_no, uint32_t baud_rate);
|
||||
|
||||
#define REG_UART_BASE(i) (0x60000000 + (i) *0xf00)
|
||||
#define UART_FIFO_REG(i) (REG_UART_BASE(i) + 0x0)
|
||||
#define UART_CONF1_REG(i) (REG_UART_BASE(i) + 0x24)
|
||||
#define UART_RX_TOUT_EN (BIT(31))
|
||||
#define UART_RX_TOUT_THRHD_S 24
|
||||
#define UART_RXFIFO_FULL_THRHD_S 0
|
||||
#define UART_INT_ST_REG(i) (REG_UART_BASE(i) + 0x8)
|
||||
#define UART_INT_ENA_REG(i) (REG_UART_BASE(i) + 0xC)
|
||||
#define UART_RXFIFO_TOUT_INT_ENA (BIT(8))
|
||||
#define UART_RXFIFO_FULL_INT_ENA (BIT(0))
|
||||
|
||||
#define UART_INT_CLR_REG(i) (REG_UART_BASE(i) + 0x10)
|
||||
|
||||
#define UART_CLKDIV_REG(i) (REG_UART_BASE(i) + 0x14)
|
||||
|
||||
#define UART_STATUS_REG(i) (REG_UART_BASE(i) + 0x1C)
|
||||
|
||||
#define UART_CONF0_REG(i) (REG_UART_BASE(i) + 0x20)
|
||||
#define UART_RXFIFO_RST (BIT(17))
|
||||
|
||||
#define ETS_UART0_INUM ETS_UART_INUM
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_STUBS_UART_H_ */
|
@ -1,23 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Analyzers output of firmware compiler with -DESP_ENABLE_MALLOC_TRACES
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
allocs = {}
|
||||
|
||||
for l in sys.stdin:
|
||||
m = re.match(r'(ca|ma|re|fr) (\S+)\s*(\S*)\s*(\S*)', l)
|
||||
if not m: continue
|
||||
op = m.group(1)
|
||||
if op in ('ca', 'ma'):
|
||||
allocs[m.group(2)] = long(m.group(3))
|
||||
else:
|
||||
if m.group(2) in allocs:
|
||||
del allocs[m.group(2)]
|
||||
if op == 're':
|
||||
allocs[m.group(3)] = long(m.group(4))
|
||||
|
||||
for k, v in sorted(allocs.iteritems()):
|
||||
print k, v
|
@ -1,136 +0,0 @@
|
||||
/* clang-format off */
|
||||
/*
|
||||
* Copyright (c) 2010 - 2011 Espressif System
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_PLATFORMS_ESP8266_UART_REGISTER_H_
|
||||
#define CS_COMMON_PLATFORMS_ESP8266_UART_REGISTER_H_
|
||||
|
||||
#define REG_UART_BASE(i) (0x60000000 + (i)*0xf00)
|
||||
//version value:32'h062000
|
||||
|
||||
#define UART_FIFO(i) (REG_UART_BASE(i) + 0x0)
|
||||
#define UART_RXFIFO_RD_BYTE 0x000000FF
|
||||
#define UART_RXFIFO_RD_BYTE_S 0
|
||||
|
||||
#define UART_INT_RAW(i) (REG_UART_BASE(i) + 0x4)
|
||||
#define UART_RXFIFO_TOUT_INT_RAW (BIT(8))
|
||||
#define UART_BRK_DET_INT_RAW (BIT(7))
|
||||
#define UART_CTS_CHG_INT_RAW (BIT(6))
|
||||
#define UART_DSR_CHG_INT_RAW (BIT(5))
|
||||
#define UART_RXFIFO_OVF_INT_RAW (BIT(4))
|
||||
#define UART_FRM_ERR_INT_RAW (BIT(3))
|
||||
#define UART_PARITY_ERR_INT_RAW (BIT(2))
|
||||
#define UART_TXFIFO_EMPTY_INT_RAW (BIT(1))
|
||||
#define UART_RXFIFO_FULL_INT_RAW (BIT(0))
|
||||
|
||||
#define UART_INT_ST(i) (REG_UART_BASE(i) + 0x8)
|
||||
#define UART_RXFIFO_TOUT_INT_ST (BIT(8))
|
||||
#define UART_BRK_DET_INT_ST (BIT(7))
|
||||
#define UART_CTS_CHG_INT_ST (BIT(6))
|
||||
#define UART_DSR_CHG_INT_ST (BIT(5))
|
||||
#define UART_RXFIFO_OVF_INT_ST (BIT(4))
|
||||
#define UART_FRM_ERR_INT_ST (BIT(3))
|
||||
#define UART_PARITY_ERR_INT_ST (BIT(2))
|
||||
#define UART_TXFIFO_EMPTY_INT_ST (BIT(1))
|
||||
#define UART_RXFIFO_FULL_INT_ST (BIT(0))
|
||||
|
||||
#define UART_INT_ENA(i) (REG_UART_BASE(i) + 0xC)
|
||||
#define UART_RXFIFO_TOUT_INT_ENA (BIT(8))
|
||||
#define UART_BRK_DET_INT_ENA (BIT(7))
|
||||
#define UART_CTS_CHG_INT_ENA (BIT(6))
|
||||
#define UART_DSR_CHG_INT_ENA (BIT(5))
|
||||
#define UART_RXFIFO_OVF_INT_ENA (BIT(4))
|
||||
#define UART_FRM_ERR_INT_ENA (BIT(3))
|
||||
#define UART_PARITY_ERR_INT_ENA (BIT(2))
|
||||
#define UART_TXFIFO_EMPTY_INT_ENA (BIT(1))
|
||||
#define UART_RXFIFO_FULL_INT_ENA (BIT(0))
|
||||
|
||||
#define UART_INT_CLR(i) (REG_UART_BASE(i) + 0x10)
|
||||
#define UART_RXFIFO_TOUT_INT_CLR (BIT(8))
|
||||
#define UART_BRK_DET_INT_CLR (BIT(7))
|
||||
#define UART_CTS_CHG_INT_CLR (BIT(6))
|
||||
#define UART_DSR_CHG_INT_CLR (BIT(5))
|
||||
#define UART_RXFIFO_OVF_INT_CLR (BIT(4))
|
||||
#define UART_FRM_ERR_INT_CLR (BIT(3))
|
||||
#define UART_PARITY_ERR_INT_CLR (BIT(2))
|
||||
#define UART_TXFIFO_EMPTY_INT_CLR (BIT(1))
|
||||
#define UART_RXFIFO_FULL_INT_CLR (BIT(0))
|
||||
|
||||
#define UART_CLKDIV(i) (REG_UART_BASE(i) + 0x14)
|
||||
#define UART_CLKDIV_CNT 0x000FFFFF
|
||||
#define UART_CLKDIV_S 0
|
||||
|
||||
#define UART_AUTOBAUD(i) (REG_UART_BASE(i) + 0x18)
|
||||
#define UART_GLITCH_FILT 0x000000FF
|
||||
#define UART_GLITCH_FILT_S 8
|
||||
#define UART_AUTOBAUD_EN (BIT(0))
|
||||
|
||||
#define UART_STATUS(i) (REG_UART_BASE(i) + 0x1C)
|
||||
#define UART_TXD (BIT(31))
|
||||
#define UART_RTSN (BIT(30))
|
||||
#define UART_DTRN (BIT(29))
|
||||
#define UART_TXFIFO_CNT 0x000000FF
|
||||
#define UART_TXFIFO_CNT_S 16
|
||||
#define UART_RXD (BIT(15))
|
||||
#define UART_CTSN (BIT(14))
|
||||
#define UART_DSRN (BIT(13))
|
||||
#define UART_RXFIFO_CNT 0x000000FF
|
||||
#define UART_RXFIFO_CNT_S 0
|
||||
|
||||
#define UART_CONF0(i) (REG_UART_BASE(i) + 0x20)
|
||||
#define UART_DTR_INV (BIT(24))
|
||||
#define UART_RTS_INV (BIT(23))
|
||||
#define UART_TXD_INV (BIT(22))
|
||||
#define UART_DSR_INV (BIT(21))
|
||||
#define UART_CTS_INV (BIT(20))
|
||||
#define UART_RXD_INV (BIT(19))
|
||||
#define UART_TXFIFO_RST (BIT(18))
|
||||
#define UART_RXFIFO_RST (BIT(17))
|
||||
#define UART_IRDA_EN (BIT(16))
|
||||
#define UART_TX_FLOW_EN (BIT(15))
|
||||
#define UART_LOOPBACK (BIT(14))
|
||||
#define UART_IRDA_RX_INV (BIT(13))
|
||||
#define UART_IRDA_TX_INV (BIT(12))
|
||||
#define UART_IRDA_WCTL (BIT(11))
|
||||
#define UART_IRDA_TX_EN (BIT(10))
|
||||
#define UART_IRDA_DPLX (BIT(9))
|
||||
#define UART_TXD_BRK (BIT(8))
|
||||
#define UART_SW_DTR (BIT(7))
|
||||
#define UART_SW_RTS (BIT(6))
|
||||
#define UART_STOP_BIT_NUM 0x00000003
|
||||
#define UART_STOP_BIT_NUM_S 4
|
||||
#define UART_BIT_NUM 0x00000003
|
||||
#define UART_BIT_NUM_S 2
|
||||
#define UART_PARITY_EN (BIT(1))
|
||||
#define UART_PARITY (BIT(0))
|
||||
|
||||
#define UART_CONF1(i) (REG_UART_BASE(i) + 0x24)
|
||||
#define UART_RX_TOUT_EN (BIT(31))
|
||||
#define UART_RX_TOUT_THRHD 0x0000007F
|
||||
#define UART_RX_TOUT_THRHD_S 24
|
||||
#define UART_RX_FLOW_EN (BIT(23))
|
||||
#define UART_RX_FLOW_THRHD 0x0000007F
|
||||
#define UART_RX_FLOW_THRHD_S 16
|
||||
#define UART_TXFIFO_EMPTY_THRHD 0x0000007F
|
||||
#define UART_TXFIFO_EMPTY_THRHD_S 8
|
||||
#define UART_RXFIFO_FULL_THRHD 0x0000007F
|
||||
#define UART_RXFIFO_FULL_THRHD_S 0
|
||||
|
||||
#define UART_LOWPULSE(i) (REG_UART_BASE(i) + 0x28)
|
||||
#define UART_LOWPULSE_MIN_CNT 0x000FFFFF
|
||||
#define UART_LOWPULSE_MIN_CNT_S 0
|
||||
|
||||
#define UART_HIGHPULSE(i) (REG_UART_BASE(i) + 0x2C)
|
||||
#define UART_HIGHPULSE_MIN_CNT 0x000FFFFF
|
||||
#define UART_HIGHPULSE_MIN_CNT_S 0
|
||||
|
||||
#define UART_PULSE_NUM(i) (REG_UART_BASE(i) + 0x30)
|
||||
#define UART_PULSE_NUM_CNT 0x0003FF
|
||||
#define UART_PULSE_NUM_CNT_S 0
|
||||
|
||||
#define UART_DATE(i) (REG_UART_BASE(i) + 0x78)
|
||||
#define UART_ID(i) (REG_UART_BASE(i) + 0x7C)
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_ESP8266_UART_REGISTER_H_ */
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_PLATFORMS_LWIP_MG_LWIP_H_
|
||||
#define CS_COMMON_PLATFORMS_LWIP_MG_LWIP_H_
|
||||
|
||||
#ifndef MG_LWIP
|
||||
#define MG_LWIP 0
|
||||
#endif
|
||||
|
||||
#if MG_LWIP
|
||||
|
||||
/*
|
||||
* When compiling for nRF5x chips with arm-none-eabi-gcc, it has BYTE_ORDER
|
||||
* already defined, so in order to avoid warnings in lwip, we have to undefine
|
||||
* it.
|
||||
*
|
||||
* TODO: Check if in the future versions of nRF5 SDK that changes.
|
||||
* Current version of nRF51 SDK: 0.8.0
|
||||
* nRF5 SDK: 0.9.0
|
||||
*/
|
||||
#if CS_PLATFORM == CS_P_NRF51 || CS_PLATFORM == CS_P_NRF52
|
||||
#undef BYTE_ORDER
|
||||
#endif
|
||||
|
||||
#include <lwip/opt.h>
|
||||
#include <lwip/err.h>
|
||||
#include <lwip/ip_addr.h>
|
||||
#include <lwip/inet.h>
|
||||
#include <lwip/netdb.h>
|
||||
#include <lwip/dns.h>
|
||||
|
||||
#ifndef LWIP_PROVIDE_ERRNO
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#if LWIP_SOCKET
|
||||
#include <lwip/sockets.h>
|
||||
#else
|
||||
/* We really need the definitions from sockets.h. */
|
||||
#undef LWIP_SOCKET
|
||||
#define LWIP_SOCKET 1
|
||||
#include <lwip/sockets.h>
|
||||
#undef LWIP_SOCKET
|
||||
#define LWIP_SOCKET 0
|
||||
#endif
|
||||
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define SOMAXCONN 10
|
||||
typedef int sock_t;
|
||||
|
||||
#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
|
||||
struct mg_mgr;
|
||||
struct mg_connection;
|
||||
uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr);
|
||||
void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
|
||||
int interval, int count);
|
||||
#endif
|
||||
|
||||
/* For older version of LWIP */
|
||||
#ifndef ipX_2_ip
|
||||
#define ipX_2_ip(x) (x)
|
||||
#endif
|
||||
|
||||
#endif /* MG_LWIP */
|
||||
|
||||
#endif /* CS_COMMON_PLATFORMS_LWIP_MG_LWIP_H_ */
|
@ -1,243 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
|
||||
|
||||
#ifndef MG_SIG_QUEUE_LEN
|
||||
#define MG_SIG_QUEUE_LEN 32
|
||||
#endif
|
||||
|
||||
struct mg_ev_mgr_lwip_signal {
|
||||
int sig;
|
||||
struct mg_connection *nc;
|
||||
};
|
||||
|
||||
struct mg_ev_mgr_lwip_data {
|
||||
struct mg_ev_mgr_lwip_signal sig_queue[MG_SIG_QUEUE_LEN];
|
||||
int sig_queue_len;
|
||||
int start_index;
|
||||
};
|
||||
|
||||
void mg_lwip_post_signal(enum mg_sig_type sig, struct mg_connection *nc) {
|
||||
struct mg_ev_mgr_lwip_data *md =
|
||||
(struct mg_ev_mgr_lwip_data *) nc->iface->data;
|
||||
mgos_lock();
|
||||
if (md->sig_queue_len >= MG_SIG_QUEUE_LEN) {
|
||||
mgos_unlock();
|
||||
return;
|
||||
}
|
||||
int end_index = (md->start_index + md->sig_queue_len) % MG_SIG_QUEUE_LEN;
|
||||
md->sig_queue[end_index].sig = sig;
|
||||
md->sig_queue[end_index].nc = nc;
|
||||
md->sig_queue_len++;
|
||||
mg_lwip_mgr_schedule_poll(nc->mgr);
|
||||
mgos_unlock();
|
||||
}
|
||||
|
||||
void mg_ev_mgr_lwip_process_signals(struct mg_mgr *mgr) {
|
||||
struct mg_ev_mgr_lwip_data *md =
|
||||
(struct mg_ev_mgr_lwip_data *) mgr->ifaces[MG_MAIN_IFACE]->data;
|
||||
while (md->sig_queue_len > 0) {
|
||||
mgos_lock();
|
||||
int sig = md->sig_queue[md->start_index].sig;
|
||||
struct mg_connection *nc = md->sig_queue[md->start_index].nc;
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
md->start_index = (md->start_index + 1) % MG_SIG_QUEUE_LEN;
|
||||
md->sig_queue_len--;
|
||||
mgos_unlock();
|
||||
if (nc->iface == NULL || nc->mgr == NULL) continue;
|
||||
switch (sig) {
|
||||
case MG_SIG_CONNECT_RESULT: {
|
||||
#if MG_ENABLE_SSL
|
||||
if (cs->err == 0 && (nc->flags & MG_F_SSL) &&
|
||||
!(nc->flags & MG_F_SSL_HANDSHAKE_DONE)) {
|
||||
mg_lwip_ssl_do_hs(nc);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
mg_if_connect_cb(nc, cs->err);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MG_SIG_CLOSE_CONN: {
|
||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
mg_close_conn(nc);
|
||||
break;
|
||||
}
|
||||
case MG_SIG_RECV: {
|
||||
cs->recv_pending = 0;
|
||||
if (nc->flags & MG_F_UDP) {
|
||||
mg_lwip_handle_recv_udp(nc);
|
||||
} else {
|
||||
mg_lwip_handle_recv_tcp(nc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MG_SIG_TOMBSTONE: {
|
||||
break;
|
||||
}
|
||||
case MG_SIG_ACCEPT: {
|
||||
mg_lwip_handle_accept(nc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mg_lwip_if_init(struct mg_iface *iface) {
|
||||
LOG(LL_INFO, ("%p Mongoose init", iface));
|
||||
iface->data = MG_CALLOC(1, sizeof(struct mg_ev_mgr_lwip_data));
|
||||
}
|
||||
|
||||
void mg_lwip_if_free(struct mg_iface *iface) {
|
||||
MG_FREE(iface->data);
|
||||
iface->data = NULL;
|
||||
}
|
||||
|
||||
void mg_lwip_if_add_conn(struct mg_connection *nc) {
|
||||
(void) nc;
|
||||
}
|
||||
|
||||
void mg_lwip_if_remove_conn(struct mg_connection *nc) {
|
||||
struct mg_ev_mgr_lwip_data *md =
|
||||
(struct mg_ev_mgr_lwip_data *) nc->iface->data;
|
||||
/* Walk the queue and null-out further signals for this conn. */
|
||||
for (int i = 0; i < MG_SIG_QUEUE_LEN; i++) {
|
||||
if (md->sig_queue[i].nc == nc) {
|
||||
md->sig_queue[i].sig = MG_SIG_TOMBSTONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms) {
|
||||
struct mg_mgr *mgr = iface->mgr;
|
||||
int n = 0;
|
||||
double now = mg_time();
|
||||
struct mg_connection *nc, *tmp;
|
||||
double min_timer = 0;
|
||||
int num_timers = 0;
|
||||
#if 0
|
||||
DBG(("begin poll @%u", (unsigned int) (now * 1000)));
|
||||
#endif
|
||||
mg_ev_mgr_lwip_process_signals(mgr);
|
||||
for (nc = mgr->active_connections; nc != NULL; nc = tmp) {
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
tmp = nc->next;
|
||||
n++;
|
||||
if ((nc->flags & MG_F_CLOSE_IMMEDIATELY) ||
|
||||
((nc->flags & MG_F_SEND_AND_CLOSE) && (nc->flags & MG_F_UDP) &&
|
||||
(nc->send_mbuf.len == 0))) {
|
||||
mg_close_conn(nc);
|
||||
continue;
|
||||
}
|
||||
mg_if_poll(nc, now);
|
||||
mg_if_timer(nc, now);
|
||||
#if MG_ENABLE_SSL
|
||||
if ((nc->flags & MG_F_SSL) && cs != NULL && cs->pcb.tcp != NULL &&
|
||||
cs->pcb.tcp->state == ESTABLISHED) {
|
||||
if (((nc->flags & MG_F_WANT_WRITE) ||
|
||||
((nc->send_mbuf.len > 0) &&
|
||||
(nc->flags & MG_F_SSL_HANDSHAKE_DONE))) &&
|
||||
cs->pcb.tcp->snd_buf > 0) {
|
||||
/* Can write more. */
|
||||
if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) {
|
||||
if (!(nc->flags & MG_F_CONNECTING)) mg_lwip_ssl_send(nc);
|
||||
} else {
|
||||
mg_lwip_ssl_do_hs(nc);
|
||||
}
|
||||
}
|
||||
if (cs->rx_chain != NULL || (nc->flags & MG_F_WANT_READ)) {
|
||||
if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) {
|
||||
if (!(nc->flags & MG_F_CONNECTING)) mg_lwip_ssl_recv(nc);
|
||||
} else {
|
||||
mg_lwip_ssl_do_hs(nc);
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif /* MG_ENABLE_SSL */
|
||||
{
|
||||
if (nc->send_mbuf.len > 0 && !(nc->flags & MG_F_CONNECTING)) {
|
||||
mg_lwip_send_more(nc);
|
||||
}
|
||||
}
|
||||
if (nc->sock != INVALID_SOCKET &&
|
||||
!(nc->flags & (MG_F_UDP | MG_F_LISTENING)) && cs->pcb.tcp != NULL &&
|
||||
cs->pcb.tcp->unsent != NULL) {
|
||||
tcpip_callback(tcp_output_tcpip, cs->pcb.tcp);
|
||||
}
|
||||
if (nc->ev_timer_time > 0) {
|
||||
if (num_timers == 0 || nc->ev_timer_time < min_timer) {
|
||||
min_timer = nc->ev_timer_time;
|
||||
}
|
||||
num_timers++;
|
||||
}
|
||||
|
||||
if (nc->sock != INVALID_SOCKET) {
|
||||
/* Try to consume data from cs->rx_chain */
|
||||
mg_lwip_consume_rx_chain_tcp(nc);
|
||||
|
||||
/*
|
||||
* If the connection is about to close, and rx_chain is finally empty,
|
||||
* send the MG_SIG_CLOSE_CONN signal
|
||||
*/
|
||||
if (cs->draining_rx_chain && cs->rx_chain == NULL) {
|
||||
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
DBG(("end poll @%u, %d conns, %d timers (min %u), next in %d ms",
|
||||
(unsigned int) (now * 1000), n, num_timers,
|
||||
(unsigned int) (min_timer * 1000), timeout_ms));
|
||||
#endif
|
||||
(void) timeout_ms;
|
||||
return now;
|
||||
}
|
||||
|
||||
uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr) {
|
||||
struct mg_connection *nc;
|
||||
double now;
|
||||
double min_timer = 0;
|
||||
int num_timers = 0;
|
||||
mg_ev_mgr_lwip_process_signals(mgr);
|
||||
for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) {
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
if (nc->ev_timer_time > 0) {
|
||||
if (num_timers == 0 || nc->ev_timer_time < min_timer) {
|
||||
min_timer = nc->ev_timer_time;
|
||||
}
|
||||
num_timers++;
|
||||
}
|
||||
if (nc->send_mbuf.len > 0
|
||||
#if MG_ENABLE_SSL
|
||||
|| (nc->flags & MG_F_WANT_WRITE)
|
||||
#endif
|
||||
) {
|
||||
int can_send = 0;
|
||||
/* We have stuff to send, but can we? */
|
||||
if (nc->flags & MG_F_UDP) {
|
||||
/* UDP is always ready for sending. */
|
||||
can_send = (cs->pcb.udp != NULL);
|
||||
} else {
|
||||
can_send = (cs->pcb.tcp != NULL && cs->pcb.tcp->snd_buf > 0);
|
||||
}
|
||||
/* We want and can send, request a poll immediately. */
|
||||
if (can_send) return 0;
|
||||
}
|
||||
}
|
||||
uint32_t timeout_ms = ~0;
|
||||
now = mg_time();
|
||||
if (num_timers > 0) {
|
||||
/* If we have a timer that is past due, do a poll ASAP. */
|
||||
if (min_timer < now) return 0;
|
||||
double timer_timeout_ms = (min_timer - now) * 1000 + 1 /* rounding */;
|
||||
if (timer_timeout_ms < timeout_ms) {
|
||||
timeout_ms = timer_timeout_ms;
|
||||
}
|
||||
}
|
||||
return timeout_ms;
|
||||
}
|
||||
|
||||
#endif /* MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL */
|
@ -1,779 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#if MG_ENABLE_NET_IF_LWIP_LOW_LEVEL
|
||||
|
||||
#include "common/mg_mem.h"
|
||||
|
||||
#include <lwip/init.h>
|
||||
#include <lwip/pbuf.h>
|
||||
#include <lwip/tcp.h>
|
||||
#include <lwip/tcpip.h>
|
||||
#if ((LWIP_VERSION_MAJOR << 8) | LWIP_VERSION_MINOR) >= 0x0105
|
||||
#include <lwip/priv/tcp_priv.h> /* For tcp_seg */
|
||||
#else
|
||||
#include <lwip/tcp_impl.h>
|
||||
#endif
|
||||
#include <lwip/udp.h>
|
||||
|
||||
#include "common/cs_dbg.h"
|
||||
|
||||
/*
|
||||
* Newest versions of LWIP have ip_2_ip4, older have ipX_2_ip,
|
||||
* even older have nothing.
|
||||
*/
|
||||
#ifndef ip_2_ip4
|
||||
#ifdef ipX_2_ip
|
||||
#define ip_2_ip4(addr) ipX_2_ip(addr)
|
||||
#else
|
||||
#define ip_2_ip4(addr) (addr)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Depending on whether Mongoose is compiled with ipv6 support, use right
|
||||
* lwip functions
|
||||
*/
|
||||
#if MG_ENABLE_IPV6
|
||||
#define TCP_NEW tcp_new_ip6
|
||||
#define TCP_BIND tcp_bind_ip6
|
||||
#define UDP_BIND udp_bind_ip6
|
||||
#define IPADDR_NTOA(x) ip6addr_ntoa((const ip6_addr_t *)(x))
|
||||
#define SET_ADDR(dst, src) \
|
||||
memcpy((dst)->sin6.sin6_addr.s6_addr, (src)->ip6.addr, \
|
||||
sizeof((dst)->sin6.sin6_addr.s6_addr))
|
||||
#else
|
||||
#define TCP_NEW tcp_new
|
||||
#define TCP_BIND tcp_bind
|
||||
#define UDP_BIND udp_bind
|
||||
#define IPADDR_NTOA ipaddr_ntoa
|
||||
#define SET_ADDR(dst, src) (dst)->sin.sin_addr.s_addr = ip_2_ip4(src)->addr
|
||||
#endif
|
||||
|
||||
#if NO_SYS
|
||||
#define tcpip_callback(fn, arg) (fn)(arg)
|
||||
typedef void (*tcpip_callback_fn)(void *arg);
|
||||
#endif
|
||||
|
||||
void mg_lwip_ssl_do_hs(struct mg_connection *nc);
|
||||
void mg_lwip_ssl_send(struct mg_connection *nc);
|
||||
void mg_lwip_ssl_recv(struct mg_connection *nc);
|
||||
|
||||
void mg_lwip_if_init(struct mg_iface *iface);
|
||||
void mg_lwip_if_free(struct mg_iface *iface);
|
||||
void mg_lwip_if_add_conn(struct mg_connection *nc);
|
||||
void mg_lwip_if_remove_conn(struct mg_connection *nc);
|
||||
time_t mg_lwip_if_poll(struct mg_iface *iface, int timeout_ms);
|
||||
|
||||
#if defined(RTOS_SDK) || defined(ESP_PLATFORM)
|
||||
extern void mgos_lock();
|
||||
extern void mgos_unlock();
|
||||
#else
|
||||
#define mgos_lock()
|
||||
#define mgos_unlock()
|
||||
#endif
|
||||
|
||||
static void mg_lwip_recv_common(struct mg_connection *nc, struct pbuf *p);
|
||||
|
||||
#if LWIP_TCP_KEEPALIVE
|
||||
void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
|
||||
int interval, int count) {
|
||||
if (nc->sock == INVALID_SOCKET || nc->flags & MG_F_UDP) {
|
||||
return;
|
||||
}
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
struct tcp_pcb *tpcb = cs->pcb.tcp;
|
||||
if (idle > 0 && interval > 0 && count > 0) {
|
||||
tpcb->keep_idle = idle * 1000;
|
||||
tpcb->keep_intvl = interval * 1000;
|
||||
tpcb->keep_cnt = count;
|
||||
tpcb->so_options |= SOF_KEEPALIVE;
|
||||
} else {
|
||||
tpcb->so_options &= ~SOF_KEEPALIVE;
|
||||
}
|
||||
}
|
||||
#elif !defined(MG_NO_LWIP_TCP_KEEPALIVE)
|
||||
#warning LWIP TCP keepalive is disabled. Please consider enabling it.
|
||||
#endif /* LWIP_TCP_KEEPALIVE */
|
||||
|
||||
static err_t mg_lwip_tcp_conn_cb(void *arg, struct tcp_pcb *tpcb, err_t err) {
|
||||
struct mg_connection *nc = (struct mg_connection *) arg;
|
||||
DBG(("%p connect to %s:%u = %d", nc, IPADDR_NTOA(ipX_2_ip(&tpcb->remote_ip)),
|
||||
tpcb->remote_port, err));
|
||||
if (nc == NULL) {
|
||||
tcp_abort(tpcb);
|
||||
return ERR_ARG;
|
||||
}
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
cs->err = err;
|
||||
#if LWIP_TCP_KEEPALIVE
|
||||
if (err == 0) mg_lwip_set_keepalive_params(nc, 60, 10, 6);
|
||||
#endif
|
||||
mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void mg_lwip_tcp_error_cb(void *arg, err_t err) {
|
||||
struct mg_connection *nc = (struct mg_connection *) arg;
|
||||
DBG(("%p conn error %d", nc, err));
|
||||
if (nc == NULL) return;
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
cs->pcb.tcp = NULL; /* Has already been deallocated */
|
||||
if (nc->flags & MG_F_CONNECTING) {
|
||||
cs->err = err;
|
||||
mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc);
|
||||
} else {
|
||||
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
||||
}
|
||||
}
|
||||
|
||||
static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
|
||||
struct pbuf *p, err_t err) {
|
||||
struct mg_connection *nc = (struct mg_connection *) arg;
|
||||
DBG(("%p %p %u %d", nc, tpcb, (p != NULL ? p->tot_len : 0), err));
|
||||
if (p == NULL) {
|
||||
if (nc != NULL && !(nc->flags & MG_F_CLOSE_IMMEDIATELY)) {
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
if (cs->rx_chain != NULL) {
|
||||
/*
|
||||
* rx_chain still contains non-consumed data, don't close the
|
||||
* connection
|
||||
*/
|
||||
cs->draining_rx_chain = 1;
|
||||
} else {
|
||||
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
||||
}
|
||||
} else {
|
||||
/* Tombstoned connection, do nothing. */
|
||||
}
|
||||
return ERR_OK;
|
||||
} else if (nc == NULL) {
|
||||
tcp_abort(tpcb);
|
||||
return ERR_ARG;
|
||||
}
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
/*
|
||||
* If we get a chain of more than one segment at once, we need to bump
|
||||
* refcount on the subsequent bufs to make them independent.
|
||||
*/
|
||||
if (p->next != NULL) {
|
||||
struct pbuf *q = p->next;
|
||||
for (; q != NULL; q = q->next) pbuf_ref(q);
|
||||
}
|
||||
mgos_lock();
|
||||
if (cs->rx_chain == NULL) {
|
||||
cs->rx_offset = 0;
|
||||
} else if (pbuf_clen(cs->rx_chain) >= 4) {
|
||||
/* ESP SDK has a limited pool of 5 pbufs. We must not hog them all or RX
|
||||
* will be completely blocked. We already have at least 4 in the chain,
|
||||
* this one is, so we have to make a copy and release this one. */
|
||||
struct pbuf *np = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
|
||||
if (np != NULL) {
|
||||
pbuf_copy(np, p);
|
||||
pbuf_free(p);
|
||||
p = np;
|
||||
}
|
||||
}
|
||||
mgos_unlock();
|
||||
mg_lwip_recv_common(nc, p);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void mg_lwip_consume_rx_chain_tcp(struct mg_connection *nc) {
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
if (cs->rx_chain == NULL) return;
|
||||
#if MG_ENABLE_SSL
|
||||
if (nc->flags & MG_F_SSL) {
|
||||
if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) {
|
||||
mg_lwip_ssl_recv(nc);
|
||||
} else {
|
||||
mg_lwip_ssl_do_hs(nc);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
mgos_lock();
|
||||
while (cs->rx_chain != NULL && nc->recv_mbuf.len < nc->recv_mbuf_limit) {
|
||||
struct pbuf *seg = cs->rx_chain;
|
||||
|
||||
size_t seg_len = (seg->len - cs->rx_offset);
|
||||
size_t buf_avail = (nc->recv_mbuf_limit - nc->recv_mbuf.len);
|
||||
size_t len = MIN(seg_len, buf_avail);
|
||||
|
||||
char *data = (char *) MG_MALLOC(len);
|
||||
if (data == NULL) {
|
||||
mgos_unlock();
|
||||
DBG(("OOM"));
|
||||
return;
|
||||
}
|
||||
pbuf_copy_partial(seg, data, len, cs->rx_offset);
|
||||
cs->rx_offset += len;
|
||||
if (cs->rx_offset == cs->rx_chain->len) {
|
||||
cs->rx_chain = pbuf_dechain(cs->rx_chain);
|
||||
pbuf_free(seg);
|
||||
cs->rx_offset = 0;
|
||||
}
|
||||
mgos_unlock();
|
||||
mg_if_recv_tcp_cb(nc, data, len, 1 /* own */);
|
||||
mgos_lock();
|
||||
}
|
||||
mgos_unlock();
|
||||
}
|
||||
|
||||
static void mg_lwip_handle_recv_tcp(struct mg_connection *nc) {
|
||||
mg_lwip_consume_rx_chain_tcp(nc);
|
||||
|
||||
if (nc->send_mbuf.len > 0) {
|
||||
mg_lwip_mgr_schedule_poll(nc->mgr);
|
||||
}
|
||||
}
|
||||
|
||||
static err_t mg_lwip_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb,
|
||||
u16_t num_sent) {
|
||||
struct mg_connection *nc = (struct mg_connection *) arg;
|
||||
DBG(("%p %p %u %p %p", nc, tpcb, num_sent, tpcb->unsent, tpcb->unacked));
|
||||
if (nc == NULL) return ERR_OK;
|
||||
if ((nc->flags & MG_F_SEND_AND_CLOSE) && !(nc->flags & MG_F_WANT_WRITE) &&
|
||||
nc->send_mbuf.len == 0 && tpcb->unsent == NULL && tpcb->unacked == NULL) {
|
||||
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
struct mg_lwip_if_connect_tcp_ctx {
|
||||
struct mg_connection *nc;
|
||||
const union socket_address *sa;
|
||||
};
|
||||
|
||||
static void mg_lwip_if_connect_tcp_tcpip(void *arg) {
|
||||
struct mg_lwip_if_connect_tcp_ctx *ctx =
|
||||
(struct mg_lwip_if_connect_tcp_ctx *) arg;
|
||||
struct mg_connection *nc = ctx->nc;
|
||||
const union socket_address *sa = ctx->sa;
|
||||
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
struct tcp_pcb *tpcb = TCP_NEW();
|
||||
cs->pcb.tcp = tpcb;
|
||||
ip_addr_t *ip = (ip_addr_t *) &sa->sin.sin_addr.s_addr;
|
||||
u16_t port = ntohs(sa->sin.sin_port);
|
||||
tcp_arg(tpcb, nc);
|
||||
tcp_err(tpcb, mg_lwip_tcp_error_cb);
|
||||
tcp_sent(tpcb, mg_lwip_tcp_sent_cb);
|
||||
tcp_recv(tpcb, mg_lwip_tcp_recv_cb);
|
||||
cs->err = TCP_BIND(tpcb, IP_ADDR_ANY, 0 /* any port */);
|
||||
DBG(("%p tcp_bind = %d", nc, cs->err));
|
||||
if (cs->err != ERR_OK) {
|
||||
mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc);
|
||||
return;
|
||||
}
|
||||
cs->err = tcp_connect(tpcb, ip, port, mg_lwip_tcp_conn_cb);
|
||||
DBG(("%p tcp_connect %p = %d", nc, tpcb, cs->err));
|
||||
if (cs->err != ERR_OK) {
|
||||
mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void mg_lwip_if_connect_tcp(struct mg_connection *nc,
|
||||
const union socket_address *sa) {
|
||||
struct mg_lwip_if_connect_tcp_ctx ctx = {.nc = nc, .sa = sa};
|
||||
tcpip_callback(mg_lwip_if_connect_tcp_tcpip, &ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lwip included in the SDKs for nRF5x chips has different type for the
|
||||
* callback of `udp_recv()`
|
||||
*/
|
||||
#if ((LWIP_VERSION_MAJOR << 8) | LWIP_VERSION_MINOR) >= 0x0105
|
||||
static void mg_lwip_udp_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
const ip_addr_t *addr, u16_t port)
|
||||
#else
|
||||
static void mg_lwip_udp_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *addr, u16_t port)
|
||||
#endif
|
||||
{
|
||||
struct mg_connection *nc = (struct mg_connection *) arg;
|
||||
DBG(("%p %s:%u %p %u %u", nc, IPADDR_NTOA(addr), port, p, p->ref, p->len));
|
||||
/* Put address in a separate pbuf and tack it onto the packet. */
|
||||
struct pbuf *sap =
|
||||
pbuf_alloc(PBUF_RAW, sizeof(union socket_address), PBUF_RAM);
|
||||
if (sap == NULL) {
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
union socket_address *sa = (union socket_address *) sap->payload;
|
||||
#if ((LWIP_VERSION_MAJOR << 8) | LWIP_VERSION_MINOR) >= 0x0105
|
||||
sa->sin.sin_addr.s_addr = ip_2_ip4(addr)->addr;
|
||||
#else
|
||||
sa->sin.sin_addr.s_addr = addr->addr;
|
||||
#endif
|
||||
sa->sin.sin_port = htons(port);
|
||||
/* Logic in the recv handler requires that there be exactly one data pbuf. */
|
||||
p = pbuf_coalesce(p, PBUF_RAW);
|
||||
pbuf_chain(sap, p);
|
||||
mg_lwip_recv_common(nc, sap);
|
||||
(void) pcb;
|
||||
}
|
||||
|
||||
static void mg_lwip_recv_common(struct mg_connection *nc, struct pbuf *p) {
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
mgos_lock();
|
||||
if (cs->rx_chain == NULL) {
|
||||
cs->rx_chain = p;
|
||||
} else {
|
||||
pbuf_chain(cs->rx_chain, p);
|
||||
}
|
||||
if (!cs->recv_pending) {
|
||||
cs->recv_pending = 1;
|
||||
mg_lwip_post_signal(MG_SIG_RECV, nc);
|
||||
}
|
||||
mgos_unlock();
|
||||
}
|
||||
|
||||
static void mg_lwip_handle_recv_udp(struct mg_connection *nc) {
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
/*
|
||||
* For UDP, RX chain consists of interleaved address and packet bufs:
|
||||
* Address pbuf followed by exactly one data pbuf (recv_cb took care of that).
|
||||
*/
|
||||
while (cs->rx_chain != NULL) {
|
||||
struct pbuf *sap = cs->rx_chain;
|
||||
struct pbuf *p = sap->next;
|
||||
cs->rx_chain = pbuf_dechain(p);
|
||||
size_t data_len = p->len;
|
||||
char *data = (char *) MG_MALLOC(data_len);
|
||||
if (data != NULL) {
|
||||
pbuf_copy_partial(p, data, data_len, 0);
|
||||
pbuf_free(p);
|
||||
mg_if_recv_udp_cb(nc, data, data_len,
|
||||
(union socket_address *) sap->payload, sap->len);
|
||||
pbuf_free(sap);
|
||||
} else {
|
||||
pbuf_free(p);
|
||||
pbuf_free(sap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mg_lwip_if_connect_udp_tcpip(void *arg) {
|
||||
struct mg_connection *nc = (struct mg_connection *) arg;
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
struct udp_pcb *upcb = udp_new();
|
||||
cs->err = UDP_BIND(upcb, IP_ADDR_ANY, 0 /* any port */);
|
||||
DBG(("%p udp_bind %p = %d", nc, upcb, cs->err));
|
||||
if (cs->err == ERR_OK) {
|
||||
udp_recv(upcb, mg_lwip_udp_recv_cb, nc);
|
||||
cs->pcb.udp = upcb;
|
||||
} else {
|
||||
udp_remove(upcb);
|
||||
}
|
||||
mg_lwip_post_signal(MG_SIG_CONNECT_RESULT, nc);
|
||||
}
|
||||
|
||||
void mg_lwip_if_connect_udp(struct mg_connection *nc) {
|
||||
tcpip_callback(mg_lwip_if_connect_udp_tcpip, nc);
|
||||
}
|
||||
|
||||
void mg_lwip_accept_conn(struct mg_connection *nc, struct tcp_pcb *tpcb) {
|
||||
union socket_address sa;
|
||||
SET_ADDR(&sa, &tpcb->remote_ip);
|
||||
sa.sin.sin_port = htons(tpcb->remote_port);
|
||||
mg_if_accept_tcp_cb(nc, &sa, sizeof(sa.sin));
|
||||
}
|
||||
|
||||
static void tcp_close_tcpip(void *arg) {
|
||||
tcp_close((struct tcp_pcb *) arg);
|
||||
}
|
||||
|
||||
void mg_lwip_handle_accept(struct mg_connection *nc) {
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
if (cs->pcb.tcp == NULL) return;
|
||||
#if MG_ENABLE_SSL
|
||||
if (cs->lc->flags & MG_F_SSL) {
|
||||
if (mg_ssl_if_conn_accept(nc, cs->lc) != MG_SSL_OK) {
|
||||
LOG(LL_ERROR, ("SSL error"));
|
||||
tcpip_callback(tcp_close_tcpip, cs->pcb.tcp);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
mg_lwip_accept_conn(nc, cs->pcb.tcp);
|
||||
}
|
||||
}
|
||||
|
||||
static err_t mg_lwip_accept_cb(void *arg, struct tcp_pcb *newtpcb, err_t err) {
|
||||
struct mg_connection *lc = (struct mg_connection *) arg, *nc;
|
||||
struct mg_lwip_conn_state *lcs, *cs;
|
||||
struct tcp_pcb_listen *lpcb;
|
||||
LOG(LL_DEBUG,
|
||||
("%p conn %p from %s:%u", lc, newtpcb,
|
||||
IPADDR_NTOA(ipX_2_ip(&newtpcb->remote_ip)), newtpcb->remote_port));
|
||||
if (lc == NULL) {
|
||||
tcp_abort(newtpcb);
|
||||
return ERR_ABRT;
|
||||
}
|
||||
lcs = (struct mg_lwip_conn_state *) lc->sock;
|
||||
lpcb = (struct tcp_pcb_listen *) lcs->pcb.tcp;
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
tcp_accepted(lpcb);
|
||||
#endif
|
||||
nc = mg_if_accept_new_conn(lc);
|
||||
if (nc == NULL) {
|
||||
tcp_abort(newtpcb);
|
||||
return ERR_ABRT;
|
||||
}
|
||||
cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
cs->lc = lc;
|
||||
cs->pcb.tcp = newtpcb;
|
||||
/* We need to set up callbacks before returning because data may start
|
||||
* arriving immediately. */
|
||||
tcp_arg(newtpcb, nc);
|
||||
tcp_err(newtpcb, mg_lwip_tcp_error_cb);
|
||||
tcp_sent(newtpcb, mg_lwip_tcp_sent_cb);
|
||||
tcp_recv(newtpcb, mg_lwip_tcp_recv_cb);
|
||||
#if LWIP_TCP_KEEPALIVE
|
||||
mg_lwip_set_keepalive_params(nc, 60, 10, 6);
|
||||
#endif
|
||||
mg_lwip_post_signal(MG_SIG_ACCEPT, nc);
|
||||
(void) err;
|
||||
(void) lpcb;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
struct mg_lwip_if_listen_ctx {
|
||||
struct mg_connection *nc;
|
||||
union socket_address *sa;
|
||||
int ret;
|
||||
};
|
||||
|
||||
static void mg_lwip_if_listen_tcp_tcpip(void *arg) {
|
||||
struct mg_lwip_if_listen_ctx *ctx = (struct mg_lwip_if_listen_ctx *) arg;
|
||||
struct mg_connection *nc = ctx->nc;
|
||||
union socket_address *sa = ctx->sa;
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
struct tcp_pcb *tpcb = TCP_NEW();
|
||||
ip_addr_t *ip = (ip_addr_t *) &sa->sin.sin_addr.s_addr;
|
||||
u16_t port = ntohs(sa->sin.sin_port);
|
||||
cs->err = TCP_BIND(tpcb, ip, port);
|
||||
DBG(("%p tcp_bind(%s:%u) = %d", nc, IPADDR_NTOA(ip), port, cs->err));
|
||||
if (cs->err != ERR_OK) {
|
||||
tcp_close(tpcb);
|
||||
ctx->ret = -1;
|
||||
return;
|
||||
}
|
||||
tcp_arg(tpcb, nc);
|
||||
tpcb = tcp_listen(tpcb);
|
||||
cs->pcb.tcp = tpcb;
|
||||
tcp_accept(tpcb, mg_lwip_accept_cb);
|
||||
ctx->ret = 0;
|
||||
}
|
||||
|
||||
int mg_lwip_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) {
|
||||
struct mg_lwip_if_listen_ctx ctx = {.nc = nc, .sa = sa};
|
||||
tcpip_callback(mg_lwip_if_listen_tcp_tcpip, &ctx);
|
||||
return ctx.ret;
|
||||
}
|
||||
|
||||
static void mg_lwip_if_listen_udp_tcpip(void *arg) {
|
||||
struct mg_lwip_if_listen_ctx *ctx = (struct mg_lwip_if_listen_ctx *) arg;
|
||||
struct mg_connection *nc = ctx->nc;
|
||||
union socket_address *sa = ctx->sa;
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
struct udp_pcb *upcb = udp_new();
|
||||
ip_addr_t *ip = (ip_addr_t *) &sa->sin.sin_addr.s_addr;
|
||||
u16_t port = ntohs(sa->sin.sin_port);
|
||||
cs->err = UDP_BIND(upcb, ip, port);
|
||||
DBG(("%p udb_bind(%s:%u) = %d", nc, IPADDR_NTOA(ip), port, cs->err));
|
||||
if (cs->err != ERR_OK) {
|
||||
udp_remove(upcb);
|
||||
ctx->ret = -1;
|
||||
} else {
|
||||
udp_recv(upcb, mg_lwip_udp_recv_cb, nc);
|
||||
cs->pcb.udp = upcb;
|
||||
ctx->ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int mg_lwip_if_listen_udp(struct mg_connection *nc, union socket_address *sa) {
|
||||
struct mg_lwip_if_listen_ctx ctx = {.nc = nc, .sa = sa};
|
||||
tcpip_callback(mg_lwip_if_listen_udp_tcpip, &ctx);
|
||||
return ctx.ret;
|
||||
}
|
||||
|
||||
struct mg_lwip_tcp_write_ctx {
|
||||
struct mg_connection *nc;
|
||||
const void *data;
|
||||
uint16_t len;
|
||||
int ret;
|
||||
};
|
||||
|
||||
static void tcp_output_tcpip(void *arg) {
|
||||
tcp_output((struct tcp_pcb *) arg);
|
||||
}
|
||||
|
||||
static void mg_lwip_tcp_write_tcpip(void *arg) {
|
||||
struct mg_lwip_tcp_write_ctx *ctx = (struct mg_lwip_tcp_write_ctx *) arg;
|
||||
struct mg_connection *nc = ctx->nc;
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
struct tcp_pcb *tpcb = cs->pcb.tcp;
|
||||
size_t len = MIN(tpcb->mss, MIN(ctx->len, tpcb->snd_buf));
|
||||
size_t unsent, unacked;
|
||||
if (len == 0) {
|
||||
DBG(("%p no buf avail %u %u %p %p", tpcb, tpcb->snd_buf, tpcb->snd_queuelen,
|
||||
tpcb->unsent, tpcb->unacked));
|
||||
tcpip_callback(tcp_output_tcpip, tpcb);
|
||||
ctx->ret = 0;
|
||||
return;
|
||||
}
|
||||
unsent = (tpcb->unsent != NULL ? tpcb->unsent->len : 0);
|
||||
unacked = (tpcb->unacked != NULL ? tpcb->unacked->len : 0);
|
||||
/*
|
||||
* On ESP8266 we only allow one TCP segment in flight at any given time.
|
||||
* This may increase latency and reduce efficiency of tcp windowing,
|
||||
* but memory is scarce and precious on that platform so we do this to
|
||||
* reduce footprint.
|
||||
*/
|
||||
#if CS_PLATFORM == CS_P_ESP8266
|
||||
if (unacked > 0) {
|
||||
ctx->ret = 0;
|
||||
return;
|
||||
}
|
||||
len = MIN(len, (TCP_MSS - unsent));
|
||||
#endif
|
||||
cs->err = tcp_write(tpcb, ctx->data, len, TCP_WRITE_FLAG_COPY);
|
||||
unsent = (tpcb->unsent != NULL ? tpcb->unsent->len : 0);
|
||||
unacked = (tpcb->unacked != NULL ? tpcb->unacked->len : 0);
|
||||
DBG(("%p tcp_write %u = %d, %u %u", tpcb, len, cs->err, unsent, unacked));
|
||||
if (cs->err != ERR_OK) {
|
||||
/*
|
||||
* We ignore ERR_MEM because memory will be freed up when the data is sent
|
||||
* and we'll retry.
|
||||
*/
|
||||
ctx->ret = (cs->err == ERR_MEM ? 0 : -1);
|
||||
return;
|
||||
}
|
||||
ctx->ret = len;
|
||||
}
|
||||
|
||||
static int mg_lwip_tcp_write(struct mg_connection *nc, const void *data,
|
||||
uint16_t len) {
|
||||
struct mg_lwip_tcp_write_ctx ctx = {.nc = nc, .data = data, .len = len};
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
struct tcp_pcb *tpcb = cs->pcb.tcp;
|
||||
if (tpcb == NULL) {
|
||||
return -1;
|
||||
}
|
||||
tcpip_callback(mg_lwip_tcp_write_tcpip, &ctx);
|
||||
return ctx.ret;
|
||||
}
|
||||
|
||||
struct udp_sendto_ctx {
|
||||
struct udp_pcb *upcb;
|
||||
struct pbuf *p;
|
||||
ip_addr_t *ip;
|
||||
uint16_t port;
|
||||
int ret;
|
||||
};
|
||||
|
||||
static void udp_sendto_tcpip(void *arg) {
|
||||
struct udp_sendto_ctx *ctx = (struct udp_sendto_ctx *) arg;
|
||||
ctx->ret = udp_sendto(ctx->upcb, ctx->p, ctx->ip, ctx->port);
|
||||
}
|
||||
|
||||
static int mg_lwip_udp_send(struct mg_connection *nc, const void *data,
|
||||
uint16_t len) {
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
if (cs->pcb.udp == NULL) {
|
||||
/*
|
||||
* In case of UDP, this usually means, what
|
||||
* async DNS resolve is still in progress and connection
|
||||
* is not ready yet
|
||||
*/
|
||||
DBG(("%p socket is not connected", nc));
|
||||
return -1;
|
||||
}
|
||||
struct udp_pcb *upcb = cs->pcb.udp;
|
||||
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
|
||||
#if defined(LWIP_IPV4) && LWIP_IPV4 && defined(LWIP_IPV6) && LWIP_IPV6
|
||||
ip_addr_t ip = {.u_addr.ip4.addr = nc->sa.sin.sin_addr.s_addr, .type = 0};
|
||||
#else
|
||||
ip_addr_t ip = {.addr = nc->sa.sin.sin_addr.s_addr};
|
||||
#endif
|
||||
u16_t port = ntohs(nc->sa.sin.sin_port);
|
||||
if (p == NULL) {
|
||||
DBG(("OOM"));
|
||||
return 0;
|
||||
}
|
||||
memcpy(p->payload, data, len);
|
||||
struct udp_sendto_ctx ctx = {.upcb = upcb, .p = p, .ip = &ip, .port = port};
|
||||
tcpip_callback(udp_sendto_tcpip, &ctx);
|
||||
cs->err = ctx.ret;
|
||||
pbuf_free(p);
|
||||
return (cs->err == ERR_OK ? len : -1);
|
||||
}
|
||||
|
||||
static void mg_lwip_send_more(struct mg_connection *nc) {
|
||||
int num_sent = 0;
|
||||
if (nc->sock == INVALID_SOCKET) return;
|
||||
if (nc->flags & MG_F_UDP) {
|
||||
num_sent = mg_lwip_udp_send(nc, nc->send_mbuf.buf, nc->send_mbuf.len);
|
||||
DBG(("%p mg_lwip_udp_send %u = %d", nc, nc->send_mbuf.len, num_sent));
|
||||
} else {
|
||||
num_sent = mg_lwip_tcp_write(nc, nc->send_mbuf.buf, nc->send_mbuf.len);
|
||||
DBG(("%p mg_lwip_tcp_write %u = %d", nc, nc->send_mbuf.len, num_sent));
|
||||
}
|
||||
if (num_sent == 0) return;
|
||||
if (num_sent > 0) {
|
||||
mg_if_sent_cb(nc, num_sent);
|
||||
} else {
|
||||
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
|
||||
}
|
||||
}
|
||||
|
||||
void mg_lwip_if_tcp_send(struct mg_connection *nc, const void *buf,
|
||||
size_t len) {
|
||||
mbuf_append(&nc->send_mbuf, buf, len);
|
||||
mg_lwip_mgr_schedule_poll(nc->mgr);
|
||||
}
|
||||
|
||||
void mg_lwip_if_udp_send(struct mg_connection *nc, const void *buf,
|
||||
size_t len) {
|
||||
mbuf_append(&nc->send_mbuf, buf, len);
|
||||
mg_lwip_mgr_schedule_poll(nc->mgr);
|
||||
}
|
||||
|
||||
struct tcp_recved_ctx {
|
||||
struct tcp_pcb *tpcb;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
void tcp_recved_tcpip(void *arg) {
|
||||
struct tcp_recved_ctx *ctx = (struct tcp_recved_ctx *) arg;
|
||||
tcp_recved(ctx->tpcb, ctx->len);
|
||||
}
|
||||
|
||||
void mg_lwip_if_recved(struct mg_connection *nc, size_t len) {
|
||||
if (nc->flags & MG_F_UDP) return;
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
if (nc->sock == INVALID_SOCKET || cs->pcb.tcp == NULL) {
|
||||
DBG(("%p invalid socket", nc));
|
||||
return;
|
||||
}
|
||||
DBG(("%p %p %u %u", nc, cs->pcb.tcp, len,
|
||||
(cs->rx_chain ? cs->rx_chain->tot_len : 0)));
|
||||
struct tcp_recved_ctx ctx = {.tpcb = cs->pcb.tcp, .len = len};
|
||||
#if MG_ENABLE_SSL
|
||||
if (!(nc->flags & MG_F_SSL)) {
|
||||
tcpip_callback(tcp_recved_tcpip, &ctx);
|
||||
} else {
|
||||
/* Currently SSL acknowledges data immediately.
|
||||
* TODO(rojer): Find a way to propagate mg_lwip_if_recved. */
|
||||
}
|
||||
#else
|
||||
tcpip_callback(tcp_recved_tcpip, &ctx);
|
||||
#endif
|
||||
mbuf_trim(&nc->recv_mbuf);
|
||||
}
|
||||
|
||||
int mg_lwip_if_create_conn(struct mg_connection *nc) {
|
||||
struct mg_lwip_conn_state *cs =
|
||||
(struct mg_lwip_conn_state *) MG_CALLOC(1, sizeof(*cs));
|
||||
if (cs == NULL) return 0;
|
||||
cs->nc = nc;
|
||||
nc->sock = (intptr_t) cs;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void udp_remove_tcpip(void *arg) {
|
||||
udp_remove((struct udp_pcb *) arg);
|
||||
}
|
||||
|
||||
void mg_lwip_if_destroy_conn(struct mg_connection *nc) {
|
||||
if (nc->sock == INVALID_SOCKET) return;
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
if (!(nc->flags & MG_F_UDP)) {
|
||||
struct tcp_pcb *tpcb = cs->pcb.tcp;
|
||||
if (tpcb != NULL) {
|
||||
tcp_arg(tpcb, NULL);
|
||||
DBG(("%p tcp_close %p", nc, tpcb));
|
||||
tcp_arg(tpcb, NULL);
|
||||
tcpip_callback(tcp_close_tcpip, tpcb);
|
||||
}
|
||||
while (cs->rx_chain != NULL) {
|
||||
struct pbuf *seg = cs->rx_chain;
|
||||
cs->rx_chain = pbuf_dechain(cs->rx_chain);
|
||||
pbuf_free(seg);
|
||||
}
|
||||
memset(cs, 0, sizeof(*cs));
|
||||
MG_FREE(cs);
|
||||
} else if (nc->listener == NULL) {
|
||||
/* Only close outgoing UDP pcb or listeners. */
|
||||
struct udp_pcb *upcb = cs->pcb.udp;
|
||||
if (upcb != NULL) {
|
||||
DBG(("%p udp_remove %p", nc, upcb));
|
||||
tcpip_callback(udp_remove_tcpip, upcb);
|
||||
}
|
||||
memset(cs, 0, sizeof(*cs));
|
||||
MG_FREE(cs);
|
||||
}
|
||||
nc->sock = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
void mg_lwip_if_get_conn_addr(struct mg_connection *nc, int remote,
|
||||
union socket_address *sa) {
|
||||
memset(sa, 0, sizeof(*sa));
|
||||
if (nc == NULL || nc->sock == INVALID_SOCKET) return;
|
||||
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
|
||||
if (nc->flags & MG_F_UDP) {
|
||||
struct udp_pcb *upcb = cs->pcb.udp;
|
||||
if (remote) {
|
||||
memcpy(sa, &nc->sa, sizeof(*sa));
|
||||
} else if (upcb != NULL) {
|
||||
sa->sin.sin_port = htons(upcb->local_port);
|
||||
SET_ADDR(sa, &upcb->local_ip);
|
||||
}
|
||||
} else {
|
||||
struct tcp_pcb *tpcb = cs->pcb.tcp;
|
||||
if (remote) {
|
||||
memcpy(sa, &nc->sa, sizeof(*sa));
|
||||
} else if (tpcb != NULL) {
|
||||
sa->sin.sin_port = htons(tpcb->local_port);
|
||||
SET_ADDR(sa, &tpcb->local_ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mg_lwip_if_sock_set(struct mg_connection *nc, sock_t sock) {
|
||||
nc->sock = sock;
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#define MG_LWIP_IFACE_VTABLE \
|
||||
{ \
|
||||
mg_lwip_if_init, \
|
||||
mg_lwip_if_free, \
|
||||
mg_lwip_if_add_conn, \
|
||||
mg_lwip_if_remove_conn, \
|
||||
mg_lwip_if_poll, \
|
||||
mg_lwip_if_listen_tcp, \
|
||||
mg_lwip_if_listen_udp, \
|
||||
mg_lwip_if_connect_tcp, \
|
||||
mg_lwip_if_connect_udp, \
|
||||
mg_lwip_if_tcp_send, \
|
||||
mg_lwip_if_udp_send, \
|
||||
mg_lwip_if_recved, \
|
||||
mg_lwip_if_create_conn, \
|
||||
mg_lwip_if_destroy_conn, \
|
||||
mg_lwip_if_sock_set, \
|
||||
mg_lwip_if_get_conn_addr, \
|
||||
}
|
||||
/* clang-format on */
|
||||
|
||||
const struct mg_iface_vtable mg_lwip_iface_vtable = MG_LWIP_IFACE_VTABLE;
|
||||
#if MG_NET_IF == MG_NET_IF_LWIP_LOW_LEVEL
|
||||
const struct mg_iface_vtable mg_default_iface_vtable = MG_LWIP_IFACE_VTABLE;
|
||||
#endif
|
||||
|
||||
#endif /* MG_ENABLE_NET_IF_LWIP_LOW_LEVEL */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user