Compare commits

...
145 Commits
Author SHA1 Message Date
Deomid Ryabkov afcb4d9df7 Do not post MG_SIG_CLOSE_CONN if the conn is already closing 2022-10-09 16:36:51 +01:00
Deomid Ryabkov 44b15b76f7 Fix leaking non-active (e.g., bound) LWIP TCP PCBs
tcp_close_tcpip() only closed active TCP PCBs, leaking other types of TCP PCBs
(notably bound only, not yet connected/used).  With time, this led to DoS
situations.

Fix by giving up on the hacky way of searching the LWIP innards for the TCP PCB
needing closing.  The searching was non-comprehensive, hence the problem in
principle, and inherently racy: could close a meanwhile freed & reused PCB.

Pass the pointer to the struct mg_lwip_conn_state of the struct mg_connection
being destroyed to tcp_close_tcpip() instead of the bare PCB pointer, so the PCB
pointer stored within can be used.  Delay unassigning that pointer from the
struct mg_connection until tcp_close_tcpip() finishes, so that
a mg_lwip_tcp_error_cb() meanwhile can clear the PCB pointer stored within.
That ensures no double-closing of the TCP PCB when a concurrent TCP error makes
LWIP close the TCP PCB from the LWIP side.

NB!  At the moment, PCBs can still leak if tcp_close() fails, which is unlikely
but possible as per the API.  Retrying tcp_close() should somehow be
implemented.  For now, at least add logging of tcp_close() failures.

Also: remove the extraneous though benign double-calling of tcp_arg(…, NULL).

h/t @QRPp
2022-09-27 09:20:15 +01:00
Deomid Ryabkov a1fcbb0718 Fix WS connections to URLs that don't end in /
Same as in mg_connect_http_opt().
2022-08-03 14:39:55 +01:00
Deomid Ryabkov 0c4d364cee LWIP: Fix races between TCP errors and queued callbacks
A TCP connection can get closed while there are TCPIP thread callbacks
queued. Add checks to close and write functions to avoid acting on
tcp_pcbs that have already been disposed of.
2022-06-14 21:27:24 +01:00
Deomid Ryabkov def2f39724 lwip: Check for accepted connection being NULL
This happens when lwip runs out of pcbs and just communicates an error.
2021-11-24 02:43:42 +00:00
Deomid Ryabkov 311fdb8bac lwip: Optimize UDP RX path and introduce a limit
Store adddress in the memory immediately preceding the packet data.
It is guaranteed to have enough space (IP header is 20 bytes).

Introduce a limit on the length of the RX chain,
MG_LWIP_MAX_UDP_RX_CHAIN_LEN. Default is 20.
2021-09-01 22:25:36 +01:00
Deomid Ryabkov 38f694d071 Update README 2021-06-12 02:00:49 +01:00
Deomid "rojer" Ryabkov da1e5438bd LWIP: (Ab)use mg_conection.priv_2 to pass input interface address
This is required to distinguish input interface for multicast traffic
and select correct output interface for outgoing traffic (advertisements).

http://savannah.nongnu.org/bugs/?49662 removed ability to receive
multicast traffic on on interface-bound sockets (making the previous
change useless, hence the revert), so for LWIP 2.0.1 and newer
multicast packets can only be received on INADDR_ANY listeners.
User is then required to distinguish input interface in the receive path.
This information is only available in the udp_recv callback, so we must
pass this down to dns-sd library somehow, and priv_2 is the how.
It is normally used for DNS resolver state, and is never used on
listening sockets. We thus avoid growing the mg_connection structure.
2021-06-12 01:58:08 +01:00
Deomid "rojer" Ryabkov e3a140c9a7 Add ability to enumerate endpoints 2021-06-12 01:56:50 +01:00
Deomid "rojer" Ryabkov a350208f35 Add SHA256 support for digest auth
https://tools.ietf.org/html/rfc7616
2021-06-12 01:56:29 +01:00
Deomid "rojer" Ryabkov 6fa305e36d Remove ESP8266 pbuf chain length check
It's been pushed up to LWIP: https://github.com/mongoose-os-libs/lwip/commit/f92662566e71238bd6559b23fee37b0728ecb8e7
2021-06-12 01:56:10 +01:00
Deomid "rojer" Ryabkov edd38f6ccd mongoose: Read file data directly into send_mbuf
Reduces stack usage and avoids an extra copy
2021-06-12 01:55:44 +01:00
Deomid "rojer" Ryabkov abced77c24 Remove NUL-temrination from cs_base64_{encode,decode} functions
Preserve for the corresponding `mg_*` variants for compatibility.
2021-06-12 01:54:51 +01:00
Deomid "rojer" Ryabkov 4699e90e99 Ensure struct mg_connect_opts size remains the same, SSL or not
It is passed by value so libraries compiled with and without SSL cannot interoperate if struct size is different.
2021-06-12 01:54:32 +01:00
Deomid "rojer" Ryabkov e9853be8f7 Reduce the size of struct mg_dns_message
From 2K to 1K. Still too big for most cases but manageable.
2021-06-12 01:54:21 +01:00
Deomid "rojer" Ryabkov fd062b530c Fix a memory leak in mg_lwip_if
When a UDP listener is closed, pending pbufs must be freed.
This was causing a leak on flappy wifi connections and dns-sd enabled.
2021-06-12 01:46:48 +01:00
Deomid "rojer" Ryabkov 2fbfe61c37 Fix connection management bugs in mg_lwip_if
* Do not set MG_F_SSL ona connection until it's been fully accepted (MG_SIG_ACCEPT is handled).
   This fixes a crash when SSL connection is polled before it's fully initialized.
 * Fix mg_lwip_tcp_error_cb to NULL out tcp_pcb pointer even if mg_connection is already shutting down.
   After mg_lwip_tcp_error_cb, tcp_pcb pointer can no longer be used and doesn't need to be freed.
   This fixes https://github.com/cesanta/mongoose-os/issues/545
2021-06-12 01:45:30 +01:00
Deomid "rojer" Ryabkov 70034b5873 Fix stack overflow when serving http files on ESP8266
ESP8266 non-OS has very limited stack - only 4K. Undetected stack
overflows cause nasty bugs and it turns out serving files over http
routinely causes stack overflow.

This was exposed by https://github.com/cesanta/mongoose-os/commit/a5f59123edcfef10c351b3e679f28720b5de9611

As a short-term workaround, push http_message into bss, this is enough
as an immediate workaround. Longer term, we need to think how to bring
8266 to parity with other platforms where we have at least 8K stack.

At the same time, get rid of the compiler bug workaround - modern
toolchain doesn't need this.
2021-06-12 00:30:51 +01:00
Deomid Ryabkov d6c9d3c181 Fix amalgam/unamalgam diffs 2021-06-12 00:22:26 +01:00
Sergey Lyubka 34d4fb8cf0 Merge pull request #1157 from rojer/qq
Add mg_next_query_string_entry_n() and mg_url_decode_n()
2020-10-26 13:25:31 +00:00
Deomid Ryabkov be64f81eee Add mg_next_query_string_entry_n() and mg_url_decode_n()
Move to mg_util.h so encode and decode are next ot each other.

Pull out mg_next_list_entry_n() for advanced use cases.

Add unit tests.
2020-10-24 22:53:50 +01:00
Sergey Lyubka 9fe1c93c9b Merge pull request #1143 from rojer/cs_log_lock
Add cs_log_{lock,unlock}
2020-08-28 20:46:37 +01:00
Deomid Ryabkov a4b6d58b24 Add cs_log_{lock,unlock}
In implementatiosn that have preemptive scheduelrs these can be implemented
to ensure logging from different threads is properly serialized.
2020-08-28 20:29:13 +01:00
Sergey Lyubka 86f391c701 Merge pull request #1139 from rojer/warns
Fix warnings and sync line numbers of unamalgamated sources
2020-08-20 00:45:02 +01:00
Sergey Lyubka 36de38bd11 Merge pull request #1138 from rojer/1135
Add missing range check in mg_get_http_header()
2020-08-20 00:44:36 +01:00
Deomid Ryabkov a308872c88 Fix warnings and sync line numbers of unamalgamated sources 2020-08-19 22:02:50 +01:00
Deomid Ryabkov a369160296 Add missing range check in mg_get_http_header()
h/t BushraAloraini

Fixes https://github.com/cesanta/mongoose/issues/1135
2020-08-19 21:48:45 +01:00
Sergey Lyubka 0a09b46c94 Merge pull request #1128 from rojer/amalgam
Sync src with amalgamated versions
2020-07-12 15:32:42 +01:00
Deomid Ryabkov b0a1cd7b0d Sync src with amalgamated versions
Now src contains exactly what's embedded in mongoose.c and .h, nothing more.

Added `tools/amalgam.sh` to aamlgamate both files at once.

There are no functional changes to mongoose.c, .h in this PR, only slight filename changes.
2020-07-08 02:08:49 +01:00
novlean 73a2b92278 Merge pull request #1124 from cesanta/novlean-patch-1
added MWS white paper
2020-06-24 17:08:49 +01:00
novlean c3bb5bd89e added MWS white paper
Download “9 Things NOT to do when embedding a web server” white paper.
2020-06-24 17:08:35 +01:00
Sergey Lyubka d22ff2fce7 Really revert 4880069 2020-06-11 19:08:55 +01:00
Sergey Lyubka fee2980d95 Merge branch 'master' of github.com:cesanta/mongoose 2020-06-11 19:04:45 +01:00
Sergey Lyubka d6693ed360 Revert 4880069 2020-06-11 19:04:24 +01:00
Sergey Lyubka 4880069775 Fix #1112 2020-06-11 18:38:42 +01:00
Sergey Lyubka 5d217a1262 Merge branch 'dev' of github.com:cesanta/mongoose into dev 2020-06-11 18:29:58 +01:00
Sergey Lyubka f778d22eac Make it possible to override default FS update algorithm
PUBLISHED_FROM=774a111548da97bd9d195e177b5fb66b0fd66135
2020-06-11 18:27:48 +01:00
Sergey Lyubka 3aa76dcaec Subst CREDPARAMS
PUBLISHED_FROM=545e8dff4ea0bef061c893252c613e3429f56184
2020-06-11 18:27:46 +01:00
Deomid "rojer" Ryabkov 4680573a6b Fixes for -pedantic build mode
PUBLISHED_FROM=d0a15356cf047e579c74869ce3e8fe813752e8c7
2020-05-23 15:55:27 +00:00
Deomid "rojer" Ryabkov 95fcb261eb Fix processing of keep-alive requests when chunks are consumed
PUBLISHED_FROM=136ce2ed4f143d7ee246e5fd1078c431e205bb3a
2020-05-22 23:07:38 +00:00
Sergey Lyubka 5867c67da2 Allow OpenSSL session reuse on 2-way SSL, integrate https://github.com/cesanta/mongoose/pull/877
PUBLISHED_FROM=6e2568b963869d062dd51b590f8e536d043c4ca2
2020-05-22 18:56:31 +00:00
Sergey Lyubka 80d74e9e34 Merge branch 'dev' 2020-05-21 16:45:34 +01:00
Sergey Lyubka 43a0b500f5 6.17 -> 6.18
PUBLISHED_FROM=7893a216b1f7e86e845122eb425e4fed271244b4
2020-05-21 16:42:09 +01:00
Sergey Lyubka 3d53ed17fb Allow OpenSSL session reuse on 2-way SSL, integrate https://github.com/cesanta/mongoose/pull/877
PUBLISHED_FROM=6e2568b963869d062dd51b590f8e536d043c4ca2
2020-05-21 16:17:14 +01:00
Sergey Lyubka 4ea452307e Update certs used for SSL test
PUBLISHED_FROM=2236ecf7fe06bdaf9a89e697b83ff69e1f8c805c
2020-05-21 16:17:12 +01:00
Deomid "rojer" Ryabkov e61f20f1ed Convert amalgam.py to Python 3
No mongoose.{c,h} diffs

PUBLISHED_FROM=a995a6d6548a914087969e28908f4e8c9ef1d379
2020-05-09 10:48:41 +00:00
Sergey Lyubka ca11f5ab49 Fix OpenSSL error issue
PUBLISHED_FROM=a3bcdb68f48a4de4a4f55b4399792fdd5211c88d
2020-05-02 11:19:29 +00:00
Sergey Lyubka 000d24d31a Add http proxy client example
PUBLISHED_FROM=443a0d3db63df1b78555a9fa4eff808bef3a9a01
2020-03-25 16:32:49 +00:00
Sergey Lyubka ef92f2e9c5 Integrate cesanta/dev#1062 - Fix dereferencing in mg_http_free_proto_data_endpoints
PUBLISHED_FROM=47fd1a4de07d2c53c994d29c88ac1d3a7f61c1a0
2020-02-21 14:30:21 +00:00
Sergey Lyubka 4e89eac8dd Integrate cesanta/dev#1074 - Fix typedef bool for MSC
PUBLISHED_FROM=f52fe15edd617d9f1ba2aa4051c116e79671554d
2020-02-21 14:24:50 +00:00
Sergey Lyubka b015e33ea5 Integrate https://github.com/cesanta/mongoose/pull/1096 - dir listing nits
PUBLISHED_FROM=a343bd61f98cbcc0f8cab02a62b912e494c27601
2020-02-14 08:30:56 +00:00
Sergey Lyubka 96e762d4a1 Change contributions section
PUBLISHED_FROM=676548efdb09989c300693a81dd592fe1cd987b0
2020-02-14 08:30:54 +00:00
Sergey Lyubka 359060a151 mongoose.h 6.17 2020-02-11 12:11:10 +00:00
Sergey Lyubka af1aff7fbb mongoose.h 6.17 2020-02-11 12:10:13 +00:00
Sergey Lyubka 517ef216c1 6.16 -> 6.17
PUBLISHED_FROM=c0cbd13faf84fdac1f4566be02b596a232b68713
2020-02-11 11:54:54 +00:00
Sergey Lyubka 734c13cdf5 Squash win32 warnings
PUBLISHED_FROM=3819e74efb9ac8ff84a68105107afcacaeeab92a
2020-02-11 11:52:07 +00:00
Deomid "rojer" Ryabkov 1bf3ad2426 MQTT ping fixes
* Actually drop the connection when no response to ping arrives within the next interval.
 * Avoid sending immediate ping when wall time is adjusted, it's usually spurious.

PUBLISHED_FROM=8049280b58edfb94dd0fcb6a1e89ffefe69bcea1
2020-02-11 08:04:02 +00:00
Deomid "rojer" Ryabkov 884b9a4813 Add Content-Encoding: gzip when serving .gz files
If file ends with .gz and has known "secondary extnesion", i.e. test.html.gz,
its content type is determined by the secondary extension and content-encoding is set to gzip.

PUBLISHED_FROM=a238763b4424bafabec2e58ccae4522cacdd7c78
2020-02-01 08:33:49 +00:00
Deomid "rojer" Ryabkov 7153690016 Keep the size of the structure the same in non-SSL build
PUBLISHED_FROM=8f93bee72bc18efff64354203ee6268f4f8e8768
2020-01-31 11:01:35 +00:00
Deomid "rojer" Ryabkov f00b3a2b3a Move ssl_if_data to the end of mg_connection
PUBLISHED_FROM=4fb65477b03bedc3206ac286e8236f0f9536f20e
2020-01-31 09:48:30 +00:00
Deomid "rojer" Ryabkov c2b5e4f3b8 Fix a leak when CA certificate file is invalid
Also free up some RAM by not allocating ca_cert when `MBEDTLS_X509_CA_CHAIN_ON_DISK` is enabled.

PUBLISHED_FROM=5e5f4103707de98c929973d2aed0aaedf0bb60da
2020-01-22 10:03:30 +00:00
Deomid "rojer" Ryabkov bc15e9ce9a Fix value of MG_MQTT_DUP
PUBLISHED_FROM=de1772bd6ea01f3dc467ceebb3b2af5cbe8eb240
2020-01-20 09:33:25 +00:00
Deomid Ryabkov 70dc6d8dc9 Add mg_strcasecmp()
CL: Add mg_strcasecmp()

PUBLISHED_FROM=cd2a26fa12473bfa0f5e7a0a1d34fb86562ee082
2019-12-29 19:39:45 +00:00
Deomid Ryabkov 10b11b03a8 Add mg_dns_encode_name_s for non-NUL terminated strings
PUBLISHED_FROM=012e2939021d1b275a39632fd2982891d2c98c4e
2019-12-29 19:33:41 +00:00
Sergey Lyubka cb602f178c Fix int overflow in parse_mqtt()
PUBLISHED_FROM=f9106d2f746c67ae004aeab12685eaf9cd558cd8
2019-12-23 11:13:41 +00:00
Sergey Lyubka 464113c5ae Sync mongoose changes
PUBLISHED_FROM=8b6ebf46728aca40f916dde88e372b4540ed6ea4
2019-12-19 11:12:57 +00:00
Deomid Ryabkov c34f6c54e7 Fix ota-shadow logic
PUBLISHED_FROM=68a57c967f8864946244893c71a397ab4e27d75d
2019-12-07 09:03:26 +00:00
Sergey Lyubka 8fb58ebbca Lsm
PUBLISHED_FROM=5f465d245bb9ada5202cdd23ddc5b9856df26951
2019-11-04 13:48:28 +00:00
Sergey Lyubka dce60c6dbb Merge pull request #1054 from M4GNV5/master
fix typo in tools/README.md
2019-10-07 09:08:58 +01:00
Jakob Löw f668d08804 fix typo in tools/README.md 2019-10-01 00:14:11 +02:00
Sergey Lyubka c41a22195c Merge pull request #1020 from nliviu/patch-2
Fix ASAN build for examples/cookie_auth
2019-09-30 07:46:39 +01:00
Sergey Lyubka 900c05213b 6.15 -> 6.16 2019-09-30 07:44:10 +01:00
Sergey c5850e4b05 Merge branch 'dev' 2019-09-30 07:41:04 +01:00
Sergey Lyubka ff4649fe42 Better UI
PUBLISHED_FROM=50f0cafa84cd06428f0da376d85766dcf62af9da
2019-07-12 12:33:28 +00:00
Sergey Lyubka 1a38e91042 Next
PUBLISHED_FROM=6fa0be81ce429b8db9e3ed572cb4a876b6fb2693
2019-07-12 09:33:26 +00:00
Sergey Lyubka b6196371bb Lsm
PUBLISHED_FROM=18d9d1e6411db84788c527d1c34ad2adc846df00
2019-06-26 10:33:24 +00:00
Sergey Lyubka d5beb7ba3f Merge branch 'dev' 2019-06-13 09:50:09 +01:00
Sergey Lyubka 19acf23c49 6.14 -> 6.15
PUBLISHED_FROM=69f3a5f14d4ebce0fb89728fc345f90f1e7b1700
2019-06-13 08:49:37 +00:00
Sergey Lyubka 5cd3291fec Merge branch 'dev' 2019-06-13 09:45:43 +01:00
Sergey Lyubka b3e0f780c3 Fix heap-based overflow in parse_mqtt
PUBLISHED_FROM=3306592896298597fff5269634df0c1a1555113b
2019-06-13 08:18:14 +00:00
Sergey Lyubka 2bdbfc27f6 Integrate https://github.com/cesanta/mongoose/issues/1008
PUBLISHED_FROM=1b7bf2d7318568851e6c8f07451cd3982d9498b6
2019-06-13 07:48:28 +00:00
Sergey Lyubka 3fc61a3edc Fix mg_resolve2()
PUBLISHED_FROM=b0df728a75073c6ea9fc1984bb6a6b463f539347
2019-05-24 12:33:25 +00:00
Liviu 12339bbf4c Fix ASAN build
The ASAN build fails with
```
cookie_auth.c:62:7: error: variable 'ret' is used uninitialized whenever 'if' condition is true [-Werror,-Wsometimes-uninitialized]
  if (cookie_header == NULL) goto clean;
      ^~~~~~~~~~~~~~~~~~~~~
cookie_auth.c:84:10: note: uninitialized use occurs here
  return ret;
         ^~~
cookie_auth.c:62:3: note: remove the 'if' if its condition is always false
  if (cookie_header == NULL) goto clean;
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cookie_auth.c:65:3: note: variable 'ret' is declared here
  struct session *ret = NULL;
  ^
cookie_auth.c:62:7: error: variable 'ssid' is used uninitialized whenever 'if' condition is true [-Werror,-Wsometimes-uninitialized]
  if (cookie_header == NULL) goto clean;
      ^~~~~~~~~~~~~~~~~~~~~
cookie_auth.c:81:7: note: uninitialized use occurs here
  if (ssid != ssid_buf) {
      ^~~~
cookie_auth.c:62:3: note: remove the 'if' if its condition is always false
  if (cookie_header == NULL) goto clean;
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cookie_auth.c:64:3: note: variable 'ssid' is declared here
  char *ssid = ssid_buf;
  ^
2 errors generated.
```
2019-05-08 14:54:31 +03:00
Deomid Ryabkov 1fb9f922b0 Fix mgos compile check
CL: none

PUBLISHED_FROM=a1320658181aa19cd1a269d7ae62e11b3439ef84
2019-05-03 16:36:08 +00:00
Deomid Ryabkov b93bc02ab0 Delete mos tool and related libraries from dev
Moved to https://github.com/mongoose-os/mos

PUBLISHED_FROM=8a0475678dba38fd6e057b8a530e9d08054ff74f
2019-05-02 12:03:33 +00:00
novlean 747e393a54 updated link to forum
PUBLISHED_FROM=784159d816e78f18fbfa6826f18bdea7d88dccbb
2019-04-29 12:40:14 +00:00
Deomid Ryabkov 4e8660a21f RS14100 fixes
CL: none

PUBLISHED_FROM=4d5d68f92d6c082b5b0c25ed8935fc097939001f
2019-04-24 19:16:41 +00:00
Deomid Ryabkov 3fe77fa9a6 RS14100: Optimize flash reads
CL: none

PUBLISHED_FROM=49d4f4a3c83520fd6ec9714b74333f75f3a2aa1c
2019-04-24 16:18:28 +00:00
Deomid Ryabkov b4fbaf7c13 Fix locking in lwip net_if
Was not being enabled when it should have been.

CL: Fix locking in lwip net_if

PUBLISHED_FROM=4810e73417c7599f0ea08a09812ed320d02f7cae
2019-04-23 20:03:44 +00:00
Deomid Ryabkov 9884241df8 mg_net_if_lwip: Fix invoking callbacks on tcpip thread
tcpip_callback doesn't wait for the callback to run (as was previosuly assumed).

CL: mg_net_if_lwip: Fix invoking callbacks on tcpip thread

PUBLISHED_FROM=930c45f1346f9c3b024e5e684f4a452c762db92b
2019-04-15 16:33:40 +00:00
Deomid Ryabkov 63d7a4fa45 Core dump analysis improvements
* ARM
   * Provide MSP and PSP
   * Provide FreeRTOS task info
   * Profide target specification XML (extra regs and FPU / no FPU Cortex cores)
 * ESP32
   * Use uxTaskGetSystemState instead of uxTaskGetTaskHandles
 * General cleanup and refactoring

CL: Core dump analysis improvements

PUBLISHED_FROM=3297ffb2e6069a3a6a598367273bc2183063cf1e
2019-04-10 19:18:33 +00:00
Deomid Ryabkov 8f4b6c41a2 Make FreeRTOS a library, upgrade to 10.2.0
All the platforms except esp32 (which uses heavily patched 9.0 from IDF) and esp8266 (doesn't use RTOS at all) are using the same version of FreeRTOS now.

CL: Make FreeRTOS a library, upgrade to 10.2.0

PUBLISHED_FROM=a4f7949a9f1546d23fc183412445859830f02d1a
2019-04-01 19:02:26 +00:00
Deomid Ryabkov 4493d65ec9 RS14100: Flash and FS support, increase CPU and flash clock
Run CPU at 180 MHz, flash at up to 100.

CL: RS14100: FS support, increase CPU and flash clock

PUBLISHED_FROM=e9f995bf03e4e36dc66e19a2a2d60ae1675ecaae
2019-03-28 23:18:36 +00:00
Deomid Ryabkov e5910da300 Deliver EV_CLOSE to the last endpoint handler
CL: mg: Deliver EV_CLOSE to the last endpoint handler

PUBLISHED_FROM=02ee2c6627ed9ee1d35022244f71dfe1877ce2c0
2019-03-19 13:15:41 +00:00
Deomid Ryabkov c277a1d878 Do not amalgamate platform_custom.h include
CL: none

PUBLISHED_FROM=4f84111ef76bd609348c439304f46556ce5d4497
2019-03-12 11:48:27 +00:00
Deomid Ryabkov 7820ad3a59 RS14100: Blinky
The humble beginning...

CL: RS14100: Blinky

PUBLISHED_FROM=7f1dc4d826122ababae44b52c52ed84b15d0ae5c
2019-03-08 23:03:39 +00:00
Sergey Lyubka 23533b83a4 Allow NULL handler for mg_bind and mg_connect
CL:  Allow NULL handler for mg_bind and mg_connect

PUBLISHED_FROM=4963d5c022c2c57dd03101d9c7e72ca910c3bb61
2019-03-06 12:33:24 +00:00
Deomid Ryabkov ab650ec5c9 Merge branch 'dev' 2019-03-04 15:19:32 +00:00
Deomid Ryabkov 8f36597048 Mongoose 6.14
PUBLISHED_FROM=3e6e17d1f1cfb05efc37d76279dcbedb7f1add5d
2019-03-04 15:15:35 +00:00
Deomid Ryabkov d0213ee90a ESP32: Add support for the 3/4 key encoding scheme
* Add calculated redundancy values when writing eFuse blocks 1-3
 * Perform 192 -> 256 bit key extension when encrypting images for flashing

Fixes https://github.com/cesanta/mos-tool/issues/37

CL: mos: ESP32: Add support for the 3/4 key encoding scheme

PUBLISHED_FROM=16639fb25d5200550ad2097929239d896e188b5b
2019-03-04 09:18:28 +00:00
Deomid Ryabkov 1e9fabe1ca Fix handling of WS handshake error response
Check response code, make sure it's 101.
Pass http_message to the client to keep it appraised.
This represents a slight change in the API -
in case of an error MG_EV_WEBSOCKET_HANDSHAKE_DONE will now be delivered where previosuly connection would just hang.
Clients that do not examine the argument may for a moment think handshake has succeeded but in fact connection will be closed immediately.

CL: mg: Fix handling of WS handshake error response

PUBLISHED_FROM=645a43d9e5bee216e54411f85827c9b974e9a7d1
2019-02-14 21:19:34 +00:00
Deomid Ryabkov 148d3f0562 STM32F2 and Particle Electron board support
CL: STM32F2 and Particle Electron board support

PUBLISHED_FROM=20dede6546e9f99d2829508177924790d87e985a
2019-02-12 13:36:54 +00:00
Deomid Ryabkov c3057df3f5 Fix mongoose CI test
CL: none

PUBLISHED_FROM=9510e460251c250cb6a67a40edc0af515044f9fe
2019-02-08 17:38:56 +00:00
Deomid Ryabkov 0b2e474d52 Improve ESP flasher baud rate setting
Use old baud rate and autodetected divider to calculate new divider.

This works better with higher baud rates and drifting clocks.

CL: mos: Improve ESP flasher baud rate setting

PUBLISHED_FROM=7761e756c3ae7cc76e3b9a4fe3e40d06a779b2e8
2019-02-08 17:38:55 +00:00
Deomid Ryabkov 95a36b1759 Log file:line instead of function; add cs_log_set_file_level()
cs_log_set_filter() is removed in favor of cs_log_set_file_level() which
allows setting log verbosity of individual files and/or lines.

E.g.: `mg_=1,mjs=1,=4` - level for for everything except mjs and mongoose.

We use the fact that we are usually pretty careful with our file names and use prefixes consistently.

In mos, `debug.file_level` sets the option on boot and `Sys.SetDebug` is updated to parse `file_level` option to change it at runtime.

CL: Log file:line instead of function; add cs_log_set_file_level()

PUBLISHED_FROM=49f18d4d0d3dd224865129a4f8fe6cccd1d9bc12
2019-01-30 12:57:19 +00:00
Deomid Ryabkov 86ffa3a3ea Properly support MQTT wildcards when matching topics
CL: mg: Properly support MQTT wildcards when matching topics

PUBLISHED_FROM=aa60a71d488f4b56dff0951886c8a9a4066fd4f2
2019-01-22 12:19:04 +00:00
Deomid Ryabkov 69e2b2985d Add mg_strfree()
CL: Add mg_strfree()

PUBLISHED_FROM=b80566218986e0607a9d2758bf776a1031b27212
2019-01-16 22:48:59 +00:00
Бобби c431904b56 Send extra options with OPTIONS
CL: Send extra options with OPTIONS. Integrate https://github.com/cesanta/mongoose/pull/657

PUBLISHED_FROM=6ee609a92febd8d908f7713f94fb73657443a09a
2019-01-16 11:33:57 +00:00
Deomid Ryabkov c2a10601b9 Fix nsleep100 on STM32
CL: Fix nsleep100 on STM32

PUBLISHED_FROM=cabb98a0541bac9bb66bfa702d54bf8ff20063e7
2019-01-08 20:43:55 +00:00
Deomid Ryabkov e9a8e5468d Convert Python scripts to Python 3, delete unused ones
CL: none

PUBLISHED_FROM=4bbc2175634e20a726dd4b2dadff57f945b261d0
2018-12-25 20:38:58 +00:00
Sergey Lyubka 22e602debb Check for NULL in tcp_recved_tcpip()
CL: Check for NULL in tcp_recved_tcpip()

PUBLISHED_FROM=3f5bbc2e35b79d363eac4b99a1f0d17c9b81d4ec
2018-12-21 13:03:48 +00:00
Deomid Ryabkov 455cec67a5 CC3220: Enterprise auth support
CL: wifi: CC3220: Enterprise auth support

PUBLISHED_FROM=ce445eb5b740073c9a3f9811f1acd404ce134f2e
2018-12-18 18:19:21 +00:00
Deomid Ryabkov e2dfac946d Ensure that user sees all the data before connection is closed
If user throttles receive by setting recv_mbuf_limit,
after the net interface reports connection as closed we must wait
for data to trickle through before disposing of it.
There can still b data in the buffers (e.g. SSL).

CL: mg: Ensure that user sees all the data before connection is closed

PUBLISHED_FROM=22be0fa368950a9fdb03cfb00febc7c0a1674b01
2018-12-10 21:04:49 +00:00
Бобби c198d2e5f1 Make MG_CTL_MSG_MESSAGE_SIZE overridable
CL: Make MG_CTL_MSG_MESSAGE_SIZE overridable

Fix https://github.com/cesanta/mongoose/pull/987

PUBLISHED_FROM=b0a7c67297b98f616c9eadcd3c34b8747939c918
2018-12-07 10:04:00 +00:00
Deomid Ryabkov 9a70abef24 Add mbuf_append_and_free() and mbuf_move()
CL: Add mbuf_append_and_free() and mbuf_move()

PUBLISHED_FROM=bdf73906dd93b2ebeace160596508e15480b54b4
2018-12-05 21:49:01 +00:00
Deomid Ryabkov 53e1c469a2 Add ability for multipart data handler to provide pushback
It can specify how much data was actually processed and the rest will be re-delivered on next poll.

CL: mg: Add ability for multipart data handler to provide pushback

PUBLISHED_FROM=e0168c5064c3a32921c9209bc09f4da2079cd616
2018-12-05 16:02:56 +00:00
Deomid Ryabkov 139c2061a8 Add create-fw-bundle command
Replacement for fw_meta.py commands and also supports unbundling .hex files.

General syntax is:

```
 $ mos create-fw-bundle -o fw.zip part1:prop1=val1,prop2=val2,... part2:...
```

Example of building a mos fw bundle for ESP8266:
```
 $ mos create-fw-bundle -o fw.zip --platform esp8266 --build-info=build_info.json \
    boot:addr=0x0,src=rboot.bin,update=false \
    boot_cfg:addr=0x7000,size=0x1000,fill=0xff \
    fw:addr=0x100000,src=demo-c.bin \
    fs:src=fs.bin,type=fs,addr=0x8000,fs_size=262144,fs_block_size=4096,fs_page_size=256,fs_erase_size=4096
```

Example of converting a HEX file to a bundle:
```
 $ mos create-fw-bundle -o fw.zip host:type=host,src=hostfw.hex
```

CL: mos: Add create-fw-bundle command

PUBLISHED_FROM=35f52ea53e4b5900463415257323a4c08cf45deb
2018-11-28 20:34:06 +00:00
Deomid Ryabkov 15b361fbac Add mbuf_clear()
PUBLISHED_FROM=754b98b3000b24ad3b3d9cc0b4c480ca005a1c3f
2018-11-23 15:50:55 +00:00
Deomid Ryabkov 3130e59244 Stop reading if connection is closing
CL: none

PUBLISHED_FROM=3b74ca02e2960bbbf130f6d95aef679f2917e824
2018-11-02 18:12:34 +00:00
Deomid Ryabkov 93286836f9 Read all available data during recv poll
CL: mg: Read all available data during recv poll

PUBLISHED_FROM=b081025b9fb392c988924c7097b5333c38053f6f
2018-11-02 14:50:32 +00:00
Deomid Ryabkov 91b57aa9a8 Add MG_MK_STR_N() and mg_str_starts_with()
CL: Add MG_MK_STR_N() and mg_str_starts_with()

PUBLISHED_FROM=f01003efc6aa6ff45fa99c7ad6e5319f5002f22d
2018-10-29 15:50:31 +00:00
Deomid Ryabkov 220231e647 Fix digest auth result comparison
Should use length of the exected response, not the response sent by the user.

CL: mg: Fix digest auth result comparison

PUBLISHED_FROM=23375133b8babac0b276b51395917ad975e1bd3c
2018-10-15 16:47:18 +00:00
Deomid Ryabkov c438bb0bc5 Make mg_rpc more easily portable
CL: none

PUBLISHED_FROM=2e77d72cdf82454349a7fe29cc77bd0b90ac4369
2018-10-09 12:04:12 +00:00
Deomid Ryabkov 95afa323c0 Merge pull request #978 from cesanta/dev
Mongoose 6.13
2018-10-08 14:06:45 +01:00
Deomid Ryabkov bc56353a79 Mongoose 6.13
CL: none

PUBLISHED_FROM=32418b7da17a68193e88405547152f58a4dd877f
2018-10-08 12:20:32 +00:00
Deomid Ryabkov 1ffccdb7b2 Remove a spammy log line
PUBLISHED_FROM=b3ec2b3b43a464700a6e6d75b7336f823549cce3
2018-10-04 15:48:48 +00:00
Deomid Ryabkov e79fe4b8f0 Update mbedTLS to 2.13.1
CL: Update mbedTLS to 2.13.1

PUBLISHED_FROM=bd1216f727605a901f062a044c0c0ca762f4a6d1
2018-10-04 10:06:35 +00:00
Deomid Ryabkov aaf1fc3a4a Schedule a poll when LwIP reports TCP data sent
PUBLISHED_FROM=0cf3029d9a9b851882325e2298b878bc83fc2d33
2018-09-28 11:03:47 +00:00
Deomid Ryabkov 8b42353039 Check HTTP chunk size, ensure it's reasonable
CL: mg: Check HTTP chunk size, ensure it's reasonable

PUBLISHED_FROM=d9f6babd314c092b42ce9e7fe31d6b30a38366a2
2018-09-27 12:51:21 +00:00
Deomid Ryabkov 05c687e251 Fix handling of keepalive HTTP requests/responses
Clean the HTTP connection state when ia request/response has been fully
buffered and handler invoked.

Fixes https://github.com/cesanta/mongoose/issues/971

CL: mg: Fix handling of keepalive HTTP requests/responses

PUBLISHED_FROM=70c854aa306aacb9161f6ee48841f38dc0312e6b
2018-09-27 12:51:18 +00:00
Deomid Ryabkov 492b8f6950 CC3200: Fix boot loader regression
Go back to Ubuntu 16.04 and older gcc-arm (4.9.3).

Boot loader just won't run when compiled with newer GCC (7.x).
It's likely that it can be fixed with compile switches but I couldn't figure it out quickly, so going to just downgrade for now to get it back to workign state.

CL: CC3200: Fix boot loader regression

PUBLISHED_FROM=b70b03bd17e03c7dae02328b32b855f3ca3ad6a9
2018-09-25 20:32:35 +00:00
Deomid Ryabkov 8ccee82059 Add mgos_gpio_blink()
CL: Add mgos_gpio_blink()

PUBLISHED_FROM=a5d2e2f44413d1ab363abeeaf0fb497bd8f63d6d
2018-09-25 20:32:33 +00:00
Deomid Ryabkov b99a94a652 Fix build w/o logging
PUBLISHED_FROM=694346bd6562c55e5ab00886df47f7cbfb0a3720
2018-09-25 11:34:05 +00:00
Deomid Ryabkov 41e5d7e471 Use mbedTLS from mongoose-os-libs/mbedtls
mbedTLS is just another lib now

CL: Use mbedTLS from mongoose-os-libs/mbedtls

PUBLISHED_FROM=bae4739d22e871bd268b8a3233dbb69634770243
2018-09-20 20:38:11 +00:00
Sergey Lyubka 1adea37c45 Integrate https://github.com/cesanta/mongoose/pull/667, fix documentation
CL: Integrate https://github.com/cesanta/mongoose/pull/667, fix documentation

PUBLISHED_FROM=80a939fc3276b89c29716e7373f674dba86769ee
2018-09-20 15:34:36 +00:00
Deomid Ryabkov 98f6c8aa4f Trim recv_mbuf when we know the size of the data
CL: none

PUBLISHED_FROM=e354b67ab6f8246af50c601f5f70d36c029601ea
2018-09-17 16:04:00 +00:00
Deomid Ryabkov 341ae53e85 Update mongoose.h (amalgamation)
PUBLISHED_FROM=1fbe72f99bda5745c4b9b9def0601bdc5bf70e65
2018-09-14 21:19:15 +00:00
Sergey Lyubka 291fc024cd Docs nits
CL: Docs nits

PUBLISHED_FROM=1a2fc8080d94673acf300c6f07aba3a1e6272295
2018-09-14 08:03:58 +00:00
Deomid Ryabkov f63d833a33 Update STM32 build image
* Update CubeL4 to 1.13.0
 * Rebuild OurTLS with `-DMBEDTLS_X509_CA_CHAIN_ON_DISK`
 * Add `-Wextra` and fix build issues

CL: Update STM32 build image

PUBLISHED_FROM=a7eacff7580bab6c6e40bdaf6164df575a717c55
2018-09-11 11:49:08 +00:00
Deomid Ryabkov ab035901f8 ISM43XXX networking support (TCP, UDP client)
Listeners still TODO

CL: ISM43XXX networking support (TCP, UDP client)

PUBLISHED_FROM=b58ba88b9e6bd7b55ccb607d0b69cea98cb52fa5
2018-09-11 06:34:08 +00:00
Deomid Ryabkov 20f54059ad STM32: Make LWIP optional
CL: STM32: Make LWIP optional

PUBLISHED_FROM=eebffe7800a74d7b69aafd95e476b2e90328be98
2018-09-06 11:27:58 +00:00
Deomid Ryabkov 563c31303e Add net_if_null, a no-op net interface
Can be used for cases where device has no networking but mongoose is still needed for its event loop.

CL: mg: Add net_if_null, a no-op net interface

PUBLISHED_FROM=e79b4a8667508bbde1437dda9dad77ce3a3aa630
2018-09-06 08:34:17 +00:00
Deomid Ryabkov 421e099f2b Refactor mg polling
* Change return type of mg_mgr_poll to return number of events
 * Add mg_mgr_min_timer
 * Refactor main poll loop to remove LwIP-specific stuff

CL: Refactor mg polling

PUBLISHED_FROM=dc94618b32fa3c84a2f053bd04d134297780ec82
2018-09-06 06:34:18 +00:00
Бобби 955d4a3129 Fix file upload on windows
CL: Fix https://github.com/cesanta/mongoose/issues/962 - file upload on windows

PUBLISHED_FROM=85688eee147a1df468cca92f4ac61526ce9c02bf
2018-08-21 15:06:40 +00:00
Deomid Ryabkov b84981ad03 STM32 OTA support for L475-IOT01 and DISCO-F746
A smattering of other related changes

CL: STM32 OTA support for L475-IOT01 and DISCO-F746

PUBLISHED_FROM=e7142337086d09ba21437455b22d00db47ab33f1
2018-08-18 07:49:30 +00:00
246 changed files with 6769 additions and 28935 deletions

No files matched your search

+6
View File
@@ -0,0 +1,6 @@
BasedOnStyle: Google
AllowShortFunctionsOnASingleLine: false
SpaceAfterCStyleCast: true
PointerBindsToType: false
DerivePointerBinding: false
IncludeBlocks: Preserve
+2 -2
View File
@@ -1,5 +1,5 @@
Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com> Copyright (c) 2004-2013 Sergey Lyubka
Copyright (c) 2013-2018 Cesanta Software Limited Copyright (c) 2013-2020 Cesanta Software Limited
All rights reserved All rights reserved
This software is dual-licensed: you can redistribute it and/or modify This software is dual-licensed: you can redistribute it and/or modify
+2 -58
View File
@@ -2,67 +2,11 @@
![](https://img.shields.io/badge/license-GPL_2-green.svg "License") ![](https://img.shields.io/badge/license-GPL_2-green.svg "License")
Mongoose is ideal for embedded environments. It has been designed This branch is only for use by [Mongoose OS](https://github.com/cesanta/mongoose-os),
for connecting devices and bringing them online. On the market since 2004, for other projects please use the master branch.
used by vast number of open source and
commercial products - it even runs on the International Space station!
Mongoose makes embedded network programming fast, robust, and easy.
- [Download Mongoose Source Code here](https://www.cesanta.com/download.html)
Looking for a complete IoT firmware solution?
Check out [Mongoose OS](https://mongoose-os.com) - open source embedded operating system for low-power connected microcontrollers. Secure, designed for Internet of Things, complete environment for prototyping, development and managing.
# Support
- [Study mongoose example code](https://github.com/cesanta/mongoose/tree/master/examples)
- [Read User Guide and API reference](https://cesanta.com/docs/overview/intro.html)
- [Support Forum - ask your technical questions here](https://forum.mongoose-os.com/categories/mongoose)
- [Commercial licensing and support available](https://www.cesanta.com/licensing.html)
- [Check our latest releases](https://github.com/cesanta/mongoose/releases)
# Features
* Cross-platform: works on Linux/UNIX, MacOS, QNX, eCos, Windows, Android,
iPhone, FreeRTOS (TI CC3200, ESP8266), etc
* Supported hardware platforms: TI CC3200, TI MSP432, NRF52, STM32, PIC32, ESP8266, ESP32 and more
* Builtin protocols:
- plain TCP, plain UDP, SSL/TLS (over TCP, one-way or two-way)
- HTTP client, HTTP server
- WebSocket client, WebSocket server
- MQTT client, MQTT broker
- CoAP client, CoAP server
- DNS client, DNS server, async DNS resolver
* Single-threaded, asynchronous, non-blocking core with simple event-based API
* Native support for [PicoTCP embedded TCP/IP stack](http://www.picotcp.com),
[LWIP embedded TCP/IP stack](https://en.wikipedia.org/wiki/LwIP)
* Tiny static and run-time footprint
* Source code is both ISO C and ISO C++ compliant
* Very easy to integrate: just copy
[mongoose.c](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.c) and
[mongoose.h](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.h)
files to your build tree
# Licensing # 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. 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) Commercial Projects: [Contact us for commercial license.](https://www.cesanta.com/contact.html)
# Dashboard Example
Mongoose is often used to implement device dashboards and real-time
data exchange over Websocket. Here is a dashboard example that illustrates
the functionality:
![](http://www.cesanta.com/images/dashboard.png)
[Developing a new product? Contact us today to discuss how Mongoose can help.](https://www.cesanta.com/contact.html)
# Contributions
To submit contributions, sign [Cesanta CLA](https://cesanta.com/cla.html)
and send GitHub pull request.
# 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)
+4 -1
View File
@@ -1,12 +1,15 @@
--- ---
title: "Memory Buffers" title: "mbuf.h"
symbol_kind: "intro" symbol_kind: "intro"
decl_name: "mbuf.h" decl_name: "mbuf.h"
items: items:
- { name: mbuf_append.md } - { name: mbuf_append.md }
- { name: mbuf_append_and_free.md }
- { name: mbuf_clear.md }
- { name: mbuf_free.md } - { name: mbuf_free.md }
- { name: mbuf_init.md } - { name: mbuf_init.md }
- { name: mbuf_insert.md } - { name: mbuf_insert.md }
- { name: mbuf_move.md }
- { name: mbuf_remove.md } - { name: mbuf_remove.md }
- { name: mbuf_resize.md } - { name: mbuf_resize.md }
- { name: mbuf_trim.md } - { name: mbuf_trim.md }
+13
View File
@@ -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.
+10
View File
@@ -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).
+10
View File
@@ -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 - MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received the WebSocket
handshake request. `ev_data` contains parsed HTTP request. handshake request. `ev_data` contains parsed HTTP request.
- MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed the WebSocket - 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 - MG_EV_WEBSOCKET_FRAME: new WebSocket frame has arrived. `ev_data` is
`struct websocket_message *` `struct websocket_message *`
@@ -29,6 +29,12 @@ signature: |
/* Headers */ /* Headers */
struct mg_str header_names[MG_MAX_HTTP_HEADERS]; struct mg_str header_names[MG_MAX_HTTP_HEADERS];
struct mg_str header_values[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; struct mg_str data;
int status; /* <0 on error */ int status; /* <0 on error */
void *user_data; 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;
}; };
--- ---
+1 -1
View File
@@ -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 `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 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 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.
+1 -1
View File
@@ -3,7 +3,7 @@ title: "mg_mgr_free()"
decl_name: "mg_mgr_free" decl_name: "mg_mgr_free"
symbol_kind: "func" symbol_kind: "func"
signature: | signature: |
void mg_mgr_free(struct mg_mgr *); void mg_mgr_free(struct mg_mgr *mgr);
--- ---
De-initialises Mongoose manager. De-initialises Mongoose manager.
+2 -2
View File
@@ -3,11 +3,11 @@ title: "mg_mgr_poll()"
decl_name: "mg_mgr_poll" decl_name: "mg_mgr_poll"
symbol_kind: "func" symbol_kind: "func"
signature: | 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 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. `milli` is the maximum number of milliseconds to sleep.
`mg_mgr_poll()` checks all connections for IO readiness. If at least one `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 of the connections is IO-ready, `mg_mgr_poll()` triggers the respective
+13 -6
View File
@@ -16,9 +16,6 @@ signature: |
struct mbuf send_mbuf; /* Data scheduled for sending */ struct mbuf send_mbuf; /* Data scheduled for sending */
time_t last_io_time; /* Timestamp of the last socket IO */ time_t last_io_time; /* Timestamp of the last socket IO */
double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */ 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 */ mg_event_handler_t proto_handler; /* Protocol-specific event handler */
void *proto_data; /* Protocol-specific data */ void *proto_data; /* Protocol-specific data */
void (*proto_data_destructor)(void *proto_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_READ (1 << 6) /* SSL specific */
#define MG_F_WANT_WRITE (1 << 7) /* SSL specific */ #define MG_F_WANT_WRITE (1 << 7) /* SSL specific */
#define MG_F_IS_WEBSOCKET (1 << 8) /* Websocket 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 */ /* Flags that are settable by user */
#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */ #define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
#define MG_F_CLOSE_IMMEDIATELY (1 << 11) /* Disconnect */ #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_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_2 (1 << 21)
#define MG_F_USER_3 (1 << 22) #define MG_F_USER_3 (1 << 22)
#define MG_F_USER_4 (1 << 23) #define MG_F_USER_4 (1 << 23)
#define MG_F_USER_5 (1 << 24) #define MG_F_USER_5 (1 << 24)
#define MG_F_USER_6 (1 << 25) #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
}; };
--- ---
+1
View File
@@ -13,6 +13,7 @@ signature: |
#endif #endif
void *user_data; /* User data */ void *user_data; /* User data */
int num_ifaces; int num_ifaces;
int num_calls;
struct mg_iface **ifaces; /* network interfaces */ struct mg_iface **ifaces; /* network interfaces */
const char *nameserver; /* DNS server to use */ const char *nameserver; /* DNS server to use */
}; };
+1 -1
View File
@@ -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 behave. Below is a list of connection flags that are meant to be set by event
handlers: 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 to the `send_mbuf`. As soon as Mongoose sends it to the socket, the
connection will be closed. connection will be closed.
* `MG_F_BUFFER_BUT_DONT_SEND` tells Mongoose to append data to the `send_mbuf` * `MG_F_BUFFER_BUT_DONT_SEND` tells Mongoose to append data to the `send_mbuf`
+2 -1
View File
@@ -98,7 +98,8 @@ bool bm222_get_data(struct bm222_ctx *ctx) {
s->y = v[3]; s->y = v[3];
s->z = v[5]; s->z = v[5];
if (d > max_d) max_d = d; 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. */ return (overflow ? bm222_fifo_init(ctx) : true); /* Clear the ovf flag. */
+84 -14
View File
@@ -1,11 +1,25 @@
/* /*
* Copyright (c) 2014-2016 Cesanta Software Limited * Copyright (c) 2014-2018 Cesanta Software Limited
* All rights reserved * 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_ #ifndef CS_COMMON_CS_DBG_H_
#define CS_COMMON_CS_DBG_H_ #define CS_COMMON_CS_DBG_H_
#include "common/platform.h"
#if CS_ENABLE_STDIO #if CS_ENABLE_STDIO
#include <stdio.h> #include <stdio.h>
#endif #endif
@@ -14,6 +28,10 @@
#define CS_ENABLE_DEBUG 0 #define CS_ENABLE_DEBUG 0
#endif #endif
#ifndef CS_LOG_PREFIX_LEN
#define CS_LOG_PREFIX_LEN 24
#endif
#ifndef CS_LOG_ENABLE_TS_DIFF #ifndef CS_LOG_ENABLE_TS_DIFF
#define CS_LOG_ENABLE_TS_DIFF 0 #define CS_LOG_ENABLE_TS_DIFF 0
#endif #endif
@@ -22,6 +40,9 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
/*
* Log level; `LL_INFO` is the default. Use `cs_log_set_level()` to change it.
*/
enum cs_log_level { enum cs_log_level {
LL_NONE = -1, LL_NONE = -1,
LL_ERROR = 0, LL_ERROR = 0,
@@ -34,29 +55,78 @@ enum cs_log_level {
_LL_MAX = 5, _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); 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 #if CS_ENABLE_STDIO
/*
* Set file to write logs into. If `NULL`, logs go to `stderr`.
*/
void cs_log_set_file(FILE *file); void cs_log_set_file(FILE *file);
extern enum cs_log_level cs_log_threshold; /*
void cs_log_print_prefix(const char *func); * Prints log to the current log file, appends "\n" in the end and flushes the
void cs_log_printf(const char *fmt, ...); * stream.
*/
void cs_log_printf(const char *fmt, ...) PRINTF_LIKE(1, 2);
#define LOG(l, x) \ #if CS_ENABLE_STDIO
if (cs_log_threshold >= l) { \
cs_log_print_prefix(__func__); \ /*
cs_log_printf x; \ * 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 #ifndef CS_NDEBUG
#define DBG(x) \ /*
if (cs_log_threshold >= LL_VERBOSE_DEBUG) { \ * Shortcut for `LOG(LL_VERBOSE_DEBUG, (...))`
cs_log_print_prefix(__func__); \ */
cs_log_printf x; \ #define DBG(x) LOG(LL_VERBOSE_DEBUG, x)
}
#else /* NDEBUG */ #else /* NDEBUG */
+2 -2
View File
@@ -50,7 +50,7 @@
#define BM222_ADDR 0x18 #define BM222_ADDR 0x18
#define TMP006_ADDR 0x41 #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 = static const char *upload_form =
"\ "\
@@ -70,7 +70,7 @@ static struct mg_str upload_fname(struct mg_connection *nc,
if (nc->user_data != NULL) { if (nc->user_data != NULL) {
intptr_t cl = (intptr_t) nc->user_data; intptr_t cl = (intptr_t) nc->user_data;
if (cl >= 0) { 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; lfn.len = fname.len + 4;
+2 -2
View File
@@ -25,7 +25,7 @@ void SimpleLinkWlanEventHandler(SlWlanEvent_t *e) {
LOG(LL_INFO, ("WiFi: station disconnected")); LOG(LL_INFO, ("WiFi: station disconnected"));
break; break;
default: 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) { } else if (e->Event == SL_NETAPP_IP_LEASED_EVENT) {
LOG(LL_INFO, ("IP leased")); LOG(LL_INFO, ("IP leased"));
} else { } else {
LOG(LL_INFO, ("NetApp event %d", e->Event)); LOG(LL_INFO, ("NetApp event %d", (int) e->Event));
} }
} }
+2 -2
View File
@@ -58,11 +58,11 @@ static int check_pass(const char *user, const char *pass) {
* or NULL if not found. * or NULL if not found.
*/ */
static struct session *get_session(struct http_message *hm) { 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_buf[21];
char *ssid = ssid_buf; char *ssid = ssid_buf;
struct session *ret = NULL; 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, if (!mg_http_parse_header2(cookie_header, SESSION_COOKIE_NAME, &ssid,
sizeof(ssid_buf))) { sizeof(ssid_buf))) {
goto clean; goto clean;
+4
View File
@@ -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 int s_is_connected = 0;
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
struct websocket_message *wm = (struct websocket_message *) ev_data;
(void) nc; (void) nc;
switch (ev) { switch (ev) {
@@ -26,8 +25,14 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
break; break;
} }
case MG_EV_WEBSOCKET_HANDSHAKE_DONE: { case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
printf("-- Connected\n"); struct http_message *hm = (struct http_message *) ev_data;
s_is_connected = 1; 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; break;
} }
case MG_EV_POLL: { case MG_EV_POLL: {
@@ -66,6 +71,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
break; break;
} }
case MG_EV_WEBSOCKET_FRAME: { case MG_EV_WEBSOCKET_FRAME: {
struct websocket_message *wm = (struct websocket_message *) ev_data;
printf("%.*s\n", (int) wm->size, wm->data); printf("%.*s\n", (int) wm->size, wm->data);
break; break;
} }
+1393 -1342
View File
File diff suppressed because it is too large. Load diff
+294 -604
View File
File diff suppressed because it is too large. Load diff
+6
View File
@@ -0,0 +1,6 @@
BasedOnStyle: Google
AllowShortFunctionsOnASingleLine: false
SpaceAfterCStyleCast: true
PointerBindsToType: false
DerivePointerBinding: false
IncludeBlocks: Preserve
-1
View File
@@ -1 +0,0 @@
exclude_files=sha1\.c
+191
View File
@@ -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 */
+50
View File
@@ -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_ */
+66 -44
View File
@@ -1,19 +1,3 @@
/*
* 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.
*/
#include "common/cs_dbg.h" #include "common/cs_dbg.h"
@@ -24,7 +8,7 @@
#include "common/cs_time.h" #include "common/cs_time.h"
#include "common/str_util.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 #if CS_ENABLE_DEBUG
LL_VERBOSE_DEBUG; LL_VERBOSE_DEBUG;
#else #else
@@ -32,10 +16,9 @@ enum cs_log_level cs_log_threshold WEAK =
#endif #endif
#if CS_ENABLE_STDIO #if CS_ENABLE_STDIO
static char *s_filter_pattern = NULL; static char *s_file_level = NULL;
static size_t s_filter_pattern_len;
void cs_log_set_filter(const char *pattern) WEAK; void cs_log_set_file_level(const char *file_level) WEAK;
FILE *cs_log_file WEAK = NULL; FILE *cs_log_file WEAK = NULL;
@@ -45,34 +28,72 @@ double cs_log_ts WEAK;
enum cs_log_level cs_log_cur_msg_level WEAK = LL_NONE; enum cs_log_level cs_log_cur_msg_level WEAK = LL_NONE;
void cs_log_set_filter(const char *pattern) { /* In implementations that require locking, these can be overridden. */
free(s_filter_pattern); void cs_log_lock(void) WEAK;
if (pattern != NULL) { void cs_log_lock(void) {
s_filter_pattern = strdup(pattern);
s_filter_pattern_len = strlen(pattern);
} else {
s_filter_pattern = NULL;
s_filter_pattern_len = 0;
}
} }
int cs_log_print_prefix(enum cs_log_level, const char *, const char *) WEAK; void cs_log_unlock(void) WEAK;
int cs_log_print_prefix(enum cs_log_level level, const char *func, void cs_log_unlock(void) {
const char *filename) { }
char prefix[21];
if (level > cs_log_threshold) return 0; void cs_log_set_file_level(const char *file_level) {
if (s_filter_pattern != NULL && char *fl = s_file_level;
mg_match_prefix(s_filter_pattern, s_filter_pattern_len, func) == 0 && if (file_level != NULL) {
mg_match_prefix(s_filter_pattern, s_filter_pattern_len, filename) == 0) { s_file_level = strdup(file_level);
return 0; } 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); ll = (ln < 10000 ? (ln < 1000 ? (ln < 100 ? (ln < 10 ? 1 : 2) : 3) : 4) : 5);
prefix[20] = '\0'; 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; if (cs_log_file == NULL) cs_log_file = stderr;
cs_log_cur_msg_level = level; 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 #if CS_LOG_ENABLE_TS_DIFF
{ {
double now = cs_time(); double now = cs_time();
@@ -92,6 +113,7 @@ void cs_log_printf(const char *fmt, ...) {
fputc('\n', cs_log_file); fputc('\n', cs_log_file);
fflush(cs_log_file); fflush(cs_log_file);
cs_log_cur_msg_level = LL_NONE; cs_log_cur_msg_level = LL_NONE;
cs_log_unlock();
} }
void cs_log_set_file(FILE *file) WEAK; void cs_log_set_file(FILE *file) WEAK;
@@ -101,15 +123,15 @@ void cs_log_set_file(FILE *file) {
#else #else
void cs_log_set_filter(const char *pattern) { void cs_log_set_file_level(const char *file_level) {
(void) pattern; (void) file_level;
} }
#endif /* CS_ENABLE_STDIO */ #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) WEAK;
void cs_log_set_level(enum cs_log_level level) { 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 #if CS_LOG_ENABLE_TS_DIFF && CS_ENABLE_STDIO
cs_log_ts = cs_time(); cs_log_ts = cs_time();
#endif #endif
+22 -55
View File
@@ -1,19 +1,3 @@
/*
* 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_ #ifndef CS_COMMON_CS_DBG_H_
#define CS_COMMON_CS_DBG_H_ #define CS_COMMON_CS_DBG_H_
@@ -28,6 +12,10 @@
#define CS_ENABLE_DEBUG 0 #define CS_ENABLE_DEBUG 0
#endif #endif
#ifndef CS_LOG_PREFIX_LEN
#define CS_LOG_PREFIX_LEN 24
#endif
#ifndef CS_LOG_ENABLE_TS_DIFF #ifndef CS_LOG_ENABLE_TS_DIFF
#define CS_LOG_ENABLE_TS_DIFF 0 #define CS_LOG_ENABLE_TS_DIFF 0
#endif #endif
@@ -58,51 +46,28 @@ enum cs_log_level {
void cs_log_set_level(enum cs_log_level level); void cs_log_set_level(enum cs_log_level level);
/* /*
* Set log filter. NULL (a default) logs everything. * A comma-separated set of prefix=level.
* Otherwise, function name and file name will be tested against the given * prefix is matched against the log prefix exactly as printed, including line
* pattern, and only matching messages will be printed. * 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 * Helper function which prints message prefix with the given `level`.
* name `func` and `filename`. If message should be printed (accordingly to the * If message should be printed (according to the current log level
* current log level and filter), prints the prefix and returns 1, otherwise * and filter), prints the prefix and returns 1, otherwise returns 0.
* returns 0.
* *
* Clients should typically just use `LOG()` macro. * Clients should typically just use `LOG()` macro.
*/ */
int cs_log_print_prefix(enum cs_log_level level, const char *func, int cs_log_print_prefix(enum cs_log_level level, const char *fname, int line);
const char *filename);
extern enum cs_log_level cs_log_threshold; extern enum cs_log_level cs_log_level;
#if CS_ENABLE_STDIO #if CS_ENABLE_STDIO
@@ -127,9 +92,11 @@ void cs_log_printf(const char *fmt, ...) PRINTF_LIKE(1, 2);
* LOG(LL_DEBUG, ("my debug message: %d", 123)); * LOG(LL_DEBUG, ("my debug message: %d", 123));
* ``` * ```
*/ */
#define LOG(l, x) \ #define LOG(l, x) \
do { \ do { \
if (cs_log_print_prefix(l, __func__, __FILE__)) cs_log_printf x; \ if (cs_log_print_prefix(l, __FILE__, __LINE__)) { \
cs_log_printf x; \
} \
} while (0) } while (0)
#else #else
+92
View File
@@ -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;
+35
View File
@@ -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_ */
+28
View File
@@ -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
View File
@@ -1,3 +1,4 @@
/* /*
* This code implements the MD5 message-digest algorithm. * This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was * The algorithm is due to Ron Rivest. This code was
-16
View File
@@ -1,19 +1,3 @@
/*
* 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_MD5_H_ #ifndef CS_COMMON_MD5_H_
#define CS_COMMON_MD5_H_ #define CS_COMMON_MD5_H_
+254
View File
@@ -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 */
+35
View File
@@ -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_ */
-16
View File
@@ -1,19 +1,3 @@
/*
* 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.
*/
#include "common/cs_time.h" #include "common/cs_time.h"
-16
View File
@@ -1,19 +1,3 @@
/*
* 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_TIME_H_ #ifndef CS_COMMON_CS_TIME_H_
#define CS_COMMON_CS_TIME_H_ #define CS_COMMON_CS_TIME_H_
+135
View File
@@ -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 */
+95
View File
@@ -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_ */
-16
View File
@@ -1,19 +1,3 @@
/*
* 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_MG_MEM_H_ #ifndef CS_COMMON_MG_MEM_H_
#define CS_COMMON_MG_MEM_H_ #define CS_COMMON_MG_MEM_H_
+163
View File
@@ -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);
}
+97
View File
@@ -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_ */
+10 -1
View File
@@ -1,3 +1,4 @@
#ifndef CS_COMMON_PLATFORM_H_ #ifndef CS_COMMON_PLATFORM_H_
#define CS_COMMON_PLATFORM_H_ #define CS_COMMON_PLATFORM_H_
@@ -22,8 +23,9 @@
#define CS_P_NRF51 12 #define CS_P_NRF51 12
#define CS_P_NRF52 10 #define CS_P_NRF52 10
#define CS_P_PIC32 11 #define CS_P_PIC32 11
#define CS_P_RS14100 18
#define CS_P_STM32 16 #define CS_P_STM32 16
/* Next id: 18 */ /* Next id: 19 */
/* If not specified explicitly, we guess platform by defines. */ /* If not specified explicitly, we guess platform by defines. */
#ifndef CS_PLATFORM #ifndef CS_PLATFORM
@@ -55,6 +57,8 @@
#elif defined(TARGET_IS_TM4C129_RA0) || defined(TARGET_IS_TM4C129_RA1) || \ #elif defined(TARGET_IS_TM4C129_RA0) || defined(TARGET_IS_TM4C129_RA1) || \
defined(TARGET_IS_TM4C129_RA2) defined(TARGET_IS_TM4C129_RA2)
#define CS_PLATFORM CS_P_TM4C129 #define CS_PLATFORM CS_P_TM4C129
#elif defined(RS14100)
#define CS_PLATFORM CS_P_RS14100
#elif defined(STM32) #elif defined(STM32)
#define CS_PLATFORM CS_P_STM32 #define CS_PLATFORM CS_P_STM32
#endif #endif
@@ -69,6 +73,7 @@
#define MG_NET_IF_SIMPLELINK 2 #define MG_NET_IF_SIMPLELINK 2
#define MG_NET_IF_LWIP_LOW_LEVEL 3 #define MG_NET_IF_LWIP_LOW_LEVEL 3
#define MG_NET_IF_PIC32 4 #define MG_NET_IF_PIC32 4
#define MG_NET_IF_NULL 5
#define MG_SSL_IF_OPENSSL 1 #define MG_SSL_IF_OPENSSL 1
#define MG_SSL_IF_MBEDTLS 2 #define MG_SSL_IF_MBEDTLS 2
@@ -88,7 +93,11 @@
#include "common/platforms/platform_nxp_lpc.h" #include "common/platforms/platform_nxp_lpc.h"
#include "common/platforms/platform_nxp_kinetis.h" #include "common/platforms/platform_nxp_kinetis.h"
#include "common/platforms/platform_pic32.h" #include "common/platforms/platform_pic32.h"
#include "common/platforms/platform_rs14100.h"
#include "common/platforms/platform_stm32.h" #include "common/platforms/platform_stm32.h"
#if CS_PLATFORM == CS_P_CUSTOM
#include <platform_custom.h>
#endif
/* Common stuff */ /* Common stuff */
-180
View File
@@ -1,180 +0,0 @@
/*
* 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.
*/
#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
}
-69
View File
@@ -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
-34
View File
@@ -1,34 +0,0 @@
/*
* 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.
*/
#include <math.h>
#include "mgos.h"
#include "mgos_system.h"
void (*mgos_nsleep100)(uint32_t n);
uint32_t mgos_nsleep100_loop_count = 0;
/* Provided by arm_nsleep100_{m4,m7}.S for M4 and M7 respectively. */
extern void mgos_nsleep100_impl(uint32_t n);
void mgos_nsleep100_cal(void) {
uint32_t cpu_freq = mgos_get_cpu_freq();
/* # of instruction cycles per 100 ns */
mgos_nsleep100_loop_count =
roundf((100.0f / 1000000000.0f) / (1.0f / cpu_freq));
mgos_nsleep100 = mgos_nsleep100_impl;
}
@@ -1,46 +0,0 @@
/*
* 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.
*/
.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 mgos_nsleep100_impl
.global mgos_nsleep100_loop_count
.section .iram.mgos_nsleep100_impl
.type mgos_nsleep100_impl, %function
.align 4
mgos_nsleep100_impl:
ldr r3, =mgos_nsleep100_loop_count
ldr r3, [r3]
mul r0, r3
mov r1, #6
udiv r0, r0, r1
cbz r0, xxx
lxx:
subs r0, #1
bne lxx
xxx:
bx lr
.align 4
.size mgos_nsleep100_impl, . - mgos_nsleep100_impl
@@ -1,45 +0,0 @@
/*
* 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.
*/
.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 mgos_nsleep100_impl
.global mgos_nsleep100_loop_count
.section .iram.mgos_nsleep100_impl
.type mgos_nsleep100_impl, %function
.align 4
mgos_nsleep100_impl:
ldr r3, =mgos_nsleep100_loop_count
ldr r3, [r3]
/* Because of speculative fetch, the core loop only takes 1 cycle. */
muls r0, r3
cbz r0, xxx
lxx:
subs r0, #1
bne lxx
xxx:
bx lr
.align 4
.size mgos_nsleep100_impl, . - mgos_nsleep100_impl
-92
View File
@@ -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
}
-16
View File
@@ -1,19 +1,3 @@
/*
* 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.
*/
#if CS_PLATFORM == CS_P_CC3200 #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)
}
-52
View File
@@ -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
-52
View File
@@ -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
-35
View File
@@ -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;
}
-9
View File
@@ -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_ */
-557
View File
@@ -1,557 +0,0 @@
/*
* 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.
*/
#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;
}
-96
View File
@@ -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
-4
View File
@@ -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
-163
View File
@@ -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);
}
-16
View File
@@ -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
-4
View File
@@ -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
-28
View File
@@ -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
-51
View File
@@ -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"
-50
View File
@@ -1,50 +0,0 @@
/*
* 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.
*/
#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);
}
}
-23
View File
@@ -1,23 +0,0 @@
/*
* 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.
*/
#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
-46
View File
@@ -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,41 +0,0 @@
/*
* 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.
*/
#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) {
}
}
-27
View File
@@ -1,27 +0,0 @@
/*
* 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.
*/
#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);
}
-25
View File
@@ -1,25 +0,0 @@
/*
* 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_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_ */
-77
View File
@@ -1,77 +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"
$(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 \
-Wno-missing-field-initializers \
-pipe -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=gnu99 $(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
-123
View File
@@ -1,123 +0,0 @@
/*
* 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.
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "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,65 +0,0 @@
/*
* 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_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,76 +0,0 @@
/*
* 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_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,29 +0,0 @@
/*
* 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_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,120 +0,0 @@
/*
* 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.
*/
#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,35 +0,0 @@
/*
* 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.
*/
#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.
Loaded 100 of 246 files, more files were not shown because too many files have changed in this diff. Show more