iMX6 получает U-Boot для временной загрузки другого U-Boot - PullRequest
0 голосов
/ 30 октября 2018

Сначала немного фона:

У нас есть следующая настройка в нашей встроенной системе на базе iMX6. Есть два раздела U-Boot и два системных (Linux) раздела. В настоящее время мы используем только первый раздел U-Boot, и он использует стандартный метод выбора, запуска и (при необходимости) отката системных разделов.

Сейчас мы рассматриваем аналогичную схему для обновления самого U-Boot (это случается очень редко, но мы хотим иметь возможность делать это без необходимости возвращать устройства на базу).

Однако, это более опасно, потому что, как только вы скажете устройству iMX6 загрузиться с альтернативного раздела U-Boot, все - нет комбинации U-Boot / watchdog, которая вернется к предыдущему, если загрузка не удалась поэтому плохое обновление создает серьезную угрозу блокирования устройства до тех пор, пока мы не сможем вернуть его на базу для ремонта (дорогостоящий вариант, поэтому мы стараемся максимально его смягчить).

Выбранный метод представляет собой двухэтапную процедуру установки U-Boot, состоящую из «write» и «activ». Он основан на нашей способности успешно определить, какой раздел U-Boot будет запущен, если устройство перезагружается (выбранный), и какой в ​​данный момент запускается (загруженный). С этим битом уже разобрались.

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

Во-первых, к mmcboot добавлен префикс, чтобы он проверял передачу управления, в частности он установлен на run ub_xer_chk ; <original content of mmcboot>.

Во-вторых, у нас есть переменная ub_xfer_flag, обычно равная 0.

В-третьих, у нас есть функция проверки ub_xfer_chk, определенная как:

if test ${ub_xfer_flag} -eq 1 ; then
    echo Soft-booting other UBoot...
    setenv ub_xfer_flag 0
    saveenv
    weave_magic
fi

Код weave_magic - это то место, где у нас возникают проблемы :-) Идея состоит в том, что он загрузит другой раздел UBoot в память (при CONFIS_SYS_TEXT_BASE из 0x1780000) и выполнит его так, как если бы оно было на самом устройстве. сделал это.

Мы протестировали основную часть этого решения, используя reset вместо weave_magic, и оно успешно перезапустило устройство один раз, поэтому мы уверены, что сможем сделать его безопасным.


Мой конкретный вопрос: как как убедить U-Boot загрузить вторую копию из другого раздела и запустить ее?

Два раздела UBoot находятся на устройствах /dev/mmcblk3boot0 и /dev/mmcblk3boot1, доступных из системного раздела, и представляют собой файлы размером 2 МБ, включая вводный заголовок 1 КБ и небольшой отступ в конце.


Обновление:

На самом деле мы достигли некоторого успеха и нам удалось загрузить образ IMX из загрузочного раздела с помощью команды:

ext4load mmc ${mmcdev}:${mmcpart} 0x17800000 ${bootdir}/u-boot.imx

но при попытке выполнить его с помощью:

go 0x17800000

получаем недопустимую инструкцию и немедленную перезагрузку:

pc : [<17800070>]          lr : [<4ff83c64>]
sp : 4f579ac0  ip : 00000030     fp : 4f57be58
r10: 00000002  r9 : 4f579efc     r8 : 4ffbe2b0
r7 : 4f57be68  r6 : 17800000     r5 : fffff200  r4 : 000002cc
r3 : 17800000  r2 : 4f57be6c     r1 : 4f57be6c  r0 : 00000000
Flags: nZCv  IRQs off  FIQs off  Mode SVC_32
Resetting CPU ...

Так что я предполагаю, что это не исполняемый код в начале этого файла. Любые идеи о том, куда идти отсюда?

1 Ответ

0 голосов
/ 09 ноября 2018

Фактический код в файле IMX находится не в начале. Вы можете обнаружить этот факт с помощью превосходного онлайнового дизассемблера с архитектурой armv5 big-endian no-thumb, чтобы выяснить, что байты в начале часто дают вам недопустимый и / или не очень чувствительный код:

ldtdmi  a1, [a1], -a2             ; <UNPREDICTABLE>
strne   a1, [a1, a1]
andeq   a1, a1, a1
ldrbne  pc, [pc, -ip, lsr #8]!    ; <UNPREDICTABLE>

В любом случае известно, что данные в начале файла IMX являются информацией заголовка (d1 в начале - это «магический» маркер, указывающий заголовок IVT, и после этого также должен быть блок DCD). Однако, даже за пределами блоков IVT и DCD (на основании их предполагаемой длины в полях заголовка) код не имеет смысла.

Тем не менее, существует жизнеспособная информация по смещению 0xc00 после большого фрагмента 0x00 байтов:

00000be0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000bf0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000c00: 0f00 00ea 14f0 9fe5 14f0 9fe5 14f0 9fe5  ................
00000c10: 14f0 9fe5 14f0 9fe5 14f0 9fe5 14f0 9fe5  ................

Подстановка шестнадцатеричных байтов со смещением 0xc00 в дизассемблер и корректировка областей, пропускаемых ветвями, показывает действительный и здравый код ARM.

И, действительно, удаление файла IMX с помощью:

dd if=u-boot.imx bs=1 skip=3072 of=ub-at-c00.imx

должен дать вам файл, с которым вы можете загрузиться:

ext4load mmc ${mmcdev}:${mmcpart} 0x17800000 ${bootdir}/ub-at-c00.imx
go 0x17800000

Когда мы делаем это, он выводит:

U-Boot 2014.04 (Nov 07 2018 - 19:05:32)
CPU:   Freescale i.MX6Q rev1.5 at 792 MHz
CPU:   Temperature 32 C, calibration data: 0x5764e169
Reset cause: unknown reset
Board: DTI BRD0208 (Spitfire I) 05/01/2017
I2C:   ready
DRAM:  1 GiB

Мы знаем , это более новый UBoot просто потому, что обычный, который мы используем, выводит октябрьскую, а не ноябрьскую дату.

К сожалению, в этот момент он зависает, когда сторожевой таймер в конечном итоге запускается и перезагружается к исходному UBoot, но я подозреваю, что это связано с тем, что UBoot не нравится текущее состояние устройства (т. Е. Ему не нравится инициализировать его дважды).

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

...