Uboot android что это

Android, из чего состоит прошивка ROM

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

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

Каждая ее ячейка состояла из небольшого кольца, выполненного из специального материала – феррита, который легко намагничивается. И в каждое кольцо продевалось две петельки провода, предназначенные для записи (намагничивания), стирания (размагничивания) и считывания информации из этого кольца. А информации в нем хранилось всего лишь один бит: 0 – когда кольцо размагничено и 1, когда намагничено. Знаете, сколько таких колец нужно, чтобы обеспечить устройству 1 гигабайт встроенной памяти? Я вам скажу: всего лишь 8 589 934 592 штуки.

И вот процесс продевания проводов в эти кольца при изготовлении постоянной памяти для старых устройств так и назывался – прошивка.

А теперь вернемся к нашим планшетам и смартфонам. Они, как и любой современный компьютер работают под управлением операционной системы (Windows, Linux, iOS, Android и т.п), которая полностью отвечает за их работу. Иными словами, если внутреннее железо компьютера – это его мозг, то операционная система – это его сознание, которое управляет компьютером.

Без операционной системы любой компьютер, планшет или смартфон – набор мертвого железа. И если на компьютер, операционную систему мы устанавливаем, записывая ее на его жесткий диск, то в планшете или смартфоне операционная система хранится в его внутренней памяти, занимая часть тех 4, 8, 16, 32 или даже 64 гигабайт, которые имеют современные устройства.

Вы наверное уже догадались, что именно эта процедура «установки» операционной системы на планшет или смартфон и называется прошивкой, поскольку система записывается (прошивается) в его постоянную, внутреннюю память.

Теперь вы понимаете, что выражение «сменить пошивку» на планшете или телефоне означает примерно то же самое, что «переустановить Виндовс» на компьютере.

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

1. Официальные, выпущенные производителем устройства, которые или автоматически загружаются на планшет или телефон через интернет подключение (так называемые прошивки по «воздуху»). Их также чаще всего можно скачать на планшет с сайта производителя и установить вручную. Этот тип прошивок еще часто называют обновлением системы.

2. Самодельные прошивки, их еще называют «кастомные» или «альтернативные». Обычно это улучшенные или доработанные независимыми разработчиками официальные прошивки. К ним также относятся прошивки основанные на официальных версиях «чистой» операционной системы Android от компании Google, такие как CyanogenMod или MIUI.

Рассмотрим состав прошивки , на примере состава прошивки от ZTE , в принципе она с небольшими изменениями идентична на всех Android устройствах

0.25 Мб.) — предзагрузчик. Обеспечивает связь телефона с FlashTool-ом в «режиме USB» для прошивки, а также обеспечивает запуск устройства. Предположительно грузит в оперативную память uboot и передаёт ему управление.
dsp_bl (

0.75 Мб.) — Малоизвестная вещь. Судя по названию микропрограмма процессора. Порча его превращает телефон в планшет без комуникаций. Какими потом прошивками не прошивай телефон беспроводные сети работать не будут. Решение: прошить рабочий dsp_bl. (Только MT65x3, MT65x5, MT65x7!)
nvram (

3.0 Мб.) — хранит калибровки железок, IMEI, MAC-адреса BT и WIFI и другое. Точка монтирования /data/nvram.
seccnfg (

0,125Мб.) — неизвестная штука, обычно содержит только пустоту «FF FF. «.
uboot (

0.375 Мб.) — загрузчик операционной системы + драйверы для инициализации основного оборудования (дисплей, процессор, GPIO).
boot (

6.0 Мб.) — ядро и драйверы операционной системы (камеры, датчики, сенсоры). Точка монтирования /.
recovery (

6.0 Мб.) — минисистема (система в ядре) функцией которой является только резервирование/восстановление приложений системы, сброс до заводских установок. В расширенном recovery функционал конечно же намного богаче.
secstatic (

1.156 Мб.) — sec_ro , зачем нужно не понятно, при стирании на Android 2.2.1 и 2.3.5 ничего не происходит. На Android 2.2.2 (преимущественно у Fly-ying) этот раздел занимает хороший кусок ROM и в нём находятся службы Google. Точка монтирования /system/secro. Файловая система yaffs2.
misc (

Читайте также:  Миллионер кто хочет стать миллионером для андроид

0.375 Мб.) — неизвестная штука, обычно содержит только пустоту «FF FF. «.
logo (

3.0 Мб.) — Первая картинка при включении, картинка зарядки. На 95% содержит только пустоту «FF FF. «.
expdb (

0.65 Мб.) — неизвестная штука, обычно содержит только пустоту «FF FF. «.
system (

160-210 Мб.) — системный раздел Android. Тут всё что относится к функционированию аппарата, от «морды» до поддерживаемых функций операционной системы. Всё, что здесь изменяется не подлежит востановлению заводским сбросом. Точка монтирования /system. Файловая система yaffs2.
cache (

62.0 Мб.) — раздел для расположения временных файлов. Обычно используется приложениями («Маркет», «ROM Manager» . ). При утрате содержимого раздела функционирование системы не пострадает. Неверное же содержимое может привести к зависанию при загрузке устройства. Полностью стирается при заводском сбросе. Точка монтирования /cache. Файловая система yaffs2.
userdata (

220-290 Мб.) — data, это раздел для установки программ календарей, телефонок, профилей, настроек различных программ и системы. При утрате содержимого раздела обычно* функционирование системы не страдает. Неверное же содержимое может привести к зависанию при загрузке устройства. Полностью стирается при заводском сбросе. Точка монтирования /data. Файловая система yaffs2.

Источник

Искусство шаманства или кастомная прошивка для Olinuxino. UBOOT Часть 2

Все это собиралось из под Ubuntu 16.04.

Решение собрать прошивку родилось из за отсутствия в свободном доступе образа для этой платы (Olimex A13-Olinuxino). А производитель предлагал преобрести SD карту с образом и стоило что то около 10 евро на тот момент, что очень не устроило, к тому же она была рассчитана на наличие монитора.

Конфигурирование загрузчика будем формировать для загрузки с SD карты. Поскольку NAND памяти на плате нету а все остальные варианты загрузки слегка кривоваты (у кого получиться собрать uboot для загрузки с USB носителя, пусть сделает два шага вперед и поделится). Алгоритм загрузки процессора allwinner a13 можно найти на сайте производителя. Или вот вырезка из даташита.

Из алгоритма хорошо видно что сначала идет проверка загрузчика на SD карте, потом все остальные и только в конце проверяется наличие загрузчика на USB. Поэтому планшеты и смартфоны вполне можно сделать с Ubuntu если им подсунуть SD карту с соответствующим образом. И судя по всему примерно такой алгоритм будет если не у всех, то у многих производителей arm процессоров.

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

Сборка UBOOT

Остановимся по подробней на загрузчике, а в качестве оного выбираем UBOOT выкачиваем версию u-boot-2018.05, последнюю на тот момент.

Предполагается что уже стоит весь необходимый софт для сборки. И начнем сборку с конфигурирования загрузчика.

Для запуска конфигурирования необходимо зайти в папку с UBOOT и из неё выполнить команду:

В результате выполнения получим такое окно.

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

А дальше если у вас много времени или вам себя не жалко, можно самим с нуля сконфигурировать загрузчик. Однако лучше через меню файл загрузить готовую конфигурацию этой платы. В папке с исходником загрузчика по адресу /u-boot-2018.05/configs/ выбираем файл A13-OlinuXino_defconfig это и есть наша конфигурация, где все уже установлено. Дальше нажимаем сохранить и закрываем окно, ибо менять тут ничего не нужно.

Остаётся запустить команду сборки:

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

После окончания сборки, в папке указанной в команде, нам нужно найти этот файл “u-boot-sunxi-with-spl.bin” это и есть нужный загрузчик.

Дальше для заливки загрузчика на SD карту воспользуемся командой:

Загрузчик что только что записали после загрузки укажет на следующий раздел SD карты /dev/sdb1, и там будет искать скрипт файл с переменными окружения в котором содержаться инструкции по дальнейшей загрузке.

Этот файл должен иметь имя boot.scr, файл с этим названием ищет uboot после своей загрузки. Название файла конечно можно изменить как и метод загрузки если влезть в конфигурацию UBOOT, но остановимся на этом варианте.

Читайте также:  Visual studio install android sdk

Также следует за одно скомпилировать devicetree файлы, они лежат в исходниках с загрузчиком по адресу /u-boot-2018.05/arch/arm/dts/ нас интересует файл sun5i-a13-olinuxino.dts. Он представляет собой конфигруацию регистров и переферии процессора. Этакий универсальный файл конфигурации, поэтому вполне возможен вариант когда один загрузчик uboot используется для разных процессоров но при этом используются разные файлы dts. Такие же файлы dts есть и в исходниках ядра линукса, они в принципе одинаковы только написанны немного по разному и откуда брать собранное дерево устройств это уже выбирать вам. В общем для сборки dts файлов нужно запустить эту команду:

Скомпилированный файл будет лежать по адресу ../olimex-uboot/arch/arm/dts/.
Рассмотрим подробней получение файла boot.scr.
Для начала создадим файл boot.cmd с содержимым:

Но для того чтоб uboot понял инструкции, этот файл должен быть в виде скрипта и для этого нужно запустить команду:

Где boot.scr необходимый файл.

Первая строка load mmc 0 0x43000000 sun5i-a13-olinuxino.dtb загружает файл дерева устройств по указанному адресу в оперативной памяти. load mmc 0 указывает что загружать нужно файл с первого раздела SD карты, при этом нумерация для uboot происходит нуля а не единицы.

Вторая строка load mmc 0 0x42000000 uImage загружает по указанному адресу собранное ядро линукса.

Для нашего варианта переменная setenv video-mode которая обычно дальше используется, нам не нужна так как монитор использовать не планируется.

Ну и последняя команда bootm загружает ядро с раннее загруженного в памяти.

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

Источник

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).

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

Читайте также:  Блокировки экрана miui для андроид

В случае нашей железки это выглядит следующим образом. Снова запускаем 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. Но это уже в других статьях.

Источник

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