// prevent this function being placed inline with main // to keep main's stack size as small as possible static uint32 NOINLINE find_image() { uint8 flag; uint32 runAddr; uint32 flashsize; int32 romToBoot; uint8 gpio_boot = FALSE; uint8 updateConfig = TRUE; uint8 buffer[SECTOR_SIZE]; rboot_config *romconf = (rboot_config*)buffer; rom_header *header = (rom_header*)buffer; ets_delay_us(2000000); ets_printf("\r\nrBoot v1.0.0 - [email protected]\r\n"); // read rom header SPIRead(0, header, sizeof(rom_header)); // print and get flash size ets_printf("Flash Size: "); flag = header->flags2 >> 4; if (flag == 0) { ets_printf("4 Mbit\r\n"); flashsize = 0x80000; } else if (flag == 1) { ets_printf("2 Mbit\r\n"); flashsize = 0x40000; } else if (flag == 2) { ets_printf("8 Mbit\r\n"); flashsize = 0x100000; } else if (flag == 3) { ets_printf("16 Mbit\r\n"); flashsize = 0x200000; } else if (flag == 4) { ets_printf("32 Mbit\r\n"); flashsize = 0x400000; } else { ets_printf("unknown\r\n"); // assume at least 4mbit flashsize = 0x80000; } // print spi mode ets_printf("Flash Mode: "); if (header->flags1 == 0) { ets_printf("QIO\r\n"); } else if (header->flags1 == 1) { ets_printf("QOUT\r\n"); } else if (header->flags1 == 2) { ets_printf("DIO\r\n"); } else if (header->flags1 == 3) { ets_printf("DOUT\r\n"); } else { ets_printf("unknown\r\n"); } // print spi speed ets_printf("Flash Speed: "); flag = header->flags2 & 0x0f; if (flag == 0) ets_printf("40 MHz\r\n"); else if (flag == 1) ets_printf("26.7 MHz\r\n"); else if (flag == 2) ets_printf("20 MHz\r\n"); else if (flag == 0x0f) ets_printf("80 MHz\r\n"); else ets_printf("unknown\r\n"); // read boot config SPIRead(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE); // fresh install or old version? if (romconf->magic != BOOT_CONFIG_MAGIC || romconf->version != BOOT_CONFIG_VERSION) { // create a default config for a standard 2 rom setup ets_printf("Writing default boot config.\r\n"); ets_memset(romconf, 0x00, sizeof(rboot_config)); romconf->magic = BOOT_CONFIG_MAGIC; romconf->version = BOOT_CONFIG_VERSION; romconf->mode = MODE_STANDARD; romconf->current_rom = 0; romconf->count = 2; romconf->current_rom = 0; romconf->roms[0] = SECTOR_SIZE * 2; romconf->roms[1] = (flashsize / 2) + (SECTOR_SIZE * 2); // write new config sector SPIEraseSector(BOOT_CONFIG_SECTOR); SPIWrite(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE); } // if gpio mode enabled check status of the gpio if ((romconf->mode & MODE_GPIO_ROM) && (get_gpio16() == 0)) { ets_printf("Booting GPIO-selected.\r\n"); romToBoot = romconf->gpio_rom; gpio_boot = TRUE; } else if (romconf->current_rom >= romconf->count) { // if invalid rom selected try rom 0 ets_printf("Invalid rom selected, defaulting.\r\n"); romToBoot = 0; romconf->current_rom = 0; updateConfig = TRUE; } else { // try rom selected in the config romToBoot = romconf->current_rom; } // try to find a good rom do { runAddr = check_image(romconf->roms[romToBoot]); if (runAddr == 0) { ets_printf("Rom %d is bad.\r\n", romToBoot); if (gpio_boot) { // don't switch to backup for gpio-selected rom ets_printf("GPIO boot failed.\r\n"); return 0; } else { // for normal mode try each previous rom // until we find a good one or run out updateConfig = TRUE; romToBoot--; if (romToBoot < 0) romToBoot = romconf->count - 1; if (romToBoot == romconf->current_rom) { // tried them all and all are bad! ets_printf("No good rom available.\r\n"); return 0; } } } } while (runAddr == 0); // re-write config, if required if (updateConfig) { romconf->current_rom = romToBoot; SPIEraseSector(BOOT_CONFIG_SECTOR); SPIWrite(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE); } ets_printf("Booting rom %d.\r\n", romToBoot); // copy the loader to top of iram ets_memcpy((void*)_text_addr, _text_data, _text_len); // return address to load from return runAddr; }
// prevent this function being placed inline with main // to keep main's stack size as small as possible // don't mark as static or it'll be optimised out when // using the assembler stub uint32 NOINLINE find_image() { uint8 flag; uint32 runAddr; uint32 flashsize; int32 romToBoot; uint8 gpio_boot = FALSE; uint8 updateConfig = TRUE; uint8 buffer[SECTOR_SIZE]; rboot_config *romconf = (rboot_config*)buffer; rom_header *header = (rom_header*)buffer; // delay to slow boot (help see messages when debugging) //ets_delay_us(2000000); ets_printf("\r\nrBoot v1.2.1 - [email protected]\r\n"); // read rom header SPIRead(0, header, sizeof(rom_header)); // print and get flash size ets_printf("Flash Size: "); flag = header->flags2 >> 4; if (flag == 0) { ets_printf("4 Mbit\r\n"); flashsize = 0x80000; } else if (flag == 1) { ets_printf("2 Mbit\r\n"); flashsize = 0x40000; } else if (flag == 2) { ets_printf("8 Mbit\r\n"); flashsize = 0x100000; } else if (flag == 3) { ets_printf("16 Mbit\r\n"); #ifdef BOOT_BIG_FLASH flashsize = 0x200000; #else flashsize = 0x100000; // limit to 8Mbit #endif } else if (flag == 4) { ets_printf("32 Mbit\r\n"); #ifdef BOOT_BIG_FLASH flashsize = 0x400000; #else flashsize = 0x100000; // limit to 8Mbit #endif } else { ets_printf("unknown\r\n"); // assume at least 4mbit flashsize = 0x80000; } // print spi mode ets_printf("Flash Mode: "); if (header->flags1 == 0) { ets_printf("QIO\r\n"); } else if (header->flags1 == 1) { ets_printf("QOUT\r\n"); } else if (header->flags1 == 2) { ets_printf("DIO\r\n"); } else if (header->flags1 == 3) { ets_printf("DOUT\r\n"); } else { ets_printf("unknown\r\n"); } // print spi speed ets_printf("Flash Speed: "); flag = header->flags2 & 0x0f; if (flag == 0) ets_printf("40 MHz\r\n"); else if (flag == 1) ets_printf("26.7 MHz\r\n"); else if (flag == 2) ets_printf("20 MHz\r\n"); else if (flag == 0x0f) ets_printf("80 MHz\r\n"); else ets_printf("unknown\r\n"); // print enabled options #ifdef BOOT_BIG_FLASH ets_printf("rBoot Option: Big flash\r\n"); #endif #ifdef BOOT_CONFIG_CHKSUM ets_printf("rBoot Option: Config chksum\r\n"); #endif #ifdef BOOT_IROM_CHKSUM ets_printf("rBoot Option: irom chksum\r\n"); #endif ets_printf("\r\n"); // read boot config SPIRead(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE); // fresh install or old version? if (romconf->magic != BOOT_CONFIG_MAGIC || romconf->version != BOOT_CONFIG_VERSION #ifdef BOOT_CONFIG_CHKSUM || romconf->chksum != calc_chksum((uint8*)romconf, (uint8*)&romconf->chksum) #endif ) { /* Modified by Cesanta */ ets_printf("Writing default boot config.\r\n"); ets_memset(romconf, 0x00, sizeof(rboot_config)); romconf->magic = BOOT_CONFIG_MAGIC; romconf->version = BOOT_CONFIG_VERSION; romconf->count = 2; romconf->mode = MODE_STANDARD; /* FWx_ADDR, FWx_FS_ADDR and FS_SIZE, FW_SIZE must be defined by -D */ romconf->roms[0] = FW1_ADDR; romconf->roms[1] = FW2_ADDR; romconf->fs_addresses[0] = FW1_FS_ADDR; romconf->fs_addresses[1] = FW2_FS_ADDR; romconf->fs_sizes[0] = romconf->fs_sizes[1] = FS_SIZE; romconf->roms_sizes[0] = romconf->roms_sizes[1] = FW_SIZE; #ifdef BOOT_CONFIG_CHKSUM romconf->chksum = calc_chksum((uint8*)romconf, (uint8*)&romconf->chksum); #endif // write new config sector SPIEraseSector(BOOT_CONFIG_SECTOR); SPIWrite(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE); } // if gpio mode enabled check status of the gpio if ((romconf->mode & MODE_GPIO_ROM) && (get_gpio16() == 0)) { ets_printf("Booting GPIO-selected.\r\n"); romToBoot = romconf->previous_rom; /* * Modified by Cesanta * Make FD current */ updateConfig = TRUE; romconf->fw_updated = 0; romconf->is_first_boot = 0; gpio_boot = TRUE; } else if (romconf->current_rom >= romconf->count) { // if invalid rom selected try rom 0 ets_printf("Invalid rom selected, defaulting.\r\n"); romToBoot = 0; romconf->current_rom = 0; romconf->fw_updated = 0; romconf->is_first_boot = 0; updateConfig = TRUE; } else { /* Modified by Cesanta */ if (romconf->is_first_boot != 0) { ets_printf("First boot, attempt %d\n", romconf->boot_attempts); /* boot is unconfirmed */ if (romconf->boot_attempts == 0) { /* haven't try to load yes */ ets_printf("Boot is unconfirmed\r\n"); romconf->boot_attempts++; } else { ets_printf("Boot failed, fallback to fw #%d\r\n", romconf->previous_rom); romconf->current_rom = romconf->previous_rom; /* clear fw update flag, to avoid post-update acttions */ romconf->fw_updated = 0; romconf->boot_attempts = 0; } updateConfig = TRUE; } /* End of Cesanta modifications */ // try rom selected in the config romToBoot = romconf->current_rom; } // try to find a good rom do { runAddr = check_image(romconf->roms[romToBoot]); if (runAddr == 0) { ets_printf("Rom %d is bad.\r\n", romToBoot); if (gpio_boot) { // don't switch to backup for gpio-selected rom ets_printf("GPIO boot failed.\r\n"); return 0; } else { // for normal mode try each previous rom // until we find a good one or run out updateConfig = TRUE; romToBoot--; if (romToBoot < 0) romToBoot = romconf->count - 1; if (romToBoot == romconf->current_rom) { // tried them all and all are bad! ets_printf("No good rom available.\r\n"); return 0; } } } } while (runAddr == 0); // re-write config, if required if (updateConfig) { romconf->current_rom = romToBoot; #ifdef BOOT_CONFIG_CHKSUM romconf->chksum = calc_chksum((uint8*)romconf, (uint8*)&romconf->chksum); #endif SPIEraseSector(BOOT_CONFIG_SECTOR); SPIWrite(BOOT_CONFIG_SECTOR * SECTOR_SIZE, buffer, SECTOR_SIZE); } ets_printf("Booting rom %d.\r\n", romToBoot); // copy the loader to top of iram ets_memcpy((void*)_text_addr, _text_data, _text_len); // return address to load from return runAddr; }