mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-25 12:04:47 +00:00
Compare commits
189
Commits
6.11
..
mongoose-os
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afcb4d9df7 | ||
|
|
44b15b76f7 | ||
|
|
a1fcbb0718 | ||
|
|
0c4d364cee | ||
|
|
def2f39724 | ||
|
|
311fdb8bac | ||
|
|
38f694d071 | ||
|
|
da1e5438bd | ||
|
|
e3a140c9a7 | ||
|
|
a350208f35 | ||
|
|
6fa305e36d | ||
|
|
edd38f6ccd | ||
|
|
abced77c24 | ||
|
|
4699e90e99 | ||
|
|
e9853be8f7 | ||
|
|
fd062b530c | ||
|
|
2fbfe61c37 | ||
|
|
70034b5873 | ||
|
|
d6c9d3c181 | ||
|
|
34d4fb8cf0 | ||
|
|
be64f81eee | ||
|
|
9fe1c93c9b | ||
|
|
a4b6d58b24 | ||
|
|
86f391c701 | ||
|
|
36de38bd11 | ||
|
|
a308872c88 | ||
|
|
a369160296 | ||
|
|
0a09b46c94 | ||
|
|
b0a1cd7b0d | ||
|
|
73a2b92278 | ||
|
|
c3bb5bd89e | ||
|
|
d22ff2fce7 | ||
|
|
fee2980d95 | ||
|
|
d6693ed360 | ||
|
|
4880069775 | ||
|
|
5d217a1262 | ||
|
|
f778d22eac | ||
|
|
3aa76dcaec | ||
|
|
4680573a6b | ||
|
|
95fcb261eb | ||
|
|
5867c67da2 | ||
|
|
80d74e9e34 | ||
|
|
43a0b500f5 | ||
|
|
3d53ed17fb | ||
|
|
4ea452307e | ||
|
|
e61f20f1ed | ||
|
|
ca11f5ab49 | ||
|
|
000d24d31a | ||
|
|
ef92f2e9c5 | ||
|
|
4e89eac8dd | ||
|
|
b015e33ea5 | ||
|
|
96e762d4a1 | ||
|
|
359060a151 | ||
|
|
af1aff7fbb | ||
|
|
517ef216c1 | ||
|
|
734c13cdf5 | ||
|
|
1bf3ad2426 | ||
|
|
884b9a4813 | ||
|
|
7153690016 | ||
|
|
f00b3a2b3a | ||
|
|
c2b5e4f3b8 | ||
|
|
bc15e9ce9a | ||
|
|
70dc6d8dc9 | ||
|
|
10b11b03a8 | ||
|
|
cb602f178c | ||
|
|
464113c5ae | ||
|
|
c34f6c54e7 | ||
|
|
8fb58ebbca | ||
|
|
dce60c6dbb | ||
|
|
f668d08804 | ||
|
|
c41a22195c | ||
|
|
900c05213b | ||
|
|
c5850e4b05 | ||
|
|
ff4649fe42 | ||
|
|
1a38e91042 | ||
|
|
b6196371bb | ||
|
|
d5beb7ba3f | ||
|
|
19acf23c49 | ||
|
|
5cd3291fec | ||
|
|
b3e0f780c3 | ||
|
|
2bdbfc27f6 | ||
|
|
3fc61a3edc | ||
|
|
12339bbf4c | ||
|
|
1fb9f922b0 | ||
|
|
b93bc02ab0 | ||
|
|
747e393a54 | ||
|
|
4e8660a21f | ||
|
|
3fe77fa9a6 | ||
|
|
b4fbaf7c13 | ||
|
|
9884241df8 | ||
|
|
63d7a4fa45 | ||
|
|
8f4b6c41a2 | ||
|
|
4493d65ec9 | ||
|
|
e5910da300 | ||
|
|
c277a1d878 | ||
|
|
7820ad3a59 | ||
|
|
23533b83a4 | ||
|
|
ab650ec5c9 | ||
|
|
8f36597048 | ||
|
|
d0213ee90a | ||
|
|
1e9fabe1ca | ||
|
|
148d3f0562 | ||
|
|
c3057df3f5 | ||
|
|
0b2e474d52 | ||
|
|
95a36b1759 | ||
|
|
86ffa3a3ea | ||
|
|
69e2b2985d | ||
|
|
c431904b56 | ||
|
|
c2a10601b9 | ||
|
|
e9a8e5468d | ||
|
|
22e602debb | ||
|
|
455cec67a5 | ||
|
|
e2dfac946d | ||
|
|
c198d2e5f1 | ||
|
|
9a70abef24 | ||
|
|
53e1c469a2 | ||
|
|
139c2061a8 | ||
|
|
15b361fbac | ||
|
|
3130e59244 | ||
|
|
93286836f9 | ||
|
|
91b57aa9a8 | ||
|
|
220231e647 | ||
|
|
c438bb0bc5 | ||
|
|
95afa323c0 | ||
|
|
bc56353a79 | ||
|
|
1ffccdb7b2 | ||
|
|
e79fe4b8f0 | ||
|
|
aaf1fc3a4a | ||
|
|
8b42353039 | ||
|
|
05c687e251 | ||
|
|
492b8f6950 | ||
|
|
8ccee82059 | ||
|
|
b99a94a652 | ||
|
|
41e5d7e471 | ||
|
|
1adea37c45 | ||
|
|
98f6c8aa4f | ||
|
|
341ae53e85 | ||
|
|
291fc024cd | ||
|
|
f63d833a33 | ||
|
|
ab035901f8 | ||
|
|
20f54059ad | ||
|
|
563c31303e | ||
|
|
421e099f2b | ||
|
|
955d4a3129 | ||
|
|
b84981ad03 | ||
|
|
777b8e94e2 | ||
|
|
6df642623a | ||
|
|
0a3e186f11 | ||
|
|
c2d83a9db0 | ||
|
|
f33d3a4e02 | ||
|
|
86b8a56b05 | ||
|
|
ac6ec15aed | ||
|
|
31632c6361 | ||
|
|
98c99279c3 | ||
|
|
cdb8d7b692 | ||
|
|
93ac3e19f0 | ||
|
|
6a51af9efe | ||
|
|
9d73b3470b | ||
|
|
1c8449cea6 | ||
|
|
3bbbd41196 | ||
|
|
339bbee0df | ||
|
|
9ba6eb716d | ||
|
|
d949c19c7e | ||
|
|
1299d6118f | ||
|
|
244ff92e78 | ||
|
|
53f34dea04 | ||
|
|
1f5c3fac31 | ||
|
|
7014258c8d | ||
|
|
1614e7ba8d | ||
|
|
43b5a4e735 | ||
|
|
43191db63e | ||
|
|
e89be2e944 | ||
|
|
c2fbff6d0e | ||
|
|
b8eca17c55 | ||
|
|
4650e491df | ||
|
|
3e33e57707 | ||
|
|
c80f4c5313 | ||
|
|
132ecbec2f | ||
|
|
0a90cab44a | ||
|
|
d16dbc197f | ||
|
|
127f27e375 | ||
|
|
6523cc4da0 | ||
|
|
2516da1c89 | ||
|
|
0ae2b82b60 | ||
|
|
dab526936f | ||
|
|
780077d118 | ||
|
|
ad8f1d88d4 | ||
|
|
a3c4a48ef7 | ||
|
|
84a11fe3b1 |
No files matched your search
@@ -0,0 +1,6 @@
|
||||
BasedOnStyle: Google
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
SpaceAfterCStyleCast: true
|
||||
PointerBindsToType: false
|
||||
DerivePointerBinding: false
|
||||
IncludeBlocks: Preserve
|
||||
@@ -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,5 +1,5 @@
|
||||
Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
||||
Copyright (c) 2013-2016 Cesanta Software Limited
|
||||
Copyright (c) 2004-2013 Sergey Lyubka
|
||||
Copyright (c) 2013-2020 Cesanta Software Limited
|
||||
All rights reserved
|
||||
|
||||
This software is dual-licensed: you can redistribute it and/or modify
|
||||
|
||||
@@ -2,67 +2,11 @@
|
||||
|
||||

|
||||
|
||||
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
|
||||
This branch is only for use by [Mongoose OS](https://github.com/cesanta/mongoose-os),
|
||||
for other projects please use the master branch.
|
||||
|
||||
# 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:
|
||||
|
||||

|
||||
|
||||
[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,12 +1,15 @@
|
||||
---
|
||||
title: "Memory Buffers"
|
||||
title: "mbuf.h"
|
||||
symbol_kind: "intro"
|
||||
decl_name: "mbuf.h"
|
||||
items:
|
||||
- { name: mbuf_append.md }
|
||||
- { name: mbuf_append_and_free.md }
|
||||
- { name: mbuf_clear.md }
|
||||
- { name: mbuf_free.md }
|
||||
- { name: mbuf_init.md }
|
||||
- { name: mbuf_insert.md }
|
||||
- { name: mbuf_move.md }
|
||||
- { name: mbuf_remove.md }
|
||||
- { name: mbuf_resize.md }
|
||||
- { name: mbuf_trim.md }
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: "mbuf_append_and_free()"
|
||||
decl_name: "mbuf_append_and_free"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
size_t mbuf_append_and_free(struct mbuf *, void *data, size_t data_size);
|
||||
---
|
||||
|
||||
Appends data to the Mbuf and frees it (data must be heap-allocated).
|
||||
|
||||
Returns the number of bytes appended or 0 if out of memory.
|
||||
data is freed irrespective of return value.
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: "mbuf_clear()"
|
||||
decl_name: "mbuf_clear"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
void mbuf_clear(struct mbuf *);
|
||||
---
|
||||
|
||||
Removes all the data from mbuf (if any).
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: "mbuf_move()"
|
||||
decl_name: "mbuf_move"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
void mbuf_move(struct mbuf *from, struct mbuf *to);
|
||||
---
|
||||
|
||||
Moves the state from one mbuf to the other.
|
||||
|
||||
@@ -30,7 +30,9 @@ The user-defined event handler will receive following extra events:
|
||||
- MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received the WebSocket
|
||||
handshake request. `ev_data` contains parsed HTTP request.
|
||||
- MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed the WebSocket
|
||||
handshake. `ev_data` is `NULL`.
|
||||
handshake. `ev_data` is a `struct http_message` containing the
|
||||
client's request (server mode) or server's response (client).
|
||||
In client mode handler can examine `resp_code`, which should be 101.
|
||||
- MG_EV_WEBSOCKET_FRAME: new WebSocket frame has arrived. `ev_data` is
|
||||
`struct websocket_message *`
|
||||
|
||||
|
||||
@@ -29,6 +29,12 @@ signature: |
|
||||
/* Headers */
|
||||
struct mg_str header_names[MG_MAX_HTTP_HEADERS];
|
||||
struct mg_str header_values[MG_MAX_HTTP_HEADERS];
|
||||
|
||||
/*
|
||||
* Value of the Content-Length header if present,
|
||||
* otherwise MG_HTTP_CONTENT_LENGTH_UNKNOWN.
|
||||
*/
|
||||
size_t content_length;
|
||||
};
|
||||
---
|
||||
|
||||
|
||||
@@ -9,6 +9,14 @@ signature: |
|
||||
struct mg_str data;
|
||||
int status; /* <0 on error */
|
||||
void *user_data;
|
||||
/*
|
||||
* User handler can indicate how much of the data was consumed
|
||||
* by setting this variable. By default, it is assumed that all
|
||||
* data has been consumed by the handler.
|
||||
* If not all data was consumed, user's handler will be invoked again later
|
||||
* with the remainder.
|
||||
*/
|
||||
size_t num_data_consumed;
|
||||
};
|
||||
---
|
||||
|
||||
|
||||
@@ -16,5 +16,5 @@ that can be, and must be, called from a different (non-IO) thread.
|
||||
`func` callback function will be called by the IO thread for each
|
||||
connection. When called, the event will be `MG_EV_POLL`, and a message will
|
||||
be passed as the `ev_data` pointer. Maximum message size is capped
|
||||
by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes.
|
||||
by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes by default.
|
||||
|
||||
@@ -3,7 +3,7 @@ title: "mg_mgr_free()"
|
||||
decl_name: "mg_mgr_free"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
void mg_mgr_free(struct mg_mgr *);
|
||||
void mg_mgr_free(struct mg_mgr *mgr);
|
||||
---
|
||||
|
||||
De-initialises Mongoose manager.
|
||||
|
||||
@@ -3,11 +3,11 @@ title: "mg_mgr_poll()"
|
||||
decl_name: "mg_mgr_poll"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
time_t mg_mgr_poll(struct mg_mgr *, int milli);
|
||||
int mg_mgr_poll(struct mg_mgr *mgr, int milli);
|
||||
---
|
||||
|
||||
This function performs the actual IO and must be called in a loop
|
||||
(an event loop). It returns the current timestamp.
|
||||
(an event loop). It returns number of user events generated (except POLLs).
|
||||
`milli` is the maximum number of milliseconds to sleep.
|
||||
`mg_mgr_poll()` checks all connections for IO readiness. If at least one
|
||||
of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
|
||||
|
||||
@@ -16,9 +16,6 @@ signature: |
|
||||
struct mbuf send_mbuf; /* Data scheduled for sending */
|
||||
time_t last_io_time; /* Timestamp of the last socket IO */
|
||||
double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */
|
||||
#if MG_ENABLE_SSL
|
||||
void *ssl_if_data; /* SSL library data. */
|
||||
#endif
|
||||
mg_event_handler_t proto_handler; /* Protocol-specific event handler */
|
||||
void *proto_data; /* Protocol-specific data */
|
||||
void (*proto_data_destructor)(void *proto_data);
|
||||
@@ -46,20 +43,30 @@ signature: |
|
||||
#define MG_F_WANT_READ (1 << 6) /* SSL specific */
|
||||
#define MG_F_WANT_WRITE (1 << 7) /* SSL specific */
|
||||
#define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket specific */
|
||||
#define MG_F_RECV_AND_CLOSE (1 << 9) /* Drain rx and close the connection. */
|
||||
|
||||
/* Flags that are settable by user */
|
||||
#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
|
||||
#define MG_F_CLOSE_IMMEDIATELY (1 << 11) /* Disconnect */
|
||||
#define MG_F_WEBSOCKET_NO_DEFRAG (1 << 12) /* Websocket specific */
|
||||
#define MG_F_DELETE_CHUNK (1 << 13) /* HTTP specific */
|
||||
|
||||
/* Flags for protocol handlers */
|
||||
#define MG_F_PROTO_1 (1 << 12)
|
||||
#define MG_F_PROTO_2 (1 << 13)
|
||||
#define MG_F_ENABLE_BROADCAST (1 << 14) /* Allow broadcast address usage */
|
||||
|
||||
#define MG_F_USER_1 (1 << 20) /* Flags left for application */
|
||||
/* Flags left for application */
|
||||
#define MG_F_USER_1 (1 << 20)
|
||||
#define MG_F_USER_2 (1 << 21)
|
||||
#define MG_F_USER_3 (1 << 22)
|
||||
#define MG_F_USER_4 (1 << 23)
|
||||
#define MG_F_USER_5 (1 << 24)
|
||||
#define MG_F_USER_6 (1 << 25)
|
||||
|
||||
#if MG_ENABLE_SSL
|
||||
void *ssl_if_data; /* SSL library data. */
|
||||
#else
|
||||
void *unused_ssl_if_data; /* To keep the size of the structure the same. */
|
||||
#endif
|
||||
};
|
||||
---
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ signature: |
|
||||
#endif
|
||||
void *user_data; /* User data */
|
||||
int num_ifaces;
|
||||
int num_calls;
|
||||
struct mg_iface **ifaces; /* network interfaces */
|
||||
const char *nameserver; /* DNS server to use */
|
||||
};
|
||||
|
||||
@@ -6,8 +6,5 @@ signature: |
|
||||
struct mg_str mg_url_encode(const struct mg_str src);
|
||||
---
|
||||
|
||||
URL-escape the specified string.
|
||||
All non-printable characters are escaped, plus `._-$,;~()/`.
|
||||
Input need not be NUL-terminated, but the returned string is.
|
||||
Returned string is heap-allocated and must be free()'d.
|
||||
Same as `mg_url_encode_opt(src, "._-$,;~()/", 0)`.
|
||||
|
||||
@@ -7,7 +7,7 @@ flags are meant to be set only by the user event handler to tell Mongoose how to
|
||||
behave. Below is a list of connection flags that are meant to be set by event
|
||||
handlers:
|
||||
|
||||
* `MG_F_FINISHED_SENDING_DATA` tells Mongoose that all data has been appended
|
||||
* `MG_F_SEND_AND_CLOSE` tells Mongoose that all data has been appended
|
||||
to the `send_mbuf`. As soon as Mongoose sends it to the socket, the
|
||||
connection will be closed.
|
||||
* `MG_F_BUFFER_BUT_DONT_SEND` tells Mongoose to append data to the `send_mbuf`
|
||||
|
||||
@@ -98,7 +98,8 @@ bool bm222_get_data(struct bm222_ctx *ctx) {
|
||||
s->y = v[3];
|
||||
s->z = v[5];
|
||||
if (d > max_d) max_d = d;
|
||||
LOG(LL_VERBOSE_DEBUG, ("dx %d dy %d dz %d d %d", dx, dy, dz, d));
|
||||
LOG(LL_VERBOSE_DEBUG,
|
||||
("dx %d dy %d dz %d d %d", (int) dx, (int) dy, (int) dz, (int) d));
|
||||
}
|
||||
}
|
||||
return (overflow ? bm222_fifo_init(ctx) : true); /* Clear the ovf flag. */
|
||||
|
||||
+84
-14
@@ -1,11 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* Copyright (c) 2014-2018 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the ""License"");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an ""AS IS"" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_CS_DBG_H_
|
||||
#define CS_COMMON_CS_DBG_H_
|
||||
|
||||
#include "common/platform.h"
|
||||
|
||||
#if CS_ENABLE_STDIO
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
@@ -14,6 +28,10 @@
|
||||
#define CS_ENABLE_DEBUG 0
|
||||
#endif
|
||||
|
||||
#ifndef CS_LOG_PREFIX_LEN
|
||||
#define CS_LOG_PREFIX_LEN 24
|
||||
#endif
|
||||
|
||||
#ifndef CS_LOG_ENABLE_TS_DIFF
|
||||
#define CS_LOG_ENABLE_TS_DIFF 0
|
||||
#endif
|
||||
@@ -22,6 +40,9 @@
|
||||
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,
|
||||
@@ -34,29 +55,78 @@ enum cs_log_level {
|
||||
_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);
|
||||
|
||||
/*
|
||||
* A comma-separated set of prefix=level.
|
||||
* prefix is matched against the log prefix exactly as printed, including line
|
||||
* number, but partial match is ok. Check stops on first matching entry.
|
||||
* If nothing matches, default level is used.
|
||||
*
|
||||
* Examples:
|
||||
* main.c:=4 - everything from main C at verbose debug level.
|
||||
* mongoose.c=1,mjs.c=1,=4 - everything at verbose debug except mg_* and mjs_*
|
||||
*
|
||||
*/
|
||||
void cs_log_set_file_level(const char *file_level);
|
||||
|
||||
/*
|
||||
* Helper function which prints message prefix with the given `level`.
|
||||
* If message should be printed (according 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 *fname, int line);
|
||||
|
||||
extern enum cs_log_level cs_log_level;
|
||||
|
||||
#if CS_ENABLE_STDIO
|
||||
|
||||
/*
|
||||
* Set file to write logs into. If `NULL`, logs go to `stderr`.
|
||||
*/
|
||||
void cs_log_set_file(FILE *file);
|
||||
|
||||
extern enum cs_log_level cs_log_threshold;
|
||||
void cs_log_print_prefix(const char *func);
|
||||
void cs_log_printf(const char *fmt, ...);
|
||||
/*
|
||||
* Prints log to the current log file, appends "\n" in the end and flushes the
|
||||
* stream.
|
||||
*/
|
||||
void cs_log_printf(const char *fmt, ...) PRINTF_LIKE(1, 2);
|
||||
|
||||
#define LOG(l, x) \
|
||||
if (cs_log_threshold >= l) { \
|
||||
cs_log_print_prefix(__func__); \
|
||||
cs_log_printf x; \
|
||||
}
|
||||
#if CS_ENABLE_STDIO
|
||||
|
||||
/*
|
||||
* 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, __FILE__, __LINE__)) { \
|
||||
cs_log_printf x; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define LOG(l, x) ((void) l)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef CS_NDEBUG
|
||||
|
||||
#define DBG(x) \
|
||||
if (cs_log_threshold >= LL_VERBOSE_DEBUG) { \
|
||||
cs_log_print_prefix(__func__); \
|
||||
cs_log_printf x; \
|
||||
}
|
||||
/*
|
||||
* Shortcut for `LOG(LL_VERBOSE_DEBUG, (...))`
|
||||
*/
|
||||
#define DBG(x) LOG(LL_VERBOSE_DEBUG, x)
|
||||
|
||||
#else /* NDEBUG */
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
#define BM222_ADDR 0x18
|
||||
#define TMP006_ADDR 0x41
|
||||
|
||||
void fs_slfs_set_new_file_size(const char *name, size_t size);
|
||||
void fs_slfs_set_file_size(const char *name, size_t size);
|
||||
|
||||
static const char *upload_form =
|
||||
"\
|
||||
@@ -70,7 +70,7 @@ static struct mg_str upload_fname(struct mg_connection *nc,
|
||||
if (nc->user_data != NULL) {
|
||||
intptr_t cl = (intptr_t) nc->user_data;
|
||||
if (cl >= 0) {
|
||||
fs_slfs_set_new_file_size(fn + 3, cl);
|
||||
fs_slfs_set_file_size(fn + 3, cl);
|
||||
}
|
||||
}
|
||||
lfn.len = fname.len + 4;
|
||||
|
||||
@@ -25,7 +25,7 @@ void SimpleLinkWlanEventHandler(SlWlanEvent_t *e) {
|
||||
LOG(LL_INFO, ("WiFi: station disconnected"));
|
||||
break;
|
||||
default:
|
||||
LOG(LL_INFO, ("WiFi: event %d", e->Event));
|
||||
LOG(LL_INFO, ("WiFi: event %d", (int) e->Event));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *e) {
|
||||
} else if (e->Event == SL_NETAPP_IP_LEASED_EVENT) {
|
||||
LOG(LL_INFO, ("IP leased"));
|
||||
} else {
|
||||
LOG(LL_INFO, ("NetApp event %d", e->Event));
|
||||
LOG(LL_INFO, ("NetApp event %d", (int) e->Event));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,11 +58,11 @@ static int check_pass(const char *user, const char *pass) {
|
||||
* or NULL if not found.
|
||||
*/
|
||||
static struct session *get_session(struct http_message *hm) {
|
||||
struct mg_str *cookie_header = mg_get_http_header(hm, "cookie");
|
||||
if (cookie_header == NULL) goto clean;
|
||||
char ssid_buf[21];
|
||||
char *ssid = ssid_buf;
|
||||
struct session *ret = NULL;
|
||||
struct mg_str *cookie_header = mg_get_http_header(hm, "cookie");
|
||||
if (cookie_header == NULL) goto clean;
|
||||
if (!mg_http_parse_header2(cookie_header, SESSION_COOKIE_NAME, &ssid,
|
||||
sizeof(ssid_buf))) {
|
||||
goto clean;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
PROG = http_proxy_client
|
||||
#SSL_LIB=openssl
|
||||
CFLAGS_EXTRA = -DMG_ENABLE_CALLBACK_USERDATA=1
|
||||
include ../examples.mk
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* This program fetches HTTP URLs.
|
||||
*/
|
||||
|
||||
#define MG_ENABLE_CALLBACK_USERDATA 1
|
||||
#include "mongoose.h"
|
||||
|
||||
static int s_exit_flag = 0;
|
||||
static int s_show_headers = 0;
|
||||
|
||||
static void ev_handler(struct mg_connection *c, int ev, void *ev_data,
|
||||
void *userdata) {
|
||||
struct http_message *hm = (struct http_message *) ev_data;
|
||||
|
||||
switch (ev) {
|
||||
case MG_EV_CONNECT:
|
||||
if (*(int *) ev_data != 0) {
|
||||
fprintf(stderr, "connect() failed: %s\n", strerror(*(int *) ev_data));
|
||||
s_exit_flag = 1;
|
||||
} else {
|
||||
// Stage 2. Connection to the HTTP proxy is established.
|
||||
// Write CONNECT request, and turn this connection to HTTP.
|
||||
// NOTE: target URL is passed to us as userdata.
|
||||
unsigned port = 80;
|
||||
struct mg_str scheme, host;
|
||||
mg_parse_uri(mg_mk_str((char *) userdata), &scheme, NULL, &host, &port,
|
||||
NULL, NULL, NULL);
|
||||
if (port == 0) port = (scheme.len == 5) ? 443 : 80;
|
||||
mg_printf(c, "CONNECT %.*s:%u HTTP/1.1\r\n\r\n", (int) host.len, host.p,
|
||||
port);
|
||||
// Now set the flag and wait for the connection establishment
|
||||
c->flags |= MG_F_USER_1;
|
||||
}
|
||||
break;
|
||||
case MG_EV_RECV:
|
||||
// Stage 3. Check if proxy replied. Here, we don't parse the reply
|
||||
// for simplicity. Assume success, and write HTTP request.
|
||||
if (c->flags & MG_F_USER_1) {
|
||||
struct mg_str host, path;
|
||||
c->flags &= ~MG_F_USER_1;
|
||||
mg_parse_uri(mg_mk_str((char *) userdata), NULL, NULL, &host, NULL,
|
||||
&path, NULL, NULL);
|
||||
if (path.len == 0) path = mg_mk_str("/");
|
||||
mg_printf(c, "GET %.*s HTTP/1.0\r\nHost: %.*s\r\n\r\n", (int) path.len,
|
||||
path.p, (int) host.len, host.p);
|
||||
mg_set_protocol_http_websocket(c);
|
||||
}
|
||||
break;
|
||||
case MG_EV_HTTP_REPLY:
|
||||
c->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||
if (s_show_headers) {
|
||||
fwrite(hm->message.p, 1, hm->message.len, stdout);
|
||||
} else {
|
||||
fwrite(hm->body.p, 1, hm->body.len, stdout);
|
||||
}
|
||||
putchar('\n');
|
||||
s_exit_flag = 1;
|
||||
break;
|
||||
case MG_EV_CLOSE:
|
||||
if (s_exit_flag == 0) {
|
||||
printf("Server closed connection\n");
|
||||
s_exit_flag = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct mg_mgr mgr;
|
||||
int i;
|
||||
|
||||
mg_mgr_init(&mgr, NULL);
|
||||
|
||||
/* Process command line arguments */
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--show-headers") == 0) {
|
||||
s_show_headers = 1;
|
||||
} else if (strcmp(argv[i], "--hexdump") == 0 && i + 1 < argc) {
|
||||
mgr.hexdump_file = argv[++i];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i + 2 != argc) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s [--hexdump <file>] "
|
||||
"[--show-headers] PROXY_HOST:PROXY_PORT URL\n",
|
||||
argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Stage 1. Connect to the HTTP proxy as to a plain TCP server.
|
||||
// Pass URL as a callback argument
|
||||
mg_connect(&mgr, argv[i], ev_handler, argv[i + 1]);
|
||||
|
||||
while (s_exit_flag == 0) {
|
||||
mg_mgr_poll(&mgr, 1000);
|
||||
}
|
||||
mg_mgr_free(&mgr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -14,7 +14,6 @@ static int s_done = 0;
|
||||
static int s_is_connected = 0;
|
||||
|
||||
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
||||
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
||||
(void) nc;
|
||||
|
||||
switch (ev) {
|
||||
@@ -26,8 +25,14 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
||||
break;
|
||||
}
|
||||
case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
|
||||
printf("-- Connected\n");
|
||||
s_is_connected = 1;
|
||||
struct http_message *hm = (struct http_message *) ev_data;
|
||||
if (hm->resp_code == 101) {
|
||||
printf("-- Connected\n");
|
||||
s_is_connected = 1;
|
||||
} else {
|
||||
printf("-- Connection failed! HTTP code %d\n", hm->resp_code);
|
||||
/* Connection will be closed after this. */
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MG_EV_POLL: {
|
||||
@@ -66,6 +71,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
||||
break;
|
||||
}
|
||||
case MG_EV_WEBSOCKET_FRAME: {
|
||||
struct websocket_message *wm = (struct websocket_message *) ev_data;
|
||||
printf("%.*s\n", (int) wm->size, wm->data);
|
||||
break;
|
||||
}
|
||||
|
||||
+2244
-2106
File diff suppressed because it is too large.
Load diff
+456
-347
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,6 @@
|
||||
BasedOnStyle: Google
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
SpaceAfterCStyleCast: true
|
||||
PointerBindsToType: false
|
||||
DerivePointerBinding: false
|
||||
IncludeBlocks: Preserve
|
||||
@@ -1 +0,0 @@
|
||||
exclude_files=sha1\.c
|
||||
@@ -0,0 +1,191 @@
|
||||
|
||||
#ifndef EXCLUDE_COMMON
|
||||
|
||||
#include "common/cs_base64.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "common/cs_dbg.h"
|
||||
|
||||
/* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ */
|
||||
|
||||
#define NUM_UPPERCASES ('Z' - 'A' + 1)
|
||||
#define NUM_LETTERS (NUM_UPPERCASES * 2)
|
||||
#define NUM_DIGITS ('9' - '0' + 1)
|
||||
|
||||
/*
|
||||
* Emit a base64 code char.
|
||||
*
|
||||
* Doesn't use memory, thus it's safe to use to safely dump memory in crashdumps
|
||||
*/
|
||||
static void cs_base64_emit_code(struct cs_base64_ctx *ctx, int v) {
|
||||
if (v < NUM_UPPERCASES) {
|
||||
ctx->b64_putc(v + 'A', ctx->user_data);
|
||||
} else if (v < (NUM_LETTERS)) {
|
||||
ctx->b64_putc(v - NUM_UPPERCASES + 'a', ctx->user_data);
|
||||
} else if (v < (NUM_LETTERS + NUM_DIGITS)) {
|
||||
ctx->b64_putc(v - NUM_LETTERS + '0', ctx->user_data);
|
||||
} else {
|
||||
ctx->b64_putc(v - NUM_LETTERS - NUM_DIGITS == 0 ? '+' : '/',
|
||||
ctx->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void cs_base64_emit_chunk(struct cs_base64_ctx *ctx) {
|
||||
int a, b, c;
|
||||
|
||||
a = ctx->chunk[0];
|
||||
b = ctx->chunk[1];
|
||||
c = ctx->chunk[2];
|
||||
|
||||
cs_base64_emit_code(ctx, a >> 2);
|
||||
cs_base64_emit_code(ctx, ((a & 3) << 4) | (b >> 4));
|
||||
if (ctx->chunk_size > 1) {
|
||||
cs_base64_emit_code(ctx, (b & 15) << 2 | (c >> 6));
|
||||
}
|
||||
if (ctx->chunk_size > 2) {
|
||||
cs_base64_emit_code(ctx, c & 63);
|
||||
}
|
||||
}
|
||||
|
||||
void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t b64_putc,
|
||||
void *user_data) {
|
||||
ctx->chunk_size = 0;
|
||||
ctx->b64_putc = b64_putc;
|
||||
ctx->user_data = user_data;
|
||||
}
|
||||
|
||||
void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len) {
|
||||
const unsigned char *src = (const unsigned char *) str;
|
||||
size_t i;
|
||||
for (i = 0; i < len; i++) {
|
||||
ctx->chunk[ctx->chunk_size++] = src[i];
|
||||
if (ctx->chunk_size == 3) {
|
||||
cs_base64_emit_chunk(ctx);
|
||||
ctx->chunk_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cs_base64_finish(struct cs_base64_ctx *ctx) {
|
||||
if (ctx->chunk_size > 0) {
|
||||
int i;
|
||||
memset(&ctx->chunk[ctx->chunk_size], 0, 3 - ctx->chunk_size);
|
||||
cs_base64_emit_chunk(ctx);
|
||||
for (i = 0; i < (3 - ctx->chunk_size); i++) {
|
||||
ctx->b64_putc('=', ctx->user_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define BASE64_ENCODE_BODY \
|
||||
static const char *b64 = \
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; \
|
||||
int i, j, a, b, c; \
|
||||
\
|
||||
for (i = j = 0; i < src_len; i += 3) { \
|
||||
a = src[i]; \
|
||||
b = i + 1 >= src_len ? 0 : src[i + 1]; \
|
||||
c = i + 2 >= src_len ? 0 : src[i + 2]; \
|
||||
\
|
||||
BASE64_OUT(b64[a >> 2]); \
|
||||
BASE64_OUT(b64[((a & 3) << 4) | (b >> 4)]); \
|
||||
if (i + 1 < src_len) { \
|
||||
BASE64_OUT(b64[(b & 15) << 2 | (c >> 6)]); \
|
||||
} \
|
||||
if (i + 2 < src_len) { \
|
||||
BASE64_OUT(b64[c & 63]); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
while (j % 4 != 0) { \
|
||||
BASE64_OUT('='); \
|
||||
} \
|
||||
|
||||
#define BASE64_OUT(ch) \
|
||||
do { \
|
||||
dst[j++] = (ch); \
|
||||
} while (0)
|
||||
|
||||
void cs_base64_encode(const unsigned char *src, int src_len, char *dst, int *enc_len) {
|
||||
BASE64_ENCODE_BODY;
|
||||
if (enc_len != NULL) *enc_len = j;
|
||||
}
|
||||
|
||||
#undef BASE64_OUT
|
||||
|
||||
#if CS_ENABLE_STDIO
|
||||
#define BASE64_OUT(ch) \
|
||||
do { \
|
||||
fprintf(f, "%c", (ch)); \
|
||||
j++; \
|
||||
} while (0)
|
||||
|
||||
void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len) {
|
||||
BASE64_ENCODE_BODY;
|
||||
}
|
||||
|
||||
#undef BASE64_OUT
|
||||
#endif /* CS_ENABLE_STDIO */
|
||||
|
||||
/* Convert one byte of encoded base64 input stream to 6-bit chunk */
|
||||
static unsigned char from_b64(unsigned char ch) {
|
||||
/* Inverse lookup map */
|
||||
static const unsigned char tab[128] = {
|
||||
255, 255, 255, 255,
|
||||
255, 255, 255, 255, /* 0 */
|
||||
255, 255, 255, 255,
|
||||
255, 255, 255, 255, /* 8 */
|
||||
255, 255, 255, 255,
|
||||
255, 255, 255, 255, /* 16 */
|
||||
255, 255, 255, 255,
|
||||
255, 255, 255, 255, /* 24 */
|
||||
255, 255, 255, 255,
|
||||
255, 255, 255, 255, /* 32 */
|
||||
255, 255, 255, 62,
|
||||
255, 255, 255, 63, /* 40 */
|
||||
52, 53, 54, 55,
|
||||
56, 57, 58, 59, /* 48 */
|
||||
60, 61, 255, 255,
|
||||
255, 200, 255, 255, /* 56 '=' is 200, on index 61 */
|
||||
255, 0, 1, 2,
|
||||
3, 4, 5, 6, /* 64 */
|
||||
7, 8, 9, 10,
|
||||
11, 12, 13, 14, /* 72 */
|
||||
15, 16, 17, 18,
|
||||
19, 20, 21, 22, /* 80 */
|
||||
23, 24, 25, 255,
|
||||
255, 255, 255, 255, /* 88 */
|
||||
255, 26, 27, 28,
|
||||
29, 30, 31, 32, /* 96 */
|
||||
33, 34, 35, 36,
|
||||
37, 38, 39, 40, /* 104 */
|
||||
41, 42, 43, 44,
|
||||
45, 46, 47, 48, /* 112 */
|
||||
49, 50, 51, 255,
|
||||
255, 255, 255, 255, /* 120 */
|
||||
};
|
||||
return tab[ch & 127];
|
||||
}
|
||||
|
||||
int cs_base64_decode(const unsigned char *s, int len, char *dst, int *dec_len) {
|
||||
unsigned char a, b, c, d;
|
||||
int orig_len = len;
|
||||
char *orig_dst = dst;
|
||||
while (len >= 4 && (a = from_b64(s[0])) != 255 &&
|
||||
(b = from_b64(s[1])) != 255 && (c = from_b64(s[2])) != 255 &&
|
||||
(d = from_b64(s[3])) != 255) {
|
||||
s += 4;
|
||||
len -= 4;
|
||||
if (a == 200 || b == 200) break; /* '=' can't be there */
|
||||
*dst++ = a << 2 | b >> 4;
|
||||
if (c == 200) break;
|
||||
*dst++ = b << 4 | c >> 2;
|
||||
if (d == 200) break;
|
||||
*dst++ = c << 6 | d;
|
||||
}
|
||||
if (dec_len != NULL) *dec_len = (dst - orig_dst);
|
||||
return orig_len - len;
|
||||
}
|
||||
|
||||
#endif /* EXCLUDE_COMMON */
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
#ifndef CS_COMMON_CS_BASE64_H_
|
||||
#define CS_COMMON_CS_BASE64_H_
|
||||
|
||||
#ifndef DISABLE_BASE64
|
||||
#define DISABLE_BASE64 0
|
||||
#endif
|
||||
|
||||
#if !DISABLE_BASE64
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*cs_base64_putc_t)(char, void *);
|
||||
|
||||
struct cs_base64_ctx {
|
||||
/* cannot call it putc because it's a macro on some environments */
|
||||
cs_base64_putc_t b64_putc;
|
||||
unsigned char chunk[3];
|
||||
int chunk_size;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t putc,
|
||||
void *user_data);
|
||||
void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len);
|
||||
void cs_base64_finish(struct cs_base64_ctx *ctx);
|
||||
|
||||
void cs_base64_encode(const unsigned char *src, int src_len, char *dst, int *enc_len);
|
||||
void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len);
|
||||
|
||||
/*
|
||||
* Decodes a base64 string `s` length `len` into `dst`.
|
||||
* `dst` must have enough space to hold the result.
|
||||
* `*dec_len` will contain the resulting length of the string in `dst`
|
||||
* while return value will return number of processed bytes in `src`.
|
||||
* Return value == len indicates successful processing of all the data.
|
||||
*/
|
||||
int cs_base64_decode(const unsigned char *s, int len, char *dst, int *dec_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DISABLE_BASE64 */
|
||||
|
||||
#endif /* CS_COMMON_CS_BASE64_H_ */
|
||||
+67
-34
@@ -1,7 +1,3 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include "common/cs_dbg.h"
|
||||
|
||||
@@ -12,19 +8,17 @@
|
||||
#include "common/cs_time.h"
|
||||
#include "common/str_util.h"
|
||||
|
||||
enum cs_log_level cs_log_threshold WEAK =
|
||||
enum cs_log_level cs_log_level 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
|
||||
static char *s_file_level = NULL;
|
||||
|
||||
void cs_log_set_file_level(const char *file_level) WEAK;
|
||||
|
||||
FILE *cs_log_file WEAK = NULL;
|
||||
|
||||
@@ -34,34 +28,72 @@ double cs_log_ts WEAK;
|
||||
|
||||
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;
|
||||
}
|
||||
/* In implementations that require locking, these can be overridden. */
|
||||
void cs_log_lock(void) WEAK;
|
||||
void cs_log_lock(void) {
|
||||
}
|
||||
|
||||
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];
|
||||
void cs_log_unlock(void) WEAK;
|
||||
void cs_log_unlock(void) {
|
||||
}
|
||||
|
||||
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;
|
||||
void cs_log_set_file_level(const char *file_level) {
|
||||
char *fl = s_file_level;
|
||||
if (file_level != NULL) {
|
||||
s_file_level = strdup(file_level);
|
||||
} else {
|
||||
s_file_level = NULL;
|
||||
}
|
||||
free(fl);
|
||||
}
|
||||
|
||||
int cs_log_print_prefix(enum cs_log_level level, const char *file, int ln) WEAK;
|
||||
int cs_log_print_prefix(enum cs_log_level level, const char *file, int ln) {
|
||||
char prefix[CS_LOG_PREFIX_LEN], *q;
|
||||
const char *p;
|
||||
size_t fl = 0, ll = 0, pl = 0;
|
||||
|
||||
if (level > cs_log_level && s_file_level == NULL) return 0;
|
||||
|
||||
p = file + strlen(file);
|
||||
|
||||
while (p != file) {
|
||||
const char c = *(p - 1);
|
||||
if (c == '/' || c == '\\') break;
|
||||
p--;
|
||||
fl++;
|
||||
}
|
||||
|
||||
strncpy(prefix, func, 20);
|
||||
prefix[20] = '\0';
|
||||
ll = (ln < 10000 ? (ln < 1000 ? (ln < 100 ? (ln < 10 ? 1 : 2) : 3) : 4) : 5);
|
||||
if (fl > (sizeof(prefix) - ll - 2)) fl = (sizeof(prefix) - ll - 2);
|
||||
|
||||
pl = fl + 1 + ll;
|
||||
memcpy(prefix, p, fl);
|
||||
q = prefix + pl;
|
||||
memset(q, ' ', sizeof(prefix) - pl);
|
||||
do {
|
||||
*(--q) = '0' + (ln % 10);
|
||||
ln /= 10;
|
||||
} while (ln > 0);
|
||||
*(--q) = ':';
|
||||
|
||||
if (s_file_level != NULL) {
|
||||
enum cs_log_level pll = cs_log_level;
|
||||
struct mg_str fl = mg_mk_str(s_file_level), ps = MG_MK_STR_N(prefix, pl);
|
||||
struct mg_str k, v;
|
||||
while ((fl = mg_next_comma_list_entry_n(fl, &k, &v)).p != NULL) {
|
||||
bool yes = !(!mg_str_starts_with(ps, k) || v.len == 0);
|
||||
if (!yes) continue;
|
||||
pll = (enum cs_log_level)(*v.p - '0');
|
||||
break;
|
||||
}
|
||||
if (level > pll) return 0;
|
||||
}
|
||||
|
||||
cs_log_lock();
|
||||
if (cs_log_file == NULL) cs_log_file = stderr;
|
||||
cs_log_cur_msg_level = level;
|
||||
fprintf(cs_log_file, "%-20s ", prefix);
|
||||
fwrite(prefix, 1, sizeof(prefix), cs_log_file);
|
||||
#if CS_LOG_ENABLE_TS_DIFF
|
||||
{
|
||||
double now = cs_time();
|
||||
@@ -81,6 +113,7 @@ void cs_log_printf(const char *fmt, ...) {
|
||||
fputc('\n', cs_log_file);
|
||||
fflush(cs_log_file);
|
||||
cs_log_cur_msg_level = LL_NONE;
|
||||
cs_log_unlock();
|
||||
}
|
||||
|
||||
void cs_log_set_file(FILE *file) WEAK;
|
||||
@@ -90,15 +123,15 @@ void cs_log_set_file(FILE *file) {
|
||||
|
||||
#else
|
||||
|
||||
void cs_log_set_filter(const char *pattern) {
|
||||
(void) pattern;
|
||||
void cs_log_set_file_level(const char *file_level) {
|
||||
(void) file_level;
|
||||
}
|
||||
|
||||
#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;
|
||||
cs_log_level = level;
|
||||
#if CS_LOG_ENABLE_TS_DIFF && CS_ENABLE_STDIO
|
||||
cs_log_ts = cs_time();
|
||||
#endif
|
||||
|
||||
+31
-48
@@ -1,7 +1,3 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_CS_DBG_H_
|
||||
#define CS_COMMON_CS_DBG_H_
|
||||
@@ -16,6 +12,10 @@
|
||||
#define CS_ENABLE_DEBUG 0
|
||||
#endif
|
||||
|
||||
#ifndef CS_LOG_PREFIX_LEN
|
||||
#define CS_LOG_PREFIX_LEN 24
|
||||
#endif
|
||||
|
||||
#ifndef CS_LOG_ENABLE_TS_DIFF
|
||||
#define CS_LOG_ENABLE_TS_DIFF 0
|
||||
#endif
|
||||
@@ -46,51 +46,28 @@ enum cs_log_level {
|
||||
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.
|
||||
* A comma-separated set of prefix=level.
|
||||
* prefix is matched against the log prefix exactly as printed, including line
|
||||
* number, but partial match is ok. Check stops on first matching entry.
|
||||
* If nothing matches, default level is used.
|
||||
*
|
||||
* For the pattern syntax, refer to `mg_match_prefix()` in `str_util.h`.
|
||||
* Examples:
|
||||
* main.c:=4 - everything from main C at verbose debug level.
|
||||
* mongoose.c=1,mjs.c=1,=4 - everything at verbose debug except mg_* and mjs_*
|
||||
*
|
||||
* 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);
|
||||
void cs_log_set_file_level(const char *file_level);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* Helper function which prints message prefix with the given `level`.
|
||||
* If message should be printed (according 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);
|
||||
int cs_log_print_prefix(enum cs_log_level level, const char *fname, int line);
|
||||
|
||||
extern enum cs_log_level cs_log_threshold;
|
||||
extern enum cs_log_level cs_log_level;
|
||||
|
||||
#if CS_ENABLE_STDIO
|
||||
|
||||
@@ -103,11 +80,9 @@ 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
|
||||
;
|
||||
void cs_log_printf(const char *fmt, ...) PRINTF_LIKE(1, 2);
|
||||
|
||||
#if CS_ENABLE_STDIO
|
||||
|
||||
/*
|
||||
* Format and print message `x` with the given level `l`. Example:
|
||||
@@ -117,11 +92,19 @@ void cs_log_printf(const char *fmt, ...)
|
||||
* 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; \
|
||||
#define LOG(l, x) \
|
||||
do { \
|
||||
if (cs_log_print_prefix(l, __FILE__, __LINE__)) { \
|
||||
cs_log_printf x; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define LOG(l, x) ((void) l)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef CS_NDEBUG
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
|
||||
#ifndef EXCLUDE_COMMON
|
||||
|
||||
#include "common/mg_mem.h"
|
||||
#include "common/cs_dirent.h"
|
||||
|
||||
/*
|
||||
* This file contains POSIX opendir/closedir/readdir API implementation
|
||||
* for systems which do not natively support it (e.g. Windows).
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
struct win32_dir {
|
||||
DIR d;
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATAW info;
|
||||
struct dirent result;
|
||||
};
|
||||
|
||||
DIR *opendir(const char *name) {
|
||||
struct win32_dir *dir = NULL;
|
||||
wchar_t wpath[MAX_PATH];
|
||||
DWORD attrs;
|
||||
|
||||
if (name == NULL) {
|
||||
SetLastError(ERROR_BAD_ARGUMENTS);
|
||||
} else if ((dir = (struct win32_dir *) MG_MALLOC(sizeof(*dir))) == NULL) {
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
} else {
|
||||
to_wchar(name, wpath, ARRAY_SIZE(wpath));
|
||||
attrs = GetFileAttributesW(wpath);
|
||||
if (attrs != 0xFFFFFFFF && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
(void) wcscat(wpath, L"\\*");
|
||||
dir->handle = FindFirstFileW(wpath, &dir->info);
|
||||
dir->result.d_name[0] = '\0';
|
||||
} else {
|
||||
MG_FREE(dir);
|
||||
dir = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (DIR *) dir;
|
||||
}
|
||||
|
||||
int closedir(DIR *d) {
|
||||
struct win32_dir *dir = (struct win32_dir *) d;
|
||||
int result = 0;
|
||||
|
||||
if (dir != NULL) {
|
||||
if (dir->handle != INVALID_HANDLE_VALUE)
|
||||
result = FindClose(dir->handle) ? 0 : -1;
|
||||
MG_FREE(dir);
|
||||
} else {
|
||||
result = -1;
|
||||
SetLastError(ERROR_BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct dirent *readdir(DIR *d) {
|
||||
struct win32_dir *dir = (struct win32_dir *) d;
|
||||
struct dirent *result = NULL;
|
||||
|
||||
if (dir) {
|
||||
memset(&dir->result, 0, sizeof(dir->result));
|
||||
if (dir->handle != INVALID_HANDLE_VALUE) {
|
||||
result = &dir->result;
|
||||
(void) WideCharToMultiByte(CP_UTF8, 0, dir->info.cFileName, -1,
|
||||
result->d_name, sizeof(result->d_name), NULL,
|
||||
NULL);
|
||||
|
||||
if (!FindNextFileW(dir->handle, &dir->info)) {
|
||||
(void) FindClose(dir->handle);
|
||||
dir->handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
} else {
|
||||
SetLastError(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
} else {
|
||||
SetLastError(ERROR_BAD_ARGUMENTS);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EXCLUDE_COMMON */
|
||||
|
||||
/* ISO C requires a translation unit to contain at least one declaration */
|
||||
typedef int cs_dirent_dummy;
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
#ifndef CS_COMMON_CS_DIRENT_H_
|
||||
#define CS_COMMON_CS_DIRENT_H_
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "common/platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef CS_DEFINE_DIRENT
|
||||
typedef struct { int dummy; } DIR;
|
||||
|
||||
struct dirent {
|
||||
int d_ino;
|
||||
#ifdef _WIN32
|
||||
char d_name[MAX_PATH];
|
||||
#else
|
||||
/* TODO(rojer): Use PATH_MAX but make sure it's sane on every platform */
|
||||
char d_name[256];
|
||||
#endif
|
||||
};
|
||||
|
||||
DIR *opendir(const char *dir_name);
|
||||
int closedir(DIR *dir);
|
||||
struct dirent *readdir(DIR *dir);
|
||||
#endif /* CS_DEFINE_DIRENT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* CS_COMMON_CS_DIRENT_H_ */
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
#ifndef CS_COMMON_CS_ENDIAN_H_
|
||||
#define CS_COMMON_CS_ENDIAN_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* clang with std=-c99 uses __LITTLE_ENDIAN, by default
|
||||
* while for ex, RTOS gcc - LITTLE_ENDIAN, by default
|
||||
* it depends on __USE_BSD, but let's have everything
|
||||
*/
|
||||
#if !defined(BYTE_ORDER) && defined(__BYTE_ORDER)
|
||||
#define BYTE_ORDER __BYTE_ORDER
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN __LITTLE_ENDIAN
|
||||
#endif /* LITTLE_ENDIAN */
|
||||
#ifndef BIG_ENDIAN
|
||||
#define BIG_ENDIAN __LITTLE_ENDIAN
|
||||
#endif /* BIG_ENDIAN */
|
||||
#endif /* BYTE_ORDER */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CS_COMMON_CS_ENDIAN_H_ */
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
/*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_MD5_H_
|
||||
#define CS_COMMON_MD5_H_
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
|
||||
/* Copyright(c) By Steve Reid <steve@edmweb.com> */
|
||||
/* 100% Public Domain */
|
||||
|
||||
#include "common/cs_sha1.h"
|
||||
|
||||
#if !CS_DISABLE_SHA1 && !defined(EXCLUDE_COMMON)
|
||||
|
||||
#include "common/cs_endian.h"
|
||||
|
||||
#define SHA1HANDSOFF
|
||||
#if defined(__sun)
|
||||
#include "common/solarisfixes.h"
|
||||
#endif
|
||||
|
||||
union char64long16 {
|
||||
unsigned char c[64];
|
||||
uint32_t l[16];
|
||||
};
|
||||
|
||||
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||
|
||||
static uint32_t blk0(union char64long16 *block, int i) {
|
||||
/* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
block->l[i] =
|
||||
(rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF);
|
||||
#endif
|
||||
return block->l[i];
|
||||
}
|
||||
|
||||
/* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */
|
||||
#undef blk
|
||||
#undef R0
|
||||
#undef R1
|
||||
#undef R2
|
||||
#undef R3
|
||||
#undef R4
|
||||
|
||||
#define blk(i) \
|
||||
(block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
|
||||
block->l[(i + 2) & 15] ^ block->l[i & 15], \
|
||||
1))
|
||||
#define R0(v, w, x, y, z, i) \
|
||||
z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R1(v, w, x, y, z, i) \
|
||||
z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R2(v, w, x, y, z, i) \
|
||||
z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R3(v, w, x, y, z, i) \
|
||||
z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R4(v, w, x, y, z, i) \
|
||||
z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
|
||||
void cs_sha1_transform(uint32_t state[5], const unsigned char buffer[64]) {
|
||||
uint32_t a, b, c, d, e;
|
||||
union char64long16 block[1];
|
||||
|
||||
memcpy(block, buffer, 64);
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
R0(a, b, c, d, e, 0);
|
||||
R0(e, a, b, c, d, 1);
|
||||
R0(d, e, a, b, c, 2);
|
||||
R0(c, d, e, a, b, 3);
|
||||
R0(b, c, d, e, a, 4);
|
||||
R0(a, b, c, d, e, 5);
|
||||
R0(e, a, b, c, d, 6);
|
||||
R0(d, e, a, b, c, 7);
|
||||
R0(c, d, e, a, b, 8);
|
||||
R0(b, c, d, e, a, 9);
|
||||
R0(a, b, c, d, e, 10);
|
||||
R0(e, a, b, c, d, 11);
|
||||
R0(d, e, a, b, c, 12);
|
||||
R0(c, d, e, a, b, 13);
|
||||
R0(b, c, d, e, a, 14);
|
||||
R0(a, b, c, d, e, 15);
|
||||
R1(e, a, b, c, d, 16);
|
||||
R1(d, e, a, b, c, 17);
|
||||
R1(c, d, e, a, b, 18);
|
||||
R1(b, c, d, e, a, 19);
|
||||
R2(a, b, c, d, e, 20);
|
||||
R2(e, a, b, c, d, 21);
|
||||
R2(d, e, a, b, c, 22);
|
||||
R2(c, d, e, a, b, 23);
|
||||
R2(b, c, d, e, a, 24);
|
||||
R2(a, b, c, d, e, 25);
|
||||
R2(e, a, b, c, d, 26);
|
||||
R2(d, e, a, b, c, 27);
|
||||
R2(c, d, e, a, b, 28);
|
||||
R2(b, c, d, e, a, 29);
|
||||
R2(a, b, c, d, e, 30);
|
||||
R2(e, a, b, c, d, 31);
|
||||
R2(d, e, a, b, c, 32);
|
||||
R2(c, d, e, a, b, 33);
|
||||
R2(b, c, d, e, a, 34);
|
||||
R2(a, b, c, d, e, 35);
|
||||
R2(e, a, b, c, d, 36);
|
||||
R2(d, e, a, b, c, 37);
|
||||
R2(c, d, e, a, b, 38);
|
||||
R2(b, c, d, e, a, 39);
|
||||
R3(a, b, c, d, e, 40);
|
||||
R3(e, a, b, c, d, 41);
|
||||
R3(d, e, a, b, c, 42);
|
||||
R3(c, d, e, a, b, 43);
|
||||
R3(b, c, d, e, a, 44);
|
||||
R3(a, b, c, d, e, 45);
|
||||
R3(e, a, b, c, d, 46);
|
||||
R3(d, e, a, b, c, 47);
|
||||
R3(c, d, e, a, b, 48);
|
||||
R3(b, c, d, e, a, 49);
|
||||
R3(a, b, c, d, e, 50);
|
||||
R3(e, a, b, c, d, 51);
|
||||
R3(d, e, a, b, c, 52);
|
||||
R3(c, d, e, a, b, 53);
|
||||
R3(b, c, d, e, a, 54);
|
||||
R3(a, b, c, d, e, 55);
|
||||
R3(e, a, b, c, d, 56);
|
||||
R3(d, e, a, b, c, 57);
|
||||
R3(c, d, e, a, b, 58);
|
||||
R3(b, c, d, e, a, 59);
|
||||
R4(a, b, c, d, e, 60);
|
||||
R4(e, a, b, c, d, 61);
|
||||
R4(d, e, a, b, c, 62);
|
||||
R4(c, d, e, a, b, 63);
|
||||
R4(b, c, d, e, a, 64);
|
||||
R4(a, b, c, d, e, 65);
|
||||
R4(e, a, b, c, d, 66);
|
||||
R4(d, e, a, b, c, 67);
|
||||
R4(c, d, e, a, b, 68);
|
||||
R4(b, c, d, e, a, 69);
|
||||
R4(a, b, c, d, e, 70);
|
||||
R4(e, a, b, c, d, 71);
|
||||
R4(d, e, a, b, c, 72);
|
||||
R4(c, d, e, a, b, 73);
|
||||
R4(b, c, d, e, a, 74);
|
||||
R4(a, b, c, d, e, 75);
|
||||
R4(e, a, b, c, d, 76);
|
||||
R4(d, e, a, b, c, 77);
|
||||
R4(c, d, e, a, b, 78);
|
||||
R4(b, c, d, e, a, 79);
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
/* Erase working structures. The order of operations is important,
|
||||
* used to ensure that compiler doesn't optimize those out. */
|
||||
memset(block, 0, sizeof(block));
|
||||
a = b = c = d = e = 0;
|
||||
(void) a;
|
||||
(void) b;
|
||||
(void) c;
|
||||
(void) d;
|
||||
(void) e;
|
||||
}
|
||||
|
||||
void cs_sha1_init(cs_sha1_ctx *context) {
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xEFCDAB89;
|
||||
context->state[2] = 0x98BADCFE;
|
||||
context->state[3] = 0x10325476;
|
||||
context->state[4] = 0xC3D2E1F0;
|
||||
context->count[0] = context->count[1] = 0;
|
||||
}
|
||||
|
||||
void cs_sha1_update(cs_sha1_ctx *context, const unsigned char *data,
|
||||
uint32_t len) {
|
||||
uint32_t i, j;
|
||||
|
||||
j = context->count[0];
|
||||
if ((context->count[0] += len << 3) < j) context->count[1]++;
|
||||
context->count[1] += (len >> 29);
|
||||
j = (j >> 3) & 63;
|
||||
if ((j + len) > 63) {
|
||||
memcpy(&context->buffer[j], data, (i = 64 - j));
|
||||
cs_sha1_transform(context->state, context->buffer);
|
||||
for (; i + 63 < len; i += 64) {
|
||||
cs_sha1_transform(context->state, &data[i]);
|
||||
}
|
||||
j = 0;
|
||||
} else
|
||||
i = 0;
|
||||
memcpy(&context->buffer[j], &data[i], len - i);
|
||||
}
|
||||
|
||||
void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *context) {
|
||||
unsigned i;
|
||||
unsigned char finalcount[8], c;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >>
|
||||
((3 - (i & 3)) * 8)) &
|
||||
255);
|
||||
}
|
||||
c = 0200;
|
||||
cs_sha1_update(context, &c, 1);
|
||||
while ((context->count[0] & 504) != 448) {
|
||||
c = 0000;
|
||||
cs_sha1_update(context, &c, 1);
|
||||
}
|
||||
cs_sha1_update(context, finalcount, 8);
|
||||
for (i = 0; i < 20; i++) {
|
||||
digest[i] =
|
||||
(unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
|
||||
}
|
||||
memset(context, '\0', sizeof(*context));
|
||||
memset(&finalcount, '\0', sizeof(finalcount));
|
||||
}
|
||||
|
||||
void cs_hmac_sha1(const unsigned char *key, size_t keylen,
|
||||
const unsigned char *data, size_t datalen,
|
||||
unsigned char out[20]) {
|
||||
cs_sha1_ctx ctx;
|
||||
unsigned char buf1[64], buf2[64], tmp_key[20], i;
|
||||
|
||||
if (keylen > sizeof(buf1)) {
|
||||
cs_sha1_init(&ctx);
|
||||
cs_sha1_update(&ctx, key, keylen);
|
||||
cs_sha1_final(tmp_key, &ctx);
|
||||
key = tmp_key;
|
||||
keylen = sizeof(tmp_key);
|
||||
}
|
||||
|
||||
memset(buf1, 0, sizeof(buf1));
|
||||
memset(buf2, 0, sizeof(buf2));
|
||||
memcpy(buf1, key, keylen);
|
||||
memcpy(buf2, key, keylen);
|
||||
|
||||
for (i = 0; i < sizeof(buf1); i++) {
|
||||
buf1[i] ^= 0x36;
|
||||
buf2[i] ^= 0x5c;
|
||||
}
|
||||
|
||||
cs_sha1_init(&ctx);
|
||||
cs_sha1_update(&ctx, buf1, sizeof(buf1));
|
||||
cs_sha1_update(&ctx, data, datalen);
|
||||
cs_sha1_final(out, &ctx);
|
||||
|
||||
cs_sha1_init(&ctx);
|
||||
cs_sha1_update(&ctx, buf2, sizeof(buf2));
|
||||
cs_sha1_update(&ctx, out, 20);
|
||||
cs_sha1_final(out, &ctx);
|
||||
}
|
||||
|
||||
#endif /* EXCLUDE_COMMON */
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
#ifndef CS_COMMON_SHA1_H_
|
||||
#define CS_COMMON_SHA1_H_
|
||||
|
||||
#ifndef CS_DISABLE_SHA1
|
||||
#define CS_DISABLE_SHA1 0
|
||||
#endif
|
||||
|
||||
#if !CS_DISABLE_SHA1
|
||||
|
||||
#include "common/platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct {
|
||||
uint32_t state[5];
|
||||
uint32_t count[2];
|
||||
unsigned char buffer[64];
|
||||
} cs_sha1_ctx;
|
||||
|
||||
void cs_sha1_init(cs_sha1_ctx *);
|
||||
void cs_sha1_update(cs_sha1_ctx *, const unsigned char *data, uint32_t len);
|
||||
void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *);
|
||||
void cs_hmac_sha1(const unsigned char *key, size_t key_len,
|
||||
const unsigned char *text, size_t text_len,
|
||||
unsigned char out[20]);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* CS_DISABLE_SHA1 */
|
||||
|
||||
#endif /* CS_COMMON_SHA1_H_ */
|
||||
@@ -1,7 +1,3 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#include "common/cs_time.h"
|
||||
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_CS_TIME_H_
|
||||
#define CS_COMMON_CS_TIME_H_
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
|
||||
#ifndef EXCLUDE_COMMON
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "common/mbuf.h"
|
||||
|
||||
#ifndef MBUF_REALLOC
|
||||
#define MBUF_REALLOC realloc
|
||||
#endif
|
||||
|
||||
#ifndef MBUF_FREE
|
||||
#define MBUF_FREE free
|
||||
#endif
|
||||
|
||||
void mbuf_init(struct mbuf *mbuf, size_t initial_size) WEAK;
|
||||
void mbuf_init(struct mbuf *mbuf, size_t initial_size) {
|
||||
mbuf->len = mbuf->size = 0;
|
||||
mbuf->buf = NULL;
|
||||
mbuf_resize(mbuf, initial_size);
|
||||
}
|
||||
|
||||
void mbuf_free(struct mbuf *mbuf) WEAK;
|
||||
void mbuf_free(struct mbuf *mbuf) {
|
||||
if (mbuf->buf != NULL) {
|
||||
MBUF_FREE(mbuf->buf);
|
||||
mbuf_init(mbuf, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void mbuf_resize(struct mbuf *a, size_t new_size) WEAK;
|
||||
void mbuf_resize(struct mbuf *a, size_t new_size) {
|
||||
if (new_size > a->size || (new_size < a->size && new_size >= a->len)) {
|
||||
char *buf = (char *) MBUF_REALLOC(a->buf, new_size);
|
||||
/*
|
||||
* In case realloc fails, there's not much we can do, except keep things as
|
||||
* they are. Note that NULL is a valid return value from realloc when
|
||||
* size == 0, but that is covered too.
|
||||
*/
|
||||
if (buf == NULL && new_size != 0) return;
|
||||
a->buf = buf;
|
||||
a->size = new_size;
|
||||
}
|
||||
}
|
||||
|
||||
void mbuf_trim(struct mbuf *mbuf) WEAK;
|
||||
void mbuf_trim(struct mbuf *mbuf) {
|
||||
mbuf_resize(mbuf, mbuf->len);
|
||||
}
|
||||
|
||||
size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t) WEAK;
|
||||
size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t len) {
|
||||
char *p = NULL;
|
||||
|
||||
assert(a != NULL);
|
||||
assert(a->len <= a->size);
|
||||
assert(off <= a->len);
|
||||
|
||||
/* check overflow */
|
||||
if (~(size_t) 0 - (size_t) a->buf < len) return 0;
|
||||
|
||||
if (a->len + len <= a->size) {
|
||||
memmove(a->buf + off + len, a->buf + off, a->len - off);
|
||||
if (buf != NULL) {
|
||||
memcpy(a->buf + off, buf, len);
|
||||
}
|
||||
a->len += len;
|
||||
} else {
|
||||
size_t min_size = (a->len + len);
|
||||
size_t new_size = (size_t)(min_size * MBUF_SIZE_MULTIPLIER);
|
||||
if (new_size - min_size > MBUF_SIZE_MAX_HEADROOM) {
|
||||
new_size = min_size + MBUF_SIZE_MAX_HEADROOM;
|
||||
}
|
||||
p = (char *) MBUF_REALLOC(a->buf, new_size);
|
||||
if (p == NULL && new_size != min_size) {
|
||||
new_size = min_size;
|
||||
p = (char *) MBUF_REALLOC(a->buf, new_size);
|
||||
}
|
||||
if (p != NULL) {
|
||||
a->buf = p;
|
||||
if (off != a->len) {
|
||||
memmove(a->buf + off + len, a->buf + off, a->len - off);
|
||||
}
|
||||
if (buf != NULL) memcpy(a->buf + off, buf, len);
|
||||
a->len += len;
|
||||
a->size = new_size;
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) WEAK;
|
||||
size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) {
|
||||
return mbuf_insert(a, a->len, buf, len);
|
||||
}
|
||||
|
||||
size_t mbuf_append_and_free(struct mbuf *a, void *buf, size_t len) WEAK;
|
||||
size_t mbuf_append_and_free(struct mbuf *a, void *data, size_t len) {
|
||||
size_t ret;
|
||||
/* Optimization: if the buffer is currently empty,
|
||||
* take over the user-provided buffer. */
|
||||
if (a->len == 0) {
|
||||
if (a->buf != NULL) free(a->buf);
|
||||
a->buf = (char *) data;
|
||||
a->len = a->size = len;
|
||||
return len;
|
||||
}
|
||||
ret = mbuf_insert(a, a->len, data, len);
|
||||
free(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mbuf_remove(struct mbuf *mb, size_t n) WEAK;
|
||||
void mbuf_remove(struct mbuf *mb, size_t n) {
|
||||
if (n > 0 && n <= mb->len) {
|
||||
memmove(mb->buf, mb->buf + n, mb->len - n);
|
||||
mb->len -= n;
|
||||
}
|
||||
}
|
||||
|
||||
void mbuf_clear(struct mbuf *mb) WEAK;
|
||||
void mbuf_clear(struct mbuf *mb) {
|
||||
mb->len = 0;
|
||||
}
|
||||
|
||||
void mbuf_move(struct mbuf *from, struct mbuf *to) WEAK;
|
||||
void mbuf_move(struct mbuf *from, struct mbuf *to) {
|
||||
memcpy(to, from, sizeof(*to));
|
||||
memset(from, 0, sizeof(*from));
|
||||
}
|
||||
|
||||
#endif /* EXCLUDE_COMMON */
|
||||
@@ -0,0 +1,95 @@
|
||||
|
||||
/*
|
||||
* Mbufs are mutable/growing memory buffers, like C++ strings.
|
||||
* Mbuf can append data to the end of a buffer or insert data into arbitrary
|
||||
* position in the middle of a buffer. The buffer grows automatically when
|
||||
* needed.
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_MBUF_H_
|
||||
#define CS_COMMON_MBUF_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "common/platform.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef MBUF_SIZE_MULTIPLIER
|
||||
#define MBUF_SIZE_MULTIPLIER 1.5
|
||||
#endif
|
||||
|
||||
#ifndef MBUF_SIZE_MAX_HEADROOM
|
||||
#ifdef BUFSIZ
|
||||
#define MBUF_SIZE_MAX_HEADROOM BUFSIZ
|
||||
#else
|
||||
#define MBUF_SIZE_MAX_HEADROOM 1024
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Memory buffer descriptor */
|
||||
struct mbuf {
|
||||
char *buf; /* Buffer pointer */
|
||||
size_t len; /* Data length. Data is located between offset 0 and len. */
|
||||
size_t size; /* Buffer size allocated by realloc(1). Must be >= len */
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialises an Mbuf.
|
||||
* `initial_capacity` specifies the initial capacity of the mbuf.
|
||||
*/
|
||||
void mbuf_init(struct mbuf *, size_t initial_capacity);
|
||||
|
||||
/* Frees the space allocated for the mbuffer and resets the mbuf structure. */
|
||||
void mbuf_free(struct mbuf *);
|
||||
|
||||
/*
|
||||
* Appends data to the Mbuf.
|
||||
*
|
||||
* Returns the number of bytes appended or 0 if out of memory.
|
||||
*/
|
||||
size_t mbuf_append(struct mbuf *, const void *data, size_t data_size);
|
||||
|
||||
/*
|
||||
* Appends data to the Mbuf and frees it (data must be heap-allocated).
|
||||
*
|
||||
* Returns the number of bytes appended or 0 if out of memory.
|
||||
* data is freed irrespective of return value.
|
||||
*/
|
||||
size_t mbuf_append_and_free(struct mbuf *, void *data, size_t data_size);
|
||||
|
||||
/*
|
||||
* Inserts data at a specified offset in the Mbuf.
|
||||
*
|
||||
* Existing data will be shifted forwards and the buffer will
|
||||
* be grown if necessary.
|
||||
* Returns the number of bytes inserted.
|
||||
*/
|
||||
size_t mbuf_insert(struct mbuf *, size_t, const void *, size_t);
|
||||
|
||||
/* Removes `data_size` bytes from the beginning of the buffer. */
|
||||
void mbuf_remove(struct mbuf *, size_t data_size);
|
||||
|
||||
/*
|
||||
* Resizes an Mbuf.
|
||||
*
|
||||
* If `new_size` is smaller than buffer's `len`, the
|
||||
* resize is not performed.
|
||||
*/
|
||||
void mbuf_resize(struct mbuf *, size_t new_size);
|
||||
|
||||
/* Moves the state from one mbuf to the other. */
|
||||
void mbuf_move(struct mbuf *from, struct mbuf *to);
|
||||
|
||||
/* Removes all the data from mbuf (if any). */
|
||||
void mbuf_clear(struct mbuf *);
|
||||
|
||||
/* Shrinks an Mbuf by resizing its `size` to `len`. */
|
||||
void mbuf_trim(struct mbuf *);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* CS_COMMON_MBUF_H_ */
|
||||
@@ -1,7 +1,3 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#ifndef CS_COMMON_MG_MEM_H_
|
||||
#define CS_COMMON_MG_MEM_H_
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
|
||||
#include "common/mg_mem.h"
|
||||
#include "common/mg_str.h"
|
||||
#include "common/platform.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int mg_ncasecmp(const char *s1, const char *s2, size_t len) WEAK;
|
||||
|
||||
struct mg_str mg_mk_str(const char *s) WEAK;
|
||||
struct mg_str mg_mk_str(const char *s) {
|
||||
struct mg_str ret = {s, 0};
|
||||
if (s != NULL) ret.len = strlen(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct mg_str mg_mk_str_n(const char *s, size_t len) WEAK;
|
||||
struct mg_str mg_mk_str_n(const char *s, size_t len) {
|
||||
struct mg_str ret = {s, len};
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mg_vcmp(const struct mg_str *str1, const char *str2) WEAK;
|
||||
int mg_vcmp(const struct mg_str *str1, const char *str2) {
|
||||
size_t n2 = strlen(str2), n1 = str1->len;
|
||||
if (n1 == 0) return (n2 > 0 ? -1 : 0);
|
||||
int r = strncmp(str1->p, str2, (n1 < n2) ? n1 : n2);
|
||||
if (r == 0) {
|
||||
return n1 - n2;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int mg_vcasecmp(const struct mg_str *str1, const char *str2) WEAK;
|
||||
int mg_vcasecmp(const struct mg_str *str1, const char *str2) {
|
||||
size_t n2 = strlen(str2), n1 = str1->len;
|
||||
int r = mg_ncasecmp(str1->p, str2, (n1 < n2) ? n1 : n2);
|
||||
if (r == 0) {
|
||||
return n1 - n2;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct mg_str mg_strdup_common(const struct mg_str s,
|
||||
int nul_terminate) {
|
||||
struct mg_str r = {NULL, 0};
|
||||
if (s.len > 0 && s.p != NULL) {
|
||||
char *sc = (char *) MG_MALLOC(s.len + (nul_terminate ? 1 : 0));
|
||||
if (sc != NULL) {
|
||||
memcpy(sc, s.p, s.len);
|
||||
if (nul_terminate) sc[s.len] = '\0';
|
||||
r.p = sc;
|
||||
r.len = s.len;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
struct mg_str mg_strdup(const struct mg_str s) WEAK;
|
||||
struct mg_str mg_strdup(const struct mg_str s) {
|
||||
return mg_strdup_common(s, 0 /* NUL-terminate */);
|
||||
}
|
||||
|
||||
struct mg_str mg_strdup_nul(const struct mg_str s) WEAK;
|
||||
struct mg_str mg_strdup_nul(const struct mg_str s) {
|
||||
return mg_strdup_common(s, 1 /* NUL-terminate */);
|
||||
}
|
||||
|
||||
const char *mg_strchr(const struct mg_str s, int c) WEAK;
|
||||
const char *mg_strchr(const struct mg_str s, int c) {
|
||||
size_t i;
|
||||
for (i = 0; i < s.len; i++) {
|
||||
if (s.p[i] == c) return &s.p[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int mg_strcmp(const struct mg_str str1, const struct mg_str str2) WEAK;
|
||||
int mg_strcmp(const struct mg_str str1, const struct mg_str str2) {
|
||||
size_t i = 0;
|
||||
while (i < str1.len && i < str2.len) {
|
||||
int c1 = str1.p[i];
|
||||
int c2 = str2.p[i];
|
||||
if (c1 < c2) return -1;
|
||||
if (c1 > c2) return 1;
|
||||
i++;
|
||||
}
|
||||
if (i < str1.len) return 1;
|
||||
if (i < str2.len) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mg_strncmp(const struct mg_str, const struct mg_str, size_t n) WEAK;
|
||||
int mg_strncmp(const struct mg_str str1, const struct mg_str str2, size_t n) {
|
||||
struct mg_str s1 = str1;
|
||||
struct mg_str s2 = str2;
|
||||
|
||||
if (s1.len > n) {
|
||||
s1.len = n;
|
||||
}
|
||||
if (s2.len > n) {
|
||||
s2.len = n;
|
||||
}
|
||||
return mg_strcmp(s1, s2);
|
||||
}
|
||||
|
||||
int mg_strcasecmp(const struct mg_str str1, const struct mg_str str2) WEAK;
|
||||
int mg_strcasecmp(const struct mg_str str1, const struct mg_str str2) {
|
||||
size_t i = 0;
|
||||
while (i < str1.len && i < str2.len) {
|
||||
int c1 = tolower((int) str1.p[i]);
|
||||
int c2 = tolower((int) str2.p[i]);
|
||||
if (c1 < c2) return -1;
|
||||
if (c1 > c2) return 1;
|
||||
i++;
|
||||
}
|
||||
if (i < str1.len) return 1;
|
||||
if (i < str2.len) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mg_strfree(struct mg_str *s) WEAK;
|
||||
void mg_strfree(struct mg_str *s) {
|
||||
char *sp = (char *) s->p;
|
||||
s->p = NULL;
|
||||
s->len = 0;
|
||||
if (sp != NULL) free(sp);
|
||||
}
|
||||
|
||||
const char *mg_strstr(const struct mg_str haystack,
|
||||
const struct mg_str needle) WEAK;
|
||||
const char *mg_strstr(const struct mg_str haystack,
|
||||
const struct mg_str needle) {
|
||||
size_t i;
|
||||
if (needle.len > haystack.len) return NULL;
|
||||
for (i = 0; i <= haystack.len - needle.len; i++) {
|
||||
if (memcmp(haystack.p + i, needle.p, needle.len) == 0) {
|
||||
return haystack.p + i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct mg_str mg_strstrip(struct mg_str s) WEAK;
|
||||
struct mg_str mg_strstrip(struct mg_str s) {
|
||||
while (s.len > 0 && isspace((int) *s.p)) {
|
||||
s.p++;
|
||||
s.len--;
|
||||
}
|
||||
while (s.len > 0 && isspace((int) *(s.p + s.len - 1))) {
|
||||
s.len--;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int mg_str_starts_with(struct mg_str s, struct mg_str prefix) WEAK;
|
||||
int mg_str_starts_with(struct mg_str s, struct mg_str prefix) {
|
||||
const struct mg_str sp = MG_MK_STR_N(s.p, prefix.len);
|
||||
if (s.len < prefix.len) return 0;
|
||||
return (mg_strcmp(sp, prefix) == 0);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
|
||||
#ifndef CS_COMMON_MG_STR_H_
|
||||
#define CS_COMMON_MG_STR_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Describes chunk of memory */
|
||||
struct mg_str {
|
||||
const char *p; /* Memory chunk pointer */
|
||||
size_t len; /* Memory chunk length */
|
||||
};
|
||||
|
||||
/*
|
||||
* Helper function for creating mg_str struct from plain C string.
|
||||
* `NULL` is allowed and becomes `{NULL, 0}`.
|
||||
*/
|
||||
struct mg_str mg_mk_str(const char *s);
|
||||
|
||||
/*
|
||||
* Like `mg_mk_str`, but takes string length explicitly.
|
||||
*/
|
||||
struct mg_str mg_mk_str_n(const char *s, size_t len);
|
||||
|
||||
/* Macro for initializing mg_str. */
|
||||
#define MG_MK_STR(str_literal) \
|
||||
{ str_literal, sizeof(str_literal) - 1 }
|
||||
#define MG_MK_STR_N(str_literal, len) \
|
||||
{ str_literal, len }
|
||||
#define MG_NULL_STR \
|
||||
{ NULL, 0 }
|
||||
|
||||
/*
|
||||
* Cross-platform version of `strcmp()` where where first string is
|
||||
* specified by `struct mg_str`.
|
||||
*/
|
||||
int mg_vcmp(const struct mg_str *str2, const char *str1);
|
||||
|
||||
/*
|
||||
* Cross-platform version of `strncasecmp()` where first string is
|
||||
* specified by `struct mg_str`.
|
||||
*/
|
||||
int mg_vcasecmp(const struct mg_str *str2, const char *str1);
|
||||
|
||||
/* Creates a copy of s (heap-allocated). */
|
||||
struct mg_str mg_strdup(const struct mg_str s);
|
||||
|
||||
/*
|
||||
* Creates a copy of s (heap-allocated).
|
||||
* Resulting string is NUL-terminated (but NUL is not included in len).
|
||||
*/
|
||||
struct mg_str mg_strdup_nul(const struct mg_str s);
|
||||
|
||||
/*
|
||||
* Locates character in a string.
|
||||
*/
|
||||
const char *mg_strchr(const struct mg_str s, int c);
|
||||
|
||||
/*
|
||||
* Compare two `mg_str`s; return value is the same as `strcmp`.
|
||||
*/
|
||||
int mg_strcmp(const struct mg_str str1, const struct mg_str str2);
|
||||
|
||||
/*
|
||||
* Like `mg_strcmp`, but compares at most `n` characters.
|
||||
*/
|
||||
int mg_strncmp(const struct mg_str str1, const struct mg_str str2, size_t n);
|
||||
|
||||
/*
|
||||
* Compare two `mg_str`s ignoreing case; return value is the same as `strcmp`.
|
||||
*/
|
||||
int mg_strcasecmp(const struct mg_str str1, const struct mg_str str2);
|
||||
|
||||
/*
|
||||
* Free the string (assuming it was heap allocated).
|
||||
*/
|
||||
void mg_strfree(struct mg_str *s);
|
||||
|
||||
/*
|
||||
* Finds the first occurrence of a substring `needle` in the `haystack`.
|
||||
*/
|
||||
const char *mg_strstr(const struct mg_str haystack, const struct mg_str needle);
|
||||
|
||||
/* Strip whitespace at the start and the end of s */
|
||||
struct mg_str mg_strstrip(struct mg_str s);
|
||||
|
||||
/* Returns 1 if s starts with the given prefix. */
|
||||
int mg_str_starts_with(struct mg_str s, struct mg_str prefix);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CS_COMMON_MG_STR_H_ */
|
||||
+21
-2
@@ -1,3 +1,4 @@
|
||||
|
||||
#ifndef CS_COMMON_PLATFORM_H_
|
||||
#define CS_COMMON_PLATFORM_H_
|
||||
|
||||
@@ -22,8 +23,9 @@
|
||||
#define CS_P_NRF51 12
|
||||
#define CS_P_NRF52 10
|
||||
#define CS_P_PIC32 11
|
||||
#define CS_P_RS14100 18
|
||||
#define CS_P_STM32 16
|
||||
/* Next id: 18 */
|
||||
/* Next id: 19 */
|
||||
|
||||
/* If not specified explicitly, we guess platform by defines. */
|
||||
#ifndef CS_PLATFORM
|
||||
@@ -55,6 +57,8 @@
|
||||
#elif defined(TARGET_IS_TM4C129_RA0) || defined(TARGET_IS_TM4C129_RA1) || \
|
||||
defined(TARGET_IS_TM4C129_RA2)
|
||||
#define CS_PLATFORM CS_P_TM4C129
|
||||
#elif defined(RS14100)
|
||||
#define CS_PLATFORM CS_P_RS14100
|
||||
#elif defined(STM32)
|
||||
#define CS_PLATFORM CS_P_STM32
|
||||
#endif
|
||||
@@ -69,6 +73,7 @@
|
||||
#define MG_NET_IF_SIMPLELINK 2
|
||||
#define MG_NET_IF_LWIP_LOW_LEVEL 3
|
||||
#define MG_NET_IF_PIC32 4
|
||||
#define MG_NET_IF_NULL 5
|
||||
|
||||
#define MG_SSL_IF_OPENSSL 1
|
||||
#define MG_SSL_IF_MBEDTLS 2
|
||||
@@ -88,12 +93,26 @@
|
||||
#include "common/platforms/platform_nxp_lpc.h"
|
||||
#include "common/platforms/platform_nxp_kinetis.h"
|
||||
#include "common/platforms/platform_pic32.h"
|
||||
#include "common/platforms/platform_rs14100.h"
|
||||
#include "common/platforms/platform_stm32.h"
|
||||
#if CS_PLATFORM == CS_P_CUSTOM
|
||||
#include <platform_custom.h>
|
||||
#endif
|
||||
|
||||
/* Common stuff */
|
||||
|
||||
#if !defined(PRINTF_LIKE)
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
|
||||
#define PRINTF_LIKE(f, a) __attribute__((format(printf, f, a)))
|
||||
#else
|
||||
#define PRINTF_LIKE(f, a)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(WEAK)
|
||||
#if (defined(__GNUC__) || defined(__TI_COMPILER_VERSION__)) && !defined(_WIN32)
|
||||
#if (defined(__GNUC__) || defined(__clang__) || \
|
||||
defined(__TI_COMPILER_VERSION__)) && \
|
||||
!defined(_WIN32)
|
||||
#define WEAK __attribute__((weak))
|
||||
#else
|
||||
#define WEAK
|
||||
|
||||
@@ -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,7 +1,3 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 Cesanta Software Limited
|
||||
* All rights reserved
|
||||
*/
|
||||
|
||||
#if 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
|
||||
Loaded 100 of 248 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user