Jump to content

    
Sign in to follow this  
SapegoAL

AES bootloader от Atmel (AVR231)

Recommended Posts

Это дало существенный выигрыш в WinAVR, в IAR не пробовал.
Скорее всего ничего не даст. Насколько я помню, IAR ещё древней версии компилятора 1.30 при ужимании на размер очень неплохо выстригал общие подвыражения в подпрограммы, так что тут он сам такое действие произведёт.

Share this post


Link to post
Share on other sites

Караул!!!

Спасайте кто знает и разбирался с данным примером. :(

 

Короче сама передача работает(сделал по прерываниям - уже жалею). Декодирование тоже проходит. Сигнатуры совпадают.

 

Почему то сама запись не происходит. Флэш после операции девственно чист. И сама операция идёт - уснуть можно. Да и выспаться тоже.

 

То ли JTAGом нельзя при данной операции, то ли ещё что-то.

 

Не понимаю также записи вида

 

        spm
    #endif
        
    dw        0xFFFF
    nop

 

В даташите тоже такого не нашёл.

 

PS: ATMEGA640

Share this post


Link to post
Share on other sites

До сих пор мучаешся :)

 

Выкладывай ,что и в каком порядке и в какие регистры заносиш при записи страницы.

 

spm

#endif

 

dw 0xFFFF

nop

 

Это типа трех нопов - не актуально ,для этого кирпича :)

Share this post


Link to post
Share on other sites
Почему то сама запись не происходит. Флэш после операции девственно чист.

...

PS: ATMEGA640

Доброго времени суток, коллеги!

 

Столкнулся с подобной проблемой, не пишется FLASH из бутлоадера. Бутлоадер немного переделанный под себя из AES-аппнота, подобных бутлоадеров понаделано прилично под меги 16/32/64, все работают. А вот под 640 - не шьет :(

 

Исходные данные: камень Atmega640-16AU, питание схемы 5В, кварц 14.7456МГц.

Фузы: E:0xF4 H:0xDA L:0xD7 L:0x3F (вообще последний должен быть 0x0C, но ставлю 0x3F для тестов, чтобы уж точно была разрешена запись spm и чтобы потом FLASH можно было прочитать для сравнения)

 

Вот кусочки исходников, откуда пишется во FLASH

else if (type == TYPE_PROGRAM)
{
// Program page buffer into flash page
unsigned int *q = (unsigned int *) pageBuffer;
unsigned char APPFLASH *r = address;
do
{
	spmWriteWord(r, *q++);
	r += 2;
}
while (--size);
spmErasePage(address);
spmProgramPage(address);
}

Вот исходник spm640.asm (сделал специальный под 640, обрезав "лишнее")

NAME	spm(16)
PUBLIC	spmWriteWord
PUBLIC	spmErasePage
PUBLIC	spmProgramPage
PUBLIC	spmEEWriteByte

#define __ENABLE_BIT_DEFINITIONS__
#include INCLUDE_FILE

#if !defined( EEMWE )
#define EEMWE EEMPE
#endif
#if !defined( EEWE )
#define EEWE EEPE
#endif


//=============================================================================
// I/O registers used


RSEG	CODE

//=============================================================================
// Writes one word to a temporary page buffer

spmWriteWord:
movw	r1:r0, r19:r18
ldi		r22, (1 << SPMEN)
rjmp	spmSPM

//=============================================================================
// Erases one flash page

spmErasePage:
ldi		r22, (1 << PGERS) | (1 << SPMEN)
rjmp	spmSPM


//=============================================================================
// Programs the temporary buffer to flash memory

spmProgramPage:
ldi		r22, (1 << PGWRT) | (1 << SPMEN)


//=============================================================================
// Executes self-programming command

spmSPM:
;	movw	r31:r30, r17:r16

; в целях тестирования по адресу 0 всегда пишем константу 0x1357
ldi		r31, 0
ldi		r30, 0
ldi		r19, 0x13
ldi		r18, 0x57
movw	r1:r0, r19:r18

rcall	spmWait

in		r20, SREG
cli

sts		SPMCSR, r22
spm

dw		0xFFFF
nop

out		SREG, r20
ret

spmWait:
wdr
__spmWait:
lds		r23, SPMCSR
andi	r23, (1 << SPMEN)
brne	__spmWait	

ret


//=============================================================================
// Writes one byte to EEPROM memory

spmEEWriteByte:
rcall	spmWait
rcall	spmEEWriteByteComplete

out		EEARL, r16
out		EEARH, r17
out		EEDR, r18

sbi		EECR, EEMWE
sbi		EECR, EEWE

spmEEWriteByteComplete:
sbic	EECR, EEWE
rjmp	spmEEWriteByteComplete
ret


END

Вот настройки линкера

-ca90
-w29


//=============================================================================
// Interrupt vectors

-Z(CODE)INTVEC=(FLASH_SIZE-BOOT_SIZE)-(FLASH_SIZE-BOOT_SIZE+IVT_SIZE-1)
-H1895 -h(CODE)(FLASH_SIZE-BOOT_SIZE)-(FLASH_SIZE-BOOT_SIZE+IVT_SIZE-1)

//=============================================================================
// Code memory

-Z(CODE)NEAR_F,HUGE_F,SWITCH,INITTAB,DIFUNCT,CODE=(FLASH_SIZE-BOOT_SIZE)-(FLASH_SIZE-1)
-Z(FARCODE)FAR_F,FARCODE=(FLASH_SIZE-BOOT_SIZE)-(FLASH_SIZE-1)


//=============================================================================
// RAM
-Z(DATA)NEAR_I,NEAR_Z=RAM_BASE-(RAM_BASE+RAM_SIZE-1)
-Z(DATA)RSTACK+100=RAM_BASE-(RAM_BASE+RAM_SIZE-1)
-Z(DATA)CSTACK+(RAM_SIZE-300-APP_SRAM_USAGE)=RAM_BASE-(RAM_BASE+RAM_SIZE-1)

Вот вывод map-а

                ****************************************
               *                                      *
               *              MODULE MAP              *
               *                                      *
               ****************************************


 DEFINED ABSOLUTE ENTRIES
 PROGRAM MODULE, NAME : ?ABS_ENTRY_MOD

Absolute parts
          ENTRY                   ADDRESS         REF BY
          =====                   =======         ======
          APP_SRAM_USAGE          0000042E 
          RAM_BASE                00000200 
          RAM_SIZE                00002000 
          IVT_SIZE                000000E4 
          FLASH_SIZE              00010000 
          BOOT_SIZE               00001000 
   *************************************************************************

..............

 SEGMENTS IN THE MODULE
 ======================
INTVEC
 Common segment, address: CODE 0000F000 - 0000F063 (0x64 bytes), align: 0
 Segment part 0.




               ****************************************
               *                                      *
               *      SEGMENTS IN ADDRESS ORDER       *
               *                                      *
               ****************************************


SEGMENT              SPACE    START ADDRESS   END ADDRESS     SIZE  TYPE  ALIGN
=======              =====    =============   ===========     ====  ====  =====
INTVEC               CODE          0000F000 - 0000F063          64   com    1
NEAR_F               CODE          0000F064 - 0000F097          34   rel    0
SWITCH               CODE               0000F098                     dse    0
HUGE_F               CODE               0000F098                     dse    0
INITTAB              CODE          0000F098 - 0000F09D           6   rel    0
DIFUNCT              CODE               0000F09E                     dse    0
CODE                 CODE          0000F09E - 0000F9C9         92C   rel    1
ABSOLUTE             DATA               0000001F                     rel    0
                    DATA               00000020                   
                    DATA               00000021                   
                    DATA          00000027 - 00000028           2 
                    DATA          0000002A - 0000002B           2 
                    DATA          0000002D - 0000002E           2 
                    DATA          00000030 - 00000031           2 
                    DATA          00000033 - 00000034           2 
                    DATA          00000036 - 00000036           1 
                    DATA          0000004C - 0000004E           3 
                    DATA          00000055 - 00000055           1 
                    DATA          00000060 - 00000060           1 
                    DATA          0000006F - 0000006F           1 
                    DATA          0000007C - 0000007C           1 
                    DATA          00000080 - 00000082           3 
                    DATA          00000084 - 00000085           2 
                    DATA          000000C0 - 000000C1           2 
                    DATA          000000C4 - 000000C6           3 
                    DATA          00000101 - 00000102           2 
                    DATA          00000104 - 00000105           2 
                    DATA          00000107 - 00000108           2 
                    DATA          0000010A - 0000010B           2 
NEAR_I               DATA               00000200                     dse    0
NEAR_Z               DATA          00000200 - 0000061F         420   rel    0
RSTACK               DATA          00000620 - 0000071F         100   dse    0
CSTACK               DATA          00000720 - 00001FF1        18D2   dse    0

               ****************************************
               *                                      *
               *        END OF CROSS REFERENCE        *
               *                                      *
               ****************************************

2 506 bytes of CODE memory
7 666 bytes of DATA memory (+ 41 absolute )

Errors: none
Warnings: none

 

Пишу бутлоадер, обновляю через него прошивку, читаю FLASH - чистая с 0-го адреса (0xFFFF), с 0xF000 - бутлоадер.

Пишу бутлоадер и рабочую прошивку, обновляю через бутлоадер прошивку, читаю FLASH - прошивка по адресу 0 на константу 0x1357 не затирается, с 0xF000 - бутлоадер.

 

Прошу помощи, уже весь мозг сломал, в чем может быть причина, куда копать.

Share this post


Link to post
Share on other sites
Пишу бутлоадер, обновляю через него прошивку, читаю FLASH - чистая с 0-го адреса (0xFFFF), с 0xF000 - бутлоадер.

Вы после записи страницы разрешаете RWW section? По исходникам непонятно.

Share this post


Link to post
Share on other sites

Что-бы не плодить темы, спрошу здесь:

Поскольку существует возможность "вывалиться" в загрузчик (jump, call, ..) , то и вероятность "слёта" прошивки не равна нулю? Т.е. использовать этот способ обновления ПО в случаях ответственного применения нельзя. Командировки по разным странам обременительны. Извиняюсь, если это обсуждалось, но сходу не нашел.

 

Share this post


Link to post
Share on other sites
Вы после записи страницы разрешаете RWW section? По исходникам непонятно.

Вообще нет, и до этого случая все прекрасно работало. Не хочется думать, что мне просто несказанно везло, но за несколько лет сбоев не наблюдалось. Возможно используется какой-то хитрый трюк, давно это было.

По теме - я об этом думал и даже делал тест, в котором реализовывал такой алгоритм - стирание страницы, разрешение RWW, запись в буфер, запись страницы, разрешение RWW. Результат был тем же - не работало. Но если Вы считаете, что это критически важно, я повторю тест и выложу результат с исходником.

 

Что-бы не плодить темы, спрошу здесь:

Поскольку существует возможность "вывалиться" в загрузчик (jump, call, ..) , то и вероятность "слёта" прошивки не равна нулю? Т.е. использовать этот способ обновления ПО в случаях ответственного применения нельзя. Командировки по разным странам обременительны. Извиняюсь, если это обсуждалось, но сходу не нашел.

Смотря что Вы имеете в виду под "слетом" прошивки. Если несанкционированный вылет рабочей прошивки в код загрузчика - то да, такое теоретически возможно, и да, теоретически возможно, что МК попадет в такое место загрузчика, в котором зациклится. Но на этот случай есть WDT, который сбросит МК и все восстановится, если конечно а) в этом "цикле" не встретится команда wdr б) сам WDT не окажется временно отключенным. Повторюсь из предыдущего поста - я с таким не сталкивался.

А если Вы боитесь, что во время обновления произойдет сбой, прошивка "недообновится" и привет - то нет. Принцип такой - сначала ВСЕГДА стартует бутлоадер, смотрится некий признак, переходить ли в режим обновления. Если признака нет (тут каждый на что горазд придумывает по каким критериям переходить, смотря какой интерфейс используется, таймауты и пр.), считается CRC всей памяти МК (application, т.е. от 0 до бутлоадера), если CRC сошлась, управление передается на 0-ой адрес рабочей прошивке. Рабочая прошивка тоже должна уметь "ловить" какие-то признаки, по которым она передает управление бутлоадеру в целях обновления. Как она это делает? Тупо и цинично :) - встает колом и по WDT ресетится, попадая в бутлоадер. Ну а если бутлоадер "понял", что кто-то извне хочет обновлять - он и обновляет, ну там целый набор команд в аппноте, опять же Вы можете оставить себе только необходимые. Например я оставил только запись FLASH/EEPROM, старт/стоп, все чтения удалил, и все остальное. А фузы блокировки выставил таким образом, что из рабочей прошивки нельзя ни читать ни писать область бутлоадера, и нельзя ни читать ни писать application область, и поскольку прошивки формирую только я, и прошивки эти шифрованные (ключ внутри бутлоадера, на каждый тип устройства свой), получилось очень удобно - вероятность взлома прошивки или ее воровства практически нулевая.

Да, забыл добавить, если происходит сбой при обновлении, надо просто запустить процесс повторно - в 99.99% случаев помогает.

Share this post


Link to post
Share on other sites

Вот исходник с разрешением RWW

							else if (type == TYPE_PROGRAM)
						{
							// Program page buffer into flash page
							unsigned int *q = (unsigned int *) pageBuffer;
							unsigned char APPFLASH *r = address;
							spmErasePage(address);
							spmEnableRWW(address);
							do
							{
								spmWriteWord(r, *q++);
								r += 2;
							}
							while (--size);
							spmProgramPage(address);
							spmEnableRWW(address);
						}

Вот исходник spm640.asm

NAME	spm(16)
PUBLIC	spmWriteWord
PUBLIC	spmErasePage
PUBLIC	spmEnableRWW
PUBLIC	spmProgramPage
PUBLIC	spmEEWriteByte

#define __ENABLE_BIT_DEFINITIONS__
#include INCLUDE_FILE

#if !defined( EEMWE )
#define EEMWE EEMPE
#endif
#if !defined( EEWE )
#define EEWE EEPE
#endif


//=============================================================================
// I/O registers used


RSEG	CODE

//=============================================================================
// Writes one word to a temporary page buffer

spmWriteWord:
movw	r1:r0, r19:r18
ldi		r22, (1 << SPMEN)
rjmp	spmSPM

//=============================================================================
// Erases one flash page

spmErasePage:
ldi		r22, (1 << PGERS) | (1 << SPMEN)
rjmp	spmSPM

//=============================================================================
// Re-enables RWW section

spmEnableRWW:
ldi		r22, (1 << RWWSRE) | (1 << SPMEN)
rjmp	spmSPM


//=============================================================================
// Programs the temporary buffer to flash memory

spmProgramPage:
ldi		r22, (1 << PGWRT) | (1 << SPMEN)


//=============================================================================
// Executes self-programming command

spmSPM:
;	movw	r31:r30, r17:r16

 ldi   r31, 0
 ldi   r30, 0
 ldi   r19, 0x13
 ldi   r18, 0x57
movw	r1:r0, r19:r18

rcall	spmWait

in		r20, SREG
cli

sts		SPMCSR, r22
spm

dw		0xFFFF
nop

out		SREG, r20
ret

spmWait:
wdr
__spmWait:
lds		r23, SPMCSR
andi	r23, (1 << SPMEN)
brne	__spmWait	

ret


//=============================================================================
// Writes one byte to EEPROM memory

spmEEWriteByte:
rcall	spmWait
rcall	spmEEWriteByteComplete

out		EEARL, r16
out		EEARH, r17
out		EEDR, r18

sbi		EECR, EEMWE
sbi		EECR, EEWE

spmEEWriteByteComplete:
sbic	EECR, EEWE
rjmp	spmEEWriteByteComplete
ret


END

 

Увы, результат печальный - FLASH не пишется :(

Share this post


Link to post
Share on other sites

Процесс обновления думаю некритичен, а вот наличие в адресном пространстве кода способного стереть/записать страницу "мусора" может окончится неприятностями. Почему не реализована, например, возможность программно устанавливать флаг RWWSB? Непонятно.

Share this post


Link to post
Share on other sites
Процесс обновления думаю некритичен, а вот наличие в адресном пространстве кода способного стереть/записать страницу "мусора" может окончится неприятностями. Почему не реализована, например, возможность программно устанавливать флаг RWWSB? Непонятно.

Так этот код же находится в пространстве бутлоадера, стереть/записать самого себя он не может, а если по ошибке программиста/мантейнера прошивки зальется "левая" прошивка, которая не позволит штатным образом переходить в бутлоадер, то это проблема программиста/мантейнера. Если же произойдет сбой и запишется "мусор", то не сойдется CRC прошивки, и бутлоадер просто не передаст на нее управление, ожидая загрузки по новой.

 

По моей проблеме - ни у кого не возникло идей? Куда рыть?

Share this post


Link to post
Share on other sites
Почему не реализована, например, возможность программно устанавливать флаг RWWSB?

Зачем его устанавливать?

 

Скорее нужен бит, установка которого запрещает использование функции самопрограммирования. И чтобы его сбросить можно было только сбросом МК.

 

 

Так этот код же находится в пространстве бутлоадера, стереть/записать самого себя он не может,

Себя - может, но это редко кому надо.

По моей проблеме - ни у кого не возникло идей? Куда рыть?

Код бута расположен там где ему положено в соответсвии с фузами?

 

P.S. Проще может оказаться не искать ошибку, а взять готовый код у атмела и вставить в свою программу.

Share this post


Link to post
Share on other sites
Себя - может, но это редко кому надо.

Ну можно же и проверку адреса в бутлоадере вставить, чтобы запретить самоперезапись.

 

Код бута расположен там где ему положено в соответсвии с фузами?

 

P.S. Проще может оказаться не искать ошибку, а взять готовый код у атмела и вставить в свою программу.

Да, бутлоадер на своем месте, проверено считыванием из МК всей памяти. В моем случае - F000.

У меня все нормально работает на мегах 16/32/64, и только на 640 затык :(

Share this post


Link to post
Share on other sites

Я наверное не внятно описал гипотетическую ситуацию. Целость бутлоадера по уязвимости проблема N2. Речь про штатный режим, а не момент обновления. По проблеме N1:

"левая" прошивка, которая не позволит штатным образом переходить в бутлоадер

Это каким способом можно "не позволить", если в результате сбоя в СК окажется код из пространства бутлоадера.

RWWSB? Зачем его устанавливать?

Не этот бит так другой, позволяющий запретить самопрограммирование или делающее область загрузчика недоступной, при удачном старте основного кода. Похоже выхода нет - придется ставить внешний чип.

Share this post


Link to post
Share on other sites
Я наверное не внятно описал гипотетическую ситуацию. Целость бутлоадера по уязвимости проблема N2. Речь про штатный режим, а не момент обновления. По проблеме N1:

 

Это каким способом можно "не позволить", если в результате сбоя в СК окажется код из пространства бутлоадера.

Хм, это интересный поворот. Надо будет на досуге сымитировать подобное. Но полагаю, что вероятность порчи основной прошивки в этом случае исчезающе мала, т.к. нужно точно "попасть" в код записи/стирания, иначе весь ущерб - нештатный переход в бутлоадер и как следствие - перезагрузка в рабочую прошивку или штатно, или по WDT.

 

Внешний чип не обеспечит защиты от копирования.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this