U boot bin android

Сборка загрузчика U-boot для Orange Pi Zero

В данной статье мы соберем bootloader для Orange Pi Zero. Это пригодится тем кто хочет в дальнейшем с помощью bootloader (u-boot)+ kernel + rootfs (busybox) собрать и запустить свою embedded систему на одно платном компьютере.

Что нам необходимо:
Hardware:

— Orange PI Zero.
— Преобразователь USB-TTL.
— SD карта (минимальный размер 4Гб, и класс не ниже 6-го).

— OS Ubuntu (у меня 19.04).
— Cross compiler.
— Serial terminal (у меня GTKTerm).

Одно платный компьютер Orange Pi Zero на базу процессора Allwinner H2(Cortex A7 ) 1.2 GHz. На одноплатнике такде присутствует графический ускоритель GPU Mali400MP2. Размер ОЗУ 512 Мб DDR3 SDRAM.

Поддерживаемые ОС: Armbian, Android, Lubuntu, Debian, Raspbian и т.д.
Цена:

11$ (включая доставку в Украину).

Подключение Debug вывод Orange Pi Zero к ноутбуку:

Подключаем USB-TTL к Orange Pi соглаcно такой схемы:

Далее настраиваем GTKTerm (порт: USB0, скорость 115200, остальное по-умолчанию):

1. Сборка загрузчика U-boot для Orange Pi Zero

Das U-Boot — компьютерный загрузчик операционной системы, ориентированный на встроенные устройства архитектур MIPS, ARM и т.д.

Загрузка U-Boot происходит в два этапа:

  1. С начало первичный загрузчик BootROM копирует U-Boot SPL в оперативную память и передает ему управление.
  2. U-Boot SPL копирует основной загрузчик U-Boot в оперативную память передает ему управление.
  3. Далее U-boot загружает Kernel.

Откуда скачать (у меня версия U-Boot 2019.07-rc3):

Далее распаковываем архив и переходим в корень.

1.1 Очищаем, результат прошлой сборки:

1.2 Указывает defconfig, cross compiler и собирает загрузчик:

В результате мы получим:

Из всех файлов с префиксом u-boot. u-boot.bin, нам нужен файл с пост фиксом «u-boot-sunxi-with-spl.bin».

2. Подготавливаем разделы на SD карте

В каталоге /dev/ появится новая SD карта как SCSI-устройство (sda . ), либо как блочная MMC память (mmcblk0. )

В моем случаем имя SD карты — /dev/mmcblk0.

2.1 Отмантируем SD карту:

2.2 Разбивает SD карту на два раздела (1-й для U-boot, 2-й для корня системы):

2.3 Форматируем файловые системы на 1-м и 2-м разделе:

2.4 Записываем bootloader на SD карту:

Вставляем SD карту в Orange Pi Zero и запускаем.

Если все правильно было выполнено, то на Debug порте будет следующий вывод:

Далее у вас посыпятся ошибки и u-boot снова перегрузиться, это нормально т.к мы не указали ему Kernel и rootfs.

Источник

U-boot. Процедура инициализации по шагам

В предыдущей статье был описан процесс настройки IDE Eclipse для кросс-платформенной отладки загрузчика U-boot. В данной статье описывается устранение последних ограничений, препятствовавших полноценной его отладки. После чего, получив возможность полноценной отладки кода, пройдемся по всей процедуре инициализации загрузчика от первой инструкции и до конца в режиме отладки.

Устранение проблемы с fdtcontroladdr

Если помните, в прошлый раз остановились на том, что в коде пришлось захардкодить магическое число, позволявшее запустить процессор под отладчиком. Этот костыль не давал покоя. В итоге, продолжив бороздить просторы интернета и исходных кодов загрузчика удалось разобраться что к чему. Как оказалось, fdtcontroladdr — есть адрес памяти, по которому располагается бинарный файл скомпилированного дерева устройств. Подобного тому, что используется ядром Linux. Если мы хотим загрузить отладочную прошивку загрузчика, то должны также позаботиться и о том, чтобы прошивка смогла найти также и бинарь дерева устройств. Как правило, это файл с расширением .dtb. Но если есть сомнения, то открываем файл любым hex ридером и смотрим на первые четыре байта — они должны содержать магическое значение D0 0D FE ED, являющееся признаком начала скомпилированного дерева устройств:

Файл найден. По какому адресу в памяти его нужно расположить и как это сделать?

Читайте также:  Сколько должен держать заряд андроид

Ответ на первый вопрос может быть найден в той строчке кода, в которой мы хардкодили адрес:

_end — адрес конца прошивки, который можно узнать, заглянув в файл u-boot.map, — карту памяти, полученную по завершении процедуры линковки:

Ответ на второй вопрос — команда gdb:

Настало время проверить гипотезу.

Запускаем GDB сервер:

Запускаем отладочную сессию:

Здесь мы переходим в каталог, где лежат исходники u-boot и скомпилированный образ прошивки (файл u-boot).
Далее подключаемся к железке и загружаем прошивку:

Подгружаем device tree blob и запускаем работу процессора:

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

Теперь можно добавить эту команду в Debug конфигурацию Eclipse:

Казалось бы все, — мы получили долгожданную возможность полноценной отладки кода, получили способ проследить весь путь процедуры инициализации, заглянуть в каждый закоулок исходного кода. Перезапускаем GDB сессию, ставим точку остановки в одной из самыъ последних вызываемых функций (main_loop) и запускаем работу процессора:

и с удивлением обнаруживаем, что U-boot стартанул, прогрузился сам и запустил процедуру инициализации ядра Linux, но точка остановки так и не сработала! Магия!

Снова лезем в исходники и интернет. Несколько часов поисков и находим то, что лежало под носом (да-да, rtfm).

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

В случае нашей железки это выглядит следующим образом. Снова запускаем gdb сервер:

Смотрим адрес, с которого начнется исполнение кода:

Ставим точку остановки в функции relocate_code, как это описывается в документации и запускаем работу процессора:

Теперь, нам нужно загрузить ту же самую отладочную прошивку (с отладочными символами), но уже по другому адресу, в который намеревается перепрыгнуть процессор. Если мы этого не сделаем, то ничего страшного не случится, — u-boot продолжит работу штатно, но мы уже не сможем ловить процессор точками остановки, поскольку он будет работать по новым адресам. Подгрузим по этому адресу отладочные символы, — и сохраним возможность сопровождать процессор дебаггером. Определить адрес, по которому планируется прыжок можно двумя способами:

в консоли загрузчика ввести команду bdinfo:

и глянуть значение переменной relocaddr (0x8FF2B000).

дебаггером вывести значение переменной gd->relocaddr:

Итак, располагаем отладочные символы по этому адресу, проверяем расположение счетчика программы:

И пробегаем функцию relocation_code:

Снова смотрим расположение счетчика программ:

И вздыхаем с облегчением, — адрес больше того значения, по которому мы только что разместили прошивку. Значит перепрыгнули)

Теперь ставим точку остановки в функции board_init_r и видим, что установилось две точки (в прошивке по первоначальному адресу и в прошивке по адресу релокации):

запускаем исполнение процессора и убеждаемся, что точка остановки по новому адресу сработала:

В Eclipse то же самое будет выглядеть следующим образом. Ставим точку остановки на функцию relocate_code

Запускаем работу процессора:

И перед тем как выполнить релокацию кода, в отладочной консоли (Debugger console) вводим те же самые команды:

Вот теперь можно смело сказать, что появилась полноценная возможность дебажить U-boot. И в качестве вознаграждения можем пробежаться отладчиком от самой первой исполняемой команды и до самой последней, построив попутно подробную диаграмму процедуры инициализации загрузчика:

Сама диаграмма в виде png, pdf и libreOffice.

Процедура инициализации загрузчика U-boot

В целом, всю процедуру можно разделить на два этапа:

Инициализация до релокации (фиолетовая ветвь/путь, шаги 1-43)

Инициализация после релокации (зеленая ветвь/путь, шаги 45-80)

разделенных между собой упоминавшейся выше процедурой релокации (красный узел — узел 44)

На каждом из этапов происходит вызов одной и той же функции — initcall_run_list, принимающей на вход аргумент в виде массива указателей на функции инициализации, которые она вызывает в цикле). Естественно, на каждом этапе передаются разные массивы функций. На первом этапе это init_sequence_f, который можно найти в файле common/board_f.c:

Читайте также:  Правая кнопка мыши для андроид

На втором этапе — init_sequnce_r (файл common/board_r.c):

Где все начинается

Да, все начинается с ассемблера. Если вы пришли в embedded linux, из микроконтроллеров, то, возможно, вы уже сталкивались с ним.

Последовательно производится: отключение предываний, инициализация таблицы векторов прерываний, отключение MMU и TLBs, инициализация временного стека и минимально необходимой периферии.

Функция _main выделяет память под глобальный дескриптор (global_data, gd), — структуру данных, описывающей текущее состояние загрузчика.

После чего происходит вызов функции board_init_f, в свою очередь вызывающую уже упоминавшуюся функцию initcall_run_list в первый раз.

которая вызывает в цикле все переденные ей входным аргументом функции инициализации. Тут происходит и инициализация переменных окружения u-boot, и инициализация консоли, вывод первых логов, парсинг дерева устройств, бинд драйверов, соответствующих узлам дерева. Под конец производится вычисления адреса, по которому будет произведена релокация загрузчика.

Собственно, релокация, в процессе которой загрузчик копирует сам себя в конец оперативной памяти, чтобы выделить мах количество свободной оперативной памяти для ядра linux в виде единого цельного участка памяти.

Происходит вызов функции board_init_r, вызывающей, в свою очередь, функцию initcall_run_list во второй раз.

Последовательно вызываются все функции, переданные board_init_r. Самой последней вызывается функция run_main_loop, которая вызывает main_loop, в которой запускается таймер обратного отсчета, по прошествии которого управление передается ядру Linux, либо нет, если пользователь ввел что-либо в консоль.

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

Источник

Собираем свой Android для BeagleBoard


В этой статье, я хочу рассказать о процессе сборки Android, для контроллеров ARM. Надеюсь что для кого то эта статья окажется полезной, не только разработчику но и не искушённому пользователю. В основном конечно, хотелось бы показать как происходит сам процесс сборки, операционной системы для мобильных устройств. В качестве «подопытного кролика» я выбрал BeagleBoard-xM.
Это одна из отладочных плат, которые, как нельзя лучше подходят для подобных целей. кроме всего прочего она обладает HDMI и S-VIDEO выходами, для того что бы «пощупать» результат. А так же 4-я USB портами, которых вполне хватает для подключения клавиатуры, мышки и т.п. В своих экспериментах, я использовал BeadaFrame купленную на eBay, однако это условие абсолютно не принципиально, так как подойдёт любой «телевизор».

И так, грузиться наша плата будет с microSD, а для сборки Android нам понадобится Linux машина, например c Ubuntu 13.04-AMD x64, вполне можно использовать виртуальную машину, однако рекомендую убедиться в том что виртуальной машине доступно MMC устройство, т.е. сама microSD карточка, а для начала нам понадобится установить следующие пакеты:

Для нашего Android понадобится собрать три основные вещи:

  • само ядро операционной системы, по сути, — это бинарный файл, который будет загружать загрузчик.
  • загрузчик, в нашем случае — это будет u-boot, хотя можно использовать и x-loader.
  • файловая система

А для работы создадим какую ни будь рабочую директорию, например: /home/ubuntu/Adroid/

и сразу добавим эту директорию в пути:

Если на Вашей виртуальной машине, не был установлен git, то придётся это сделать:

Инициализация репозитория

Теперь нам нужно получить исходный код самого Android, из которого, в дальнейшем, мы будем собирать само ядро операционной системы и файловую систему. Для этого внутри рабочей директории /home/ubuntu/Adroid, выполним следующую команду:

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

Далее, внутри наше рабочей директории, создаём каталог для исходного кода:

и инициируем репозиторий:

После успешной инициации, выполняем синхронизацию с репозиторием

Синхронизация — это достаточно долгий процесс, поскольку содержит ни только исподники ядра, но и файловую систему а так же компилятор с помощью которого и будет собираться и загрузчик, и само ядро.
По окончанию синхронизации, мы должны увидеть информацию об успешной синхронизации, что то вроде этого:
Syncing work tree: 100% (261/261), done.
Теперь, перед сборкой нам нужно настроить путь к компилятору, которым мы будем собирать и ядро и загрузчик. Сам компилятор находится внутри самого репозитория в директории prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin, так что устанавливаем путь к нему в переменной PATH.

Читайте также:  Посмотреть ошибки системы андроид

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

Сборка загрузчика

Как я уже писал, что в качестве загрузчика, мы будем использовать u-boot. Для сборки нам понадобится сделать клон репозитория u-boot, в нашей рабочей папке:

И собираем наш загрузчик, первую команду distclean, при самой первой сборке, можно пропустить.
Для сборки u-boot используется компилятор arm-eabi-gcc, путь к которому у нас уже установлен.

Результат сборки загрузчика — это два файла MLO, и u-boot.bin. Оба этих файла находятся в корне директории u-boot. Сразу перенесём их куда ни будь, просто для удобства, например в каталог build.

Сборка ядра

Теперь мы добрались до сборки самого ядра. Физически это один файл uImage, который по факту представляет ни что иное как — Linux ядро. Однако перед тем как приступать к сборке, необходимо установить Java SE 1.6. И именно версию 1.6, установить которую можно из репозитория:

или, например как описано в этой статье.
Далее, для сборки ядра, нам нужно зайти в директорию kernel, внутри Android репозитория. В нашем случае: /home/ubuntu/Adroid/source/kernel, и по примеру сборки загрузчика u-boot, выполнить сборку:

Надо заметить, что omap3_beagle_android_defconfig взят из каталога kernel/arch/arm/configs, в котором находятся конфигурации ядра. При желании можно изменить, добавить, или подобрать подходящую конфигурацию для конкретного «железа».
Результат сборки, будет находится в папке kernel/arch/arm/boot, т.е. в нашем случае /home/ubuntu/Adroid/source/kernel/arch/arm/boot, откуда мы берём файл uImage, собственно само ядро, и переносим его в уже удобную, для нас директорию build.

Сборка файловой системы

Это последний этап сборки нашей операционной системы, для этого нужно перейти в корень репозитория, и собрать её:

Файловая система собирается достаточно долгое время, да и места на диске требует около 20Gb. После компиляции самой файловой системы, нужно получить архив, в который войдут все необходимые файлы.

После окончания сборки архива, мы получаем файл footfs.tar.bz2, который находится в директории out: /home/ubuntu/Adroid/source/out/target/product/beagleboard/rootfs.tar.bz2, и собственно содержит файловую систему Android. Тут находятся все системные файлы, приложения, и утилиты входящие в состав операционной системы.

Конфигурирование системы

Сам процесс конфигурирования достаточно прост, а для упрощения, воспользуемся Rowboat Tools от Texas Instruments. Нам понадобится файл конфигурации загрузчика boot.scr, который содержит настройки переменных загрузчика.
Скачиваем и распаковываем непосредственно сам Rowboat Tools:

Для нас, сейчас интересен файл mkbootscr, который находится в каталоге RowboatTools-JB/am37x/mk-bootscr. Если заглянуть внутрь файла, то можно найти подобные строки:

Это и есть установка переменных загрузчика, т.е. например нам нужно установить разрешение экрана отличным от «по умолчанию», значит мы должны изменить значение dvi:1024×768-16, и выполнить mkbootscr. В результате мы получаем файл boot.scr с нашими новыми настройками. Менять сразу boot.scr не выйдет, потому что он несёт информацию о контрольной сумме, которая, конечно же, должна совпадать с размером самого файла.

Установка и загрузка

Сама плата, как в принципе и большинство устройств на ARM контроллерах могут загрузиться с NAND памяти, SD/MMC или USB/RS-232. В нашем случае, мы будем загружаться с MMC. Во первых этот безопаснее чем прошивка NAND памяти, а во вторых, на мой взгляд, просто удобнее особенно в демонстрационных целях.
И так, нам понадобится MMC, желательно от 2 до 8 Gb. Подключаем MMC к Linux машине, и подготавливаем файловую систему.
Загрузочный MMC диск должен содержать минимум два раздела. Первый FAT16 назовём его boot, с которого собственно и будет происходить загрузка u-boot и ядра операционной системы, и второй Ext4, на котором будет находится наша файловая система, назовём его rootfs.
Для упрощения создания файловой системы, я подготовил маленький bash скрипт, просто для удобства пользования. Если контроллер не найдёт загрузочный сектор, наша платформа просто не сможет загрузится.

Источник

Оцените статью