1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

Heap addendum to handle changes in NON-OS SDK 3.0.x (#8746)

## WPA2 Enterprise connections
References - merged PRs:
* https://github.com/esp8266/Arduino/pull/8529
* https://github.com/esp8266/Arduino/pull/8566 - these occurred with connect/disconnect with WPA-Enterprise
* https://github.com/esp8266/Arduino/pull/8736#issue-1470774550

The NON-OS SDK 3.0.x has breaking changes to the [`pvPortMalloc`](bf890b22e5/include/mem.h (L42)) function. They added a new `bool` argument for selecting a heap. 
```cpp
void *pvPortMalloc (size_t sz, const char *, unsigned, bool);
```

To avoid breaking the build, I added a new thin wrapper function `sdk3_pvPortMalloc` to `heap.cpp`. 
Edited new SDK LIBs to call `pvPortMalloc`'s replacement `sdk3_pvPortMalloc`.

They also added `pvPortZallocIram` and `pvPortCallocIram`, which are not a problem to support. Support added to `heap.cpp`.

Issues with WPA2 Enterprise in new SDKs:
* v3.0.0 and v3.0.1 - have the same memory leak and duplicate free bugs from before
* v3.0.2 through v3.0.5 - have the same memory leak; however, _no_ duplicate free crash.
* memory leak can be seen by cycling through setup, connect, disconnect, and clear setup - repeatedly.

Updated `wpa2_eap_patch.cpp` and binary patch scripts to handle v3.0.0 through v3.0.5.
Patched SDKs v3.0.0 through v3.0.5

## Duplicate Non-32-bit exception handler
Issue: At v3.0.0 and above `libmain.a` supplies a built-in exception handler (`load_non_32_wide_handler`) for non-32-bit access. Our non-32-bit access handler (`non32xfer_exception_handler`) overrides it. 

Solution: Add "weak" attribute to symbol `load_non_32_wide_handler`. Adjust the build to default to the SDK's built-in non-32-bit handler.  If there is a need to use our non-32-bit handler, make the selection from the Arduino IDE Tools menu `Non-32-Bit Access: "Byte/Word access to IRAM/PROGMEM (very slow)"`.

With SDKs v3.0.0 and above a "non-32-bit exception handler" is always present.
This commit is contained in:
M Hightower 2022-12-16 00:11:19 -08:00 committed by GitHub
parent d3c8d272d7
commit 4a0b66b017
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
76 changed files with 317 additions and 66 deletions

View File

@ -496,7 +496,7 @@ extern "C" void user_init(void) {
install_vm_exception_handler(); install_vm_exception_handler();
#endif #endif
#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP) #if defined(NON32XFER_HANDLER) || (defined(MMU_IRAM_HEAP) && (NONOSDK < (0x30000 - 1)))
install_non32xfer_exception_handler(); install_non32xfer_exception_handler();
#endif #endif

View File

@ -26,10 +26,14 @@
* Code taken directly from @pvvx's public domain code in * Code taken directly from @pvvx's public domain code in
* https://github.com/pvvx/esp8266web/blob/master/app/sdklib/system/app_main.c * https://github.com/pvvx/esp8266web/blob/master/app/sdklib/system/app_main.c
* *
* In Espressif versions NONOSDK v3.0.0+ a similar feature was added
* load_non_32_wide_handler. Theirs is always loaded. Add weak attribute to
* theirs so we can choose by adding an alias to ours.
* *
*/ */
#include <Arduino.h> #include <Arduino.h>
#include <user_interface.h>
#define VERIFY_C_ASM_EXCEPTION_FRAME_STRUCTURE #define VERIFY_C_ASM_EXCEPTION_FRAME_STRUCTURE
#include <esp8266_undocumented.h> #include <esp8266_undocumented.h>
#include <core_esp8266_non32xfer.h> #include <core_esp8266_non32xfer.h>
@ -58,10 +62,13 @@ extern "C" {
#define EXCCAUSE_LOAD_STORE_ERROR 3 /* Non 32-bit read/write error */ #define EXCCAUSE_LOAD_STORE_ERROR 3 /* Non 32-bit read/write error */
#if (defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP)) && (NONOSDK < (0x30000 - 1))
static fn_c_exception_handler_t old_c_handler = NULL; static fn_c_exception_handler_t old_c_handler = NULL;
#endif
#if defined(NON32XFER_HANDLER) || (defined(MMU_IRAM_HEAP) && (NONOSDK < (0x30000 - 1)))
static static
IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, int cause) IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, [[maybe_unused]] int cause)
{ {
do { do {
uint32_t insn, excvaddr; uint32_t insn, excvaddr;
@ -138,6 +145,7 @@ IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, int cau
} while(false); } while(false);
/* Fail request, die */ /* Fail request, die */
#if (NONOSDK < (0x30000 - 1))
/* /*
The old handler points to the SDK. Be alert for HWDT when Calling with The old handler points to the SDK. Be alert for HWDT when Calling with
INTLEVEL != 0. I cannot create it any more. I thought I saw this as a INTLEVEL != 0. I cannot create it any more. I thought I saw this as a
@ -148,16 +156,23 @@ IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, int cau
old_c_handler(ef, cause); old_c_handler(ef, cause);
return; return;
} }
#endif
/* /*
Calling _xtos_unhandled_exception(ef, cause) in the Boot ROM, gets us a Calling _xtos_unhandled_exception(ef, cause) in the Boot ROM, gets us a
hardware wdt. hardware wdt.
Use panic instead as a fall back. It will produce a stack trace. Use panic instead as a fall back. It will produce a stack trace.
*/ */
#if defined(DEBUG_ESP_PORT) || defined(DEBUG_ESP_MMU)
panic(); panic();
#else
// For non-debug builds, save on resources
abort();
#endif
} }
#endif // #if defined(NON32XFER_HANDLER) || (defined(MMU_IRAM_HEAP) && (NONOSDK < (0x30000 - 1)))
#if (defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP)) && (NONOSDK < (0x30000 - 1))
/* /*
To operate reliably, this module requires the new To operate reliably, this module requires the new
`_xtos_set_exception_handler` from `exc-sethandler.cpp` and `_xtos_set_exception_handler` from `exc-sethandler.cpp` and
@ -174,5 +189,17 @@ void install_non32xfer_exception_handler(void) {
non32xfer_exception_handler); non32xfer_exception_handler);
} }
} }
#else
// For v3.0.x SDKs, no need for install - call_user_start will do the job.
// Need this for build dependencies
void install_non32xfer_exception_handler(void) __attribute__((weak));
void install_non32xfer_exception_handler(void) {}
#endif
#if defined(NON32XFER_HANDLER)
// For SDKs 3.0.x, we made load_non_32_wide_handler in
// libmain.c:user_exceptions.o a weak symbol allowing this override to work.
extern void load_non_32_wide_handler(struct __exception_frame *ef, int cause) __attribute__((alias("non32xfer_exception_handler")));
#endif
}; };

View File

@ -39,8 +39,10 @@
* architecture, I am not convinced it can be done safely. * architecture, I am not convinced it can be done safely.
* *
*/ */
#include <user_interface.h> // need NONOSDK
#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP) || defined(NEW_EXC_C_WRAPPER) || defined(MMU_EXTERNAL_HEAP) #if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP) || \
defined(NEW_EXC_C_WRAPPER) || defined(MMU_EXTERNAL_HEAP) || (NONOSDK >= (0x30000 - 1))
/* /*
* The original module source code came from: * The original module source code came from:

View File

@ -356,25 +356,25 @@ void system_show_malloc(void)
void* IRAM_ATTR pvPortMalloc(size_t size, const char* file, int line) void* IRAM_ATTR pvPortMalloc(size_t size, const char* file, int line)
{ {
HeapSelectDram ephemeral; HeapSelectDram ephemeral;
return heap_pvPortMalloc(size, file, line);; return heap_pvPortMalloc(size, file, line);;
} }
void* IRAM_ATTR pvPortCalloc(size_t count, size_t size, const char* file, int line) void* IRAM_ATTR pvPortCalloc(size_t count, size_t size, const char* file, int line)
{ {
HeapSelectDram ephemeral; HeapSelectDram ephemeral;
return heap_pvPortCalloc(count, size, file, line); return heap_pvPortCalloc(count, size, file, line);
} }
void* IRAM_ATTR pvPortRealloc(void *ptr, size_t size, const char* file, int line) void* IRAM_ATTR pvPortRealloc(void *ptr, size_t size, const char* file, int line)
{ {
HeapSelectDram ephemeral; HeapSelectDram ephemeral;
return heap_pvPortRealloc(ptr, size, file, line); return heap_pvPortRealloc(ptr, size, file, line);
} }
void* IRAM_ATTR pvPortZalloc(size_t size, const char* file, int line) void* IRAM_ATTR pvPortZalloc(size_t size, const char* file, int line)
{ {
HeapSelectDram ephemeral; HeapSelectDram ephemeral;
return heap_pvPortZalloc(size, file, line); return heap_pvPortZalloc(size, file, line);
} }
void IRAM_ATTR vPortFree(void *ptr, const char* file, int line) void IRAM_ATTR vPortFree(void *ptr, const char* file, int line)
@ -384,7 +384,62 @@ void IRAM_ATTR vPortFree(void *ptr, const char* file, int line)
// correct context. umm_malloc free internally determines the correct heap. // correct context. umm_malloc free internally determines the correct heap.
HeapSelectDram ephemeral; HeapSelectDram ephemeral;
#endif #endif
return heap_vPortFree(ptr, file, line); return heap_vPortFree(ptr, file, line);
} }
#if (NONOSDK >= (0x30000))
////////////////////////////////////////////////////////////////////////////////
/*
New for NON-OS SDK 3.0.0 and up
Needed for WPA2 Enterprise support. This was not present in SDK pre 3.0
The NON-OS SDK 3.0.x has breaking changes to pvPortMalloc. They added one more
argument for selecting a heap. To avoid breaking the build, I renamed their
broken version pvEsprMalloc. To be used, the LIBS need to be edited.
They also added pvPortZallocIram and pvPortCallocIram, which are not a
problem.
WPA2 Enterprise connect crashing is fixed at v3.0.2 and up.
Not used for unreleased version NONOSDK3V0.
*/
void* IRAM_ATTR sdk3_pvPortMalloc(size_t size, const char* file, int line, bool iram)
{
if (iram) {
HeapSelectIram ephemeral;
return heap_pvPortMalloc(size, file, line);
} else {
HeapSelectDram ephemeral;
return heap_pvPortMalloc(size, file, line);
}
}
void* IRAM_ATTR pvPortCallocIram(size_t count, size_t size, const char* file, int line)
{
HeapSelectIram ephemeral;
return heap_pvPortCalloc(count, size, file, line);
}
void* IRAM_ATTR pvPortZallocIram(size_t size, const char* file, int line)
{
HeapSelectIram ephemeral;
return heap_pvPortZalloc(size, file, line);
}
/*
uint32_t IRAM_ATTR user_iram_memory_is_enabled(void)
{
return CONFIG_ENABLE_IRAM_MEMORY;
}
We do not need the function user_iram_memory_is_enabled().
1. It was used by mem_manager.o which was replaced with this custom heap
implementation. IRAM memory selection is handled differently.
2. In libmain.a, Cache_Read_Enable_New uses it for cache size. However, When
using IRAM for memory or running with 48K IRAM for code, we use a
replacement Cache_Read_Enable to correct the cache size ignoring
Cache_Read_Enable_New's selected value.
*/
#endif
}; };

View File

@ -5,12 +5,44 @@
* modules. * modules.
* *
*/ */
#include <string.h> #include <string.h>
#include <ets_sys.h> #include <ets_sys.h>
#include <pgmspace.h> #include <pgmspace.h>
#include "coredecls.h" #include "coredecls.h"
#if defined(NONOSDK22x_190703) || \
defined(NONOSDK22x_191122) || \
defined(NONOSDK22x_191105) || \
defined(NONOSDK22x_191124) || \
defined(NONOSDK22x_190313) || \
defined(NONOSDK221) || \
defined(NONOSDK3V0) || \
defined(NONOSDK300) || \
defined(NONOSDK301) || \
defined(NONOSDK302) || \
defined(NONOSDK303) || \
defined(NONOSDK304) || \
defined(NONOSDK305)
// eap_peer_config_deinit() - For this list of SDKs there are no significant
// changes in the function. Just the line number reference for when vPortFree
// is called. When vPortFree is called, register a12 continues to hold a pointer
// to the struct StateMachine. Our cleanup routine should continue to work.
#if defined(NONOSDK300) || defined(NONOSDK301)
// Minor changes only line number changed
#define SDK_LEAK_LINE 809
#elif defined(NONOSDK302) || defined(NONOSDK303) || defined(NONOSDK304)
// Minor changes only line number changed
#define SDK_LEAK_LINE 831
#elif defined(NONOSDK305)
// At v3.0.5 Espressif moved `.text.eap_peer_config_deinit` to
// `eap_peer_config_deinit` then later in latest git they moved it
// back. For our linker script both are placed in flash.
#define SDK_LEAK_LINE 831
#else
#define SDK_LEAK_LINE 799
#endif
#ifdef DEBUG_WPA2_EAP_PATCH #ifdef DEBUG_WPA2_EAP_PATCH
#include "esp8266_undocumented.h" #include "esp8266_undocumented.h"
#define DEBUG_PRINTF ets_uart_printf #define DEBUG_PRINTF ets_uart_printf
@ -100,7 +132,7 @@ struct StateMachine { // size 200 bytes
* same line. * same line.
*/ */
void patch_wpa2_eap_vPortFree_a12(void *ptr, const char* file, int line, void* a12) { void patch_wpa2_eap_vPortFree_a12(void *ptr, const char* file, int line, void* a12) {
if (799 == line) { if (SDK_LEAK_LINE == line) {
// This caller is eap_peer_config_deinit() // This caller is eap_peer_config_deinit()
struct StateMachine* sm = (struct StateMachine*)a12; struct StateMachine* sm = (struct StateMachine*)a12;
if (ptr == sm->config[0]) { if (ptr == sm->config[0]) {
@ -126,21 +158,38 @@ void patch_wpa2_eap_vPortFree_a12(void *ptr, const char* file, int line, void* a
} }
#endif #endif
} }
#if 0
// This is not needed because the call was NO-OPed in the library. This code #if defined(NONOSDK300) || defined(NONOSDK301)
// snippit is just to show how a future memory free issue might be resolved. else if (682 == line) {
else if (672 == line) {
// This caller is wpa2_sm_rx_eapol() // This caller is wpa2_sm_rx_eapol()
// 1st of a double free // 1st of a double free
// let the 2nd free handle it. // let the 2nd free handle it.
return; return;
} }
#elif defined(NONOSDK302) || defined(NONOSDK303) || defined(NONOSDK304) || defined(NONOSDK305)
// It looks like double free is fixed. WPA2 Enterpise connections work
// without crashing. wpa2_sm_rx_eapol() has a few changes between NONOSDK301
// and NONOSDK302. However, this set of releases still have memory leaks.
#else
// This is not needed because the call was NO-OPed in the library.
// Keep code snippit for reference.
// else if (672 == line) {
// // This caller is wpa2_sm_rx_eapol()
// // 1st of a double free
// // let the 2nd free handle it.
// return;
// }
#endif #endif
vPortFree(ptr, file, line); vPortFree(ptr, file, line);
} }
}; };
#else
#error "Internal error: A new SDK has been added. This module must be updated."
#error " Need to test WPA2 Enterpise connectivity."
#endif
/* /*
* This will minimize code space for non-wifi enterprise sketches which do not * This will minimize code space for non-wifi enterprise sketches which do not
* need the patch and disable_extra4k_at_link_time(). * need the patch and disable_extra4k_at_link_time().

View File

@ -76,19 +76,28 @@ The Arduino IDE Tools menu option, ``MMU`` has the following selections:
MMU related build defines and possible values. These values change as MMU related build defines and possible values. These values change as
indicated with the menu options above: indicated with the menu options above:
+-------------------------+--------------+--------------+------------------------------------+------------------------------+ +-------------+------------+------------+-------------+-------------+
| ``#define`` | balanced | IRAM | shared (IRAM and Heap) | not shared (IRAM and Heap) | | ``#define`` | balanced | IRAM | shared | not shared |
+=========================+==============+==============+====================================+==============================+ | | | | (IRAM and | (IRAM and |
| ``MMU_IRAM_SIZE`` | ``0x8000`` | ``0xC000`` | ``0xC000`` | ``0x8000`` | | | | | Heap) | Heap) |
+-------------------------+--------------+--------------+------------------------------------+------------------------------+ +=============+============+============+=============+=============+
| ``MMU_ICACHE_SIZE`` | ``0x8000`` | ``0x4000`` | ``0x4000`` | ``0x4000`` | | ``MMU_ | ``0x8000`` | ``0xC000`` | ``0xC000`` | ``0x8000`` |
+-------------------------+--------------+--------------+------------------------------------+------------------------------+ | IRAM_SIZE`` | | | | |
| ``MMU_IRAM_HEAP`` | -- | -- | defined, enables\ ``umm_malloc`` | -- | +-------------+------------+------------+-------------+-------------+
+-------------------------+--------------+--------------+------------------------------------+------------------------------+ | ``MMU_IC | ``0x8000`` | ``0x4000`` | ``0x4000`` | ``0x4000`` |
| ``MMU_SEC_HEAP`` | -- | \*\* | \*\* | ``0x40108000`` | | ACHE_SIZE`` | | | | |
+-------------------------+--------------+--------------+------------------------------------+------------------------------+ +-------------+------------+------------+-------------+-------------+
| ``MMU_SEC_HEAP_SIZE`` | -- | \*\* | \*\* | ``0x4000`` | | ``MMU_ | | | defined, | |
+-------------------------+--------------+--------------+------------------------------------+------------------------------+ | IRAM_HEAP`` | | | e | |
| | | | nables\ ``u | |
| | | | mm_malloc`` | |
+-------------+------------+------------+-------------+-------------+
| ``MMU | | \*\* | \*\* | ``0 |
| _SEC_HEAP`` | | | | x40108000`` |
+-------------+------------+------------+-------------+-------------+
| ``MMU_SEC_ | | \*\* | \*\* | ``0x4000`` |
| HEAP_SIZE`` | | | | |
+-------------+------------+------------+-------------+-------------+
\*\* This define is to an inline function that calculates the value, \*\* This define is to an inline function that calculates the value,
based on unused code space, requires ``#include <mmu_iram.h>``. based on unused code space, requires ``#include <mmu_iram.h>``.
@ -112,8 +121,8 @@ The Arduino IDE Tools menu option, ``Non-32-Bit Access`` has the following selec
option ``16KB cache + 48KB IRAM and 2nd Heap (shared)``. option ``16KB cache + 48KB IRAM and 2nd Heap (shared)``.
IRAM, unlike DRAM, must be accessed as aligned full 32-bit words, no IRAM, unlike DRAM, must be accessed as aligned full 32-bit words, no
byte or short access. The pgm\_read macros are an option; however, the byte or short access. The pgm_read macros are an option; however, the
store operation remains an issue. For a block copy, ets\_memcpy appears store operation remains an issue. For a block copy, ets_memcpy appears
to work well as long as the byte count is rounded up to be evenly to work well as long as the byte count is rounded up to be evenly
divided by 4, and source and destination addresses are 4 bytes aligned. divided by 4, and source and destination addresses are 4 bytes aligned.
@ -125,6 +134,11 @@ over-optimization.
To get a sense of how memory access time is effected, see examples To get a sense of how memory access time is effected, see examples
``MMU48K`` and ``irammem`` in ``ESP8266``. ``MMU48K`` and ``irammem`` in ``ESP8266``.
NON-OS SDK v3.0.0 and above have builtin support for Non-32-Bit Access.
Selecting ``Byte/Word access to IRAM/PROGMEM`` will override the builtin
version with ours. However, there is no known reason to do this other
than debugging.
Miscellaneous Miscellaneous
------------- -------------
@ -133,41 +147,43 @@ For calls to ``umm_malloc`` with interrupts disabled.
- ``malloc`` will always allocate from the ``DRAM`` heap when called - ``malloc`` will always allocate from the ``DRAM`` heap when called
with interrupts disabled. with interrupts disabled.
- ``realloc`` with a NULL pointer will use ``malloc`` and return a
``DRAM`` heap allocation. Note, calling ``realloc`` with interrupts - ``realloc`` with a NULL pointer will use ``malloc`` and return a
disabled is **not** officially supported. You are on your own if you ``DRAM`` heap allocation. Note, calling ``realloc`` with
do this. interrupts disabled is **not** officially supported. You are on
your own if you do this.
- If you must use IRAM memory in your ISR, allocate the memory in your - If you must use IRAM memory in your ISR, allocate the memory in your
init code. To reduce the time spent in the ISR, avoid non32-bit init code. To reduce the time spent in the ISR, avoid non32-bit
access that would trigger the exception handler. For short or byte access that would trigger the exception handler. For short or byte
access, consider using the inline functions described in section access, consider using the inline functions described in section
"Performance Functions" below. “Performance Functions” below.
How to Select Heap How to Select Heap
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
The ``MMU`` selection ``16KB cache + 48KB IRAM and 2nd Heap (shared)`` The ``MMU`` selection ``16KB cache + 48KB IRAM and 2nd Heap (shared)``
allows you to use the standard heap API function calls (``malloc``, allows you to use the standard heap API function calls (``malloc``,
``calloc``, ``free``, ... ). to allocate memory from DRAM or IRAM. This ``calloc``, ``free``, ). to allocate memory from DRAM or IRAM. This
selection can be made by instantiating the class ``HeapSelectIram`` or selection can be made by instantiating the class ``HeapSelectIram`` or
``HeapSelectDram``. The usage is similar to that of the ``HeapSelectDram``. The usage is similar to that of the
``InterruptLock`` class. The default/initial heap source is DRAM. The ``InterruptLock`` class. The default/initial heap source is DRAM. The
class is in ``umm_malloc/umm_heap_select.h``. class is in ``umm_malloc/umm_heap_select.h``.
:: .. code:: cpp
... ...
char *bufferDram; char *bufferDram;
bufferDram = (char *)malloc(33); bufferDram = (char *)malloc(33);
char *bufferIram; char *bufferIram;
{ {
HeapSelectIram ephemeral; HeapSelectIram ephemeral;
bufferIram = (char *)malloc(33); bufferIram = (char *)malloc(33);
} }
... ...
free(bufferIram); free(bufferIram);
free(bufferDram); free(bufferDram);
... ...
``free`` will always return memory to the correct heap. There is no need ``free`` will always return memory to the correct heap. There is no need
for tracking and selecting before freeing. for tracking and selecting before freeing.
@ -182,8 +198,9 @@ Classes:
- ``umm_get_current_heap_id()`` - ``umm_get_current_heap_id()``
- ``umm_set_heap_by_id( ID value )`` - ``umm_set_heap_by_id( ID value )``
- Possible ID values - Possible ID values
- ``UMM_HEAP_DRAM``
- ``UMM_HEAP_IRAM`` - ``UMM_HEAP_DRAM``
- ``UMM_HEAP_IRAM``
Also, an alternate stack select method API is available. This is not as Also, an alternate stack select method API is available. This is not as
easy as the class method; however, for some small set of cases, it may easy as the class method; however, for some small set of cases, it may
@ -201,9 +218,9 @@ a pointer:
.. code:: cpp .. code:: cpp
bool mmu_is_iram(const void *addr); bool mmu_is_iram(const void *addr);
bool mmu_is_dram(const void *addr); bool mmu_is_dram(const void *addr);
bool mmu_is_icache(const void *addr); bool mmu_is_icache(const void *addr);
Performance Functions Performance Functions
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
@ -213,23 +230,25 @@ exception handler reducing execution time and stack use, it comes at the
cost of increased code size. cost of increased code size.
These are an alternative to the ``pgm_read`` macros for reading from These are an alternative to the ``pgm_read`` macros for reading from
IRAM. When compiled with 'Debug Level: core' range checks are performed IRAM. When compiled with Debug Level: core range checks are performed
on the pointer value to make sure you are reading from the address range on the pointer value to make sure you are reading from the address range
of IRAM, DRAM, or ICACHE. of IRAM, DRAM, or ICACHE.
.. code:: cpp .. code:: cpp
uint8_t mmu_get_uint8(const void *p8); uint8_t mmu_get_uint8(const void *p8);
uint16_t mmu_get_uint16(const uint16_t *p16); uint16_t mmu_get_uint16(const uint16_t *p16);
int16_t mmu_get_int16(const int16_t *p16); int16_t mmu_get_int16(const int16_t *p16);
While these functions are intended for writing to IRAM, they will work While these functions are intended for writing to IRAM, they will work
with DRAM. When compiled with 'Debug Level: core', range checks are with DRAM. When compiled with Debug Level: core, range checks are
performed on the pointer value to make sure you are writing to the performed on the pointer value to make sure you are writing to the
address range of IRAM or DRAM. address range of IRAM or DRAM.
.. code:: cpp .. code:: cpp
uint8_t mmu_set_uint8(void *p8, const uint8_t val); uint8_t mmu_set_uint8(void *p8, const uint8_t val);
uint16_t mmu_set_uint16(uint16_t *p16, const uint16_t val); uint16_t mmu_set_uint16(uint16_t *p16, const uint16_t val);
int16_t mmu_set_int16(int16_t *p16, const int16_t val); int16_t mmu_set_int16(int16_t *p16, const int16_t val);
::

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,8 +1,20 @@
## Adding a new SDK library
- Create a directory for the new SDK.
- Copy .a files from SDK `lib` directory to the new directory
- Add the new SDK directory to those supported in `eval_fix_sdks.sh` and `fix_sdk_libs.sh`.
- To support WPA2 Enterprise connections, some patches are reguired review `wpa2_eap_patch.cpp` and `eval_fix_sdks.sh` for details.
- Use `./eval_fix_sdks.sh --analyze` to aid in finding relevant differences.
- Also, you can compare two SDKs with something like `./eval_fix_sdks.sh --analyze "NONOSDK305\nNONOSDK306"`
- Apply updates to `fix_sdk_libs.sh` and `wpa2_eap_patch.cpp`. You can run `./eval_fix_sdks.sh --patch` to do a batch run of `fix_sdk_libs.sh` against each SDK.
- If you used this section, you can skip _Updating SDK libraries_.
## Updating SDK libraries ## Updating SDK libraries
- Copy .a files from SDK `lib` directory to this directory - Copy .a files from SDK `lib` directory to this directory
- Run `fix_sdk_libs.sh` - Run `fix_sdk_libs.sh`
## Updating libstdc++ ## Updating libstdc++
After building gcc using crosstool-NG, get compiled libstdc++ and remove some objects: After building gcc using crosstool-NG, get compiled libstdc++ and remove some objects:
@ -17,4 +29,3 @@ xtensa-lx106-elf-ar d libstdc++.a del_opv.o
xtensa-lx106-elf-ar d libstdc++.a new_op.o xtensa-lx106-elf-ar d libstdc++.a new_op.o
xtensa-lx106-elf-ar d libstdc++.a new_opv.o xtensa-lx106-elf-ar d libstdc++.a new_opv.o
``` ```

View File

@ -1,6 +1,13 @@
#!/bin/bash #!/bin/bash
# set -e # set -e
single_sdk="${2}"
if [[ -n "$single_sdk" ]]; then
if [[ "NONOSDK" != "${single_sdk:0:7}" ]]; then
single_sdk=""
fi
fi
add_path_ifexist() { add_path_ifexist() {
if [[ -d $1 ]]; then if [[ -d $1 ]]; then
export PATH=$( realpath $1 ):$PATH export PATH=$( realpath $1 ):$PATH
@ -24,6 +31,10 @@ EOF
} }
list_sdks() { list_sdks() {
if [[ -n "$single_sdk" ]]; then
echo -e "$single_sdk"
return
fi
cat <<EOF cat <<EOF
NONOSDK22x_190313 NONOSDK22x_190313
NONOSDK22x_190703 NONOSDK22x_190703
@ -68,7 +79,7 @@ analyze() {
done done
echo "" echo ""
find . -name eap.o -exec md5sum {} \; | sort find . -name eap.o -exec md5sum {} \; | sort -k2
echo "" echo ""
unset prev_sdk unset prev_sdk

View File

@ -42,6 +42,58 @@ patchFile() {
fi fi
} }
grepPatchFiles() {
local SDKVER OLDNAME NEWNAME FILES OLDNAME64 NEWNAME64 FILE OFFSET PATTERN
SDKVER="${1}"
OLDNAME="${2}"
NEWNAME="${3}"
FILES="${4}"
[[ "${SDKVER:0:9}" != "NONOSDK30" ]] && return
if [[ -z "${FILES}" ]]; then
echo "grepPatchFile: bad input: file specification required"
exit 1
fi
if [[ "${#OLDNAME}" != "${#NEWNAME}" ]]; then
echo "grepPatchFile: bad input: old name ${OLDNAME}(${#OLDNAME}) and new name ${NEWNAME}(${#NEWNAME}) must be the same length."
exit 1
fi
OLDNAME64=( `echo -n "${OLDNAME}" | base64 -w0` )
NEWNAME64=( `echo -n "${NEWNAME}" | base64 -w0` )
while read -u3 FILE OFFSET PATTERN; do
if [[ "${#OLDNAME}" == "${#PATTERN}" ]] && [[ "${OLDNAME}" == "${PATTERN}" ]]; then
patchFile "$FILE" "$OFFSET" "${#PATTERN}" "${OLDNAME64}" "${NEWNAME64}"
else
echo "grepPatchFile: bad parameters FILE=${FILE} OFFSET=${OFFSET} PATTERN=${PATTERN}"
exit 1
fi
done 3< <( grep --with-filename --byte-offset --only-matching --text "${OLDNAME}" $FILES | tr ":" " " )
return
}
redefineSym() {
local SDKVER OLDNAME NEWNAME FILES FILE EXTRA PATTERN
SDKVER="${1}"
OLDNAME="${2}"
NEWNAME="${3}"
FILES="${4}"
[[ "${SDKVER:0:9}" != "NONOSDK30" ]] && return
if [[ -z "${FILES}" ]]; then
echo "redefineSym: bad input: file specification required"
exit 1
fi
PATTERN="UND ${OLDNAME}"
for FILE in $FILES ; do
echo "xtensa-lx106-elf-objcopy --redefine-sym ${OLDNAME}=${NEWNAME} \"$FILE\""
echo "Before:"
xtensa-lx106-elf-nm "$FILE" | grep ${OLDNAME} | sort -u
xtensa-lx106-elf-objcopy --redefine-sym ${OLDNAME}=${NEWNAME} "$FILE"
echo "After:"
xtensa-lx106-elf-nm "$FILE" | grep ${OLDNAME} | sort -u
done
return
}
# # xtensa-lx106-elf-ar x libwpa2.a eap.o # # xtensa-lx106-elf-ar x libwpa2.a eap.o
if [[ "--shell" == "$1" ]]; then if [[ "--shell" == "$1" ]]; then
# need to poke around a bit # need to poke around a bit
@ -81,12 +133,28 @@ elif [[ ${VERSION} == "NONOSDK22x"* ]]; then
addSymbol_system_func1 "0x54" addSymbol_system_func1 "0x54"
patchFile "eap.o" "3059" "2" "wAA=" "8CA=" # WPA2-Enterprise patch which replaces a double-free with nop, see #8082 patchFile "eap.o" "3059" "2" "wAA=" "8CA=" # WPA2-Enterprise patch which replaces a double-free with nop, see #8082
patchFile "eap.o" "26356" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory patchFile "eap.o" "26356" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
elif [[ ${VERSION} == "NONOSDK3V0"* ]]; then elif [[ ${VERSION} == "NONOSDK3V0" ]]; then
addSymbol_system_func1 "0x60" addSymbol_system_func1 "0x60"
patchFile "eap.o" "3059" "2" "wAA=" "8CA=" # WPA2-Enterprise patch which replaces a double-free with nop, see #8082 patchFile "eap.o" "3059" "2" "wAA=" "8CA=" # WPA2-Enterprise patch which replaces a double-free with nop, see #8082
patchFile "eap.o" "26356" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory patchFile "eap.o" "26356" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
elif [[ ${VERSION} == "NONOSDK3"* ]]; then elif [[ ${VERSION} == "NONOSDK300" ]]; then
addSymbol_system_func1 "0x54" addSymbol_system_func1 "0x54"
patchFile "eap.o" "19204" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
elif [[ ${VERSION} == "NONOSDK301" ]]; then
addSymbol_system_func1 "0x54"
patchFile "eap.o" "26364" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
elif [[ ${VERSION} == "NONOSDK302" ]]; then
addSymbol_system_func1 "0x54"
patchFile "eap.o" "26536" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
elif [[ ${VERSION} == "NONOSDK303" ]]; then
addSymbol_system_func1 "0x54"
patchFile "eap.o" "26536" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
elif [[ ${VERSION} == "NONOSDK304" ]]; then
addSymbol_system_func1 "0x54"
patchFile "eap.o" "19376" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
elif [[ ${VERSION} == "NONOSDK305" ]]; then
addSymbol_system_func1 "0x54"
patchFile "eap.o" "67670" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
else else
echo "WARN: Unknown address for system_func1() called by system_restart_local()" echo "WARN: Unknown address for system_func1() called by system_restart_local()"
fi fi
@ -98,3 +166,12 @@ if [[ $(sha256sum user_interface.o | awk '{print $1}') != $uics || $(sha256sum e
xtensa-lx106-elf-ar r libmain.a eagle_lwip_if.o user_interface.o xtensa-lx106-elf-ar r libmain.a eagle_lwip_if.o user_interface.o
fi fi
rm -f eagle_lwip_if.o user_interface.o eap.o rm -f eagle_lwip_if.o user_interface.o eap.o
if [[ ${VERSION} == "NONOSDK3V0" ]]; then
xtensa-lx106-elf-objcopy --weaken-symbol load_non_32_wide_handler libmain.a
elif [[ ${VERSION:0:9} == "NONOSDK30" ]]; then
# v3.0.0 and up use a non-standard pvPortMalloc.
# SDK Library global replace
redefineSym "${VERSION}" "pvPortMalloc" "sdk3_pvPortMalloc" '*.a'
xtensa-lx106-elf-objcopy --weaken-symbol load_non_32_wide_handler libmain.a
fi