К1921ВГ015 и защита прошивки

32-разрядные микроконтроллеры разработки АО "НИИЭТ"

Модераторы: ea, dav, bkolbov, Alis, pip, _sva_

Аватара пользователя
ejsan
Сообщения: 108
Зарегистрирован: 15 авг 2022, 21:17
Предприятие: vbrspb.ru

К1921ВГ015 и защита прошивки

Сообщение ejsan »

Собственно, сабж предлагаю обсудить тут.
Разумеется, самый очевидный способ не дать злостным пиратам просто взять и спиратить вашу Интеллектуальную Собственность - вырубить единственную аппаратную связь контроллера с миром в лице JTAG-интерфейса. :evil: И согласно разделу 7.1 даташита, у К1921ВГ015 такая возможность имеется!
Поскольку мне недавно удалось без проблем сделать запись и чтение в NVR область флешки, решил рискнуть и попробовать временно выключить JTAG. Делал я это из программы таким способом:
Во-первых, подготовил файл NVR.c, сделано частично на основе исходников от Дыхно. ;)

Код: Выделить всё

/*
 * NVR.c
 * Чтобы было удобнее работать с FLASH-разделом "NVR"
 * контроллера КР1921ВГ015
 * E.J.SanYo 2o25
 */

#include <plib015.h>
#include <system_k1921vg015.h>
#include "NVR.h"

//небольшая задержка "на пересинхронизацию", согласно даташиту
void flash_delay(void)
{
	uint8_t i;

	for (i = 0; i < 5; i++)
		__NOP();
}

//стирает страницу в области NVR
void nvr_page_erase(uint32_t addr)
{
	FLASH->ADDR = addr;
	FLASH->CMD = (FLASH_CMD_KEY_Access << FLASH_CMD_KEY_Pos) | FLASH_CMD_ERSEC_Msk | FLASH_CMD_NVRON_Msk;
	flash_delay();
	while (FLASH->STAT & FLASH_STAT_BUSY_Msk)
		__NOP();
}

//пишет данные в NVR по 4 32-битных слова
void nvr_write_128b(uint32_t addr, uint32_t *data)
{
	FLASH->ADDR = addr;
	FLASH->DATA[0].DATA = (uint32_t)data[0];
	FLASH->DATA[1].DATA = (uint32_t)data[1];
	FLASH->DATA[2].DATA = (uint32_t)data[2];
	FLASH->DATA[3].DATA = (uint32_t)data[3];

	FLASH->CMD = (FLASH_CMD_KEY_Access << FLASH_CMD_KEY_Pos) | FLASH_CMD_WR_Msk | FLASH_CMD_NVRON_Msk;
	flash_delay();
	while (FLASH->STAT & FLASH_STAT_BUSY_Msk)
		__NOP();
}

//читает данные из NVR по 4 32-битных слова
void nvr_read_128b(uint32_t addr, uint32_t *data)
{
	FLASH->ADDR = addr;
	FLASH->CMD = (FLASH_CMD_KEY_Access << FLASH_CMD_KEY_Pos) | FLASH_CMD_RD_Msk | FLASH_CMD_NVRON_Msk;
	flash_delay();
	while (FLASH->STAT & FLASH_STAT_BUSY_Msk)
		__NOP();
	data[0] = FLASH->DATA[0].DATA;
	data[1] = FLASH->DATA[1].DATA;
	data[2] = FLASH->DATA[2].DATA;
	data[3] = FLASH->DATA[3].DATA;
}
Макрос для __NOP() я сразу прописал в plib015.h, пригодится ещё много где

Код: Выделить всё

#define __NOP() __asm volatile ("ADDI x0, x0, 0")
NVR.h

Код: Выделить всё

#ifndef USER_NVR_H_
#define USER_NVR_H_

void nvr_page_erase(uint32_t);
void nvr_write_128b(uint32_t, uint32_t *);
void nvr_read_128b(uint32_t, uint32_t *);

#endif /* USER_NVR_H_ */
В основной части прошивки:

Код: Выделить всё

uint32_t cfg_buffer[4];
.
.
.
//чтобы выключить JTAG
nvr_read_128b(CFGWORD_BASE, cfg_buffer);
cfg_buffer[0] = 0xFFFFFFFB;
InterruptDisable();
nvr_page_erase(CFGWORD_BASE);
nvr_write_128b(CFGWORD_BASE, cfg_buffer);
InterruptEnable();
.
.
.
//чтобы снова включить JTAG
nvr_read_128b(CFGWORD_BASE, cfg_buffer);
cfg_buffer[0] = 0xFFFFFFFF;
InterruptDisable();
nvr_page_erase(CFGWORD_BASE);
nvr_write_128b(CFGWORD_BASE, cfg_buffer);
InterruptEnable();
У меня там ещё прерывания в коде используются, поэтому добавлены InterruptDisable() и InterruptEnable(), чтобы прерывания не прерывали процесс записи. В последнем случае, скорее всего, 0xFFFFFFFF можно было не записывать, но я перестраховывался. :oops: Ведь есть же у НИИЭТ и контроллеры, флешка которых стирается в нули!
Может, кто-то придумает, как провернуть всё это через OpenOCD, не засоряя код программы?
Vcoder
Сообщения: 22
Зарегистрирован: 01 май 2025, 14:50
Предприятие: .
Откуда: Уфа

Re: К1921ВГ015 и защита прошивки

Сообщение Vcoder »

Получилось!

Код: Выделить всё

$ /opt/xpack-openocd-k1921vk-0.12.0-k1921vk/bin/openocd -f connect_jlink_jtag.cfg -c "k1921vg015 write nvr erase 0x1FF0 0xFFFFFFF8 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF" -c "resume" -c "exit"
После этого надо передёрнуть питание. Reset-а недостаточно.

Код: Выделить всё

$ /opt/xpack-openocd-k1921vk-0.12.0-k1921vk/bin/openocd -f connect_jlink_jtag.cfg -c "k1921vg015 read main 0x80000000" -c "resume" -c "exit"
xPack Open On-Chip Debugger 0.12.0+dev-00520-gc670187e1-dirty (2023-11-17-06:08)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
DEPRECATED! use 'adapter speed' not 'adapter_khz'
Info : J-Link V9 compiled Sep  1 2016 18:29:50
Info : Hardware version: 9.60
Info : VTarget = 3.349 V
Info : clock speed 1000 kHz
Error: JTAG scan chain interrogation failed: all ones
Error: Check JTAG interface, timings, target power, etc.
Error: Trying to use configured scan chain anyway...
Error: K1921VG015.cpu: IR capture error; saw 0x1f not 0x01
Warn : Bypassing JTAG setup events due to errors
Error: Unsupported DTM version: 15
Warn : target K1921VG015.cpu examination failed
Info : starting gdb server for K1921VG015.cpu on 3333
Info : Listening on port 3333 for gdb connections
Error: JTAG scan chain interrogation failed: all ones
Error: Check JTAG interface, timings, target power, etc.
Error: Trying to use configured scan chain anyway...
Error: K1921VG015.cpu: IR capture error; saw 0x1f not 0x01
Warn : Bypassing JTAG setup events due to errors
Error: Unsupported DTM version: 15
Error: Unsupported DTM version: 15
zsh: segmentation fault (core dumped)  /opt/xpack-openocd-k1921vk-0.12.0-k1921vk/bin/openocd -f  -c  -c "resume" -c
openocd даже в segmentation fault улетел.
Для srv_erase тоже нужно отключить питание, замкнуть вывод SERVEN на Vcc и подать питание.

Код: Выделить всё

$ /opt/xpack-openocd-k1921vk-0.12.0-k1921vk/bin/openocd -f connect_jlink_jtag.cfg -c "k1921vg015 srv_erase" -c "resume" -c "exit"
После выполнения srv_erase тоже нужно передёрнуть питание.

Приложу здесь же используемый файл connect_jlink_jtag.cfg, чтобы всё было в одном месте:

Код: Выделить всё

source [find interface/jlink.cfg]
transport select jtag
source [find target/k1921vg015.cfg]
reset_config trst_only
adapter speed 1000
init
reset halt
---
Получается, в руководстве пользователя (версия от 14.05.2025) в разделе 7.1 "Flash-память" содержится неточность:
В последней ячейке второй страницы NVR области располагается конфигурационное слово микроконтроллера CFGWORD.
Под "ячейкой памяти" обычно понимается байт, в крайнем случае слово, соответствующее разрядности процессора. В данном случае это 32 бита. Возможно здесь имелась в виду "ячейка" из 4-х 32-битных слов, но такая формулировка контринтуитивна и сбивает с толку.

Предлагаю НИИЭТ заменить данный текст на:
В области NVR по адресу 0x1FF0 располагается конфигурационное слово микроконтроллера CFGWORD.
Заголовок таблицы 7.3 тоже сложен для понимания:
CFGWORD +1FF0h (смещение относительно начального адреса CFG дополнительной области FLASH)
Непонятно, к чему надо прибавить 1FF0: к адресу CFGWORD, к начальному адресу CFG (а что это вообще?) или куда-то ещё.
Предлагаю заменить на:
CFGWORD (адрес 0x1FF0h в области NVR)
Аватара пользователя
ejsan
Сообщения: 108
Зарегистрирован: 15 авг 2022, 21:17
Предприятие: vbrspb.ru

Re: К1921ВГ015 и защита прошивки

Сообщение ejsan »

Vcoder писал(а): 18 май 2025, 11:53 Под "ячейкой памяти" обычно понимается байт, в крайнем случае слово, соответствующее разрядности процессора. В данном случае это 32 бита. Возможно здесь имелась в виду "ячейка" из 4-х 32-битных слов, но такая формулировка контринтуитивна и сбивает с толку.
Так понимаю, здесь прикол в том, что местный контроллер флеша не умеет писать по отдельным словам, только одним махом по 4. Так что, даже если в настройках участвует только адрес 0x1FF0, переписывать приходится всю четвёрку, до самого конца 0x1FFF. Вероятно, при желании в оставшихся трёх словах юзер может хранить какую-то свою информацию. :geek:
Vcoder
Сообщения: 22
Зарегистрирован: 01 май 2025, 14:50
Предприятие: .
Откуда: Уфа

Re: К1921ВГ015 и защита прошивки

Сообщение Vcoder »

ejsan писал(а): 18 май 2025, 15:41 Так понимаю, здесь прикол в том, что местный контроллер флеша не умеет писать по отдельным словам, только одним махом по 4.
Судя по всему, так и есть. Возможно это тоже стоит явно указать в документации.

По хорошему надо читать всю страницу (для CFGWORD это 0x1000-0x1FFF), менять нужное, стирать страницу и записывать изменённый образ обратно.

Интересно, какой ресурс у flash-памяти?
Аватара пользователя
ejsan
Сообщения: 108
Зарегистрирован: 15 авг 2022, 21:17
Предприятие: vbrspb.ru

Re: К1921ВГ015 и защита прошивки

Сообщение ejsan »

Меня терзают смутные сомнения...помимо ядра, что понятно, JTAG всегда видит на шине это:

Код: Выделить всё

Info : JTAG tap: BSCAN.bscan tap/device found: 0x20c5f44d (mfg: 0x226 (MediaTek), part: 0x0c5f, ver: 0x2)
Это просто глюк, или идентификатор флеш-чипа? Странно, что это "Mediatek", который свою память, вроде как, не делает. :?
Vcoder
Сообщения: 22
Зарегистрирован: 01 май 2025, 14:50
Предприятие: .
Откуда: Уфа

Re: К1921ВГ015 и защита прошивки

Сообщение Vcoder »

Тоже очень интересно, чего это идентификатор.
petrd
Сообщения: 5
Зарегистрирован: 03 апр 2025, 10:07
Предприятие: ООО ТСА

Re: К1921ВГ015 и защита прошивки

Сообщение petrd »

Vcoder писал(а): 18 май 2025, 11:53 Получилось!

Код: Выделить всё

$ /opt/xpack-openocd-k1921vk-0.12.0-k1921vk/bin/openocd -f connect_jlink_jtag.cfg -c "k1921vg015 write nvr erase 0x1FF0 0xFFFFFFF8 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF" -c "resume" -c "exit"
После этого надо передёрнуть питание. Reset-а недостаточно.

Код: Выделить всё

$ /opt/xpack-openocd-k1921vk-0.12.0-k1921vk/bin/openocd -f connect_jlink_jtag.cfg -c "k1921vg015 read main 0x80000000" -c "resume" -c "exit"
xPack Open On-Chip Debugger 0.12.0+dev-00520-gc670187e1-dirty (2023-11-17-06:08)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
DEPRECATED! use 'adapter speed' not 'adapter_khz'
Info : J-Link V9 compiled Sep  1 2016 18:29:50
Info : Hardware version: 9.60
Info : VTarget = 3.349 V
Info : clock speed 1000 kHz
Error: JTAG scan chain interrogation failed: all ones
Error: Check JTAG interface, timings, target power, etc.
Error: Trying to use configured scan chain anyway...
Error: K1921VG015.cpu: IR capture error; saw 0x1f not 0x01
Warn : Bypassing JTAG setup events due to errors
Error: Unsupported DTM version: 15
Warn : target K1921VG015.cpu examination failed
Info : starting gdb server for K1921VG015.cpu on 3333
Info : Listening on port 3333 for gdb connections
Error: JTAG scan chain interrogation failed: all ones
Error: Check JTAG interface, timings, target power, etc.
Error: Trying to use configured scan chain anyway...
Error: K1921VG015.cpu: IR capture error; saw 0x1f not 0x01
Warn : Bypassing JTAG setup events due to errors
Error: Unsupported DTM version: 15
Error: Unsupported DTM version: 15
zsh: segmentation fault (core dumped)  /opt/xpack-openocd-k1921vk-0.12.0-k1921vk/bin/openocd -f  -c  -c "resume" -c
openocd даже в segmentation fault улетел.
Для srv_erase тоже нужно отключить питание, замкнуть вывод SERVEN на Vcc и подать питание.

Код: Выделить всё

$ /opt/xpack-openocd-k1921vk-0.12.0-k1921vk/bin/openocd -f connect_jlink_jtag.cfg -c "k1921vg015 srv_erase" -c "resume" -c "exit"
После выполнения srv_erase тоже нужно передёрнуть питание.

Приложу здесь же используемый файл connect_jlink_jtag.cfg, чтобы всё было в одном месте:

Код: Выделить всё

source [find interface/jlink.cfg]
transport select jtag
source [find target/k1921vg015.cfg]
reset_config trst_only
adapter speed 1000
init
reset halt
---
Получается, в руководстве пользователя (версия от 14.05.2025) в разделе 7.1 "Flash-память" содержится неточность:
В последней ячейке второй страницы NVR области располагается конфигурационное слово микроконтроллера CFGWORD.
Под "ячейкой памяти" обычно понимается байт, в крайнем случае слово, соответствующее разрядности процессора. В данном случае это 32 бита. Возможно здесь имелась в виду "ячейка" из 4-х 32-битных слов, но такая формулировка контринтуитивна и сбивает с толку.

Предлагаю НИИЭТ заменить данный текст на:
В области NVR по адресу 0x1FF0 располагается конфигурационное слово микроконтроллера CFGWORD.
Заголовок таблицы 7.3 тоже сложен для понимания:
CFGWORD +1FF0h (смещение относительно начального адреса CFG дополнительной области FLASH)
Непонятно, к чему надо прибавить 1FF0: к адресу CFGWORD, к начальному адресу CFG (а что это вообще?) или куда-то ещё.
Предлагаю заменить на:
CFGWORD (адрес 0x1FF0h в области NVR)
Не понятно. Отключили JTAG, доступа внутрь чипа по JTAG нет. Даже полное стирание работать не будет. МК с одноразовой прошивкой?
p_k
Сообщения: 10
Зарегистрирован: 16 май 2025, 10:32
Предприятие: i.d

Re: К1921ВГ015 и защита прошивки

Сообщение p_k »

petrd писал(а): 08 сен 2025, 08:25 Не понятно. Отключили JTAG, доступа внутрь чипа по JTAG нет. Даже полное стирание работать не будет. МК с одноразовой прошивкой?
Сервисное стирание работать будет
petrd
Сообщения: 5
Зарегистрирован: 03 апр 2025, 10:07
Предприятие: ООО ТСА

Re: К1921ВГ015 и защита прошивки

Сообщение petrd »

p_k писал(а): 08 сен 2025, 10:45
petrd писал(а): 08 сен 2025, 08:25 Не понятно. Отключили JTAG, доступа внутрь чипа по JTAG нет. Даже полное стирание работать не будет. МК с одноразовой прошивкой?
Сервисное стирание работать будет
А как? Чтобы запустить сервисное стирание (ошибся, это и имел ввиду говоря про полное стирание), помимо замыкания SERVEN надо еще во флеш контроллер по JTAG как минимум две команды отправить, а JTAG-то отключен. Можете пояснить?
p_k
Сообщения: 10
Зарегистрирован: 16 май 2025, 10:32
Предприятие: i.d

Re: К1921ВГ015 и защита прошивки

Сообщение p_k »

petrd писал(а): 08 сен 2025, 14:32 А как? Чтобы запустить сервисное стирание (ошибся, это и имел ввиду говоря про полное стирание), помимо замыкания SERVEN надо еще во флеш контроллер по JTAG как минимум две команды отправить, а JTAG-то отключен. Можете пояснить?
Я пробовал описанным выше способом отключать JTAG и сервисным стиранием потом возвращать его. Видимо в сервисном режиме JTAG становится активен. Но флеш не должна быть при этом доступна. Кстати надо это проверить будет
Ответить

Вернуться в «32-разрядные микроконтроллеры»