@@ -400,79 +400,230 @@ extern "C" void __disableWiFiAtBootTime (void)
400400
401401#if FLASH_MAP_SUPPORT
402402#include " flash_hal.h"
403- extern " C" void flashinit (void );
403+ extern " C" bool flashinit (void );
404+ #if (NONOSDK >= (0x30000))
405+ uint32_t __flashindex __attribute__ ((section(" .noinit" )));
406+ #else
404407uint32_t __flashindex;
405408#endif
409+ #endif
406410
407411#if (NONOSDK >= (0x30000))
412+ #undef ETS_PRINTF
413+ #define ETS_PRINTF (...) ets_uart_printf(__VA_ARGS__)
414+ extern " C" uint8_t uart_rx_one_char_block ();
415+
416+ #if ! FLASH_MAP_SUPPORT
417+ #include " flash_hal.h"
418+ #endif
408419
409420extern " C" void ICACHE_FLASH_ATTR user_pre_init (void )
410421{
411- uint32_t rf_cal = 0 ;
422+ const char *flash_map_str = NULL ;
423+ const char *chip_sz_str = NULL ;
424+ const char *table_regist_str = NULL ;
425+ [[maybe_unused]] uint32_t ld_config_chip_size = 0 ;
426+ uint32_t flash_size = 0 ;
412427 uint32_t phy_data = 0 ;
428+ uint32_t rf_cal = 0 ;
413429 uint32_t system_parameter = 0 ;
414-
415- switch (system_get_flash_size_map ())
416- {
417- case FLASH_SIZE_2M:
418- rf_cal = 0x3b000 ;
419- phy_data = 0x3c000 ;
420- system_parameter = 0x3d000 ;
421- break ;
422- case FLASH_SIZE_4M_MAP_256_256:
423- rf_cal = 0x7b000 ;
424- phy_data = 0x7c000 ;
425- system_parameter = 0x7d000 ;
426- break ;
427- case FLASH_SIZE_8M_MAP_512_512:
428- rf_cal = 0xfb000 ;
429- phy_data = 0xfc000 ;
430- system_parameter = 0xfd000 ;
431- break ;
432- case FLASH_SIZE_16M_MAP_512_512:
433- case FLASH_SIZE_16M_MAP_1024_1024:
434- rf_cal = 0x1fb000 ;
435- phy_data = 0x1fc000 ;
436- system_parameter = 0x1fd000 ;
437- break ;
438- case FLASH_SIZE_32M_MAP_512_512:
439- case FLASH_SIZE_32M_MAP_1024_1024:
440- case FLASH_SIZE_32M_MAP_2048_2048:
441- rf_cal = 0x3fb000 ;
442- phy_data = 0x3fc000 ;
443- system_parameter = 0x3fd000 ;
444- break ;
445- case FLASH_SIZE_64M_MAP_1024_1024:
446- rf_cal = 0x7fb000 ;
447- phy_data = 0x7fc000 ;
448- system_parameter = 0x7fd000 ;
449- break ;
450- case FLASH_SIZE_128M_MAP_1024_1024:
451- rf_cal = 0xffb000 ;
452- phy_data = 0xffc000 ;
453- system_parameter = 0xffd000 ;
454- break ;
430+ [[maybe_unused]] const partition_item_t *_at_partition_table = NULL ;
431+ size_t _at_partition_table_sz = 0 ;
432+
433+ do {
434+ #if FLASH_MAP_SUPPORT
435+ if (!flashinit ()) {
436+ flash_map_str = PSTR (" flashinit: flash size missing from FLASH_MAP table\n " );
437+ continue ;
438+ }
439+ #endif
440+
441+ // For SDKs 3.0.0 and later, place phy_data readonly overlay on top of
442+ // the EEPROM address. For older SDKs without a system partition, RF_CAL
443+ // and PHY_DATA shared the same flash segment.
444+ //
445+ // For the Arduino ESP8266 core, the sectors for "EEPROM = size -
446+ // 0x5000", "RF_CAL = size - 0x4000", and "SYSTEM_PARAMETER = size -
447+ // 0x3000" are positioned in the last five sectors of flash memory.
448+ // PHY_INIT_DATA is special. It is a one time read of 128 bytes of data
449+ // that is provided by a spoofed flash read.
450+ #if FLASH_MAP_SUPPORT
451+ flash_size = __flashdesc[__flashindex].flash_size_kb * 1024u ;
452+ #else
453+ // flashchip->chip_size is updated by the SDK. The size is based on the
454+ // value patched into the .bin header by esptool.
455+ // system_get_flash_size_map() returns that patched value.
456+ flash_size = flashchip->chip_size ;
457+ #endif
458+
459+ // For all configurations, place RF_CAL and system_parameter in the
460+ // last 4 sectors of the flash chip.
461+ rf_cal = flash_size - 0x4000u ;
462+ system_parameter = flash_size - 0x3000u ;
463+
464+ // The system_partition_table_regist will not allow partitions to
465+ // overlap. EEPROM_start is a good choice for phy_data overlay. The SDK
466+ // does not need to know about EEPROM_start. So we can omit it from the
467+ // table. The real EEPROM access is after user_init() begins long after
468+ // the PHY_DATA read. So it should be safe from conflicts.
469+ phy_data = EEPROM_start - 0x40200000u ;
470+
471+ // For SDKs 3.0 builds, "sdk3_begin_phy_data_spoof and
472+ // user_rf_cal_sector_set" starts and stops the spoofing logic in
473+ // `core_esp8266_phy.cpp`.
474+ extern void sdk3_begin_phy_data_spoof ();
475+ sdk3_begin_phy_data_spoof ();
476+
477+ ld_config_chip_size = phy_data + 4096 * 5 ;
478+
479+ // -DALLOW_SMALL_FLASH_SIZE=1
480+ // Allows for small flash-size builds targeted for multiple devices,
481+ // commonly IoT, of varying flash sizes.
482+ #if !defined(FLASH_MAP_SUPPORT) && !defined(ALLOW_SMALL_FLASH_SIZE)
483+ // Note, system_partition_table_regist will only catch when the build
484+ // flash size value set by the Arduino IDE Tools menu is larger than
485+ // the firmware image value detected and updated on the fly by esptool.
486+ if (flashchip->chip_size != ld_config_chip_size) {
487+ // Stop to avoid possible stored flash data corruption. This
488+ // mismatch will not occur with flash size selection "Mapping
489+ // defined by Hardware and Sketch".
490+ chip_sz_str = PSTR (" Flash size mismatch, check that the build setting matches the device.\n " );
491+ continue ;
492+ }
493+ #elif defined(ALLOW_SMALL_FLASH_SIZE) && !defined(FLASH_MAP_SUPPORT)
494+ // Note, while EEPROM is confined to a smaller flash size, we are still
495+ // placing RF_CAL and SYSTEM_PARAMETER at the end of flash. To prevent
496+ // this, esptool or its equal needs to not update the flash size in the
497+ // .bin image.
498+ #endif
499+
500+ #if FLASH_MAP_SUPPORT && defined(DEBUG_ESP_PORT)
501+ // I don't think this will ever fail. Everything traces back to the results of spi_flash_get_id()
502+ if (flash_size != flashchip->chip_size ) {
503+ chip_sz_str = PSTR (" Flash size mismatch, check that the build setting matches the device.\n " );
504+ continue ;
505+ }
506+ #endif
507+
508+ // All the examples I find, show the partition table in the global address space.
509+ static const partition_item_t at_partition_table[] =
510+ {
511+ { SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 }, // type 5
512+ { SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 }, // type 4
513+ { SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 }, // type 6
514+ };
515+ _at_partition_table = at_partition_table;
516+ _at_partition_table_sz = std::size (at_partition_table);
517+ // SDK 3.0's `system_partition_table_regist` is FOTA-centric. It will report
518+ // on BOOT, OTA1, and OTA2 being missing. We are Non-FOTA. I don't see
519+ // anything we can do about this. Other than maybe turning off os_print.
520+ if (!system_partition_table_regist (at_partition_table, _at_partition_table_sz, system_get_flash_size_map ())) {
521+ table_regist_str = PSTR (" System partition table registration failed!\n " );
522+ continue ;
523+ }
524+ } while (false );
525+
526+ if (chip_sz_str || flash_map_str || table_regist_str) {
527+ // user_pre_init() is called very early in the SDK startup. When called,
528+ // the PLL CPU clock calibration hasn't not run. Since we are failing, the
529+ // calibration will never complete. And the process will repeat over and
530+ // over. The effective data rate will always be 74880 bps. If we had a
531+ // successful boot, the effective data rate would be 115200 on a restart
532+ // or HWDT. This hack relies on the CPU clock calibration never having
533+ // completed. This assumes we are starting from a hard reset.
534+
535+ // A possible exception would be a soft reset after flashing. In which
536+ // case the message will not be readable until after a hard reset or
537+ // power cycle.
538+
539+ // After flashing, the Arduino Serial Monitor needs a moment to
540+ // reconnect. This also allows time for the FIFO to clear and the host
541+ // serial port to clear any framing errors.
542+ ets_delay_us (200u * 1000u ); // For an uncalibrated CPU Clock, this is close enough.
543+
544+ #if !defined(F_CRYSTAL)
545+ #define F_CRYSTAL 26000000
546+ #endif
547+ // For print messages to be readable, the UART clock rate is based on the
548+ // precalibration rate.
549+ if (F_CRYSTAL != 40000000 ) {
550+ uart_div_modify (0 , F_CRYSTAL * 2 / 115200 );
551+ ets_delay_us (150 );
552+ }
553+ do {
554+ ETS_PRINTF (" \n\n " );
555+ // Because SDK v3.0.x always has a non-32-bit wide exception handler
556+ // installed, we can use PROGMEM strings with Boot ROM print functions.
557+ #if defined(DEBUG_ESP_CORE) || defined(DEBUG_ESP_PORT) // DEBUG_ESP_CORE => verbose
558+ #if FLASH_MAP_SUPPORT
559+ if (flash_map_str) {
560+ ETS_PRINTF (flash_map_str);
561+ #if defined(DEBUG_ESP_CORE)
562+ size_t num = __flashindex; // On failure __flashindex is the size of __flashdesc[]; :/
563+ ETS_PRINTF (PSTR (" Table of __flashdesc[%u].flash_size_kb entries converted to bytes:\n " ), num);
564+ for (size_t i = 0 ; i < num; i++) {
565+ uint32_t size = __flashdesc[i].flash_size_kb << 10 ;
566+ ETS_PRINTF (PSTR (" [%02u] 0x%08X %8u\n " ), i, size, size);
567+ }
568+ #endif
569+ ETS_PRINTF (PSTR (" Reference info:\n " ));
570+ uint32_t flash_chip_size = 1 << ((spi_flash_get_id () >> 16 ) & 0xff );
571+ ETS_PRINTF (PSTR (" %-24s 0x%08X %8u\n " ), PSTR (" fn(spi_flash_get_id())" ), flash_chip_size, flash_chip_size);
572+ ETS_PRINTF (PSTR (" %-24s 0x%08X %8u\n " ), PSTR (" bin_chip_size" ), flashchip->chip_size , flashchip->chip_size );
573+ } else
574+ #endif
575+ if (chip_sz_str) {
576+ ETS_PRINTF (chip_sz_str);
577+ } else
578+ if (table_regist_str) {
579+ ETS_PRINTF (table_regist_str);
580+ // (printing now works) repeat ...regist error messages
581+ system_partition_table_regist (_at_partition_table, _at_partition_table_sz, system_get_flash_size_map ());
582+ }
583+ if (chip_sz_str || table_regist_str) {
584+ ETS_PRINTF (PSTR (" Reference info:\n " ));
585+ #if FLASH_MAP_SUPPORT
586+ ETS_PRINTF (PSTR (" %-24s 0x%08X %8u\n " ), PSTR (" fn(...ex].flash_size_kb)" ), flash_size, flash_size);
587+ uint32_t flash_chip_size = 1 << ((spi_flash_get_id () >> 16 ) & 0xff );
588+ ETS_PRINTF (PSTR (" %-24s 0x%08X %8u\n " ), PSTR (" fn(spi_flash_get_id())" ), flash_chip_size, flash_chip_size);
589+ ETS_PRINTF (PSTR (" %-24s 0x%08X %8u\n " ), PSTR (" bin_chip_size" ), flashchip->chip_size , flashchip->chip_size );
590+ #else
591+ ETS_PRINTF (PSTR (" %-24s 0x%08X %8u\n " ), PSTR (" config_flash_size" ), ld_config_chip_size, ld_config_chip_size);
592+ ETS_PRINTF (PSTR (" %-24s 0x%08X %8u\n " ), PSTR (" bin_chip_size" ), flashchip->chip_size , flashchip->chip_size );
593+ #endif
594+ #if defined(DEBUG_ESP_CORE)
595+ ETS_PRINTF (PSTR (" %-24s 0x%08X\n " ), PSTR (" PHY_DATA" ), phy_data);
596+ ETS_PRINTF (PSTR (" %-24s 0x%08X\n " ), PSTR (" RF_CAL" ), rf_cal);
597+ ETS_PRINTF (PSTR (" %-24s 0x%08X\n " ), PSTR (" SYSTEM_PARAMETER" ), system_parameter);
598+ ETS_PRINTF (PSTR (" %-24s 0x%08X\n " ), PSTR (" EEPROM_start" ), EEPROM_start);
599+ ETS_PRINTF (PSTR (" %-24s 0x%08X\n " ), PSTR (" FS_start" ), FS_start);
600+ ETS_PRINTF (PSTR (" %-24s 0x%08X\n " ), PSTR (" FS_end" ), FS_end);
601+ ETS_PRINTF (PSTR (" %-24s 0x%08X\n " ), PSTR (" FS_page" ), FS_page);
602+ ETS_PRINTF (PSTR (" %-24s 0x%08X\n " ), PSTR (" FS_block" ), FS_block);
603+ #endif
604+ }
605+ #else
606+ if (flash_map_str) {
607+ ETS_PRINTF (flash_map_str);
608+ } else
609+ if (chip_sz_str) {
610+ ETS_PRINTF (chip_sz_str);
611+ } else
612+ if (table_regist_str) {
613+ ETS_PRINTF (table_regist_str);
614+ }
615+ #endif
616+ uart_rx_one_char_block (); // Someone said hello - repeat message
617+ } while (true );
455618 }
456-
457- extern uint32_t user_rf_cal_sector_set (void );
458- user_rf_cal_sector_set ();
459-
460- const partition_item_t at_partition_table[] =
461- {
462- { SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 },
463- { SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 },
464- { SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 },
465- };
466- system_partition_table_regist (at_partition_table, sizeof (at_partition_table) / sizeof (at_partition_table[0 ]), system_get_flash_size_map ());
467619}
468-
469- #endif
620+ #endif // #if (NONOSDK >= (0x30000))
470621
471622extern " C" void user_init (void ) {
472623
473624#if (NONOSDK >= (0x30000))
474625 extern void user_rf_pre_init ();
475- user_rf_pre_init ();
626+ user_rf_pre_init (); // Stop spoofing logic
476627#endif
477628
478629 struct rst_info *rtc_info_ptr = system_get_rst_info ();
@@ -503,8 +654,10 @@ extern "C" void user_init(void) {
503654#if defined(MMU_IRAM_HEAP)
504655 umm_init_iram ();
505656#endif
506- #if FLASH_MAP_SUPPORT
507- flashinit ();
657+ #if FLASH_MAP_SUPPORT && (NONOSDK < 0x30000)
658+ if (!flashinit ()) {
659+ panic ();
660+ }
508661#endif
509662 preinit (); // Prior to C++ Dynamic Init (not related to above init() ). Meant to be user redefinable.
510663 __disableWiFiAtBootTime (); // default weak function disables WiFi
0 commit comments