示例#1
0
/** @brief Dump fuse values
 *
 * Reply fields: low, high, extended fuse bytes (u8s)
 */
static void cmd_fuse_read(void)
{
  reply_success(3);
  send_u8(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
  send_u8(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
  send_u8(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
}
示例#2
0
文件: avr.c 项目: fachat/XD2031
void fuse_info(void) {
	uint8_t lowfuse, hifuse, extfuse, lockfuse;

	cli();
	lowfuse = boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS);
	hifuse = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
	extfuse = boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS);
	lockfuse = boot_lock_fuse_bits_get(GET_LOCK_BITS);
	sei();
	term_printf("\r\nFuses: l=%02X h=%02X e=%02X l=%02X\r\n", lowfuse, hifuse, extfuse, lockfuse);
}
示例#3
0
	CDWORD BootloaderAllocatedSize()
	{
		#ifndef SPM_PAGESIZE

			return 0;

		#else

			STATIC DWORD BOOTLOADER_SIZE = 0;

		#if defined (__AVR_ATmega88__) || defined (__AVR_ATmega168__)
			#define BOOTSIZE_FACTOR_FUSE_BYTE	GET_EXTENDED_FUSE_BITS
			#define BOOTSIZE_FACTOR_FACTOR		5
		#else
			#define BOOTSIZE_FACTOR_FUSE_BYTE	GET_HIGH_FUSE_BITS
			#define BOOTSIZE_FACTOR_FACTOR		4
		#endif

			__fuse_byte_high_or_extended = boot_lock_fuse_bits_get(BOOTSIZE_FACTOR_FUSE_BYTE);
			STATIC BYTE bootSizeFactor = CHECK_BITS(__fuse_byte_high_or_extended, BOOTSZ1 OR BOOTSZ0) SHR 0b1;

			BOOTLOADER_SIZE = 2 ^ (BOOTSIZE_FACTOR_FACTOR - bootSizeFactor) * SPM_PAGESIZE;

			return static_cast<CDWORD>(BOOTLOADER_SIZE);

		#endif
	}
示例#4
0
/** \brief initialize MCU status by watchdog reset 
 *
 * FIXME: needs doc
 */
void bootloader_jump(void) {

    #if !defined(BOOTLOADER_SIZE)
        uint8_t high_fuse = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);

        if (high_fuse & BOOT_SIZE_256) { 
            bootloader_start = (FLASH_SIZE - 512) >> 1;
        } else if (high_fuse & BOOT_SIZE_512) {
示例#5
0
uint8_t BootloaderAPI_ReadLock(void)
{
	return boot_lock_fuse_bits_get(GET_LOCK_BITS);
}
示例#6
0
uint8_t BootloaderAPI_ReadFuse(const uint16_t Address)
{
	return boot_lock_fuse_bits_get(Address);
}
/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
 *  start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
 *  this will force the user application to start via a software jump.
 */
void Application_Jump_Check(void)
{
	bool JumpToApplication = false;

	#if (BOARD == BOARD_LEONARDO)
		/* Enable pull-up on the IO13 pin so we can use it to select the mode */
		PORTC |= (1 << 7);
		Delay_MS(10);

		/* If IO13 is not jumpered to ground, start the user application instead */
		JumpToApplication = ((PINC & (1 << 7)) != 0);

		/* Disable pull-up after the check has completed */
		PORTC &= ~(1 << 7);
	#elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
		/* Disable JTAG debugging */
		JTAG_DISABLE();

		/* Enable pull-up on the JTAG TCK pin so we can use it to select the mode */
		PORTF |= (1 << 4);
		Delay_MS(10);

		/* If the TCK pin is not jumpered to ground, start the user application instead */
		JumpToApplication = ((PINF & (1 << 4)) != 0);

		/* Re-enable JTAG debugging */
		JTAG_ENABLE();
	#else
		/* Check if the device's BOOTRST fuse is set */
		if (boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS) & FUSE_BOOTRST)
		{
			/* If the reset source was not an external reset or the key is correct, clear it and jump to the application */
			if (!(MCUSR & (1 << EXTRF)) || (MagicBootKey == MAGIC_BOOT_KEY))
			  JumpToApplication = true;

			/* Clear reset source */
			MCUSR &= ~(1 << EXTRF);
		}
		else
		{
			/* If the reset source was the bootloader and the key is correct, clear it and jump to the application;
			 * this can happen in the HWBE fuse is set, and the HBE pin is low during the watchdog reset */
			if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
				JumpToApplication = true;

			/* Clear reset source */
			MCUSR &= ~(1 << WDRF);
		}
	#endif

	/* Don't run the user application if the reset vector is blank (no app loaded) */
	bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF);

	/* If a request has been made to jump to the user application, honor it */
	if (JumpToApplication && ApplicationValid)
	{
		/* Turn off the watchdog */
		MCUSR &= ~(1 << WDRF);
		wdt_disable();

		/* Clear the boot key and jump to the user application */
		MagicBootKey = 0;

		// cppcheck-suppress constStatement
		((void (*)(void))0x0000)();
	}
}
示例#8
0
/*! \fn     main(void)
*   \brief  Main function
*/
int main(void)
{
    uint16_t current_bootkey_val = eeprom_read_word((uint16_t*)EEP_BOOTKEY_ADDR);
    RET_TYPE flash_init_result;
    RET_TYPE touch_init_result;
    RET_TYPE card_detect_ret;
    uint8_t fuse_ok = TRUE;
    
    // Disable JTAG to gain access to pins, set prescaler to 1 (fuses not set)
    #ifndef PRODUCTION_KICKSTARTER_SETUP
        disableJTAG();
        CPU_PRESCALE(0);
    #endif
        
    // Check fuse settings: boot reset vector, 2k words, SPIEN, BOD 2.6V, programming & ver disabled
    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) != 0xFB) || (boot_lock_fuse_bits_get(GET_LOCK_BITS) != 0xFC))
    {
        fuse_ok = FALSE;
    }
    
    // Check if PB5 is low to start electrical test
    DDRB &= ~(1 << 5); PORTB |= (1 << 5);
    smallForLoopBasedDelay();
    if (!(PINB & (1 << 5)))
    {
        // Test result, true by default
        uint8_t test_result = TRUE;
        // Leave flash nS off
        DDR_FLASH_nS |= (1 << PORTID_FLASH_nS);
        PORT_FLASH_nS |= (1 << PORTID_FLASH_nS);
        // Set PORTD as output, leave PORTID_OLED_SS high
        DDRD |= 0xFF; PORTD |= 0xFF;
        // All other pins are input by default, run our test
        for (uint8_t i = 0; i < 4; i++)
        {
            PORTD |= 0xFF;
            smallForLoopBasedDelay();
            if (!(PINF & (0xC3)) || !(PINC & (1 << 6)) || !(PINE & (1 << 6)) || !(PINB & (1 << 4)))
            {
                test_result = FALSE;
            }
            PORTD &= (1 << PORTID_OLED_SS);
            smallForLoopBasedDelay();
            if ((PINF & (0xC3)) || (PINC & (1 << 6)) || (PINE & (1 << 6)) || (PINB & (1 << 4)))
            {
                test_result = FALSE;
            }
        }               
        // PB6 as test result output
        DDRB |= (1 << 6);
        // If test successful, light green LED
        if ((test_result == TRUE) && (fuse_ok == TRUE))
        {
            PORTB |= (1 << 6);
        } 
        else
        {
            PORTB &= ~(1 << 6);
        }
        while(1);
    }
    
    // This code will only be used for developers and beta testers
    #if !defined(PRODUCTION_SETUP) && !defined(PRODUCTION_KICKSTARTER_SETUP)
        // Check if we were reset and want to go to the bootloader
        if (current_bootkey_val == BOOTLOADER_BOOTKEY)
        {
            // Disable WDT
            wdt_reset();
            wdt_clear_flag();
            wdt_change_enable();
            wdt_stop();
            // Store correct bootkey
            eeprom_write_word((uint16_t*)EEP_BOOTKEY_ADDR, CORRECT_BOOTKEY);
            // Jump to bootloader
            start_bootloader();
        }
        // Check if there was a change in the mooltipass setting storage to reset the parameters to their correct values
        if (getMooltipassParameterInEeprom(USER_PARAM_INIT_KEY_PARAM) != USER_PARAM_CORRECT_INIT_KEY)
        {
            mooltipassParametersInit();
            setMooltipassParameterInEeprom(USER_PARAM_INIT_KEY_PARAM, USER_PARAM_CORRECT_INIT_KEY);
        }
    #endif

    // First time initializations for Eeprom (first boot at production or flash layout changes for beta testers)
    if (current_bootkey_val != CORRECT_BOOTKEY)
    {
        // Erase Mooltipass parameters
        mooltipassParametersInit();
        // Set bootloader password bool to FALSE
        eeprom_write_byte((uint8_t*)EEP_BOOT_PWD_SET, FALSE);
    }

    /* Check if a card is inserted in the Mooltipass to go to the bootloader */
    #ifdef AVR_BOOTLOADER_PROGRAMMING
        /* Disable JTAG to get access to the pins */
        disableJTAG();
        /* Init SMC port */
        initPortSMC();
        /* Delay for detection */
        smallForLoopBasedDelay();
        #if defined(HARDWARE_V1)
        if (PIN_SC_DET & (1 << PORTID_SC_DET))
        #elif defined(HARDWARE_OLIVIER_V1)
        if (!(PIN_SC_DET & (1 << PORTID_SC_DET)))
        #endif
        {
            uint16_t tempuint16;
            /* What follows is a copy from firstDetectFunctionSMC() */
            /* Enable power to the card */
            PORT_SC_POW &= ~(1 << PORTID_SC_POW);
            /* Default state: PGM to 0 and RST to 1 */
            PORT_SC_PGM &= ~(1 << PORTID_SC_PGM);
            DDR_SC_PGM |= (1 << PORTID_SC_PGM);
            PORT_SC_RST |= (1 << PORTID_SC_RST);
            DDR_SC_RST |= (1 << PORTID_SC_RST);
            /* Activate SPI port */
            PORT_SPI_NATIVE &= ~((1 << SCK_SPI_NATIVE) | (1 << MOSI_SPI_NATIVE));
            DDRB |= (1 << SCK_SPI_NATIVE) | (1 << MOSI_SPI_NATIVE);
            setSPIModeSMC();
            /* Let the card come online */
            smallForLoopBasedDelay();
            /* Check smart card FZ */
            readFabricationZone((uint8_t*)&tempuint16);
            if ((swap16(tempuint16)) != SMARTCARD_FABRICATION_ZONE)
            {
                removeFunctionSMC();
                start_bootloader();
            }
            else
            {
                removeFunctionSMC();
            }
        }
    #endif

    initPortSMC();                      // Initialize smart card port
    initPwm();                          // Initialize PWM controller
    initIRQ();                          // Initialize interrupts
    powerSettlingDelay();               // Let the power settle   
    initUsb();                          // Initialize USB controller
    powerSettlingDelay();               // Let the USB 3.3V LDO rise
    initI2cPort();                      // Initialize I2C interface
    rngInit();                          // Initialize avrentropy library
    oledInitIOs();                      // Initialize OLED input/outputs
    spiUsartBegin(SPI_RATE_8_MHZ);      // Start USART SPI at 8MHz

    // If offline mode isn't enabled, wait for device to be enumerated
    if (getMooltipassParameterInEeprom(OFFLINE_MODE_PARAM) == FALSE)
    {
        while(!isUsbConfigured());      // Wait for host to set configuration
    }    
    
    // Set correct timeout_enabled val
    mp_timeout_enabled = getMooltipassParameterInEeprom(LOCK_TIMEOUT_ENABLE_PARAM);

    // Launch the before flash initialization tests
    #ifdef TESTS_ENABLED
        beforeFlashInitTests();
    #endif
    
    // Check if we can initialize the Flash memory
    flash_init_result = initFlash();
    
    // Launch the after flash initialization tests
    #ifdef TESTS_ENABLED
        afterFlashInitTests();
    #endif
    
    // Set up OLED now that USB is receiving full 500mA.
    oledBegin(FONT_DEFAULT);
    
    // First time initializations for Flash (first time power up at production)
    if (current_bootkey_val != CORRECT_BOOTKEY)
    {
        // Erase everything non graphic in flash
        eraseFlashUsersContents();
        // Erase # of cards and # of users
        firstTimeUserHandlingInit();
    }
    
    // Check if we can initialize the touch sensing element
    touch_init_result = initTouchSensing();

    // Enable proximity detection
    #ifndef HARDWARE_V1
        activateProxDetection();
    #endif
    
    // Launch the after touch initialization tests
    #ifdef TESTS_ENABLED
        afterTouchInitTests();
    #endif
    
    // Test procedure to check that all HW is working
    #if defined(PRODUCTION_SETUP) || defined(PRODUCTION_KICKSTARTER_SETUP)
        if (current_bootkey_val != CORRECT_BOOTKEY)
        {
            RET_TYPE temp_rettype;        
            // Wait for USB host to upload bundle, which then sets USER_PARAM_INIT_KEY_PARAM
            //#ifdef PRODUCTION_KICKSTARTER_SETUP
            while(getMooltipassParameterInEeprom(USER_PARAM_INIT_KEY_PARAM) != 0xF1)
            {
                usbProcessIncoming(USB_CALLER_MAIN);
            }
            //#endif
            // Bundle uploaded, start the screen
            oledBegin(FONT_DEFAULT);
            oledWriteActiveBuffer();
            oledSetXY(0,0);
            // LEDs ON, to check
            setPwmDc(MAX_PWM_VAL);
            switchOnButtonWheelLeds();
            guiDisplayRawString(ID_STRING_TEST_LEDS_CH);
            // Check flash init
            if (flash_init_result != RETURN_OK)
            {
                 guiDisplayRawString(ID_STRING_TEST_FLASH_PB);
            }
            // Check touch init
            if (touch_init_result != RETURN_OK)
            {
                guiDisplayRawString(ID_STRING_TEST_TOUCH_PB);
            }
            // Touch instructions
            guiDisplayRawString(ID_STRING_TEST_INST_TCH);
            // Check prox
            while(!(touchDetectionRoutine(0) & RETURN_PROX_DETECTION));
            guiDisplayRawString(ID_STRING_TEST_DET);
            activateGuardKey();
            // Check left
            while(!(touchDetectionRoutine(0) & RETURN_LEFT_PRESSED));
            guiDisplayRawString(ID_STRING_TEST_LEFT);
            // Check wheel
            while(!(touchDetectionRoutine(0) & RETURN_WHEEL_PRESSED));
            guiDisplayRawString(ID_STRING_TEST_WHEEL);
            // Check right
            while(!(touchDetectionRoutine(0) & RETURN_RIGHT_PRESSED));
            guiDisplayRawString(ID_STRING_TEST_RIGHT);
            // Insert card
            guiDisplayRawString(ID_STRING_TEST_CARD_INS);
            while(isCardPlugged() != RETURN_JDETECT);
            temp_rettype = cardDetectedRoutine();
            // Check card
            if (!((temp_rettype == RETURN_MOOLTIPASS_BLANK) || (temp_rettype == RETURN_MOOLTIPASS_USER)))
            {
                guiDisplayRawString(ID_STRING_TEST_CARD_PB);
            }
            // Display result
            uint8_t script_return = RETURN_OK;
            if ((flash_init_result == RETURN_OK) && (touch_init_result == RETURN_OK) && ((temp_rettype == RETURN_MOOLTIPASS_BLANK) || (temp_rettype == RETURN_MOOLTIPASS_USER)))
            {
                // Inform script of success
                usbSendMessage(CMD_FUNCTIONAL_TEST_RES, 1, &script_return);
                // Wait for password to be set
                while(eeprom_read_byte((uint8_t*)EEP_BOOT_PWD_SET) != BOOTLOADER_PWDOK_KEY)
                {
                    usbProcessIncoming(USB_CALLER_MAIN);
                }
                // Display test result
                guiDisplayRawString(ID_STRING_TEST_OK);
                timerBasedDelayMs(3000);
            }
            else
            {
                // Set correct bool
                script_return = RETURN_NOK;
                // Display test result
                guiDisplayRawString(ID_STRING_TEST_NOK);
                // Inform script of failure
                usbSendMessage(CMD_FUNCTIONAL_TEST_RES, 1, &script_return);
                while(1)
                {
                    usbProcessIncoming(USB_CALLER_MAIN);
                }
            }
        }
    #endif
    
    // Stop the Mooltipass if we can't communicate with the flash or the touch interface
    #if defined(HARDWARE_OLIVIER_V1)
        #ifdef PRODUCTION_KICKSTARTER_SETUP
            while ((flash_init_result != RETURN_OK) || (touch_init_result != RETURN_OK) || (fuse_ok != TRUE));
        #else
            while ((flash_init_result != RETURN_OK) || (touch_init_result != RETURN_OK));
        #endif
    #endif
    
    // First time initializations done.... write correct value in eeprom
    if (current_bootkey_val != CORRECT_BOOTKEY)
    {
        // Store correct bootkey
        eeprom_write_word((uint16_t*)EEP_BOOTKEY_ADDR, CORRECT_BOOTKEY);
    }

    // Write inactive buffer & go to startup screen
    oledWriteInactiveBuffer();
    guiSetCurrentScreen(SCREEN_DEFAULT_NINSERTED);
    guiGetBackToCurrentScreen();
        
    // Launch the after HaD logo display tests
    #ifdef TESTS_ENABLED
        afterHadLogoDisplayTests();  
    #endif
    
    // Let's fade in the LEDs
    for (uint16_t i = 0; i < MAX_PWM_VAL; i++)
    {
        setPwmDc(i);
        timerBasedDelayMs(0);
    }
    activityDetectedRoutine();
    launchCalibrationCycle();
    touchClearCurrentDetections();
    
    // Inhibit touch inputs for the first 3 seconds
    activateTimer(TIMER_TOUCH_INHIBIT, 3000);
    while (1)
    {
        // Process possible incoming USB packets
        usbProcessIncoming(USB_CALLER_MAIN);
        
        // Call GUI routine once the touch input inhibit timer is finished
        if (hasTimerExpired(TIMER_TOUCH_INHIBIT, FALSE) == TIMER_EXPIRED)
        {
            guiMainLoop();
        }
        
        // Check if a card just got inserted / removed
        card_detect_ret = isCardPlugged();
        
        // Do appropriate actions on smartcard insertion / removal
        if (card_detect_ret == RETURN_JDETECT)
        {
            // Light up the Mooltipass and call the dedicated function
            activityDetectedRoutine();
            handleSmartcardInserted();
        }
        else if (card_detect_ret == RETURN_JRELEASED)
        {
            // Light up the Mooltipass and call the dedicated function
            activityDetectedRoutine();
            handleSmartcardRemoved();
            
            // Set correct screen
            guiDisplayInformationOnScreen(ID_STRING_CARD_REMOVED);
            guiSetCurrentScreen(SCREEN_DEFAULT_NINSERTED);
            userViewDelay();
            guiGetBackToCurrentScreen();
        }
        
        // Two quick caps lock presses wakes up the device        
        if ((hasTimerExpired(TIMER_CAPS, FALSE) == TIMER_EXPIRED) && (getKeyboardLeds() & HID_CAPS_MASK) && (wasCapsLockTimerArmed == FALSE))
        {
            wasCapsLockTimerArmed = TRUE;
            activateTimer(TIMER_CAPS, CAPS_LOCK_DEL);
        }
        else if ((hasTimerExpired(TIMER_CAPS, FALSE) == TIMER_RUNNING) && !(getKeyboardLeds() & HID_CAPS_MASK))
        {
            activityDetectedRoutine();
        }
        else if ((hasTimerExpired(TIMER_CAPS, FALSE) == TIMER_EXPIRED) && !(getKeyboardLeds() & HID_CAPS_MASK))
        {
            wasCapsLockTimerArmed = FALSE;            
        }
        
        // If we have a timeout lock
        if ((mp_timeout_enabled == TRUE) && (hasTimerExpired(SLOW_TIMER_LOCKOUT, TRUE) == TIMER_EXPIRED))
        {
            guiSetCurrentScreen(SCREEN_DEFAULT_INSERTED_LCK);
            guiGetBackToCurrentScreen();
            handleSmartcardRemoved();
        }
    }
}
示例#9
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);
            }
        }
    }
}
示例#10
0
文件: main.c 项目: Ceitec/F-00011
void try_receive_data(void)
{
	byte i;
	byte *ptr;
	
	if (uart0_flags.data_received)
	{
		ptr = uart0_get_data_begin();
		for (i=0; i<9; i++)
		{
			TB_bufIn[i] = *ptr;
			ptr++;
		}
		uart0_get_data_end();
		uart0_flags.data_received = FALSE;
		if (TB_Read() == 0)
		{
			switch (TB_Decode())
			{
				case ENTER_BOOTLOADER:
					BootStatus = 1;
					TB_SendAck(TB_ERR_OK, ENTER_BOOTLOADER);
					break;
				case READ_LOCK_BITS:
					TB_SendAck(TB_ERR_OK, boot_lock_fuse_bits_get(GET_LOCK_BITS));
					break;
				case CHIP_ERASE_FLASH:
					ChipErase();
					TB_SendAck(TB_ERR_OK, CHIP_ERASE_FLASH);
					break;
				case CHIP_ERASE_EEPROM:
					EepromErase();
					TB_SendAck(TB_ERR_OK, CHIP_ERASE_EEPROM);
					break;
				case CHIP_ERASE_ALL:
					ChipErase();
					EepromErase();
					TB_SendAck(TB_ERR_OK, CHIP_ERASE_ALL);
					break;
				case WRITE_LOCK_BITS:
					TB_SendAck(TB_ERR_NOTEVALUABLE, WRITE_LOCK_BITS);
					break;
				case READ_LOW_FUSE:
					TB_SendAck(TB_ERR_OK, boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
					break;
				case READ_HIGH_FUSE:
					TB_SendAck(TB_ERR_OK, boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
					break;
				case READ_EXTENDED_FUSE:
					TB_SendAck(TB_ERR_NOTEVALUABLE, boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
					break;
				case READ_SIGNATURE:
					Signature = 0x1E9502;
					TB_SendAck(TB_ERR_OK, Signature);
					break;
				case READ_SOFTWARE_VERSION:
					TB_SendAck(TB_ERR_OK, SOFTWARE_IDENTIFIER);
					break;
				case READ_BOOTLOADER_VERSION:
					TB_SendAck(TB_ERR_OK, BOOTLOADER_VERSION);
					break;
				case VERIFY_FLASH:
					Address = TB_bufIn[TB_BUF_TYPE] << 8;
					Address |= TB_bufIn[TB_BUF_MOTOR];
					if (Address < (START_BOOT_ADDRESS_BYTES - 4))
					{
						VerifyFlash(Address);
					}
					else
					{
						TB_SendAck(TB_ERR_VALUE, Address);
					}
					break;
				case WRITE_FLASH:
					Address = TB_bufIn[TB_BUF_TYPE] << 8;
					Address |= TB_bufIn[TB_BUF_MOTOR];
					Aktualni = (Address & ADDRESS_MASK_MSB);
					if (Address < (START_BOOT_ADDRESS_BYTES - 4))
					{
						if (Aktualni == Predchozi)
						{
							FillBufferData(Address);
							EndComFlash = 1;
							TB_SendAck(TB_ERR_OK, WRITE_FLASH);
						} 
						else
						{
							if (EndComFlash)
							{
								WriteFlashPages(Predchozi, BufferFlash);
								memset(BufferFlash, 0xFF, SPM_PAGESIZE);
								FillBufferData(Address);
								TB_SendAck(TB_ERR_OK, Address);
								Predchozi = Address;
							}
							else
							{
								memset(BufferFlash, 0xFF, SPM_PAGESIZE);
								FillBufferData(Address);
								TB_SendAck(TB_ERR_OK, WRITE_FLASH);
								Predchozi = Address;
							}
						}
						NowFlash = 1;
					}
					else
					{
						TB_SendAck(TB_ERR_VALUE, Address);	
					}
					break;
				case WRITE_EEPROM:
					Address = TB_bufIn[TB_BUF_TYPE] << 8;
					Address |= TB_bufIn[TB_BUF_MOTOR];
					Aktualni = (Address & ADDRESS_MASK_MSB);
					if (Address < (START_EEPROM_ADDRESS - 4))
					{
						if (Aktualni == Predchozi)
						{
							FillBufferData(Address);
							EndComEeprom = 1;
							TB_SendAck(TB_ERR_OK, WRITE_EEPROM);
						}
						else
						{
							if (EndComEeprom)
							{
								WriteEepromPages(Predchozi, BufferFlash);
								memset(BufferFlash, 0xFF, SPM_PAGESIZE);
								FillBufferData(Address);
								TB_SendAck(TB_ERR_OK, Address);
								Predchozi = Address;
							}
							else
							{
								memset(BufferFlash, 0xFF, SPM_PAGESIZE);
								FillBufferData(Address);
								TB_SendAck(TB_ERR_OK, WRITE_EEPROM);
							}
						}
						NowEeprom = 1;
					}
					else
					{
						TB_SendAck(TB_ERR_VALUE, Address);
					}
					break;
				case END_WRITE_ALL:
					if (NowFlash)
					{
						WriteFlashPages(Predchozi, BufferFlash);
						EndComFlash=0;
						TB_SendAck(TB_ERR_OK, END_WRITE_ALL);
					}
					else if(NowEeprom)
					{
						WriteEepromPages(Predchozi, BufferFlash);
						EndComEeprom = 0;
						TB_SendAck(TB_ERR_OK, END_WRITE_ALL);
					}
					else
					{
						TB_SendAck(TB_ERR_VALUE, 0);
					}
					memset(BufferFlash, 0xFF, SPM_PAGESIZE);
					Predchozi = 0;
					Aktualni = 0;
					break;
				case READ_FLASH:
					Address = TB_bufIn[TB_BUF_TYPE] << 8;
					Address |= TB_bufIn[TB_BUF_MOTOR];
					if (Address < (START_BOOT_ADDRESS_BYTES - 4))
					{
						ReadFlashPages(Address);
					}
					else
					{
						TB_SendAck(TB_ERR_VALUE, 0);	
					}
					break;
				case READ_EEPROM:
					Address = TB_bufIn[TB_BUF_TYPE] << 8;
					Address |= TB_bufIn[TB_BUF_MOTOR];
					if (Address < (START_EEPROM_ADDRESS - 4))
					{
						ReadEepromPages(Address);
					}
					else
					{
						TB_SendAck(TB_ERR_VALUE, READ_EEPROM);
					}
					break;
				case CMD_SPM_PAGE_SIZE:
					TB_SendAck(TB_ERR_OK, SPM_PAGESIZE);
					break;
				case CMD_ALL_PAGE_SIZE:	
					TB_SendAck(TB_ERR_OK, PAGE_SIZE);
					break;
				case EXIT_BOOTLOADER:
					TB_SendAck(TB_ERR_OK, EXIT_BOOTLOADER);
					jumpaddress();
					break;
			}
		}
	}
}
// ----------------------------------------------------------------------
// Handle a non-standard SETUP packet.
// ----------------------------------------------------------------------
uchar	usbFunctionSetup ( uchar data[8] )
{
	uchar	req;
	usbRequest_t *rq = (void *)data;

	idle_cnt = idle_cnt2 = 0;

	// Generic requests
	req = data[1];
	if ( req == USBTINY_READ) {
		// do nothing
		return 1;
	}
	else if ( req == USBTINY_POWERDOWN )
	{
		usb_maybe_finalizing = 1;
		#ifndef ENABLE_WRITE_WHEN_TOLD
		finalize_flash_if_dirty();
		#endif
		return 0;
	}
	else if ( req == USBTINY_SPI )
	{
		usb_maybe_finalizing = 1;
		#ifndef ENABLE_WRITE_WHEN_TOLD
		finalize_flash_if_dirty(); // partial page writes are not fully written unless this is called here, it must be HERE
		#endif

		usbMsgPtr = (usbMsgPtr_t)buffer;

		buffer[2] = data[3]; // this tricks "usbtiny_cmd" into succeeding
		buffer[3] = 0; // fools safemode into succeeding

		// for the commands, refer to ATmega datasheet under "Serial Programming Instruction Set"
		// usage of avr/boot.h here is experimental

		if (0) { } // fools the C preprocessor
		#ifdef ENABLE_SIG_READING
		else if (data[2] == 0x30 && data[3] == 0x00) {
			// read signature byte
			#ifdef ENABLE_SIG_FAKING
			buffer[3] = 0x01;
			#else
			buffer[3] = boot_signature_byte_get(data[4] * 2);
			#endif
		}
		#endif
		#ifdef ENABLE_FUSE_READING
		else if (data[2] == 0x50 && data[3] == 0x00 && data[4] == 0x00) {
			// read LFUSE
			buffer[3] = boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS);
		}
		else if (data[2] == 0x58 && data[3] == 0x08 && data[4] == 0x00) {
			// read HFUSE
			buffer[3] = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS);
		}
		else if (data[2] == 0x50 && data[3] == 0x08 && data[4] == 0x00) {
			// read EFUSE
			buffer[3] = boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS);
		}
		else if (data[2] == 0x58 && data[3] == 0x00 && data[4] == 0x00) {
			// read lock bits
			buffer[3] = boot_lock_fuse_bits_get(GET_LOCK_BITS);
		}
		else if (data[2] == 0x38 && data[3] == 0x00 && data[4] == 0x00) {
			// read calibration
			buffer[3] = boot_signature_byte_get(0);
		}
		#endif
		#ifdef ENABLE_CHIP_ERASE
		else if (data[2] == 0xAC && data[3] == 0x80 && data[4] == 0x00 && data[5] == 0x00)
		{
			// chip erase, will erase all pages except the first page and the bootloader region
			full_erase_requested = 1;
		}
		#endif
		#ifdef ENABLE_WRITE_WHEN_TOLD
		else if (data[2] == 0x4C && data[5] == 0x00)
		{
			// write memory page
			// page is data[3] as MSB and data[4] as LSB
			need_write_page = 1;
		}
		#endif

		// all other commands are unhandled

		return 4;
	}
	/*
	else if ( req == USBTINY_SPI1 )
	{
		// I don't know what this is used for, there are no single SPI transactions in the ISP protocol
		usb_maybe_finalizing = 1;
		#ifndef ENABLE_WRITE_WHEN_TOLD
		finalize_flash_if_dirty();
		#endif
		return 1;
	}
	*/
	else if ( req == USBTINY_POLL_BYTES )
	{
		usb_maybe_finalizing = 1;
		#ifndef ENABLE_WRITE_WHEN_TOLD
		finalize_flash_if_dirty();
		#endif
		return 0;
	}
	CUR_ADDR = *((uint16_t*)(&data[4]));
	remaining = rq->wLength.bytes[0];
	if ( req >= USBTINY_FLASH_READ && req <= USBTINY_EEPROM_WRITE )
	{
		#ifdef ENABLE_LED_BLINK
		OCR0B = 0x7F;
		#endif
		usb_has_activity = 1;
		
		cmd0 = req;
		if ( cmd0 != USBTINY_FLASH_WRITE ) {
			usb_maybe_finalizing = 1;
			#ifndef ENABLE_WRITE_WHEN_TOLD
			finalize_flash_if_dirty();
			#endif
		}
		return USB_NO_MSG;	// usbFunctionRead() or usbFunctionWrite() will be called to handle the data
	}

	// do nothing if nothing done
	return 0;
}
void receive_at_command(void)
{

unsigned char received_bytes = 0;
unsigned char rx_char_buffer = 0;
unsigned char x = 0;
#if defined BOOTLOCK_BIT_SET_SUPPORT && BOOTLOCK_BIT_SET_SUPPORT == 1
unsigned char blb = 0;
unsigned char lock_bits = 0;
#endif
#if defined VERSION_INFO_NEEDED && VERSION_INFO_NEEDED == 1
unsigned int eep_address = 0;
#endif

while(memory_to_write == 0)
    {
      x=_UDR_;
      x=_UDR_;
      sput_str(prompt);
       do{
             received_bytes = 0;
             //uart_rx_timeout = UART_TIMEOUT_ABS_MAX_VALUE;
             rx_char_buffer = sget_char();
             if(rx_char_buffer){ sput_char(rx_char_buffer); }

             if( rx_char_buffer == 'A' || rx_char_buffer == 'a' )
               {
                  rx_char_buffer = sget_char();
                  if(rx_char_buffer){ sput_char(rx_char_buffer); }
                  if( rx_char_buffer == 'T' || rx_char_buffer == 't' )
                   {
                      while(1)
                          {
                             rx_char_buffer = sget_char();
                             sput_char(rx_char_buffer);
                             if(received_bytes > 10 )
                              {
                                received_bytes = 0xff;
                                sput_str(error_message);
                                break;
                              }
                             if(rx_char_buffer == '\r' || rx_char_buffer == '\n')
                              {
                                 x_buffer[received_bytes] = '\0';
                                 break;
                              }
                             x_buffer[received_bytes++] = rx_char_buffer;
                             if(rx_char_buffer == 0) { received_bytes = 0; break; }
                          }
                   }

               }else if( rx_char_buffer == '\n' || rx_char_buffer == '\r' ) { sput_str(prompt); }

           }while(received_bytes == 0 ); // end of "while(1)" loop

       if(received_bytes == 0Xff){ continue; }
       strupr((char*)x_buffer);
       memory_to_write = 0;
       switch(x_buffer[0])
            {
               case('W'):  switch(x_buffer[1])
                                {
                                   case('F'):  memory_to_write = 1;  break;
                                   case('E'):  memory_to_write = 2;  break;
#if defined BOOTLOCK_BIT_SET_SUPPORT && BOOTLOCK_BIT_SET_SUPPORT == 1
                                   case('B'):  blb = 7; lock_bits = 0xFF;
                                               for(x=2; x<=9; x++)
                                                 {
                                                     rx_char_buffer = x_buffer[x];
                                                     if(rx_char_buffer == '0'){ lock_bits &= (~(1<<blb)); }
                                                     blb--;
                                                 }
                                               x_buffer[10] = '\0';
                                               utoa(lock_bits,(char*)x_buffer, 2);
                                               sput_str((char*)x_buffer);
                                               sput_str("Y/N");
                                               rx_char_buffer = sget_char();
                                               if(rx_char_buffer == 'Y' || rx_char_buffer == 'y')
                                                {
                                                   boot_lock_bits_set(~lock_bits);
                                                   sput_str(success_message);
                                                }else{ sput_str("Aborted");  }
                                               break;
#endif
                                   default  :  sput_str(error_message); break;
                                }
                           break;

#if defined BOOTLOCK_BIT_READ_SUPPORT && BOOTLOCK_BIT_READ_SUPPORT == 1
              case('R'):  switch(x_buffer[1])
                               {
                                  case('B'): utoa(boot_lock_fuse_bits_get(GET_LOCK_BITS), (char*)x_buffer, 2);
                                             sput_str((char*)x_buffer);
                                             break;

                                  case('L'): utoa(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS), (char*)x_buffer, 2);
                                             sput_str((char*)x_buffer);
                                             break;

                                  case('H'): utoa(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS), (char*)x_buffer, 2);
                                             sput_str((char*)x_buffer);
                                             break;

                                  case('E'): utoa(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS), (char*)x_buffer, 2);
                                             sput_str((char*)x_buffer);
                                             break;

                                  default  : sput_str(error_message); break;

                               }

                           break;

#endif //END of #if defined BOOTLOCK_BIT_READ_SUPPORT && BOOTLOCK_BIT_READ_SUPPORT == 1
              case('I'):
#if defined VERSION_INFO_NEEDED && VERSION_INFO_NEEDED == 1
                           sput_char('\r'); sput_char('\n');
                           eep_address = (E2END - 31);
                           while(eep_address <= E2END)
                               {
                                  x = eeprom_read_byte((unsigned char*)eep_address++);
                                  if(x < 0xff && x > 0){ sput_char(x); }
                               }
#endif
                           sput_str("BootLoader V3.2\r\nChris Efstathiou 2009");
                           break;

              default  :   sput_str(error_message);
                           break;

            }

    }//end of "while(memory_to_write == 0)" loop.

return;
}