示例#1
0
/*	cgiGetAppVer	*/
int ICACHE_FLASH_ATTR cgiGetAppVer(HttpdConnection *	ptConnection)
{
	/* initialization */
	int iRet = 0;

	if (NULL == ptConnection->ptEspConnection)
	{
		/* connection aborted - clean up */
		iRet = HTTPD_CGI_DONE;
		goto lblCleanup;
	}
	
	char bVersion[1] = { 0 };

	/* set and send app version */
	os_sprintf(bVersion, "%d", system_upgrade_userbin_check() + 1);
	httpdStartResponse(ptConnection, 200);
	httpdHeader(ptConnection, CONTENT_LENGTH_STRING, "1");
	httpdEndHeaders(ptConnection);
	httpdSend(ptConnection, bVersion, 1);

	iRet = HTTPD_CGI_DONE;

lblCleanup:
	return iRet;
}
示例#2
0
void ICACHE_FLASH_ATTR
tcpserver_init(void)
{
    int8_t res;

    tcp_server.type = ESPCONN_TCP;
    tcp_server.state = ESPCONN_NONE;
    tcp_server.proto.tcp = &tcp_config;
    tcp_server.proto.tcp->local_port = TCP_SERVER_LOCAL_PORT;

    espconn_regist_connectcb(&tcp_server, incoming_connection_callback);

    espconn_tcp_set_max_con_allow(&tcp_server, 1); //Allow 1 connection max

    res = espconn_accept(&tcp_server);

    if(res == 0)
        os_printf("Created TCP server on port %d, running on ROM %d, AP RSSI: %ddBm, WiFi mode: %d.\r\n", 
                tcp_server.proto.tcp->local_port,
                system_upgrade_userbin_check(),
                wifi_station_get_rssi(),
                wifi_get_phy_mode());
    else
        os_printf("Failed to create TCP server, error code: %d.\r\n", res);
}
示例#3
0
/******************************************************************************
 * FunctionName : user_esp_platform_upgrade_begin
 * Description  : Processing the received data from the server
 * Parameters   : pespconn -- the espconn used to connetion with the host
 *                server -- upgrade param
 * Returns      : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
v_user_esp_platform_upgrade_begin(struct espconn *pespconn, struct upgrade_server_info *server)
{
    uint8 user_bin[9] = {0};


    server->pespconn = pespconn;
    server->port = 80;
    server->check_cb = v_user_esp_platform_upgrade_rsp;
    server->check_times = 120000;
    const char esp_server_ip[4] = {52,68,48,85};
    os_memcpy(server->ip, esp_server_ip, 4);

    if (server->url == NULL) {
        server->url = (uint8 *)os_zalloc(512);
    }
#if 0 // in general, we need to check user bin here
    if (system_upgrade_userbin_check() == UPGRADE_FW_BIN1) {
        os_memcpy(user_bin, "user2.bin", 10);
    } else if (system_upgrade_userbin_check() == UPGRADE_FW_BIN2) {
        os_memcpy(user_bin, "user1.bin", 10);
    }
    
    os_sprintf(server->url, "GET /%s HTTP/1.0\r\nHost: "IPSTR":%d\r\n"pheadbuffer"",
           user_bin, IP2STR(server->ip),
           80);
#else

    os_sprintf(server->url, "GET /%s HTTP/1.0\r\nHost: "IPSTR":%d\r\n"pheadbuffer"",
           "download/file/user1.1024.new.bin", IP2STR(server->ip),
           80);


    //http://192.168.31.229/test/user1.1024.new.2.bin

    //52.68.48.85/download/file/user1.1024.new.bin

#endif


    if (system_upgrade_start(server) == false) {

        ESP_DBG("upgrade is already started\n");
    }
}
示例#4
0
/**
  * @brief  Get version connection version
  * @param  arg: contain the ip link information
  * @retval None
  */
void ICACHE_FLASH_ATTR
get_version_connect_cb(void *arg)
{
  struct espconn *pespconn = (struct espconn *)arg;
  fota_client_t *fota_client = (fota_client_t *)pespconn->reverse;

  espconn_regist_recvcb(pespconn, get_version_recv);
  espconn_regist_sentcb(pespconn, get_version_sent_cb);

  uint8_t user_bin[12] = {0};
  if(system_upgrade_userbin_check() == UPGRADE_FW_BIN1) {
    os_memcpy(user_bin, "image2", os_strlen("image2"));
  }
  else if(system_upgrade_userbin_check() == UPGRADE_FW_BIN2) {
    os_memcpy(user_bin, "image1", os_strlen("image1"));
  }

  char *temp = NULL;
  temp = (uint8 *) os_zalloc(512);

  os_sprintf(temp, "GET /api/%s/versions/%s HTTP/1.0\r\nHost: %s\r\n"pHeadStatic""pHeadAuthen"\r\n",
    PROJECT,
    user_bin,
    fota_client->host,
    // fota_client->uuid,   //pHeaderAuthen
    fota_client->token
    // FOTA_CLIENT
    // VERSION
    );

  // INFO("request: %s\n", temp);

  if (FOTA_SECURE)
    espconn_secure_sent(pespconn, temp, os_strlen(temp));
  else
    espconn_sent(pespconn, temp, os_strlen(temp));

  FREE(temp);

  // prepare to get response
  get_version_body_len = -1;
}
示例#5
0
static void ICACHE_FLASH_ATTR handleUpgrade(uint8_t serverVersion, const char *server_ip, uint16_t port, const char *path)
{
    const char* file;
    struct upgrade_server_info* update;
    uint8_t userBin = system_upgrade_userbin_check();
    DBG_MSG("UserBIn = %d\r\n", userBin);
    switch (ROMNUM)
    {
        case 1: file = "user2.1024.new.2.bin"; break;
        case 2: file = "user1.1024.new.2.bin"; break;
        default:
            DBG_MSG("[OTA]Invalid userbin number!\r\n");
            return;
    }

    uint16_t version=1;
    if (serverVersion <= version)
    {
        DBG_MSG("[OTA]No update. Server version:%d, local version %d\r\n", serverVersion, version);
        return;
    }

    DBG_MSG("[OTA]Upgrade available version: %d\r\n", serverVersion);

    update = (struct upgrade_server_info *)os_zalloc(sizeof(struct upgrade_server_info));
    update->pespconn = (struct espconn *)os_zalloc(sizeof(struct espconn));

    os_memcpy(update->ip, server_ip, 4);
    update->port = port;

    DBG_MSG("[OTA]Server "IPSTR":%d. Path: %s%s\r\n", IP2STR(update->ip), update->port, path, file);

    update->check_cb = ota_finished_callback;
    update->check_times = 10000;
    update->url = (uint8 *)os_zalloc(512);

    os_sprintf((char*)update->url,
        "GET %s%s HTTP/1.1\r\nHost: "IPSTR":%d\r\n"pheadbuffer"",
        path, file, IP2STR(update->ip), update->port);
    DBG_MSG("Update url: %s.\r\n", update->url);

    if (system_upgrade_start(update) == false)
    {
        DBG_MSG("[OTA]Could not start upgrade\r\n");

        os_free(update->pespconn);
        os_free(update->url);
        os_free(update);
    }
    else
    {
        DBG_MSG("[OTA]Upgrading...\r\n");
    }
}
int8_t ICACHE_FLASH_ATTR cb_fota_slot_free(uint8_t IsFirstCall, char* OutputData, uint16_t MaxBytes, uint16_t* RetBytes, uint8_t* RetDone){
/* TAG CALLBACK FUNCTION for [[FOTA_SLOT_FREE]]
 * --------------------------------------------
 * ! See whttpd_pp_item_struct structure definition to know what is passed to / what is expected from tag callback function.
 * ! This function could be called multiple times for one tag, if we signal by RetDone that we didn't end yet (probably because MaxBytes was less that what we needed).
 */
	*RetBytes = 0;
	*RetDone = 0;
	if(MaxBytes<1) return 0; //we are not able pass at least 1 byte - not enough space in OutputData => skip this call, report no error (don't abort tag preprocessing - it will be called again with more MaxBytes)
	OutputData[0] = (system_upgrade_userbin_check()==UPGRADE_FW_BIN1)?'2':'1';
	*RetBytes = 1;
	*RetDone = 1;
	return 0; //no error (don't abort tag preprocessing)
}
示例#7
0
/**
  * @brief  Get version connection version
  * @param  arg: contain the ip link information
  * @retval None
  */
void ICACHE_FLASH_ATTR
get_version_connect_cb(void *arg)
{
  struct espconn *pespconn = (struct espconn *)arg;
  fota_client_t *fota_client = (fota_client_t *)pespconn->reverse;

  espconn_regist_recvcb(pespconn, get_version_recv);
  espconn_regist_sentcb(pespconn, get_version_sent_cb);

  uint8_t user_bin[12] = {0};
  if(system_upgrade_userbin_check() == UPGRADE_FW_BIN1) {
    os_memcpy(user_bin, "user1.bin", 10);
  }
  else if(system_upgrade_userbin_check() == UPGRADE_FW_BIN2) {
    os_memcpy(user_bin, "user2.bin", 10);
  }

  char *temp = NULL;
  temp = (uint8 *) os_zalloc(512);

  os_sprintf(temp, "GET /firmware/%s/versions HTTP/1.0\r\nHost: %s\r\n"pHeadStatic""pHeadAuthen"\r\n",
    PROJECT,
    fota_client->host,
    fota_client->uuid,   //pHeaderAuthen
    fota_client->token,
    FOTA_CLIENT,
    user_bin,
    VERSION
    );

#if (FOTA_SECURE)
  espconn_secure_sent(pespconn, temp, os_strlen(temp));
#else
  espconn_sent(pespconn, temp, os_strlen(temp));
#endif
  FREE(temp);
}
示例#8
0
// Cgi to query which firmware needs to be uploaded next
int ICACHE_FLASH_ATTR cgiGetFirmwareNext(HttpdConnData *connData) {
    if (connData->conn==NULL) {
        //Connection aborted. Clean up.
        return HTTPD_CGI_DONE;
    }
    uint8 id = system_upgrade_userbin_check();
    httpdStartResponse(connData, 200);
    httpdHeader(connData, "Content-Type", "text/plain");
    httpdHeader(connData, "Content-Length", "9");
    httpdEndHeaders(connData);
    char *next = id == 1 ? "user1.bin" : "user2.bin";
    httpdSend(connData, next, -1);
    os_printf("Next firmware: %s (got %d)\n", next, id);
    return HTTPD_CGI_DONE;
}
示例#9
0
/************************************************
*	name:			user_init
*	parameters:		none
*	return value:	none
*	purpose:		main logic
************************************************/
void user_init(void)
{	
	/* initialization */
	struct softap_config 	tWifiSettings = { 0 };
	uint8 					puMacAddress[6] = { 0 };

	os_memset((void *)&tWifiSettings, 0, sizeof(tWifiSettings));

	wifi_softap_get_config(&tWifiSettings);
	
	/* retrieve mac address */
	wifi_get_macaddr(1, puMacAddress);
	
	/* append to ssid name */
	memcpy(tWifiSettings.ssid, HOTSPOT_SSID_STRING, sizeof(HOTSPOT_SSID_STRING));

	os_sprintf(tWifiSettings.ssid + sizeof(HOTSPOT_SSID_STRING) - 1, "%x%x%x%x%x%x", puMacAddress[0],
							  												  	 	 puMacAddress[1],
							  												  	 	 puMacAddress[2],
							  												  	 	 puMacAddress[3],
							  												  	 	 puMacAddress[4],
							  												  	 	 puMacAddress[5]);
	/* set password */
	memcpy(tWifiSettings.password, HOTSPOT_PASSWORD_STRING, os_strlen(HOTSPOT_PASSWORD_STRING));
	
	/* update other settings */
	tWifiSettings.authmode = AUTH_WPA_WPA2_PSK;
	tWifiSettings.ssid_len = 0;
	tWifiSettings.channel = 6;
	tWifiSettings.max_connection = 4;
	
	/* update wifi configuration */
	wifi_softap_set_config(&tWifiSettings);
	
	/* initialize stdout */
	stdoutInit();
	
	/* initialize IOs */
	ioInit();
	
	/* initialize server */
	httpdInit(g_ptSupportedUrls, 80);
	
#ifdef USER_MAIN_DEBUG
	os_printf("user_init: ready; partition %d\n", system_upgrade_userbin_check());
#endif
}
示例#10
0
文件: main.c 项目: icamgo/noduino-sdk
void user_init(void)
{
#ifdef DEBUG
	uart_init(115200, 115200);
#endif
	INFO("\r\nWelcom to Noduino Open miniK Plug!\r\n");
	INFO("Current firmware is user%d.bin\r\n", system_upgrade_userbin_check()+1);
	INFO("%s", noduino_banner);

	param_init();
	led_init();
	relay_init();
	xkey_init();

	// restore the relay status quickly
	relay_set_status(param_get_status());

	system_init_done_cb(init_yun);
}
示例#11
0
/* get_updatable_partition */
int get_updatable_partition()
{
	/* initialization */
	int iRet = 0;

#ifndef OTA
	iRet = 1;
#endif

	if (0 == system_upgrade_userbin_check())
	{
		iRet = 4;
	}
	else
	{
		iRet = 1;
	}

	return iRet;
}
示例#12
0
文件: OTADemo.cpp 项目: oter/BSPTools
static void __attribute__((section(".irom.text"))) upgradeCb(void *arg) 
{
	struct espconn *pConn = (struct espconn*)arg;
    espconn_sent(pConn, (uint8_t *)s_UpgradeMessage, strlen(s_UpgradeMessage));
	espconn_disconnect(pConn);
    
    upgrade_server_info *pUpgrade = (upgrade_server_info *)pvPortZalloc(sizeof(upgrade_server_info));
	pUpgrade->pespconn = pConn;
    memcpy(pUpgrade->ip, pConn->proto.tcp->remote_ip, 4);
    pUpgrade->check_cb = ota_finished_callback;
    pUpgrade->check_times = 60000;
    pUpgrade->port = 8888;
    pUpgrade->upgrade_version[0] = '1';
    if (system_upgrade_userbin_check() == UPGRADE_FW_BIN1)
        pUpgrade->url = (uint8_t *)"GET /user2.bin HTTP/1.0\r\nConnection: close\r\n\r\n\r";
    else
        pUpgrade->url = (uint8_t *)"GET /user1.bin HTTP/1.0\r\nConnection: close\r\n\r\n\r";
    
    system_upgrade_start(pUpgrade);
}
示例#13
0
文件: main.c 项目: icamgo/noduino-sdk
irom void setup()
{
#ifdef DEBUG
	uart_init(115200, 115200);
#endif
	os_delay_us(100);
	INFO("\r\n\r\n\r\n\r\n\r\n\r\n");
	INFO("\r\nWelcom to Noduino Open Ctrl4relay!\r\n");
	INFO("Current firmware is user%d.bin\r\n", system_upgrade_userbin_check()+1);
	INFO("%s", noduino_banner);

	param_load();
	relay_init();

	led_init();
	xkey_init();

	init_yun();

	wifi_set_sleep_type(MODEM_SLEEP_T);
}
示例#14
0
void user_init(void)
{
	// Configure the UART
	uart_init(BIT_RATE_115200, BIT_RATE_115200);
	// Enable system messages
	system_set_os_print(1);
	DHT22_DEBUG("\n==== System info: ====\n");
	DHT22_DEBUG("SDK version:%s rom %d\n", system_get_sdk_version(), system_upgrade_userbin_check());
	DHT22_DEBUG("Time = %ld\n", system_get_time());
	DHT22_DEBUG("Chip id = 0x%x\n", system_get_chip_id());
	DHT22_DEBUG("CPU freq = %d MHz\n", system_get_cpu_freq());
	DHT22_DEBUG("Flash size map = %s\n", FlashSizeMap[system_get_flash_size_map()]);
	DHT22_DEBUG("Free heap size = %d\n", system_get_free_heap_size());
	DHT22_DEBUG("==== End System info ====\n");
	os_delay_us(10000);
	DHT22_DEBUG("System init...\r\n");

	if(wifi_get_opmode() != STATION_MODE)
	{
		DHT22_DEBUG("ESP8266 is %s mode, restarting in %s mode...\r\n", WiFiMode[wifi_get_opmode()], WiFiMode[STATION_MODE]);
		setup_wifi_st_mode();
	}
	if(wifi_get_phy_mode() != PHY_MODE_11N)
		wifi_set_phy_mode(PHY_MODE_11N);
	if(wifi_station_get_auto_connect() == 0)
		wifi_station_set_auto_connect(1);


	// Wait for Wi-Fi connection
	os_timer_disarm(&WiFiLinker);
	os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL);
	os_timer_arm(&WiFiLinker, WIFI_CHECK_DELAY, 0);

	UDP_Init();

	DHT22_DEBUG("System init done.\n");
}
示例#15
0
/**
  * @brief  Udp server receive data callback function.
  * @param  arg: contain the ip link information
  * @retval None
  */
LOCAL void ICACHE_FLASH_ATTR
at_upDate_recv(void *arg, char *pusrdata, unsigned short len)
{
  struct espconn *pespconn = (struct espconn *)arg;
  char temp[32];
  char *pTemp;
  uint8_t user_bin[9] = {0};
//  uint8_t devkey[41] = {0};
  uint8_t i;

  os_timer_disarm(&at_delayChack);
//  os_printf("get upRom:\r\n");
  uart0_sendStr("+CIPUPDATE:3\r\n");

//  os_printf("%s",pusrdata);
  pTemp = (char *)os_strstr(pusrdata,"rom_version\": ");
  if(pTemp == NULL)
  {
    return;
  }
  pTemp += sizeof("rom_version\": ");

//  user_esp_platform_load_param(&esp_param);

  upServer = (struct upgrade_server_info *)os_zalloc(sizeof(struct upgrade_server_info));
  os_memcpy(upServer->upgrade_version, pTemp, 5);
  upServer->upgrade_version[5] = '\0';
  os_sprintf(upServer->pre_version, "v%d.%d", AT_VERSION_main, AT_VERSION_sub);

  upServer->pespconn = pespconn;

//  os_memcpy(devkey, esp_param.devkey, 40);
  os_memcpy(upServer->ip, pespconn->proto.tcp->remote_ip, 4);

  upServer->port = 80;

  upServer->check_cb = at_upDate_rsp;
  upServer->check_times = 60000;

  if(upServer->url == NULL)
  {
    upServer->url = (uint8 *) os_zalloc(512);
  }

  if(system_upgrade_userbin_check() == UPGRADE_FW_BIN1)
  {
    os_memcpy(user_bin, "user2.bin", 10);
  }
  else if(system_upgrade_userbin_check() == UPGRADE_FW_BIN2)
  {
    os_memcpy(user_bin, "user1.bin", 10);
  }

  os_sprintf(upServer->url,
        "GET /v1/device/rom/?action=download_rom&version=%s&filename=%s HTTP/1.1\r\nHost: "IPSTR":%d\r\n"pheadbuffer"",
        upServer->upgrade_version, user_bin, IP2STR(upServer->ip),
        upServer->port, KEY);

  //  ESP_DBG(upServer->url);

//  espconn_disconnect(pespconn);
}
示例#16
0
/* espFsOpen */
EspFsFile ICACHE_FLASH_ATTR *	espFsOpen(char *	pszFilename)
{
	/* initialization */
	char *		pbHeaderOffset			= NULL;
	char *		pbTmpFile				= NULL;
	EspFsFile *	ptEspFile				= NULL;
	char 		pszFileNameBuffer[256]	= { 0 };
	EspFsHeader tEspFileHeader			= { 0 };

	/* acquire file system beginning */
#ifndef ESPFS_TEST
	int 		iEspFsOffset = 0;
	
	if (0 == system_upgrade_userbin_check())
	{
		iEspFsOffset = partition[ESPFS_PART].iOffset;
	}
	else
	{
		iEspFsOffset = partition[ESPFS_PART2].iOffset;
	}

	pbTmpFile = (char *)(iEspFsOffset + ESP_FLASH_OFFSET);
#else	
	pbTmpFile = espFsData;
#endif
	
	/* strip file name slashes */
	while (SLASH_SYMBOL_STRING == pszFilename[0])
	{
		++pszFilename;
	}

	/* locate file */
	while (1)
	{
		pbHeaderOffset = pbTmpFile;
		
		/* retrieve file header */
		os_memcpy(&tEspFileHeader, pbTmpFile, sizeof(EspFsHeader));

		if (ESPFS_MAGIC_HEADER != tEspFileHeader.magic)
		{
#ifdef ESPFS_DEBUG
			os_printf("espFsOpen: magic mismatch - file system image broken. found 0x%x instead\n", tEspFileHeader.magic);
#endif
			ptEspFile = NULL;
			goto lblCleanup;
		}

		if (tEspFileHeader.flags & FLAG_LASTFILE)
		{
#ifdef ESPFS_DEBUG
			os_printf("espFsOpen: end of image reached\n");
#endif
			ptEspFile = NULL;
			goto lblCleanup;
		}
		
		/* acquire file name */
		pbTmpFile += sizeof(EspFsHeader);
		os_memcpy(pszFileNameBuffer, pbTmpFile, sizeof(pszFileNameBuffer));

#ifdef ESPFS_DEBUG
		os_printf("espFsOpen: found file '%s'\nname length = %x, file length compressed = %x, compression = %d flags = %d\n",
				  pszFileNameBuffer, 
				  (unsigned int)tEspFileHeader.nameLen, 
				  (unsigned int)tEspFileHeader.fileLenComp, 
				  tEspFileHeader.compression, 
				  tEspFileHeader.flags);
#endif
		if (0 == os_strcmp(pszFileNameBuffer, pszFilename))
		{
			/* desired file */

			/* skip to content */
			pbTmpFile += tEspFileHeader.nameLen;

			/* allocate file descriptor */
			ptEspFile = (EspFsFile *)os_malloc(sizeof(EspFsFile));

#ifdef ESPFS_DEBUG
			os_printf("espFsOpen: file descriptor allocated at %p\n", ptEspFile);
#endif
			if (NULL == ptEspFile)
			{
				goto lblCleanup;
			}

			/* fill file descriptor */
			ptEspFile->header = (EspFsHeader *)pbHeaderOffset;
			ptEspFile->decompressor = tEspFileHeader.compression;
			ptEspFile->posComp = pbTmpFile;
			ptEspFile->posStart = pbTmpFile;
			ptEspFile->posDecomp = 0;
			
			if (COMPRESS_NONE == tEspFileHeader.compression)
			{
				ptEspFile->decompData = NULL;

#ifdef EFS_HEATSHRINK
			}
			else if (COMPRESS_HEATSHRINK == tEspFileHeader.compression)
			{
				/* compression used */
				char 					bDecoderParameter 	= { 0 };
				heatshrink_decoder *	ptDecoder 			= NULL;
				
				/* acquire decoder parameters - 1st byte */
				memcpyAligned(&bDecoderParameter, ptEspFile->posComp, 1);

				++ptEspFile->posComp;

#ifdef HEATSHRINK_DEBUG
				os_printf("espFsOpen: heatshrink compressed file, decoder parameters = %x\n", bDecoderParameter);
#endif
				ptDecoder = heatshrink_decoder_alloc(16, (bDecoderParameter >> 4) & 0xf, bDecoderParameter & 0xf);
				ptEspFile->decompData = ptDecoder;
#endif
			}
			else
			{
示例#17
0
//Cgi that allows the firmware to be replaced via http POST
int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
    CgiUploadFlashDef *def=(CgiUploadFlashDef*)connData->cgiArg;
    uint32_t address;
    if (connData->conn==NULL) {
        //Connection aborted. Clean up.
        return HTTPD_CGI_DONE;
    }

    int offset = connData->post->received - connData->post->buffLen;
    if (offset == 0) {
        connData->cgiPrivData = NULL;
    } else if (connData->cgiPrivData != NULL) {
        // we have an error condition, do nothing
        return HTTPD_CGI_DONE;
    }

    // assume no error yet...
    char *err = NULL;
    int code = 400;

    if (connData->post==NULL) err="No POST request.";
    if (def==NULL) err="Flash def = NULL ?";

    // check overall size
    os_printf("Max img sz 0x%X, post len 0x%X\n", def->fwSize, connData->post->len);
    if (err==NULL && connData->post->len > def->fwSize) err = "Firmware image too large";

    // check that data starts with an appropriate header
    if (err == NULL && offset == 0 && def->type==CGIFLASH_TYPE_FW) err = checkBinHeader(connData->post->buff);
    if (err == NULL && offset == 0 && def->type==CGIFLASH_TYPE_ESPFS) err = checkEspfsHeader(connData->post->buff);

    // make sure we're buffering in 1024 byte chunks
    if (err == NULL && offset % 1024 != 0) {
        err = "Buffering problem";
        code = 500;
    }

    // return an error if there is one
    if (err != NULL) {
        os_printf("Error %d: %s\n", code, err);
        httpdStartResponse(connData, code);
        httpdHeader(connData, "Content-Type", "text/plain");
        httpdEndHeaders(connData);
        httpdSend(connData, "Firmware image error:\r\n", -1);
        httpdSend(connData, err, -1);
        httpdSend(connData, "\r\n", -1);
        connData->cgiPrivData = (void *)1;
        return HTTPD_CGI_DONE;
    }

    // let's see which partition we need to flash and what flash address that puts us at
    int id=system_upgrade_userbin_check();
    if (id==1) address=def->fw1Pos;
    else address=def->fw2Pos;
    address += offset;
    // erase next flash block if necessary
    if (address % SPI_FLASH_SEC_SIZE == 0) {
        // We need to erase this block
        os_printf("Erasing flash at 0x%05x (id=%d)\n", (unsigned int)address, 2-id);
        spi_flash_erase_sector(address/SPI_FLASH_SEC_SIZE);
    }

    // Write the data
    os_printf("Writing %d bytes at 0x%05x (%d of %d)\n", connData->post->buffSize, (unsigned int)address,
              connData->post->received, connData->post->len);
    spi_flash_write(address, (uint32 *)connData->post->buff, connData->post->buffLen);

    if (connData->post->received == connData->post->len) {
        httpdStartResponse(connData, 200);
        httpdEndHeaders(connData);
        return HTTPD_CGI_DONE;
    } else {
        return HTTPD_CGI_MORE;
    }
}