int main(void)
{
  void (*applptr)( void ) = 0x0000;
  MCUCR = _BV(IVCE);  // enable wechsel der Interrupt Vectoren
  MCUCR = _BV(IVSEL); // Interrupts auf Boot Section umschalten
#if MITLED
  LEDDDR |= _BV(LEDPIN);  //LED pin auf ausgang
  blink(2, 20, 20);
#endif
  init_twi();
 

  while (1) { /* Endlosschleife weil 1 immer WAHR*/

    /* Bootloader Quit und sprung zur App */
    if(kommando == 0xFE || timeout == 0xFFFE){

      // Turn off the I2C interrupts
      TWCR = 0;

#if MITLED
      blink(5, 5, 10);
#endif
      cli();
      MCUCR = _BV(IVCE);  // enable wechsel der Interrupt Vectoren
      MCUCR = 0x00; // Interrupts auf Application Section umschalten
      applptr(); // Rücksprung zur Application
    }
    /* Datenblock (64byte) in Flash schreiben */
    if(kommando == 0x04){
#if MITLED
      STATUSLED(1);//PORTB |= _BV(PB0);
#endif
      boot_program_page (pageaddr);
#if MITLED
      STATUSLED(0);//PORTB &= ~_BV(PB0);
#endif
      kommando = 0x00;

      /* TWI wieder aktivieren */
      TWCR |= (1<<TWINT); 
    }
    if(TWSR == 0x00){
      init_twi();
    }
    if(timeout != 0xFFFF){
      timeout++;
      _delay_us(50);
    }

  }

  return 0;
}
예제 #2
0
파일: main.c 프로젝트: obulpathi/avr
int main(void)
{
	int i;
	uint16_t page;
	uint8_t data[SPM_PAGESIZE];

	init();

	page = 0;
	for( i = 0 ; i < SPM_PAGESIZE ; i++ )
		data[i] = 0x00;
	
	//prog code
	boot_program_page( page, data);

	PORTD = 0xA5;
	while(1);

	return 0;
}	
예제 #3
0
uint8_t wibo_run(void)
{
	uint8_t isLeave=0;
	uint8_t isStay=0;
	unsigned long timeout = WIBO_TIMEOUT;
	
	while(!isLeave) {
#if !defined(NO_LEDS)
		LED_CLR(PROGLED);
#endif
		if (!(isStay))
		{
			while(!(wibo_available()) && (timeout--))  _delay_ms(1);	// minimum frame time @ 250kbps ~ 2ms.
		
			if (!(wibo_available()))	// no packets received, bye bye!
			{
				isLeave=1;
				return isLeave;
			}			
		}
		else
		{
			while(!(wibo_available()));	// wait for next packet
		}

		trx_reg_write(RG_IRQ_STATUS, TRX_IRQ_RX_END); /* clear the flag */

		trx_frame_read(rxbuf.data, sizeof(rxbuf.data) / sizeof(rxbuf.data[0]),
				&tmp); /* dont use LQI, write into tmp variable */

#if !defined(NO_LEDS)
		LED_SET(PROGLED);
		/* light as long as actions are running */
#endif

		switch (rxbuf.hdr.cmd)
		{

		case P2P_PING_REQ:
			isStay=1;
			if (0 == deaf)
			{
				pingrep.hdr.dst = rxbuf.hdr.src;
				pingrep.hdr.seq++;
				pingrep.crc = datacrc;

				trx_reg_write(RG_TRX_STATE, CMD_TX_ARET_ON);

				/* no need to make block atomic since no IRQs are used */
				TRX_SLPTR_HIGH()
				;
				TRX_SLPTR_LOW()
				;
				trx_frame_write(sizeof(p2p_ping_cnf_t) + sizeof(BOARD_NAME) + 2,
						(uint8_t*) &pingrep);
				/*******************************************************/

#if defined(_DEBUG_SERIAL_)
				printf("Pinged by 0x%04X"EOL, rxbuf.hdr.src);
#endif

#if defined(TRX_IF_RFA1)
				while (!(trx_reg_read(RG_IRQ_STATUS) & TRX_IRQ_TX_END))
					;
				trx_reg_write(RG_IRQ_STATUS, TRX_IRQ_TX_END); /* clear the flag */
#else
				while (!(trx_reg_read(RG_IRQ_STATUS) & TRX_IRQ_TRX_END))
				;
#endif /* defined(TRX_IF_RFA1) */
				trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
			} /* (0 == deaf) */
			break;

		case P2P_WIBO_TARGET:
			isStay=1;
			target = rxbuf.wibo_target.targmem;
#if defined(_DEBUG_SERIAL_)
			printf("Set Target to %c"EOL, target);
#endif
			break;

		case P2P_WIBO_RESET:
			isStay=1;
#if defined(_DEBUG_SERIAL_)
			printf("Reset"EOL);
#endif

			addr = SPM_PAGESIZE; /* misuse as counter */
			ptr = pagebuf;
			do
			{
				*ptr++ = 0xFF;
			} while (--addr);

			addr = 0;
			datacrc = 0;
			pagebufidx = 0;
			deaf = 0;
			break;

		case P2P_WIBO_ADDR:
			isStay=1;
#if defined(_DEBUG_SERIAL_)
			printf("Set address: 0x%08lX"EOL, rxbuf.wibo_addr.address);
#endif
			addr = rxbuf.wibo_addr.address;
			pagebufidx = 0;
			break;

		case P2P_WIBO_DATA:
			isStay=1;
#if defined(_DEBUG_SERIAL_)
			printf("Data[%d]", rxbuf.wibo_data.dsize);
			uint8_t len = rxbuf.wibo_data.dsize;
			if (len > 10) len = 10;
			for(uint8_t j=0;j<len;j++)
			{
				printf(" %02X", rxbuf.wibo_data.data[j]);
			}
			if (len != rxbuf.wibo_data.dsize)
				printf("...");
			printf(EOL);
#endif
			tmp = rxbuf.wibo_data.dsize;
			ptr = rxbuf.wibo_data.data;
			do
			{
				datacrc = _crc_ccitt_update(datacrc, *ptr);
				pagebuf[pagebufidx++] = *ptr;
				if (pagebufidx >= PAGEBUFSIZE)
				{
					/* LED off to save current and avoid flash corruption
					 *  because of possible voltage drops
					 */
#if !defined(NO_LEDS)
					LED_CLR(PROGLED);
#endif

					if (target == 'F') /* Flash memory */
					{
						boot_program_page(addr, pagebuf);
					}
					else if (target == 'E')
					{
						/* not implemented */
					}
					else
					{
						/* unknown target, dry run */
					}

					/* also for dry run! */
					addr += SPM_PAGESIZE;
					pagebufidx = 0;
				}
				ptr++;
			} while (--tmp);
			break;
#if defined(WIBO_FLAVOUR_BOOTLUP)
		case P2P_WIBO_BOOTLUP:
			isStay=1;
			bootlup();
		break;
#endif

		case P2P_WIBO_FINISH:
			isStay=1;
#if defined(_DEBUG_SERIAL_)
			printf("Finish"EOL);
#endif
			if (target == 'F') /* Flash memory */
			{
				boot_program_page(addr, pagebuf);
			}
			else if (target == 'E')
			{
				/* not implemented */
			}
			else
			{
				/* unknown target, dry run */
			}

			/* also for dry run! */
			addr += SPM_PAGESIZE;
			pagebufidx = 0;

			break;

		case P2P_WIBO_EXIT:
#if defined(_DEBUG_SERIAL_)
			printf("Exit"EOL);
#endif
#if !defined(NO_LEDS)
			LED_CLR(PROGLED);
#endif
			isLeave=1;
			break;

		case P2P_WIBO_DEAF:
			isStay=1;
			deaf = 1;
			break;
		default:
			/* unknown or unhandled command */
			if (!(isStay)) {
				if (!(timeout--)) {
					isLeave = 1;
				}
			}
			break;
		}; /* switch (rxbuf.hdr.cmd) */
	}

	return isLeave;
}
예제 #4
0
/*! \fn     main(void)
*   \brief  Main function
*   \note   For our security chain to be valid, EEP_BOOT_PWD_SET in eeprom needs to be set to BOOTLOADER_PWDOK_KEY
*/
int main(void)
{
    /* Fetch bootkey in eeprom */
    uint16_t current_bootkey_val = eeprom_read_word((uint16_t*)EEP_BOOTKEY_ADDR);                                       // Bootkey in EEPROM
    uint8_t new_aes_key[AES_KEY_LENGTH/8];                                                                              // New AES encryption key
    uint8_t cur_aes_key[AES_KEY_LENGTH/8];                                                                              // AES encryption key
    uint8_t firmware_data[SPM_PAGESIZE];                                                                                // One page of firmware data
    aes256_context temp_aes_context;                                                                                    // AES context
    uint8_t cur_cbc_mac[16];                                                                                            // Current CBCMAC val
    uint8_t temp_data[16];                                                                                              // Temporary 16 bytes array
    RET_TYPE flash_init_result;                                                                                         // Flash initialization result
    uint16_t firmware_start_address = UINT16_MAX - MAX_FIRMWARE_SIZE - sizeof(cur_cbc_mac) - sizeof(cur_aes_key) + 1;   // Start address of firmware in external memory
    uint16_t firmware_end_address = UINT16_MAX - sizeof(cur_cbc_mac) - sizeof(cur_aes_key) + 1;                         // End address of firmware in external memory


    /* Just in case we are going to disable the watch dog timer and disable interrupts */
    cli();
    wdt_reset();
    wdt_clear_flag();
    wdt_change_enable();
    wdt_stop();

    /* Check fuses: 2k words, SPIEN, BOD 4.3V, BOOTRST programming & ver disabled >> http://www.engbedded.com/fusecalc/ */
    if ((boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS) != 0xFF) || (boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS) != 0xD8) || (boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS) != 0xF8) || (boot_lock_fuse_bits_get(GET_LOCK_BITS) != 0xFC))
    {
        while(1);
    }

    /* If security isn't set in place yet, no point in launching the bootloader */
    if (eeprom_read_byte((uint8_t*)EEP_BOOT_PWD_SET) != BOOTLOADER_PWDOK_KEY)
    {
        start_firmware();
    }

    /* Check if the device is booting normally, if the bootloader was called, or unknown state */
    if (current_bootkey_val == CORRECT_BOOTKEY)
    {
        /* Security system set, correct bootkey for firmware */
        start_firmware();
    }
    else if (current_bootkey_val != BOOTLOADER_BOOTKEY)
    {
        /* Security system set, bootkey isn't the bootloader one nor the main fw one... */
        while(1);
    }

    /* By default, brick the device so it's an all or nothing update procedure */
    eeprom_write_word((uint16_t*)EEP_BOOTKEY_ADDR, BRICKED_BOOTKEY);

    /* Init IOs */
    UHWCON = 0x01;                          // Enable USB 3.3V LDO
    initFlashIOs();                         // Init EXT Flash IOs
    spiUsartBegin();                        // Init SPI Controller    
    DDR_ACC_SS |= (1 << PORTID_ACC_SS);     // Setup PORT for the Accelerometer SS
    PORT_ACC_SS |= (1 << PORTID_ACC_SS);    // Setup PORT for the Accelerometer SS    
    DDR_OLED_SS |= (1 << PORTID_OLED_SS);   // Setup PORT for the OLED SS
    PORT_OLED_SS |= (1 << PORTID_OLED_SS);  // Setup PORT for the OLED SS
    for (uint16_t i = 0; i < 20000; i++) asm volatile ("NOP");

    /* Disable I2C block of the Accelerometer */
    PORT_ACC_SS &= ~(1 << PORTID_ACC_SS);
    spiUsartTransfer(0x23);
    spiUsartTransfer(0x02);
    PORT_ACC_SS |= (1 << PORTID_ACC_SS);

    /* Check Flash */
    flash_init_result = checkFlashID();
    if (flash_init_result != RETURN_OK)
    {
        while(1);
    }

    for (uint8_t pass_number = 0; pass_number < 2; pass_number++)
    {
        /* Init CBCMAC encryption context*/
        eeprom_read_block((void*)cur_aes_key, (void*)EEP_BOOT_PWD, sizeof(cur_aes_key));
        memset((void*)cur_cbc_mac, 0x00, sizeof(cur_cbc_mac));
        memset((void*)temp_data, 0x00, sizeof(temp_data));
        aes256_init_ecb(&temp_aes_context, cur_aes_key);

        // Compute CBCMAC for between the start of the graphics zone until the max addressing space (65536) - the size of the CBCMAC
        for (uint16_t i = GRAPHIC_ZONE_START; i < (UINT16_MAX - sizeof(cur_cbc_mac) + 1); i += sizeof(cur_cbc_mac))
        {
            // Read data from external flash
            flashRawRead(temp_data, i, sizeof(temp_data));

            // If we got to the part containing to firmware
            if ((i >= firmware_start_address) && (i < firmware_end_address))
            {
                // Append firmware data to current buffer
                uint16_t firmware_data_address = i - firmware_start_address;
                memcpy(firmware_data + (firmware_data_address & SPM_PAGE_SIZE_BYTES_BM), temp_data, sizeof(temp_data));

                // If we have a full page in buffer, flash it
                firmware_data_address += sizeof(cur_cbc_mac);
                if (((firmware_data_address & SPM_PAGE_SIZE_BYTES_BM) == 0x0000) && (pass_number == 1))
                {
                    boot_program_page(firmware_data_address - SPM_PAGESIZE, firmware_data);
                }
            }

            // If we got to the part containing the encrypted new aes key (end of the for())
            if (i >= firmware_end_address)
            {
                memcpy(new_aes_key + i - firmware_end_address, temp_data, sizeof(temp_data));
            }

            // Continue computation of CBCMAC
            aesXorVectors(cur_cbc_mac, temp_data, sizeof(temp_data));
            aes256_encrypt_ecb(&temp_aes_context, cur_cbc_mac);
        }

        // Read CBCMAC in memory and compare it with the computed value
        flashRawRead(temp_data, (UINT16_MAX - sizeof(cur_cbc_mac) + 1), sizeof(cur_cbc_mac));
        if (pass_number == 0)
        {
            // First pass, compare CBCMAC and see if we do the next pass or start the firmware
            if (sideChannelSafeMemCmp(temp_data, cur_cbc_mac, sizeof(cur_cbc_mac)) != 0)
            {
                // No match, start the main firmware
                eeprom_write_word((uint16_t*)EEP_BOOTKEY_ADDR, CORRECT_BOOTKEY);
                start_firmware();
            }
            else
            {
                // Otherwise, next pass!
            }
        }
        else
        {
            // Second pass, compare CBCMAC and then update AES keys
            if (sideChannelSafeMemCmp(temp_data, cur_cbc_mac, sizeof(cur_cbc_mac)) == 0)
            {
                // Fetch the encrypted new aes key from flash, decrypt it, store it
                aes256_decrypt_ecb(&temp_aes_context, new_aes_key);
                aes256_decrypt_ecb(&temp_aes_context, new_aes_key+16);
                eeprom_write_block((void*)new_aes_key, (void*)EEP_BOOT_PWD, sizeof(new_aes_key));
                eeprom_write_word((uint16_t*)EEP_BOOTKEY_ADDR, CORRECT_BOOTKEY);
                start_firmware();
            }
            else
            {
                // Fail, erase everything! >> maybe just write a while(1) in the future?
                for (uint16_t i = 0; i < MAX_FIRMWARE_SIZE; i += SPM_PAGESIZE)
                {
                    boot_page_erase(i);
                    boot_spm_busy_wait();
                }
                while(1);
            }
        }
    }
}
예제 #5
0
uint8_t fileParser_parseNextBlock(unsigned long filesize)
{

	switch(fileParser_parseState)
	{
		case INFO_HEADER:
		{
			//--- read info header ---
			struct InfoHeader *tmpHeader;
			tmpHeader = (struct InfoHeader *) &sd_buffer[0];
			infoHeader = *tmpHeader;

			if(	(infoHeader.headerId[0] != 'S') ||
				(infoHeader.headerId[1] != 'P') ||
				(infoHeader.headerId[2] != 'F') ||
				(infoHeader.headerId[3] != 'I')
			)
			{
				//header not right -> abort
				
				lcd_clear();
				lcd_home();
				lcd_string("header error");
				
				while(1);
				return 0;
			}
		
		
			fileParser_bytesRead += 512;
			
			if ((fileParser_bytesRead) >= filesize )
			{
				
				lcd_setcursor(0,2);
				lcd_string("EOF error");
				while(1);
			}		
			
			fileParser_parseState = AVR_DATA;
		}			
		break;
	
		case AVR_DATA:
		{
			//--- read avr code ---
			//program data into flash (512 bytes data to 4 pages a 128 bytes -> mega32 SPM_PAGESIZE = 128
			//program data into flash (512 bytes data to 2 pages a 256 bytes -> mega644 SPM_PAGESIZE = 256
			
			
			for(int i=0; (i<(512/SPM_PAGESIZE)) && (fileParser_bytesRead < (infoHeader.avrCodeSize +  512)); i++ )
			{
				
				boot_program_page(fileParser_pagesWritten,(uint8_t *)&sd_buffer[0+i*SPM_PAGESIZE]);

				fileParser_bytesRead += SPM_PAGESIZE;
				fileParser_pagesWritten+=SPM_PAGESIZE;
			}
							
			//increment the byte counter
			//fileParser_bytesRead += 512
			if ((fileParser_bytesRead) >= filesize )
			{
				 return 0;
			}				 
			
			//check if AVR code end is reached
			if(fileParser_bytesRead >= (infoHeader.avrCodeSize +  512) )
			{
				//reset cortex chip
				lcd_home();
				lcd_string("updating...(1/2)");
				lcd_setcursor(0,2);
				lcd_command(LCD_CURSOR_ON);
				
				fileParser_resetCortex();
				
				//initialize the cortex bootloader
				//try 10 times to give the cortex some time to boot and answer
				int i=0;
				for(;;)
				{
					uart_tx(INIT_BOOTLOADER);
					_delay_ms(1000);
					//if received data is available
#ifdef MEGA32					
					if( (UCSRA & (1<<RXC)) )
#else
					if( (UCSR0A & (1<<RXC0)) )
#endif
					{
						uint8_t data = uart_rxWait();	
						
						if(data == ACK)
						{
							//bootloader successfully initialized
							//it is now waiting for commands
							break;
						}
					}
					
					dout_updateOutputs();
				}
				
				//check if init is ok (ACK received)
				if(i>=10)
				{
					//an error occured
					//could not initialize bootloader
					lcd_home();
					lcd_string("mainboard error");
					while(1);
					return 0;
				}
				
				//now we can send the cortex bootloader commands and data
				fileParser_parseState = CORTEX_DATA;
				
				
				
				//give the cortex time to erase the flash
				lcd_home();
				lcd_string("updating...(2/2)");
				return 1;
			}
			}			
		break;
		
		case CORTEX_DATA:
			//--- read cortex code ---
			
			//we have 512 bytes of data
			//data is 32 bit unsigned int
			//we increment with 4 because in each run we send out 4 bytes => 1 32 bit int message
			for(int i=0;i<512;i+=4)
			{
				
				uint16_t crc;
			
				// send the address
				
				crc = calcCrc(WRITE_ADDRESS,(uint8_t*)&addressCounter);
				//send next address packet until ACK received
				do 
				{
					uart_tx(WRITE_ADDRESS);
					//lcd_home();
					//lcd_string("cmd");
					uart_tx(addressCounter>>24);
					uart_tx(addressCounter>>16);
					uart_tx(addressCounter>>8);
					uart_tx(addressCounter);

					//send calculated CRC
					uart_tx(crc>>8);
					uart_tx(crc&0xff);

				} 
				while (uart_checkAck()!=ACK);	
				
			
				//calc crc for data block
				crc = calcCrc(WRITE_DATA,&sd_buffer[i]);
				//send next data packet until ACK received
				do 
				{
					//send command
					uart_tx(WRITE_DATA);
					//after the command, send the 4 data bytes
					uart_tx(sd_buffer[i+3]);
					uart_tx(sd_buffer[i+2]);
					uart_tx(sd_buffer[i+1]);
					uart_tx(sd_buffer[i]);

					//send calculated CRC
					uart_tx(crc>>8);
					uart_tx(crc&0xff);
				} 
				while (uart_checkAck()!=ACK);
				
				//transfer succeeded
				addressCounter++;
			}	
			dout_updateOutputs();			
				
			fileParser_bytesRead+=512;
			//send cortex bootloader data
				
			if ((fileParser_bytesRead) >= filesize )
			{
				lcd_clear();
				lcd_home();
				lcd_string("success!");
				lcd_setcursor(0,2);
				lcd_string("please reboot...");
				lcd_command(LCD_CURSOR_OFF);
				uart_tx(END_BOOTLOADER);
				while(1);
				 return 0;
			}		
		break;
	}

	return 1;
}