mirror of
https://github.com/SuperBFG7/ympd
synced 2024-12-27 11:20:26 +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)
|
project (mympd C)
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR "2")
|
set(CPACK_PACKAGE_VERSION_MAJOR "2")
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR "2")
|
set(CPACK_PACKAGE_VERSION_MINOR "3")
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH "0")
|
set(CPACK_PACKAGE_VERSION_PATCH "0")
|
||||||
if(CMAKE_BUILD_TYPE MATCHES RELEASE)
|
if(CMAKE_BUILD_TYPE MATCHES RELEASE)
|
||||||
set(ASSETS_PATH "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}/htdocs")
|
set(ASSETS_PATH "${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}/htdocs")
|
||||||
else()
|
else()
|
||||||
set(ASSETS_PATH "${PROJECT_SOURCE_DIR}/htdocs")
|
set(ASSETS_PATH "${PROJECT_SOURCE_DIR}/htdocs")
|
||||||
|
set(DEBUG ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(WITH_IPV6 "enable IPv6 support" ON)
|
option(WITH_IPV6 "enable IPv6 support" ON)
|
||||||
@ -22,8 +23,9 @@ include_directories(${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR} ${LIBMPDCLIENT_I
|
|||||||
|
|
||||||
include(CheckCSourceCompiles)
|
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 "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -pedantic")
|
||||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb -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)
|
if(WITH_IPV6)
|
||||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS NS_ENABLE_IPV6)
|
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS NS_ENABLE_IPV6)
|
||||||
endif()
|
endif()
|
||||||
|
@ -30,4 +30,5 @@
|
|||||||
#define MYMPD_VERSION_PATCH ${CPACK_PACKAGE_VERSION_PATCH}
|
#define MYMPD_VERSION_PATCH ${CPACK_PACKAGE_VERSION_PATCH}
|
||||||
#define MYMPD_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}"
|
#define MYMPD_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}"
|
||||||
#define SRC_PATH "${ASSETS_PATH}"
|
#define SRC_PATH "${ASSETS_PATH}"
|
||||||
|
#cmakedefine DEBUG
|
||||||
#endif
|
#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