Skip to content

Commit 2b4016e

Browse files
Merge branch 'master' into signedupdates
2 parents b3b7477 + 2f43807 commit 2b4016e

20 files changed

+589
-60
lines changed

cores/esp8266/StackThunk.c

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
StackThunk.c - Allow use second stack for BearSSL calls
3+
4+
BearSSL uses a significant amount of stack space, much larger than
5+
the default Arduino core stack. These routines handle swapping
6+
between a secondary, user-allocated stack on the heap and the real
7+
stack.
8+
9+
Copyright (c) 2017 Earle F. Philhower, III. All rights reserved.
10+
11+
This library is free software; you can redistribute it and/or
12+
modify it under the terms of the GNU Lesser General Public
13+
License as published by the Free Software Foundation; either
14+
version 2.1 of the License, or (at your option) any later version.
15+
16+
This library is distributed in the hope that it will be useful,
17+
but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19+
Lesser General Public License for more details.
20+
21+
You should have received a copy of the GNU Lesser General Public
22+
License along with this library; if not, write to the Free Software
23+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24+
Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
25+
*/
26+
27+
#include <stdint.h>
28+
#include <stdlib.h>
29+
#include "StackThunk.h"
30+
31+
uint32_t *stack_thunk_ptr = NULL;
32+
uint32_t *stack_thunk_top = NULL;
33+
uint32_t *stack_thunk_save = NULL; /* Saved A1 while in BearSSL */
34+
uint32_t stack_thunk_refcnt = 0;
35+
36+
#define _stackSize (5600/4)
37+
#define _stackPaint 0xdeadbeef
38+
39+
/* Add a reference, and allocate the stack if necessary */
40+
void stack_thunk_add_ref()
41+
{
42+
stack_thunk_refcnt++;
43+
if (stack_thunk_refcnt == 1) {
44+
stack_thunk_ptr = (uint32_t *)malloc(_stackSize * sizeof(uint32_t));
45+
stack_thunk_top = stack_thunk_ptr + _stackSize - 1;
46+
stack_thunk_save = NULL;
47+
stack_thunk_repaint();
48+
}
49+
}
50+
51+
/* Drop a reference, and free stack if no more in use */
52+
void stack_thunk_del_ref()
53+
{
54+
if (stack_thunk_refcnt == 0) {
55+
/* Error! */
56+
return;
57+
}
58+
stack_thunk_refcnt--;
59+
if (!stack_thunk_refcnt) {
60+
free(stack_thunk_ptr);
61+
stack_thunk_ptr = NULL;
62+
stack_thunk_top = NULL;
63+
stack_thunk_save = NULL;
64+
}
65+
}
66+
67+
void stack_thunk_repaint()
68+
{
69+
for (int i=0; i < _stackSize; i++) {
70+
stack_thunk_ptr[i] = _stackPaint;
71+
}
72+
}
73+
74+
/* Simple accessor functions used by postmortem */
75+
uint32_t stack_thunk_get_refcnt() {
76+
return stack_thunk_refcnt;
77+
}
78+
79+
uint32_t stack_thunk_get_stack_top() {
80+
return (uint32_t)stack_thunk_top;
81+
}
82+
83+
uint32_t stack_thunk_get_stack_bot() {
84+
return (uint32_t)stack_thunk_ptr;
85+
}
86+
87+
uint32_t stack_thunk_get_cont_sp() {
88+
return (uint32_t)stack_thunk_save;
89+
}
90+
91+
/* Return the number of bytes ever used since the stack was created */
92+
uint32_t stack_thunk_get_max_usage()
93+
{
94+
uint32_t cnt = 0;
95+
96+
/* No stack == no usage by definition! */
97+
if (!stack_thunk_ptr) {
98+
return 0;
99+
}
100+
101+
for (cnt=0; (cnt < _stackSize) && (stack_thunk_ptr[cnt] == _stackPaint); cnt++) {
102+
/* Noop, all work done in for() */
103+
}
104+
return 4 * (_stackSize - cnt);
105+
}
106+
107+
/* Print the stack from the first used 16-byte chunk to the top, decodable by the exception decoder */
108+
void stack_thunk_dump_stack()
109+
{
110+
uint32_t *pos = stack_thunk_top;
111+
while (pos < stack_thunk_ptr) {
112+
if ((pos[0] != _stackPaint) || (pos[1] != _stackPaint) || (pos[2] != _stackPaint) || (pos[3] != _stackPaint))
113+
break;
114+
pos += 4;
115+
}
116+
ets_printf(">>>stack>>>\n");
117+
while (pos < stack_thunk_ptr) {
118+
ets_printf("%08x: %08x %08x %08x %08x\n", pos, pos[0], pos[1], pos[2], pos[3]);
119+
pos += 4;
120+
}
121+
ets_printf("<<<stack<<<\n");
122+
}

cores/esp8266/StackThunk.h

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
StackThunk.h - Allow use second stack for BearSSL calls
3+
4+
BearSSL uses a significant amount of stack space, much larger than
5+
the default Arduino core stack. These routines handle swapping
6+
between a secondary, user-allocated stack on the heap and the real
7+
stack.
8+
9+
Copyright (c) 2017 Earle F. Philhower, III. All rights reserved.
10+
11+
This library is free software; you can redistribute it and/or
12+
modify it under the terms of the GNU Lesser General Public
13+
License as published by the Free Software Foundation; either
14+
version 2.1 of the License, or (at your option) any later version.
15+
16+
This library is distributed in the hope that it will be useful,
17+
but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19+
Lesser General Public License for more details.
20+
21+
You should have received a copy of the GNU Lesser General Public
22+
License along with this library; if not, write to the Free Software
23+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24+
Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
25+
*/
26+
27+
#ifndef _STACKTHUNK_H
28+
#define _STACKTHUNK_H
29+
30+
#ifdef __cplusplus
31+
extern "C" {
32+
#endif
33+
34+
extern void stack_thunk_add_ref();
35+
extern void stack_thunk_del_ref();
36+
extern void stack_thunk_repaint();
37+
38+
extern uint32_t stack_thunk_get_refcnt();
39+
extern uint32_t stack_thunk_get_stack_top();
40+
extern uint32_t stack_thunk_get_stack_bot();
41+
extern uint32_t stack_thunk_get_cont_sp();
42+
extern uint32_t stack_thunk_get_max_usage();
43+
extern void stack_thunk_dump_stack();
44+
45+
// Globals required for thunking operation
46+
extern uint32_t *stack_thunk_ptr;
47+
extern uint32_t *stack_thunk_top;
48+
extern uint32_t *stack_thunk_save;
49+
extern uint32_t stack_thunk_refcnt;
50+
51+
// Thunking macro
52+
#define make_stack_thunk(fcnToThunk) \
53+
__asm("\n\
54+
.text\n\
55+
.literal_position\n\
56+
\n\
57+
.text\n\
58+
.global thunk_"#fcnToThunk"\n\
59+
.type thunk_"#fcnToThunk", @function\n\
60+
.align 4\n\
61+
thunk_"#fcnToThunk":\n\
62+
addi a1, a1, -16 /* Allocate space for saved registers on stack */\n\
63+
s32i a0, a1, 12 /* Store A0, trounced by calls */\n\
64+
s32i a15, a1, 8 /* Store A15 (our temporary one) */\n\
65+
movi a15, stack_thunk_save /* Store A1(SP) in temp space */\n\
66+
s32i a1, a15, 0\n\
67+
movi a15, stack_thunk_top /* Load A1(SP) with thunk stack */\n\
68+
l32i.n a1, a15, 0\n\
69+
call0 "#fcnToThunk" /* Do the call */\n\
70+
movi a15, stack_thunk_save /* Restore A1(SP) */\n\
71+
l32i.n a1, a15, 0\n\
72+
l32i.n a15, a1, 8 /* Restore the saved registers */\n\
73+
l32i.n a0, a1, 12\n\
74+
addi a1, a1, 16 /* Free up stack and return to caller */\n\
75+
ret\n\
76+
.size thunk_"#fcnToThunk", . - thunk_"#fcnToThunk"\n");
77+
78+
#ifdef __cplusplus
79+
}
80+
#endif
81+
82+
#endif

cores/esp8266/core_esp8266_postmortem.c

+14-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "cont.h"
3030
#include "pgmspace.h"
3131
#include "gdb_hooks.h"
32+
#include "StackThunk.h"
3233

3334
extern void __real_system_restart_local();
3435

@@ -147,6 +148,17 @@ void __wrap_system_restart_local() {
147148
offset = 0x10;
148149
}
149150

151+
ets_printf_P("\n>>>stack>>>\n");
152+
153+
if (sp > stack_thunk_get_stack_bot() && sp <= stack_thunk_get_stack_top()) {
154+
// BearSSL we dump the BSSL second stack and then reset SP back to the main cont stack
155+
ets_printf_P("\nctx: bearssl \n");
156+
ets_printf_P("sp: %08x end: %08x offset: %04x\n", sp, stack_thunk_get_stack_top(), offset);
157+
print_stack(sp + offset, stack_thunk_get_stack_top());
158+
offset = 0; // No offset needed anymore, the exception info was stored in the bssl stack
159+
sp = stack_thunk_get_cont_sp();
160+
}
161+
150162
if (sp > cont_stack_start && sp < cont_stack_end) {
151163
ets_printf_P("\nctx: cont \n");
152164
stack_end = cont_stack_end;
@@ -162,6 +174,8 @@ void __wrap_system_restart_local() {
162174

163175
print_stack(sp + offset, stack_end);
164176

177+
ets_printf_P("<<<stack<<<\n");
178+
165179
// Use cap-X formatting to ensure the standard EspExceptionDecoder doesn't match the address
166180
if (umm_last_fail_alloc_addr) {
167181
ets_printf_P("\nlast failed alloc call: %08X(%d)\n", (uint32_t)umm_last_fail_alloc_addr, umm_last_fail_alloc_size);
@@ -175,7 +189,6 @@ void __wrap_system_restart_local() {
175189

176190

177191
static void ICACHE_RAM_ATTR print_stack(uint32_t start, uint32_t end) {
178-
ets_printf_P("\n>>>stack>>>\n");
179192
for (uint32_t pos = start; pos < end; pos += 0x10) {
180193
uint32_t* values = (uint32_t*)(pos);
181194

@@ -185,7 +198,6 @@ static void ICACHE_RAM_ATTR print_stack(uint32_t start, uint32_t end) {
185198
ets_printf_P("%08x: %08x %08x %08x %08x %c\n",
186199
pos, values[0], values[1], values[2], values[3], (looksLikeStackFrame)?'<':' ');
187200
}
188-
ets_printf_P("<<<stack<<<\n");
189201
}
190202

191203
static void uart_write_char_d(char c) {

doc/esp8266wifi/generic-class.rst

+8-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ onEvent
1212
1313
void onEvent (WiFiEventCb cb, WiFiEvent_t event=WIFI_EVENT_ANY) __attribute__((deprecated))
1414
15-
To see how to use ``onEvent`` please check example sketch `WiFiClientEvents.ino <https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiClientEvents/WiFiClientEvents.ino>`__ available inside examples folder of the ESP8266WiFi library.
1615
1716
WiFiEventHandler
1817
~~~~~~~~~~~~~~~~
@@ -27,7 +26,14 @@ WiFiEventHandler
2726
WiFiEventHandler onSoftAPModeStationConnected (std::function< void(const WiFiEventSoftAPModeStationConnected &)>)
2827
WiFiEventHandler onSoftAPModeStationDisconnected (std::function< void(const WiFiEventSoftAPModeStationDisconnected &)>)
2928
30-
To see a sample application with ``WiFiEventHandler``, please check separate section with `examples :arrow\_right: <generic-examples.rst>`__ dedicated specifically to the Generic Class..
29+
It should be noted that when an WiFi interface goes down, all WiFiClients are stopped, and all WiFiServers stop serving. When the interface comes up, it is up to the user to reconnect the relevant WiFiClients and bring the WiFiServers back up.
30+
For the WiFi station interface, it is suggested to set a callback for onStationModeDisconnected() that shuts down the user app's WiFiClients and WiFiServers (resource cleanup), and another callback for onStationModeGotIP() that brings them back up.
31+
For the SoftAP interface, when the interface is brought up, any servers should be brought up as well.
32+
33+
A detailed explanation of ``WiFiEventHandler`` can be found in the section with `examples :arrow\_right: <generic-examples.rst>`__ dedicated specifically to the Generic Class..
34+
35+
Alternatively, check the example sketch `WiFiEvents.ino <https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiEvents/WiFiEvents.ino>`__ available inside examples folder of the ESP8266WiFi library.
36+
3137

3238
persistent
3339
~~~~~~~~~~

libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.cpp

+9-9
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,26 @@ ESP8266HTTPUpdateServer::ESP8266HTTPUpdateServer(bool serial_debug)
2020
{
2121
_serial_output = serial_debug;
2222
_server = NULL;
23-
_username = NULL;
24-
_password = NULL;
23+
_username = emptyString;
24+
_password = emptyString;
2525
_authenticated = false;
2626
}
2727

28-
void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path, const char * username, const char * password)
28+
void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const String& path, const String& username, const String& password)
2929
{
3030
_server = server;
31-
_username = (char *)username;
32-
_password = (char *)password;
31+
_username = username;
32+
_password = password;
3333

3434
// handler for the /update form page
35-
_server->on(path, HTTP_GET, [&](){
36-
if(_username != NULL && _password != NULL && !_server->authenticate(_username, _password))
35+
_server->on(path.c_str(), HTTP_GET, [&](){
36+
if(_username != emptyString && _password != emptyString && !_server->authenticate(_username.c_str(), _password.c_str()))
3737
return _server->requestAuthentication();
3838
_server->send_P(200, PSTR("text/html"), serverIndex);
3939
});
4040

4141
// handler for the /update form POST (once file upload finishes)
42-
_server->on(path, HTTP_POST, [&](){
42+
_server->on(path.c_str(), HTTP_POST, [&](){
4343
if(!_authenticated)
4444
return _server->requestAuthentication();
4545
if (Update.hasError()) {
@@ -61,7 +61,7 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path,
6161
if (_serial_output)
6262
Serial.setDebugOutput(true);
6363

64-
_authenticated = (_username == NULL || _password == NULL || _server->authenticate(_username, _password));
64+
_authenticated = (_username == emptyString || _password == emptyString || _server->authenticate(_username.c_str(), _password.c_str()));
6565
if(!_authenticated){
6666
if (_serial_output)
6767
Serial.printf("Unauthenticated Update\n");

libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h

+10-10
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,25 @@ class ESP8266HTTPUpdateServer
1010

1111
void setup(ESP8266WebServer *server)
1212
{
13-
setup(server, NULL, NULL);
13+
setup(server, emptyString, emptyString);
1414
}
1515

16-
void setup(ESP8266WebServer *server, const char * path)
16+
void setup(ESP8266WebServer *server, const String& path)
1717
{
18-
setup(server, path, NULL, NULL);
18+
setup(server, path, emptyString, emptyString);
1919
}
2020

21-
void setup(ESP8266WebServer *server, const char * username, const char * password)
21+
void setup(ESP8266WebServer *server, const String& username, const String& password)
2222
{
2323
setup(server, "/update", username, password);
2424
}
2525

26-
void setup(ESP8266WebServer *server, const char * path, const char * username, const char * password);
26+
void setup(ESP8266WebServer *server, const String& path, const String& username, const String& password);
2727

28-
void updateCredentials(const char * username, const char * password)
28+
void updateCredentials(const String& username, const String& password)
2929
{
30-
_username = (char *)username;
31-
_password = (char *)password;
30+
_username = username;
31+
_password = password;
3232
}
3333

3434
protected:
@@ -37,8 +37,8 @@ class ESP8266HTTPUpdateServer
3737
private:
3838
bool _serial_output;
3939
ESP8266WebServer *_server;
40-
char * _username;
41-
char * _password;
40+
String _username;
41+
String _password;
4242
bool _authenticated;
4343
String _updaterError;
4444
};

libraries/ESP8266WiFi/src/BearSSLHelpers.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <stdlib.h>
2828
#include <string.h>
2929
#include <Arduino.h>
30+
#include <StackThunk.h>
3031
#include "BearSSLHelpers.h"
3132

3233
namespace brssl {
@@ -881,4 +882,14 @@ bool SigningVerifier::verify(UpdaterHashClass *hash, const void *signature, uint
881882
}
882883
};
883884

885+
// Second stack thunked helpers
886+
make_stack_thunk(br_ssl_engine_recvapp_ack);
887+
make_stack_thunk(br_ssl_engine_recvapp_buf);
888+
make_stack_thunk(br_ssl_engine_recvrec_ack);
889+
make_stack_thunk(br_ssl_engine_recvrec_buf);
890+
make_stack_thunk(br_ssl_engine_sendapp_ack);
891+
make_stack_thunk(br_ssl_engine_sendapp_buf);
892+
make_stack_thunk(br_ssl_engine_sendrec_ack);
893+
make_stack_thunk(br_ssl_engine_sendrec_buf);
894+
884895
};

0 commit comments

Comments
 (0)