Как я прошивку видеорегистратора F500 ковырял

в 12:28, , рубрики: .net, Гаджеты. Устройства для гиков, Программирование

Видеорегистратор в машине штука нужная и крайне полезная, особенно, если водитель склонен ездить по правилам. Одной из оптимальных по соотношению цена/качество является линейка F500 и их старший брат Каркам Q2. Вот тут есть большая и длинная тема обсуждения этих регистраторов.
Примерно полгода назад я стал обладателем такого устройства и очень доволен. Но захотелось его немного доработать — придать индивидуальности. Возникла эта идея в контексте регистратора как подарка. Задачей минимума была замена стартовой и финальной заставок на что-то свое. Эта задача была успешно решена, но обнаружился ещё простор для творческих поисков.
Для тех кому неинтересно читать технические подробности — на GitHub выложены исходники и бинарники (нужен .Net 4.0)

Начало

Отправной точкой для изучения структуры прошивки стали вот эти ссылки:
pixeldoc.kicks-ass.net/projects/goprohdhero/firmware/v02.05.11/
goprouser.freeforums.org/search.php?author_id=4914&sr=posts
chdk.setepontos.com/index.php?topic=5890.0

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

Структура прошивки

Прошивка регистратора состоит из 5 секций (точное назначение их неизвестно):

[Bst] [Bld] [Pri] [Rom] [Dsp]

В секции Rom лежат ресурсы регистратора — она представляет для нас максимальный интерес.

Файл прошивки имеет следующую структуру:
Заголовок файла [Bst] [Bld] [Pri] [Rom] [Dsp]
Заголовок файла описывается следующей структурой:

unsafe public struct FileHeader
    {
        public Int32 BstStart;
        public Int32 BstEnd;

        public Int32 BldStart;
        public Int32 BldEnd;

        public UInt64 Empty0;

        public Int32 PriStart;
        public Int32 PriEnd;

        public UInt64 Empty1;

        public Int32 RomStart;
        public Int32 RomEnd;

        public Int32 DspStart;
        public Int32 DspEnd;

        public UInt32 Magik;

        public fixed byte Const[0x19F - 0x03C + 1];

        public fixed byte Empty2[0x7FF - 0x1A0 + 1];
}

Если для какого-либо типа секции Start и End равны нулю, то регистратор считает, что этой секции в файле нет.
В поле Const записаны данные назначение которых неизвестно, но они постоянны для любого сочетания секций в файле прошивки для текущей версии прошивки.

Каждая секция начинается со своего заголовка:

    unsafe public struct SectionHeader
    {
        public UInt32 CRC32;
        public UInt32 Version;
        public UInt32 Date;
        public Int32 ImgLen;
        public UInt32 Mem;
        public UInt32 Flags;
        public UInt32 Magik;

        public fixed byte Empty0[0x8FF - 0x81C + 1];
    }

Поле CRC32 рассчитывается для данных секции (без заголовка и байтов выравнивания) по самому тривиальному алгоритму.
ImgLen — фактическая длинна данных секции.

Секция Rom

В секции Rom хранятся ресурсы регистратора, организованные в простейшую файловую систему.
Данные секции Rom имеет следующий формат:
Заголовок Rom {Заголовок файла} {Содержимое файла}
Заголовок Rom

    unsafe public struct RomHeader
    {
        public Int32 FilesCount;
        public Int32 Magik;

        public fixed byte Empty0[0x10FF - 0x0908 + 1];
    }

Заголовок файла имеет следующую структуру:

    unsafe public struct RomFileHeader
    {
        public fixed byte FileNameBuf[Const.RomFilenameLength];
        public Int32 FileOffset;
        public Int32 FileLength;
        public UInt32 Magik;
    }

Замена ресурсов

Для замены ресурсов в регистраторе удобно пользоваться тем, что регистратор умеет отдельно прошивать файл содержащий только одну секцию. Поэтому будем генерировать файл содержащий только секцию Rom. Для этого:
1. Модифицируем FileHeader, оставив там только секцию Rom
2. Перепакуем Rom выравнивая начало каждого файла на 0x800. Количество и названия файлов нужно оставить оригинальными.
3. Пересчитаем контрольную сумму в заголовке секции.
4. Запишем всё это в выходной файл.

В итоге получилась вот такая вот программулина: github.com/magnitudo/F500Tool.

Что дальше?

В секции Rom есть файлы:
bitmaps.bin
fonts.bin
По названиям понятно, что в них хранится. С форматом пока разобраться не удалось.
Есть желающие помочь?

Автор: magnitudo

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js