Exemplo n.º 1
0
// 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;

}
Exemplo n.º 2
0
static void ICACHE_FLASH_ATTR SendSpecificService( int sid, uint8_t*namestartptr, int xactionid, int stlen, int is_prefix )
{
	uint8_t outbuff[256];
	uint8_t * obptr = outbuff;
	uint16_t * obb = (uint16_t*)outbuff;

	const char *sn = MDNSServices[sid];
	const char *st = MDNSServiceTexts[sid]; int stl = ets_strlen( st );
	int sp = MDNSServicePorts[sid];

	*(obb++) = xactionid;
	*(obb++) = HTONS(0x8400); //We are authoratative. And this is a response.
	*(obb++) = 0;
	*(obb++) = HTONS(sp?4:3); //4 answers. (or 3 if we don't have a port)
	*(obb++) = 0;
	*(obb++) = 0;


	if( !sn || !st ) return;

	obptr = (uint8_t*)obb;
//	ets_memcpy( obptr, namestartptr, stlen+1 ); //Hack: Copy the name in.
//	obptr += stlen+1;
	obptr = SendPathSegment( obptr,  sn );
	obptr = SendPathSegment( obptr,  "local" );
	*(obptr++) = 0;

	*(obptr++) = 0x00; *(obptr++) = 0x0c; //PTR record
	*(obptr++) = 0x00; *(obptr++) = 0x01; //No Flush cache + in ptr.
	*(obptr++) = 0x00; *(obptr++) = 0x00; //TTL
	*(obptr++) = 0x00; *(obptr++) = 100; //very short. (100 seconds)

	if( !is_prefix )
	{
		*(obptr++) = 0x00; *(obptr++) = ets_strlen( MDNSNames[0] ) + 3; //Service...
		obptr = TackTemp( obptr );
	}
	else
	{
		*(obptr++) = 0x00; *(obptr++) = 2;
		*(obptr++) = 0xc0; *(obptr++) = 0x0c; //continue the name.
	}


	if( !is_prefix )
	{
		obptr = TackTemp( obptr );
	}
	else
	{
		*(obptr++) = 0xc0; *(obptr++) = 0x0c; //continue the name.
	}

	*(obptr++) = 0x00; *(obptr++) = 0x10; //TXT record
	*(obptr++) = 0x80; *(obptr++) = 0x01; //Flush cache + in ptr.
	*(obptr++) = 0x00; *(obptr++) = 0x00; //TTL
	*(obptr++) = 0x00; *(obptr++) = 100; //very short. (100 seconds)
	*(obptr++) = 0x00; *(obptr++) = stl + 1; //Service...
	*(obptr++) = stl; //Service length
	ets_memcpy( obptr, st, stl );
	obptr += stl;

	//Service record
	if( sp )
	{
		int localnamelen = ets_strlen( MyLocalName );


		if( !is_prefix )
		{
			obptr = TackTemp( obptr );
		}
		else
		{
			*(obptr++) = 0xc0; *(obptr++) = 0x0c; //continue the name.
		}

		//obptr = TackTemp( obptr );
		//*(obptr++) = 0xc0; *(obptr++) = 0x2f; //continue the name.
		*(obptr++) = 0x00; *(obptr++) = 0x21; //SRV record
		*(obptr++) = 0x80; *(obptr++) = 0x01; //Don't Flush cache + in ptr.
		*(obptr++) = 0x00; *(obptr++) = 0x00; //TTL
		*(obptr++) = 0x00; *(obptr++) = 100; //very short. (100 seconds)
		*(obptr++) = 0x00; *(obptr++) = localnamelen + 7 + 1; //Service?
		*(obptr++) = 0x00; *(obptr++) = 0x00; //Priority
		*(obptr++) = 0x00; *(obptr++) = 0x00; //Weight
		*(obptr++) = sp>>8; *(obptr++) = sp&0xff; //Port#
		obptr = SendPathSegment( obptr, MyLocalName );
		*(obptr++) = 0;
	}

	//A Record
	obptr = SendPathSegment( obptr, MyLocalName );
	*(obptr++) = 0;
	*(obptr++) = 0x00; *(obptr++) = 0x01; //A record
	*(obptr++) = 0x80; *(obptr++) = 0x01; //Flush cache + in ptr.
	*(obptr++) = 0x00; *(obptr++) = 0x00; //TTL
	*(obptr++) = 0x00; *(obptr++) = 30; //very short. (30 seconds)
	*(obptr++) = 0x00; *(obptr++) = 0x04; //Size 4 (IP)
	ets_memcpy( obptr, pMDNSServer->proto.udp->local_ip, 4 );
	obptr+=4;

	//Send to broadcast.
	uint32_t md = MDNS_BRD;
	ets_memcpy( pMDNSServer->proto.udp->remote_ip, &md, 4 );
	espconn_sent( pMDNSServer, outbuff, obptr - outbuff );
}
Exemplo n.º 3
0
// 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.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");
#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
	
	// 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
		) {
		// 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));
#ifndef BOOT_BIG_FLASH
		if (flashsize > 0x100000) flashsize = 0x100000;
#else
		if (flashsize > 0x200000) flashsize = 0x200000;
#endif
		romconf->magic = BOOT_CONFIG_MAGIC;
		romconf->version = BOOT_CONFIG_VERSION;
		romconf->count = 2;
		romconf->roms[0] = SECTOR_SIZE * 2;
		romconf->roms[1] = (flashsize / 2) + (SECTOR_SIZE * 2);
#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->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;
	}

	ets_printf("ROM0: 0x%08X, ROM1: 0x%08X\r\n", romconf->roms[0], romconf->roms[1]);
	// 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;

}
Exemplo n.º 4
0
void* memcpy(void *dest, const void *src, size_t n) {
	return ets_memcpy(dest, src, n);
}
Exemplo n.º 5
0
//=============================================================================
// call_user_start
//-----------------------------------------------------------------------------
void call_user_start(void)
{
	struct SPIFlashHead sfh; // заголовок flash
	struct StoreWifiHdr wifihdr; // заголовок из последнего сектора flash с индексом на сохранение последней конфигурации WiFi
    struct BootConfig bootcfg;	// начало блока сохранения последней конфигурации WiFi, часть с boot параметрами

	ets_printf("\n2nd boot version : 1.2\n");
	SPIRead(0, &sfh, sizeof(sfh));
	ets_printf("  SPI Speed      : ");
    switch (sfh.hsz.spi_freg)
	{
	    case SPEED_40MHZ:
	    	ets_printf("40MHz\n");
	    	break;
	    case SPEED_26MHZ:
	    	ets_printf("26.7MHz\n");
	    	break;
	    case SPEED_20MHZ:
	    	ets_printf("20MHz\n");
	    	break;
	    case SPEED_80MHZ:
	    	ets_printf("80MHz\n");
	    	break;
	}
	ets_printf("  SPI Mode       : ");
	switch (sfh.spi_interface)
    {
	    case MODE_QIO:
	    	ets_printf("QIO\n");
	    	break;
	    case MODE_QOUT:
	    	ets_printf("QOUT\n");
	    	break;
	    case MODE_DIO:
	    	ets_printf("DIO\n");
	    	break;
	    case MODE_DOUT:
	    	ets_printf("DOUT\n");
	    	break;
    }
	ets_printf("  SPI Flash Size : ");
	uint32 sector;
	switch (sfh.hsz.flash_size)
	{
		case SIZE_4MBIT:
			ets_printf("4Mbit\n");
			sector = 128-4;
			break;
	    case SIZE_2MBIT:
	    	ets_printf("2Mbit\n");
	    	sector = 64-4;
	    	break;
	    case SIZE_8MBIT:
	    	ets_printf("8Mbit\n");
	    	sector = 256-4;
	    	break;
	    case SIZE_16MBIT:
	    	ets_printf("16Mbit\n");
	    	sector = 512-4;
	    	break;
	    case SIZE_32MBIT:
	    	ets_printf("32Mbit\n");
	    	sector = 1024-4;
	    	break;
	    default:
			ets_printf("4Mbit\n");
			sector = 128-4;
			break;
	}
	uint32 addr = sector * FSECTOR_SIZE;
	SPIRead(addr + 3 * FSECTOR_SIZE, &wifihdr.bank, sizeof(wifihdr));
	if(wifihdr.bank == 0) {
		SPIRead(addr + FSECTOR_SIZE, &bootcfg, sizeof(bootcfg));
	}
	else {
		SPIRead(addr + 2 * FSECTOR_SIZE, &bootcfg, sizeof(bootcfg));
	}
	if(bootcfg.boot_version == 0xff) {
		bootcfg.boot_number = 0;
	}
	if(bootcfg.boot_version != 2) {
			bootcfg.boot_version = 2;
			if(wifihdr.bank == 0) wifihdr.bank = 1;
			else wifihdr.bank = 0;
			SPIEraseSector(sector+wifihdr.bank+1);
			SPIWrite((sector+wifihdr.bank+1) * FSECTOR_SIZE, &bootcfg, sizeof(bootcfg));
			SPIEraseSector(sector+3);
			SPIWrite(addr + 3 * FSECTOR_SIZE, &wifihdr.bank, sizeof(wifihdr));
	}
	ets_memcpy((void *)0x4010800, &code_blk, size_code_blk); // загрузчик не прикреплен!
	ets_printf("jump to run user");
	switch(bootcfg.boot_number & 0x0f)
	{
		case 0:
			ets_printf("1\n\n");
			uint32 seg_size = get_seg_size(FSECTOR_SIZE);
			if(seg_size == 0xffffffff) return;
			if(seg_size == 0) {
				0x4010800C(FSECTOR_SIZE);
			} else {
				0x4010800C(seg_size + 0x1010);
			}
			break;
		case 1:
			ets_printf("2\n\n");
			if(sector == 512 - 4 || sector == 1024 - 4) sector = 256 - 4;
			get_seg_size(((sector + 4)>>1)*FSECTOR_SIZE + FSECTOR_SIZE);
			if(seg_size == 0xffffffff) return;
			if(seg_size == 0) {
				0x4010800C(FSECTOR_SIZE);
			} else {
				0x4010800C(seg_size + 0x1010);
			}
			break;
		default:
			ets_printf("error user bin flag, flag = %x\n", bootcfg.boot_number & 0x0f);
	}
}
Exemplo n.º 6
0
void ICACHE_FLASH_ATTR WebSocketGotData( uint8_t c )
{
	switch( curhttp->state_deets )
	{
	case 0:
	{
		int i = 0;
		char inkey[120];
		unsigned char hash[SHA1_HASH_LEN];
		SHA1_CTX c;
		int inkeylen = 0;

		curhttp->is_dynamic = 1;
		while( curlen > 20 )
		{
			curdata++; curlen--;
			if( strncmp( curdata, "Sec-WebSocket-Key: ", 19 ) == 0 )
			{
				break;
			}
		}

		if( curlen <= 21 )
		{
			HTDEBUG( "No websocket key found.\n" );
			curhttp->state = HTTP_WAIT_CLOSE;
			return;
		}

		curdata+= 19;
		curlen -= 19;


#define WS_KEY_LEN 36
#define WS_KEY "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
#define WS_RETKEY_SIZEM1 32

		while( curlen > 1 )
		{
			uint8_t lc = *(curdata++);
			inkey[i] = lc;
			curlen--;
			if( lc == '\r' )
			{
				inkey[i] = 0;
				break;
			}
			i++;
			if( i >= sizeof( inkey ) - WS_KEY_LEN - 5 )
			{
				HTDEBUG( "Websocket key too big.\n" );
				curhttp->state = HTTP_WAIT_CLOSE;
				return;
			}
		}
		if( curlen <= 1 )
		{
			HTDEBUG( "Invalid websocket key found.\n" );
			curhttp->state = HTTP_WAIT_CLOSE;
			return;
		}

		if( i + WS_KEY_LEN + 1 >= sizeof( inkey ) )
		{
			HTDEBUG( "WSKEY Too Big.\n" );
			curhttp->state = HTTP_WAIT_CLOSE;
			return;
		}

		ets_memcpy( &inkey[i], WS_KEY, WS_KEY_LEN + 1 );
		i += WS_KEY_LEN;
		SHA1_Init( &c );
		SHA1_Update( &c, inkey, i );
		SHA1_Final( hash, &c );

#if	(WS_RETKEY_SIZE > MAX_PATHLEN - 10 )
#error MAX_PATHLEN too short.
#endif

		my_base64_encode( hash, SHA1_HASH_LEN, curhttp->pathbuffer + (MAX_PATHLEN-WS_RETKEY_SIZEM1)  );

		curhttp->bytessofar = 0;
		curhttp->bytesleft = 0;

		NewWebSocket();

		//Respond...
		curhttp->state_deets = 1;
		break;
	}
	case 1:
		if( c == '\n' ) curhttp->state_deets = 2;
		break;
	case 2:
		if( c == '\r' ) curhttp->state_deets = 3;
		else curhttp->state_deets = 1;
		break;
	case 3:
		if( c == '\n' ) curhttp->state_deets = 4;
		else curhttp->state_deets = 1;
		break;
	case 5: //Established connection.
	{
		//XXX TODO: Seems to malfunction on large-ish packets.  I know it has problems with 140-byte payloads.

		if( curlen < 5 ) //Can't interpret packet.
			break;

		uint8_t fin = c & 1;
		uint8_t opcode = c << 4;
		uint16_t payloadlen = *(curdata++);
		curlen--;
		if( !(payloadlen & 0x80) )
		{
			HTDEBUG( "Unmasked packet.\n" );
			curhttp->state = HTTP_WAIT_CLOSE;
			break;
		}

		payloadlen &= 0x7f;

		if( payloadlen == 127 )
		{
			//Very long payload.
			//Not supported.
			HTDEBUG( "Unsupported payload packet.\n" );
			curhttp->state = HTTP_WAIT_CLOSE;
			break;
		}
		else if( payloadlen == 126 )
		{
			payloadlen = (curdata[0] << 8) | curdata[1];
			curdata += 2;
			curlen -= 2;
		}

		wsmask[0] = curdata[0];
		wsmask[1] = curdata[1];
		wsmask[2] = curdata[2];
		wsmask[3] = curdata[3];
		curdata += 4;
		curlen -= 4;
		wsmaskplace = 0;

		//XXX Warning: When packets get larger, they may split the
		//websockets packets into multiple parts.  We could handle this
		//but at the cost of prescious RAM.  I am chosing to just drop those
		//packets on the floor, and restarting the connection.
		if( curlen < payloadlen )
		{
			HTDEBUG( "Websocket Fragmented. %d %d\n", curlen, payloadlen );
			curhttp->state = HTTP_WAIT_CLOSE;
			return;
		}

		WebSocketData( payloadlen );
		curlen -= payloadlen; 
		curdata += payloadlen;

		break;
	}
	default:
		break;
	}
}
Exemplo n.º 7
0
static uint32 sub_3FFE8018(uint32 readpos) {
	
	uint8 stack[0x10];
	uint8 temp[0x10];
	
	rom_header header;
	uint32 sectaddr;
	uint32 sectcount;
	uint32 sectlen;
	uint8 chksum;
	uint32 loop;
	bool fullsize;
	uint32 blocksof16;
	uint32 remainder;
	uint32 processed;
	uint32 toprocess;




	
	uint8 *datapos;

	if (SPIRead(readpos, &header, 0x10) != 0) {
		return 1;
	}

	if (header.magic1 != 0xe9) {
		return 1;
	}

	sectaddr = header.add[3] << 24 | header.add[2] << 16 | header.add[1] << 8 | header.add[0];
	sectlen  = header.len[3] << 24 | header.len[2] << 16 | header.len[1] << 8 | header.len[0];

	if (SPIRead(readpos + 0x10, stack, 0x10) != 0) {
		return 1;
	}
	readpos += 0x20;


	if (sectcount != 0) {

		datapos = stack; // read data
		chksum = CHKSUM_INIT; // checksum init
		outaddr = sectaddr; // section address
		processed = 0;

		for (sectcount = header.count; sectcount > 0; sectcount--) {
			
			toprocess = 0x10 - processed; // left to process
			if (sectlen < toprocess) { // section shorter than remaining bytes
				fullsize = false;
				blocksof16 = 0;
				remainder = sectlen;
			} else {
				fullsize = true;
				
				// process what's left in the buffer
				if ((toprocess & 3 == 0) && (toprocess > 0)) { // non-zero exact multiple of 4
					a9 = toprocess / 4;
					for (loop = 0; loop < a9; loop++) { // process 4 bytes at a time
						chksum ^= datapos[0]; // chksum the 4 bytes
						chksum ^= datapos[1];
						chksum ^= datapos[2];
						chksum ^= datapos[3];
						*(uint32*)outaddr = *(uint32*)datapos; // copy the 4 bytes
						datapos += 4; // advance input pointer
						outaddr += 4; // advance output pointer
					}
				} else { // single byte method
					for (loop = 0; loop < toprocess; loop++) {
						chksum ^= datapos[0]; // add to chksum
						outaddr[0] = datapos[0]; // copy byte
						datapos++; // advance input pointer
						outaddr++; // advance output pointer
					}
				}
				blocksof16 = (sectlen - toprocess) / 16;
				remainder = (sectlen - toprocess) % 16;
			}

			// process full blocks of 16
			if (blocksof16) {
				for (loop = 0; loop < blocksof16; loop++) { // loop for remaining/16 times
					if (SPIRead(readpos, stack, 0x10) != 0) { // read 16 bytes
						return 1;
					}
					readpos += 0x10; // increment readpos
					for (a0 = 0; a0 < 0x10; a0++) {
						chksum ^= stack[a0]; // add to chksum
					}
					ets_memcpy(outaddr, stack, 0x10); // copy block
					outaddr += 0x10; // increment outaddr
				}
			}
			
			if (fullsize) { // get next block for remainder
				if (SPIRead(readpos, stack, 0x10) != 0) {
					return 1;
				}
				readpos += 0x10;
				datapos = stack;
				processed = 0;
			}
			
			if (remainder) { // process the remainder after the blocks of 16
				if (remainder % 4 == 0) { // multiple of 4
					a7 = remainder / 4;
					for (loop = 0; loop < a7; loop++) { // process 4 bytes at a time
						chksum ^= datapos[3]; // chksum the 4 bytes
						chksum ^= datapos[2];
						chksum ^= datapos[1];
						chksum ^= datapos[0];
						*(uint32*)(outaddr) = *(uint32*)(datapos); // copy the 4 bytes
						datapos += 4; // advance input pointer
						outaddr += 4; // advance output pointer
					}
				} else { // single byte version
					for (loop = 0; loop < remainder; loop++) {
						chksum ^= datapos[0]; // chksum
						outaddr[0] = datapos[0]; // copy byte
						datapos++;
						outaddr++;
					}
				}
				processed += remainder;
			}

			if (sectcount > 1) { // read next section
				toprocess = 0x10 - processed; // left to process in buffer
				if (toprocess >= 8) { // next header is already in buffer
					sectlen = datapos[7] << 24 | datapos[6] << 16 | datapos[5] << 8 | datapos[4];
					outaddr = datapos[3] << 24 | datapos[2] << 16 | datapos[1] << 8 | datapos[0];
					processed += 8; // processed another 8
				} else {	
					ets_memcopy(temp, stack + processed, toprocess); // copy remaining to temp buffer
					if (SPIRead(readpos, stack, 0x10) != 0) { // read as normal
						break;
					}
					readpos += 0x10;
					processed = 8 - toprocess; // how many of new will be processed in this operation
					ets_memcpy(temp + toprocess, stack, processed); // copy needed bytes from new read to temp buffer
					outaddr = *(uint32*)(temp); // get values from temp buffer
					sectlen = *(uint32*)(temp+4);
				}
				datapos = stack + processed;
			}
		}
		if (stack[0x0f] != chksum) { // compare calculated and stored checksums
			return 1; // chksum failed
		}
	}




	callx0(header.entry);
	return 0;
	
}