wiki:HDK/Общие выкладки по архитектуре прошивок

Version 4 (modified by GrAnd, 7 years ago) (diff)

--

Общие выкладки по архитектуре прошивок

Так, по свежим следам и в надежде на появление новых энтузиастов-практиков, опишу текущую схему и достигнутые результаты (с пометками по части своего s2is). Речь пойдет, очевидно, только о DII + VxWorks? фотоаппаратах.

Общая стартапная информация

ОС и процессор

Анализ прошивки s2is, найденной ранее mc.kinley, показывает наличие строк VxWorks? 5.5 и Victoria - ARM946ES (ARM)

Процедура штатной загрузки

Процедура штатной загрузки обновления выглядит так:

  • Запускается canon-овский софт UploadFirmware?. Он использует TWAIN-драйвер и недокументированную библиотеку iwrap.dll для записи файла на флешку через "модифицированный" Canon-ом протокол PTP. При этом проверяет соответствие типа аппарата и версионность прошивки.
  • Аппарат включаем в режиме просмотра, в меню нижней строкой появлять пункт "прошить".
  • По активации пункта аппарат загружает и распаковывает в ОЗУ файл прошивки, после чего запускает на исполнение WriteInFIR.bin.
  • WriteInFIR.bin выполняет последующие действия по перепрошивке.

Формат прошивки

Для семейства VxWorks? 5.5 (в т.ч. иксусы, а610, s2is) подходит распаковщик ixus_fdu.exe Вышеуказанная прошивка s2is содержит некоторый набор флагов и файлы:

 WriterInFIR.bin
 PRIMARY.BIN
 Faexe.bin
 ImgTbl.bin
 UIRes.bin
 UsrSet.BIN
 AdjTableVersion.bin
 Param.bin
 MechaParam.bin

Выводы

(что нужно для изучения и первых модификаций)

  • корректно дизасемблировать бинарные файлы из прошивки
  • корректно вносить изменения в код прошивки (с учетом возможных контрольных сумм)
  • уметь создавать файлы прошивок в корректном для аппарата формате
  • уметь корректно записывать эти файлы на флешку

Необходимый инструментарий

Распаковка/запаковка прошивки

Как указывалось ранее в качестве распаковщика подходит ixus_fdu.exe (ссылки были в этой теме ранее) В качестве запаковщика можно использовать pak.c от vitalyb, предварительно модифицированный для вашего аппарата и с учетом конкретной прошивки. Вот здесь лежит собранная версия для s2is -- http://altsoph.ru/stuff/prjs/canon/pak_s2is_v01.exe Данная версия пакует найденный в текущей директории файл WriterInFIR.bin (и только его!) в прошивку, которую называет EC164HLD.FIR, указывая при этом версию 1.0.1.0 и ModelID+ProductID аппарата s2is ("0x01640000" + "0x30F0")

Запись на флешку

Для заливки самого файла прошифки можно использовать стандартный canon-овский UploadFirmware? (после настрокий ini-файла). Взять его можно из любого официального обновления (их список с ссылками есть в первом посте этой темы). Для записи / чтения произвольного файла приходится идти на ухищрения. Если есть card-reader, следует использовать его и ни о чем не беспокоиться. В противном случае потребуется специальный софт:

  • Новые аппараты canon как-то странно поддерживают интерфейс IStillImage, поэтому утилиты типа wins10sh неприменимы.
  • Библиотека usbptp (и содержащаяся в ней тестовая утилита ptpcam) может быть собрана на платформе Linux (в моем случае это Knoppix под VMWare) на базе библиотеки libusb не ниже 0.1.8. Тонкие моменты этого варианта:
    • для получения функции записи следует наложить патч от vitalyb, ссылка проходила выше.
    • портировать под win сходу не удалось по причине отсутствия порта активно используемого mmem-а, а так же по причине очень сильной глючности libusb-win.
    • так или иначе этот вариант является нестабильным, т.к. даже под linux-ом утилита ptpcam жутко глючит.
    • но её использовать за неимением других вариантов можно
  • Другие варианты:
    • поиск подходящей реализации ptp под платформу win результатов не дал
    • утилита UploadFirmware? использует iwrap.dll и её недокументированные функции PSPutFile, PSPutFileEx и т.п. (проверено api logger-ом)
    • вывод: нужно либо писать свой драйвер, либо утилиту на основе canon-овского TWAIN-а и недокументированных функций iwrap.dll. Есть умельцы?

Дизассемблер под ARM

Используется IDA Pro, в моем случае 4.9. Некий самоучитель по IDA (за качество не ручаюсь) можно найти тут: http://www.latronik.ru/temp/idahelp.chm Полезный документ "Программная среда ARM" качаем тут: http://chuk.fromru.com/SE/Arm/Programmnaya_sreda_ARM.rar Руководство по ARM-ассемблеру от ныне покойного ЖЖ сообщества ru_ppcre называется 'ru_ppcre's arm manual.pdf', искать гуглом.

Сборка c-кода под ARM

Для сборки используется пакет GNUARM (http://gnuarm.com/), который можно запустить на платформе win под cygwin-ом (http://www.cygwin.com/) или mingw (http://mingw.org/). Примеры скриптов и настроек сборки см в коде vitalyb, ссылки он давал выше.

Выводы

  • таким образом, при наличии card-reader-а полный цикл экспериментов можно проводить под платформой win.
  • на платформе lin потребуется как-то запустить IDA, в остальном там тоже проблем не возникнет.
  • очень хочется иметь вменяемый инструмент для работы с ptp, желательно под win

Изучение содержимого прошивки

Что обычно лежит в прошивке я писал выше в 0.3. На данный момент особый интерес представляют файлы: PRIMARY.BIN -- основной файл прошивки, содержит ОС и все основные процедуры управления камерой, USB PTP, звуки и прочее.
WriterInFIR.bin -- этот файл запускается из *.fir (если он сформирован верно) залитого на флешку и осуществляет перепрошивку фотоаппарата, выставляет всякие конфигурационные таблицы и прочее.

Изучение PRIMARY.BIN

Как вычислил vitalyb, файл живет в памяти по адресу 0xff810000 -- туда же его следует загружать в IDA. Дальше надо копать и копать ) Там можно найти весь код управления аппаратом. На первых порах интерес представляют стандартные функции типа open/close/read/CreateTask/и т.п. Кроме того, там же можно поискать адреса портов лампочек, клавиатуры и прочей периферии. При разборе кода следует помнить, что полученный из fir PRIMARY.BIN, даже если он предназначен для вашего фотоаппарата, скорее всего будет отличаться от того что сейчас в памяти фотоаппарата (если вы этот fir еще не установили).

Изучение WriterInFIR.bin

На первых порах WIF представляет наибольший интерес. Как вычислил vitalyb, файл живет в памяти по адресу 0x1900 -- туда же его следует загружать в IDA. Для начала следует найти в конце файла таблицу из ~3000 функций -- она выглядит как массив, где на каждую функцию отведено 3 двойных слова.
Первое -- адрес названия функции
Второе -- тип ресурса (для функции это 50000, еще попадаются 70000 и 90000)
Третье -- адрес тела функции.
После их распознования код выглядит значительно понятнее. Например в функции InitializeUniqueLED мне удалось обнаружить адреса портов лампочек для S2 IS:

 #define LED_AF_GREEN 0xc022008C
 #define LED_AF_RED 0xc02200fC
 #define LED_PR 0xc0220088

Изучение дампа

Лично мне получить дамп пока не удалось О том как это делается в теории я напишу в следующем (3.х) разделе. Однако после получения дампа общая логика его изучения такая:

  • С адреса 0xff810000 живет реальный WriterInFIR.bin, и если на аппарат не ставились обновления firmware, то изучать внимательно следует именно его, т.к. он содержит реальные адреса функций и т.п.
  • Насколько я понимаю -- с адреса 0х0 примерно до 0х1900 живет часть ОЗУ, активно используемая ОС. Туда драйвера копируют значения портов и хранятся текущие параметры системы.
  • С адреса 0xc0220000 (а может и раньше) живут реальные адреса портов -- лампочки, кнопки, динамик и прочие.

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

Способы загрузки и исполнения своего кода на аппарате

Пока что найден один стабильный способ заливки кода на аппарат: на флеш-карту заливается файл-пакет, замасикрованный под обновление прошивки и содержащий нужный код. Фотоаппарат обнаружит его и позволит запустить (в режиме REC в меню появляется строка Update Firmware). Далее этот код может выполнять дополнительные действия, в том числе подгружать с карты дополнительные модули и запускать их так, как ему это кажется удобным. О том, как собрать и залить корректный файл-пакет обновления, было написано в 1.1 и 1.2. После запуска с карты файла *.fir, аппарат расшифровывает и распаковывает его, загружает в память файл WriterInFIR.bin по адресу 0х1900 и запускает на исполнение с того же адреса.

Кроме того, имеется информация о том, что существуют и другие способы исполнения кода (видимо, в неразведанном пока Factory Mode) -- есть подозрения, что аппарат может запускать код, получаемый непосредственно через USB. Об этом свидетельствует наличие в Primary.bin таких, например, строк, как "=== Start Faexe From USB ===". Данное направление пока не исследовано, и далее будет рассматриваться метод с загрузкой через патч прошивки.

Запуск "голого" кода

Самым простым способом запуска своего кода является полная подмена WriteInFIR.bin-а своим кодом. Примером такого кода является написанная vitalyb мигалка лампочкой (code_v0). Основные ограничения данного способа следуют из того факта, что на момент выполнения WIF-а периферия не до конца проинициализированна, да и запуск каких либо внутренних функций PRIMARY в таком непроинициализированном окружении грозит проблемами. Однако из этого кода уже можно работать с портами (если знать как с ними работать) в том числе помигать лампочками, попробовать включить клавиатуру и опозновать нажатия клавишей и т.п.

Запуск кода, внедренного в готовый WIF

Если для вашего аппарата есть фирменное обновление, можно модифицировать содержащийся там WIF, поместив свой код в точку, где основная инициализация окружения уже выполнена штатными процедурами WIF-а (использование чужого WIF-а, т.е. WIF-а от другого аппарата, скорее всего ни к чему хорошему не приведет). По такому принципу работает загрузчик elf-ов, реализованный vitalyb в рамках code_v1. Общая логика такова: основная инициализация происходит в процедуре AdditionalFunction?, в конце которой делается вызов ExecuteUpgrade?. Вот именно на место ExecuteUpgrade? заливается свой код. Преимущества этого подхода -- можно более уверено работать с периферией (в т.ч. с ФС на SD) и можно вызывать функции, имеющиеся внутри стандартного WIF-а (среди них и open/write/read/close/loadModuleAt/...). Внедренный таким образом код уже может делать дампы памяти на карточку.

Запуск elf-ов через загрузчик

Развитием предыдущего подхода является написание elf-загрузчика. Суть идеи заключается в следующем:

  • пишется специальный код загрузчика, который внедряется в WIF по методу 3.2
  • сам код выполняет открытие elf-файла с карточки и вызов loadModuleAt для этого файла
  • сам elf-код может свободно использовать функции, описанные в WIF-е, причем код является портабельным (явные адреса функций нигде не прописываются, а определяются автоматически при выполнении loadModuleAt), т.е. на S2 IS спокойно работают бинарники собранные vitalyb для a610.

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

Внедрение процесса

Следующим шагом является запуск своего процесса на аппарате, причем так, чтобы он выполнялся параллельно со штатной работой аппарата. Для этого пишется elf-код, который некоторым образом выделяет область памяти под новый процесс, размещает там код процесса и производит горячую перезагрузку аппарата, после чего процесс начинает выполняться в качестве одной из задач ОС и может влиять на происходящее во время работы аппарата. Данный подход применяется vitalyb для вытаскивания RAW прямо из памяти в момент осуществления снимка.

Некоторая информация об организации портов

Все регионы MMIO расположены, по всей видимости, в области памяти 0хсХХХХХХХ. Регионов там много, они отвечают за различное оборудование. Общий дамп области сделать не получается, видимо там не все доступно на чтение. Анализ прошивки дает такие регионы как 0хс00ХХХХХ, 0хс020ХХХХ, 0хс021ХХХХ, 0хс022ХХХХ, 0хс024ХХХХ, 0хс04ХХХХХ, 0хс0сХХХХХ, и другие.

На данном этапе наибольший интерес представляет регион 0хс022ХХХХ -- там и у a610 и у s2is (а возможно и у других моделей) находятся порты индикаторов и клавиатуры.

Некоторые из портов, назовем их "управляющими портами", чаще всего содержат значения 0х42("выключен") и 0х47("включен"). Работа с управляющими портами происходит обычно так:

  • для включения в выключенный (0х42) порт заносится значение 0х46. В ответ, в качестве подтверждения, порт выставляет первый бит, и его значение становится равным 0х47.
  • для выключения во включенный (0х47) порт заносится значение 0х44. В ответ, в качестве подтверждения, порт снимает второй бит, и его значение становится равным 0х42.

Не забываем, что порт обычно является 4хбайтным словом.

Индикаторы

На аппарате имеется некоторое количество индикаторов (лампочек), каждому из которых соответствует некоторый порт, "включение" которого зажигает индикатор. Количество индикаторов и расположение их портов зависит от модели аппарата.

Согласно vitalyb, в а610 имеются как минимум следующие индикаторы:

LED_AF 0xc0220080
LED_PR 0xc0220084

В s2is мне удалось найти такие индикаторы:

LED_AF_GREEN 0xc022008C
LED_AF_RED 0xc02200fC
LED_PR 0xc0220088

(примечание: LED_AF_GREEN и LED_AF_RED нельзя включить одновременно, т.к. это два цвета одного индикатора).

Если необходимо найти порты для какой-то новой модели, проще всего начать их поиск с анализа функции InitializeUniqueLED в родном WIF-е.

Клавиатура

В а610, согласно vitalyb, состояние всех основных клавиш отражается в битах 4хбайтного слова по адресу 0xc0220208, а кнопка выключения (и, видимо, включения) видна по адресу 0xc0220204. Соответствие некоторых кнопок битам можно посмотреть в коде jumping-cube от vitalyb.

В s2is все организовано несколько сложнее. Есть 4 независимых банка кнопок. Им соответствуют порты 0xC0220110, 0xC0220114, 0xC0220118, 0xC022011С. По ним изначально записаны 0х47. Для того чтобы проверить состояние кнопок некоторого банка, он активируется (в соответствующий порт заносится 0х44), происходит чтение и анализ порта 0xc0220208, затем банк деактивируется (в соответствующий порт заносится 0х47).

Полный цикл анализа клавиатуры согласно коду драйвера из PRIMARY выглядит так:

  • включаем первый банк (0xC0220110 заносим 0х44)
  • читаем кнопки из 0xC0220208 (!)
  • выключаем первый банк (0xC0220110 заносим 0х46)
  • включаем второй банк (0xC0220114 заносим 0х44)
  • читаем кнопки из 0xC0220208
  • выключаем второй банк (0xC0220114 заносим 0х46)
  • включаем третий банк (0xC0220118 заносим 0х44)
  • читаем кнопки из 0xC0220208
  • выключаем третий банк (0xC0220118 заносим 0х46)
  • включаем четвертый банк (0xC022011c заносим 0х44)
  • читаем кнопки из 0xC0220208
  • выключаем четвертый банк (0xC022011c заносим 0х46) (!) Судя по обработчику при проверке первого банка также вроде бы читаются 0xC0220200, 0xC0220204, 0xC0223024, 0xC022301с, но зачем -- толком пока не ясно.

Такой метод обработки клавиатуры позволяет читать состояния 36 кнопок и переключателей. Остаются пока не найденными:

  • кнопка отложенной съемки
  • кнопка отсека SD-карты
  • кнопка видео-съемки
  • кнопка POWER OFF
  • кнопка MODE PLAY
  • кнопка MODE REC

Другие порты

Другие порты могут быть найдены анализом кода прошивки или перебором

  • Имеется некий загадочный порт, при включении аппарата выставляемый в 0х46, а при выключении в 0х44. В а610 это 0xc02200a0, а в s2is, видимо, 0xC022002C. Однако, штатная процедура shutdown этим не исчерпывается, поэтому простое выставление этого порта в 0х44 приведет, скорее, к зависанию
  • На своем s2is я при некоторых обстоятельствах добился срабатывания вспышки при занесении 0х46 по адресу 0хc02200a4. Причем вспышка срабатывает даже в закрытом состоянии.

Кроме того в прошивке от s2is попадаются такие адреса:

  • в функции TurnOnSDCardPower 0xC02200B0 <= 46
  • в функции InitializeScanModeADC 0xC022c0B4 = 46
  • в функции SioDrv? 0хC0223010 <= ( 8000 | 8088 )
  • неподалеку от строки "Audio" 0xC022c0BC <= 46
  • неподалеку от строки "TgTask?" 0xC02200AC <= 46
  • неподалеку от строки "EfDrv?" 0xC02200A8 <= 46
  • неподалеку от строки "SDACDrv" 0xC0220018 <=??
  • неподалеку от строки "LATCH_E2" ("ImagePower?") 0xC0220030 <= ??

Код драйвера можно взять тут: http://altsoph.ru/stuff/prjs/canon/SDL_nullevents.c

Инструкции по сборке sdl под s2is

  1. Берем sdl с офф.сайта или из svn, мне попался что-то вроде 1.2.12.
  2. Берем http://vitalyb.mail333.com/a610/sdl-demo.zip и накладываем взятый оттуда sdl.patch<br>ИЛИ (вместо 1-2) берем пропатченные сырцы от vitalyb тут http://vitalyb.mail333.com/a610/sdl/sdl-canon.7z
  3. Заменяем sdl/src/video/dummy/SDL_nullevents.c на http://altsoph.ru/stuff/prjs/canon/SDL_nullevents.c
  4. Собираем, помахивая бубном...

Собранную версию можно взять тут http://altsoph.ru/stuff/prjs/canon/libsdl.a

Мануал по адпатации RAW-shooter-а под новые прошивки

Организация кода

Качаем и распаковываем http://vitalyb.mail333.com/a610/raw/raw-nowif-src.zip

  • в корне лежит кусок кода, который отвечает за определение версии прошивки и вызов перезагрузки с переходом на выполнение соответствующего блока.
  • в папке resetcode живет код, который осуществляет "горячую" перезагрузку аппарата и передачу управления на прошивко-специфичный код, инсталлирующий перехватчик процедуры съемки
  • в папке spycode живут в разных файлах прошивко-специфичные перехватчики -- по одному на прошивку, каждый в отдельном файле
  • в папках вида raw-shot* живут по сути исходники этих перехватчиков, используемые для генерации кода перехватчиков, хранимого в папке spycode

Для дальнейших действий необходима "текущая" прошивка вашего аппарата, полученная тем или иным способом. Весьма полезным может оказаться так же и WIF для вашего или близкого аппарата, если он у вас есть.

Реализуем определение версии

В прошивке аппарата есть надпись, содержащая полный код версии данной прошивки. Эта надпись всегда (видимо) находится в одном и том же месте для заданной модели аппарата вне зависимости от версии прошивки, но для разных моделей аппаратов она живет в разных местах.

  • Грузим дамп в IDA, ищем близко к началу (в районе 0хffc1XXXX) строку вида "Firmware Ver GM1.00E". Запоминаем адрес байта, в котором хранится точка ("."). Например, это ff81ADB0.
  • Открываем файл raw-nowif-src/entry.s и указываем там адрес там где он присваивается переменной VersPtr?, например VersPtr? = 0xff81ADB0
  • Правим файл raw-nowif-src/main.c, заводим там переменные и ветку кода под вашу версию прошивки по аналогии с теми, что уже есть. Там же указывается файл, где будет жить код перехватчика для этой версии прошивки -- например "spycode/gm1.00e.h".

Уточняем код рестарта

Далее, при необходимости, следует уточнить код, который живет в файле raw-nowif-src/resetcode/main.c. Практика показывает, что этот код вроде как без модификаций работает для a610/a620/s2is/s3is. Но, на всякий случай этот код, можно проверить следующим образом -- если у вас есть WIF для вашего аппарата, поищите в нем функцию Restart, расположенную сразу после строки "Restart called". В этой функции сначала вызывается ряд подфункций, а затем идет работа с портом и прерываниями. Вот эта часть (после вызова функций) нам и нужна в виде asm кода в raw-nowif-src/resetcode/main.c

Общий смысл выполняемых в raw-nowif-src/resetcode/main.c действий такой:

  • сначала происходит копирование кода перехватчика в некоторую область памяти
  • затем производится горячая перезагрузка аппарата и передача управления на эту область памяти

Эмуляция загрузки аппарата

Далее начинается основное шаманство. После того как "перезагруженный" аппарат передал управление на наш код, нам необходимо выполнить все штатные действия по инициализации ОС аппарата, так как это делает прошивка при обычном старте. Все эти действия выглядят, как несколько урезанная копия asm кода из прошивки и живут в файле raw-nowif-src/raw-shot*/main.c в функциях startup() и usrRoot().

Получить код для этих функций можно примерно таким образом:

  • открываем дамп прошивки в IDA, немного дизасемблируем с самого начала, так чтобы открылся код ближе к концу дампа после надписей "WD expired" и "Startup"
  • этот код (по сути это функция, осуществляющая регистрацию процесса Startup) соответствует той части asm-кода в raw-nowif-src/raw-shot*/main.c, которая находится в самом конце (после метки Startup)
  • далее возвращаемся в функцию, вызвавшую данную и перемещаемся выше по исходнику raw-nowif-src/raw-shot*/main.c, снова копируем код и так далее, пока не доберемся до самого начала.
  • аккуратно копируем весь этот код в наш процесс (в функции в main.c) внося изменения по аналогии с имеющимися для другой прошивки, в основном эти изменения сводятся к следующим:
    • исправление адресов функций и переменных
    • устранение ненужных участков кода
    • в самом конце функции usrRoot() добавляется копия кода регистрирующего процесс Startup, исправленная так, чтобы она дополнительно регистрировала наш процесс (spytask)

Далее необходимо внести все поправленные адреса вызываемых функций в файл raw-nowif-src/raw-shot*/stubs.s, где для этого используется макрос STUB().
Помимо макроса STUB в raw-nowif-src/raw-shot*/stubs.s имеется макрос NSTUB(), который используется для регистрации нескольких именованных функций прошивки, используемых нашим перехватчиком. С помощью этого макроса необходимо объявить следующие функции:

  • CreateTask?
  • SleepTask?
  • sprintf
  • open
  • write
  • read
  • close
  • taskLock
  • taskUnlock
  • (в новой версии) mkdir

Для того чтобы правильно объявить данные функции, надо найти их в вашей прошивке. Это довольно неприятный процесс связанный с более/менее ручным поиском по коду. В целом, лично мной для этого применяются три разных подхода (в сочетании):

  • сравнение с другой прошивкой: предположим у вас есть прошивка А и код уже работающего под него RAW-shooter_А, а также прошивка В, под которую вы адаптируете RAW-shooter. Открыв оба дампа можно пытаться искать (по взаимоположению между собой и относительно строк в дампе А) необходимые функции (известные в дампе А) в дампе В.
  • сравнение с WIF-ом: аналогично предыдущему, в WIF-е довольно много стандартных функций и они там поименованы (про таблицу имен я писал где-то в ранних главах данного мануала). Найдя их там, можно искать аналогичные в вашем дампе.
  • поиск по сигнатуре: можно искать функции по набору опкодов в виде последовательности байтов (следя за тем чтобы в них не попали адреса и относительные смещения). Сигнатуры функций можно опять таки взять из другой прошивки, где расположение функций уже известно, или из библиотек VxWorks5.5, если вы являетесь их счастливым обладателем.

Это было самое неприятное. Ну, или почти самое

Кроме этого в raw-nowif-src/raw-shot*/stubs.s с помощью макроса DEF следует поименовать и адрес строки Startup, которую мы нашли в начале этого пункта.

Коррекция кода перехватчика

В этой, последней, части работы, вам предстоит "угадать" как минимум 4 числа, и это может оказаться достаточно непростым делом. Первые два числа -- адрес и размер буфера матрицы, откуда наш процесс будет сохранять изображение, можно подглядеть в дампе прошивки следующим образом: в коде прошивки имеется пока недоступная нам отладочная функция SaveCraw?, живущая сразу после надписей "SaveCraw?", "A/IMG_0001.CRW", "A/%s.CRW", "CRAW1_DATA_ADDR" и т.п. Там происходит сохранение RAW-а, что нам собственно и нужно. Нам необходимо определить область памяти, откуда сохраняется RAW и его размер. По всей видимости, эти параметры являются аппаратно фиксированными, поэтому при адаптации RAW-shooter-а с одной версии прошивки на другую на той же модели, они не изменятся.

Найденные два числа нужно указать в функции makedump() в raw-nowif-src/raw-shot*/main.c в качестве параметров для вызова write().

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

    BL      WaitForEventFlag__
    MOV     R1, #0x220000
    LDR     R0, [R5]
    BL      sub_FF8208C8
    LDR     R3, =0x2F494
    LDR     R2, =0x2F490 <= это адрес переменной, в которой хранится адрес обработчика
    LDR     R0, [R3]
    MOV     LR, PC
    LDR     PC, [R2] <= здесь происходит вызов обработчика
    LDR     R3, =0x3A60 <= сюда происходит возврат после вызова обработчика
    MOV     R4, #0
    LDR     R0, [SP,#0x60+var_54]
    STR     R4, [R3]
    STR     R4, [SP,#0x60+var_38]
    BL      sub_FF8D8074
    CMN     R8, #1
    MOVEQ   R8, #4
    CMP     R8, #7
    STR     R0, [SP,#0x60+var_34]
    STR     R8, [SP,#0x60+var_40]
    BNE     loc_FF8D8C08
    MOV     R1, #0x20000
    LDR     R0, [R5]
    MOV     R2, R4
    BL      WaitForEventFlag__

Ближайшая строка сверху -- "ImgSens?.c", расположена достаточно далеко (в прошивках для s2is на 6D8h байт выше).

Как только такой участок кода найден, нужно взять два числа -- одно из которых заносится в R2 прямо перед копированием R2 в PC (в нашем примере это 0x2F490). Это число указываем в функции spytask() в raw-nowif-src/raw-shot*/main.c там, где происходит инициализация указателя p. Вторым числом является адрес возврата, т.е. адрес первой операции после LDR PC, [R2]. Этот адрес следует указать в функции myhook1() в raw-nowif-src/raw-shot*/main.c.

После выполнения всех указанных действий следует собрать код и запаковать его в виде прошивки для вашего аппарата. RAW-shooter должен работать.

Индикация

RAW-shooter вполне будет работать и без этого, но индикация удобна, и особенно полезна при отладке. Для того чтобы индикация работала (т.е. моргали лампочки) в raw-nowif-src/raw-shot*/main.c следует поправить дефайны #define LED_PR и #define LED_AF Это адреса портов лампочек, которые меняются в зависимости от модели аппарата. Узнать их можно путем анализа прошивки или WIFа, а также перебором. Адреса лампочек для s2is/s3is/a610 я упоминал где-то в ранних главах данного мануала.


(с) altsoph