Как загружается система на ARM на примере android.

Начнем с простого упоминания, о том, что чип выполненный по архитектуре ARM - это система на чипе (SoC). То есть это полный компьютер, реализован- ный на одной микросхеме. На процессорах данной архитектуры изготавли- вается множество устройств (рутеры, свичи, встроенные компьютеры в телевизорах, игровые портативные консоли и т.д. и т.п.).

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


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

Итак, перейдем непосредственно к описанию загрузки данного типа устройств. Практически каждый ARM процессор имеет встроенную на чип flash-память, в которую помещается т.н. загрузчик. В случае отсутствия на чипе такой памяти, или неиспользования ее в качестве пространства для размещения загрузчика, чип обычно обращается для запуска этого загрузчика к NOR-flash по строго определенному адресу.

Самих загрузчиков существует несколько. Ряд из них - коммерческие. Но есть и загрузчик с открытым исходным кодом - u-boot. К сожалению, при открытости кода он содержит процессоро-зависимый код, поэтому без спецификаций процессора не может быть просто портирован (адаптирован) на процессор, который не имеет открытой документации.

Теперь опишем, что же обычно делает загрузчик после его запуска. Довольно прямая аналогия может быть проведена с BIOS компьютеров на базе процессоров х86 (те с основной массой персоналок). Загрузчик ARM при запуске точно так же выполняет рад низкоуровневых инициализаций аппаратной части устройства (оперативная память, хранилища данных, сетевой адаптер и т.д. и т.п.). После инициализации последовательного порта (обычно в формате RS232, но с уровнями 3.2 вольт) появляется возможность работы с ним через консоль инициализированной на этом порту.

Выглядит это так

console

Посредством этой консоли можно выполнить практически полную настройку или перенастройку нашей железки. Например, чтобы загрузить читый Linux, нам как минимум необходимо будет перенастроить строку параметров передаваемых ядру при загрузке (при умолчальной настройке на загрузку android). Так же там можно полностью работать и с разделами нанда - стирать, разбивать, изменять, защищать от записи и наоборот и т.д. и т.п. (дабы избежать дополнительных вопросов об изменении разделов нанда). Еще в консоли можно загружать и выполнять некоторый софт. Все настройки, выполненные в этой консоли, могут быть сохранены и использоваться как настройки по умолчанию при загрузке устройства.

Сделаем небольшое отступление. Кроме NOR-flash для размещения загрузчика, в ряде случаев, может быть использован NAND-flash или даже SD-card. Кроме того, возможно использование комбинаций этих типов флеш памяти в устройстве. Например загрузчик может быть размещен в NOR, а в качестве внутреннего накопителя (для размещения OS) NAND или SD и т.п.

Итак, мы включили железку. Она загрузила загрузчик. Загрузчик проинициализировал оборудование. По окончанию этой инициализации загрузчик выполняет следующую процедуру:

1 - считывание и размещение в оперативной памяти образа ядра и рамдиска - оба по строго определенным адресам (может быть настроено в командной строке u-boot).

2 - запуск ядра с правильной точки входа, с указанием ему, где брать внешний рамдиск (initrd) с корневой файловой системой и что использовать в качестве init.

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

Дальнейшая загрузка мало отличается от загрузки Linux на обычном компьютере. Загрузившись, ядро выполняет указанный ему init (это просто еще одна программа). Настройка init осуществляется в файле init.rc, который расположен в рамдиске. В нем производится настройка переменных среды, монтирование дисковых устройств, запуск необходимых служб и т.д и т.п. По окончанию выполнения инструкций предзапуска из init.rc запускается собственно сам андроид. Вид запуска андроида обусловен параметром запуска ядра androidboot. Стандартный запуск андроид выполняется в целом посредством передачи параметров использования нужного рамдиска (в ramdisk.img) и параметра androidboot.normal. Для запуска режима восстановления, как правило, используется другой рамдиск, содержащий программу recovery (в recovery.img) и параметр ядра androidboot.recovery.

Как вариация ядра Linux для андроида могут быть собраны не с поддержкой initrd (корневая система на рамдиске), а с т.н. initramfs. В этом случае вся корневая файловая система будет расположена просто внутри ядра. В этом случае для режима восстановления нужно, как правило, второе ядро с корневой файловой системой содержащей программу recovery. И настройка загрузчика просто на загрузку и выполнение recovery ядра.

И как итог, простая схема:

Запуск процессора -> запуск загрузчика -> инициализация железа -> считывание из нанда ядра и рамдиска -> запуск ядра с использованием этого рамдиска -> выполнение программы init -> запуск собственно android.

Подробно о u-boot и его командах можно прочитать например на этом вики _http://www.denx.de/wiki/view/DULG/Manual.

Если вам мало этой информации, то подробнее про параметры запуска ядра Linux можно прочитать в Documentation/kernel-parameters.txt из архива его исходных кодов. Или найти этот файл в интернете для нужной вам версии ядра. Но не забывайте учитывать упомянутую выше специфику Android.

Автор: _Barsuk_

Популярное прошлых лет