Skip to content
139 changes: 83 additions & 56 deletions cores/esp8266/core_esp8266_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ extern "C" {
#include <umm_malloc/umm_malloc.h>
#include <core_esp8266_non32xfer.h>
#include "core_esp8266_vm.h"
#include "flash_hal.h"

#define LOOP_TASK_PRIORITY 1
#define LOOP_QUEUE_SIZE 1
Expand Down Expand Up @@ -408,71 +409,97 @@ uint32_t __flashindex;

extern "C" void ICACHE_FLASH_ATTR user_pre_init(void)
{
uint32_t rf_cal = 0;
uint32_t phy_data = 0;
uint32_t system_parameter = 0;

switch (system_get_flash_size_map())
// For SDKs 3.0.0 and later, place phy_data readonly overlay on top of the
// EEPROM address. For older SDKs without a system partition, RF_CAL and
// PHY_DATA shared the same flash segment.
//
// For the Arduino ESP8266 core, the sectors for "EEPROM +0x1000", "RF_CAL
// +0x1000", and "SYSTEM_PARAMETERs +0x3000" are positioned in the last five
// sectors of flash memory. PHY_INIT_DATA is special. It is a one time read
// of 128 bytes of data that is provided by a one time spoofed flash read.
uint32_t phy_data = EEPROM_start - 0x40200000u;
uint32_t rf_cal = phy_data + 0x1000;
uint32_t system_parameter = rf_cal + 0x1000;

// All the examples I find, show the partition table in the global address space.
static partition_item_t at_partition_table[] =
{
case FLASH_SIZE_2M:
rf_cal = 0x3b000;
phy_data = 0x3c000;
system_parameter = 0x3d000;
break;
case FLASH_SIZE_4M_MAP_256_256:
rf_cal = 0x7b000;
phy_data = 0x7c000;
system_parameter = 0x7d000;
break;
case FLASH_SIZE_8M_MAP_512_512:
rf_cal = 0xfb000;
phy_data = 0xfc000;
system_parameter = 0xfd000;
break;
case FLASH_SIZE_16M_MAP_512_512:
case FLASH_SIZE_16M_MAP_1024_1024:
rf_cal = 0x1fb000;
phy_data = 0x1fc000;
system_parameter = 0x1fd000;
break;
case FLASH_SIZE_32M_MAP_512_512:
case FLASH_SIZE_32M_MAP_1024_1024:
case FLASH_SIZE_32M_MAP_2048_2048:
rf_cal = 0x3fb000;
phy_data = 0x3fc000;
system_parameter = 0x3fd000;
break;
case FLASH_SIZE_64M_MAP_1024_1024:
rf_cal = 0x7fb000;
phy_data = 0x7fc000;
system_parameter = 0x7fd000;
break;
case FLASH_SIZE_128M_MAP_1024_1024:
rf_cal = 0xffb000;
phy_data = 0xffc000;
system_parameter = 0xffd000;
break;
}

extern uint32_t user_rf_cal_sector_set(void);
user_rf_cal_sector_set();

const partition_item_t at_partition_table[] =
{
{ SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 },
{ SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 },
{ SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 },
{ SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 },
};
system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map());
}

// SDK 3.0's `system_partition_table_regist` is FOTA-centric. It will report
// on BOOT, OTA1, and OTA2 being missing. We are Non-FOTA. I don't see
// anything we can do about this. Other than maybe turning off os_print.

// For SDKs v3.0.0 and later, the functions `uint32
// user_rf_cal_sector_set(void)` and `void user_rf_pre_init(void)` are not
// called by the SDK. We need these called to start and stop spoofing logic
// for flash read of PHY Init data.
extern uint32_t user_rf_cal_sector_set(void);
user_rf_cal_sector_set(); // Start spoofing logic

#ifdef DEV_DEBUG_PRINT
// Deeper debugging maybe delete this block later
extern void set_pll(void);
set_pll(); // fix printing for 115200 bps
ets_uart_printf(PSTR("\n\nConfig info referenced for system partition table registration:\n"));
ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("PHY_DATA"), phy_data);
ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("RF_CAL"), rf_cal);
ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("SYSTEM_PARAMETER"), system_parameter);
ets_uart_printf(PSTR(" %-18s 0x%08X %u\n"), PSTR("chip_size"), flashchip->chip_size, flashchip->chip_size);
ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("EEPROM_start"), EEPROM_start);
ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_start"), FS_start);
ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_end"), FS_end);
ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_page"), FS_page);
ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_block"), FS_block);
#if !defined(FLASH_MAP_SUPPORT)
uint32_t configured_chip_size = system_parameter + 4096 * 3;
// flashchip->chip_size is updated by the SDK. The size is based on the
// value patched into the .bin header by esptool.
// system_get_flash_size_map() returns that patched value.
if (flashchip->chip_size != configured_chip_size)
{
// For this message and postmortem to be readable, the console speed may
// need to be 74880 bps.
ets_uart_printf(PSTR("\nMissmatch between actual(%u) vs configured(%u) flash size\n"), flashchip->chip_size, configured_chip_size);
// Full stop to avoid possible stored flash data corruption. This
// missmatch does not occur with flash size selection "Mapping defined by
// Hardware and Sketch".
abort();
}
#endif
#endif
if (!system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map()))
{
// We will land here anytime the build flash size value set by the Arduino
// IDE Tools menu mismatches the firmware image value detected and updated
// on the fly by esptool.
//
// The SDKs PLL CPU clock calibration hasn't run. For this message and
// postmortem to be readable, the console speed may need to be 74880 bps.
//
// Because SDK v3.0.x always has a non-32-bit wide exception handler
// installed, we can use PROGMEM strings with Boot ROM print functions.
ets_uart_printf(PSTR("\nSystem partition table registration failed!\n"));

//C What is the best action on failure?
//C * The above printf maybe redundant. `system_partition_table_regist`
//C appears to print specific failure messages. most of the time.
//C * Things will not get better by rebooting.
//C * Most likely the error message was not readable - mismatched console speed
//C * Expressif example do a `while(true){};` on fail. HWDT appears to be
//C off and the device freezes.
abort();
}
}
#endif // #if (NONOSDK >= (0x30000))

extern "C" void user_init(void) {

#if (NONOSDK >= (0x30000))
extern void user_rf_pre_init();
user_rf_pre_init();
user_rf_pre_init(); // Stop spoofing logic
#endif

struct rst_info *rtc_info_ptr = system_get_rst_info();
Expand All @@ -496,7 +523,7 @@ extern "C" void user_init(void) {
install_vm_exception_handler();
#endif

#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP)
#if defined(NON32XFER_HANDLER) || (defined(MMU_IRAM_HEAP) && (NONOSDK < (0x30000 - 1)))
install_non32xfer_exception_handler();
#endif

Expand Down