Pull to refresh

Comments 52

Странно, что Cortex серии R отнесены к application-процессорам. Они всё-таки realtime-процессоры. У них нет mmu, вместо него используется memory protection unit. Ну, кроме процессоров архитектуры ARMv8-R, в которых ожидается и mmu и mpu (но на них ещё и документация-то не опубликована). Поэтому запуск linux на них хотя и возможен, мне не представляется целесообразным. Эти процессоры скорее подходят для RT OS, собственно для этого они и предназначены.
Да, абсолютно верно, просто на заданном уровне изложения это не сильно принципиально. Cortex-R достаточно редкий и на нем все равно запускаются довольно тяжелые ОС. Поэтому разбить на два класса проще.
Статья мне в целом нравится, но это вопросы терминологии. Для тех, кто с этим работает, статья ничего нового и не расскажет. А для тех, кто не в теме, но интересуется, может внести некоторую путаницу. Поэтому, на мой взгляд, осторожней надо с терминами.
По вопросу терминологии, хорошо было бы в статью добавить какие-то жизненные примеры: в статье используются только термины «предзагрузчик», «загрузчик», а в реальной жизни мы знаем про u-boot, xloader, preloader или какой нибудь isw_handoff.
Вот что из этого — что.
Про u-boot там написано. u-boot — это в данной схеме загрузчик ОС. Туда же идет, например, barebox.
Пример предзагрузчика: ну например, SAM-BA у Atmel Microchip. Это типичный ROM-код, который запускает внешнюю программу.

Может конечно я ошибаюсь, но когда sam-ba от atmel(microchip), стала предзагрузчиком? Для меня это по для прошивки, вы берете бинарь и льете его в ту область памяти которая Вам необходима (так же выбора интерфейса по которому льется бинарь), по поводу терминологии, вы сначала выставляете boot mode для камня, а уже по boot mode происходит переключение интерфейсов и после загрузчик первого уровня начинает, работать с тем boot mode который вы указали. Плюс sam-ba это спец пакет для заливки прошивок, так же все это можно делать и без sam-bы, можно же залить bare metal по через jtag. Такое по как sam-ba есть у многих производителей железа.
Точно, ошибка вышла. SAM-BA называется только программа для PC. А загрузчик называется Boot Program (например, на AT91SAM9G20). Не очень выразительно, вот я и перепутал.
Вот Boot Program — это как раз ROM предзагрузчик и есть.
Запуск Linux без MMU? Это как?
По поводу того, что архитектура ARM не позволяет включить L2 cache из Non-secure State. Давайте всё-таки будем точны в терминах: ARM-архитектура вообще не описывает кэш в терминах L1, L2 и тому подобных. Соответственно, архитектура и не может запрещать или разрешать включать или отключать кэш определённого уровня, это делается в документе на конкретную реализацию процессора. Например, в Cortex-A75 L2 кэш может включаться совсем не так, как это происходит в Cortex-A35, к примеру. А возможны и процессоры совсем без кэша.
В данном случае я говорил о процессорах Cortex-A, и эти процессоры без кеша представить сложно. Кеш-контроллеры, насколько я это видел на практике, предоставляются компанией ARM как компаньоны к их же ядрам. Вот, например, описание кеш-контроллера L2C-310, с которым довелось поработать: <infocenter.arm.com/help/topic/com.arm.doc.ddi0246h/DDI0246H_l2c310_r3p3_trm.pdf>. Вы можете ясно видеть, что он называется Level 2 Cache Controller. Вообще, архитектура кеша прописана в ARM, и в Cortex-A она сложная и красивая. Я бы сказал, сделана как надо. В приведенном документе Вы можете посмотреть раздел 2.3.5, там написано: «You can only write to the L2 Control Register with an access tagged as secure, to enable or disable the L2 cache». Это именно то, о чем я писал в статье.
Ещё раз: это документ на реализацию конкретного IP, а не на архитектуру. Согласен, архитектура кэша в ARM красивая. Только описывается она в терминах Instruction cache и Data cache, а так же Point of Unification, Point of Coherency и Point of Persistency (для ARMv8.1-A), но ни как не L1 и L2.
Ну давайте про архитектуру.

Возьмем, например, Cortex-A9 Technical Reference Manual. Открываем пункт 1.1 (About the Cortex-A9 processor) и читаем, что там написано.

Начинается абзац словами: «The Cortex-A9 processor is a high-performance, low-power, ARM macrocell with an L1 cache subsystem».

Дальше по тексту: «The following figure shows a Cortex-A9 uniprocessor in a design with a PL390 Interrupt Controller and an L2C-310 L2 Cache Controller.»
Вот вам и L1 cache и L2 cache и даже ссылка на контроллер кеша в описании архитектуры.

Если этого мало, то посмотрите ARMv7-A and ARMv7-R Architecture reference manual (ARM DDI 0406C.c), раздел A.3.9.2.
Cortex-A9 technical reference manual — это документ *на конкретную реализацию* процессора архитектуры ARMv7-A. Архитектурный документ называется «ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition». И если вы говорите об архитектуре, значит говорите именно в терминах этого документа.
Ну давайте тогда вспомним, что статья обзорная.
А что касается указанного вами документа, так посмотрите там раздел A.3.9.2.
Если по существу, то Non-secure OS даже не должна специально дёргать TEE. TEE может на старте правильно настроить таймер и контроллер прерываний (он в ARM тоже няшка) и периодически получать управление. Non-secure OS даже не заметит (-:
Согласен! Это может сработать, если ОС не будет полагаться на этот таймер.
В ARMv8 есть Secure Timer, который недоступен для OS (-:
Спасибо за статью, но Вы не совсем корректно описали этапы загрузки MPU, см. free-electrons.com/doc/training/embedded-linux/embedded-linux-slides.pdf (стр. 95-97), процесс запуска может отличатся от камня к камня, плюс доверенная загрузка может быть когда у Вас на борту soc(cortex A + M), тогда у Вас 2 камня, MCU общается MPU с через внутр. адреса и шины, тогда cortex M проверяет легальность данных и после разрешает запуск, чем не вариант?
Да, отличный вариант, если есть два ядра. При этом доверенная загрузка все равно должна опираться на аппаратный блок контроля загружаемого образа. Если MPU (я так понял, вы имеете в виду Cortex-M сопроцессор) будет загружен недоверенно, то и MCU будет загружен так же.

Что касается этапов загрузки в этой презентации — вы имеете в виду этап с bootstrap? Да, он чаще всего присутствует в том или ином виде. Но собирается он обычно в составе основного загрузчика, не так ли? Например, для Sitara u-boot собирает MLO. То есть, это просто деление на два бинарных образа. Я просто не хочу загружать статью такими подробностями.

Если это действительно интересно, напишу отдельно.
Да, будет не одновременный запуск, MCU-микроконтроллеры cortex M, MPU-микропроцессоры cortex A(для данного контекста). Да именно не было упоминания bootstrap (mlo, at91bootstrap и т.п.), bootstrap можно отдельно собирать, если производитель предоставляет исходники. Плюс с помощью soc можно контролировать работу cortex-A(linux) на каждом шаге работы, уйдя например от smp в сторону amp(openamp, mcapi и т.д.) можно гарантировать безопасность системы, тогда сложно будет нарушить работу системы в целом.
Супер! Как раз недавно думал что тема ОС умерла, а тут неплохая статья! Спасибо автору!
UFO just landed and posted this here
Это скорее всего делает загрузчик ОС.
То, что не предзагрузчик — понятно, потому что на этом этапе еще неизвестна подключенная периферия.
А вот загрузчик уже может быть кастомизирован. Запускается, опрашивает статус батареи (по I2C, например) и подключено ли внешнее питание. Если батарея села и питание не подключено, то выключается или засыпает. Просыпается, когда включаем зарядное устройство, инициализирует видеоподсистему, рисует картинку и спит дальше. По таймеру через некоторое время гасит экран. В этом режиме он почти не потребляет энергии и не мешает заряду аккумулятора. То есть, такая простая программа.
Запускается boot-образ, в котором лежит ядро и init-скрипт. Ядро получает состояние телефона в режиме «не грузимся, только usb, только зарядка» и рисует картинку. на мтк, как вариант, стартует boot_logo_updater
Можно и так и так, конечно. И сложно спорить с наличием той или иной реализации, в том числе в MTK.

Если бы я реализовывал такую функцию, я бы делал на уровне загрузчика. Поясню.

Если мы уже загрузили ядро Linux/android, оно спит с гораздо большими затратами энергии, потому что запускает разную периферию, потом частично отключается. Может банально не догрузиться. Потребует времени для старта. Я не слышал о таком варианте загрузки ядра, как «не грузимся, только зарядка», но наверное все можно сделать, адаптируя ядро под себя. Но это уже будет ближе к грязному хаку.

В то же время, в загрузчике это сделать совсем не сложно. Если устраивает u-boot, то тут у вас есть и графика, и много драйверов, в т.ч. драйвер батареи, питания. Можно дописать свой драйвер контроля батареи и это не будет хаком, все в ложится в архитектуру. Далее, на уровне boot-скрипта можно запустить маленькую программу, которая покажет экран зарядки или внедрить этот код в свой вариант u-boot. В любом случае, это менее травматичный способ.
Ну возможно вы правы, в плане сложностей оно может того не стоить.
Просто мне нужен по суть MK, как числодробилка, а лучше с DSP модулем, внешней периферии посути минимум, несколько i2, i2s и дисплей не большой. Может Вы посоветуете что-то более верное?
На данный момент ковыряю stm32F407, но уже вижу что его производительности совсем впритык.
Но халявные чипы MT 6xxx конечно очень прельщают)
Если stm32F407 впритык, то посоветовать сложно. Типовой ARM926 может будет быстрее вашей STM-ки всего в пару раз. На перспективу развития проекта может хватить или не хватить.
С другой стороны, есть большой выбор из Cortex-A с частотой 0.5-1ГГц и даже с несколькими ядрами, но без Linux там будет сложно запускаться.
Даже ARM926 — это уже ненужное усложнение проекта, если он живет нормально на STM32. Сейчас есть выбор из MCU на Cortex-M7, может туда посмотреть?
В принципе могу, но мне показалось они не слишком выше M4 (168 против 216мгц, возможно сама архитектура более шустрая)
Периферии там правда… можно 5 прибором моих на одном МК сделать.
Усеченную версию Linux также можно загрузить на ARM7

Полноценный линукс вполне себе комфортно жил на strongarmах.
Linux можно запустить и на m68k. Жаль, нет у меня такого железа :)
Очень интересная статья, спасибо, и назрел такой вот вопрос, возможно косвенный, но все же.
А насколько возможно использовать в bare-metal, процессоры ARM которые скажем стояли в средствах коммуникации? Ну вот чисто потенциально…
Ведь сами по себе они достаточно мощные, плюс aliexpress как кладезь в плане их доступности.
Вот на данный момент имею:
MT6235, MT6575, есть документация на само железо, есть u-boot — с чего так сказать начать, имею ввиду стратегически, ковырял u-boot но пока ничего интересного не нашел (по крайней мере то что вы описали)
Спасибо за добрые слова!
Под bare-metal вы подразумеваете использование без большой операционки? Нет ничего невозможного.
Можно начать с u-boot, посмотреть, как он работает. Далее, с u-boot можно запустить свою маленькую RTOS или программу. Только, если запускаете RTOS, то надо пускать ее как Linux, командой bootz, а не bootm, в этом случае u-boot выключит MMU, cache и т.п.
Потом, посмотрев на u-boot, можно загрузить свой софт и без него. Если повезет, бывают и bare-metal примеры программ, и порты RTOS на конкретный процессор.

Если выбирать между перечисленными вами, я бы начал с MT6235, потому что он ARM926EJ-S. По своему опыту могу сказать, что эта архитектура для таких применений удобнее, там все значительно проще.
Вообще Cortex-A не очень удобен для работы на голом железе, хотя мы и работаем на нем. Суммарный объем документации раз в 10-20 больше, чем у ARM926. Усилий по включению разных блоков, шин, настройке PLL, частот, MMU, кешей, питания, сброса будет больше.
При этом предзагрузчик – небольшая программа, с размером кода порядка нескольких десятков килобайт, и сложно представить размещение в нем полных стеков протоколов или серьезной эвристики по определению подключенных устройств

Это вы зря так. Raspberry Pi 3, например, позволяет загружаться по сети с помощью Ethernet-адаптера. Подозреваю, что это как раз средствами предзагрузчика и делается.

Да, в Raspberry Pi 3 это делается средствами предзагрузчика. Там загрузка по Ethernet, протоколы TFTP и DHCP, оба не слишком тяжелые. Вполне можно написать код под ARM, вмещающий эти протоколы и LwIP или uIP, который влезет и в 64k.

Вот когда Raspberry Pi будет из предзагрузчика грузиться по WiFi — это будет сложный стек протоколов…

Для большинства простых задач вовсе не нужно реализовывать весь стек протоколов, достаточно научиться парсить пакеты нужного типа и отправлять/принимать их с помощью устройства. Так что, подозреваю, что и загрузку по WiFi можно было бы сделать. И вообще, 64к это очень много. Нужно потратить довольно много часов своей жизни чтобы написать столько низкоуровневого кода.

То, что вы говорите про парсинг пакетов — это как раз работает хорошо с Ethernet.

С WiFi нет однозначности. Разные сети, логин, пароль, частоты в разных странах. С Ethernet/DHCP/TFTP этого нет. Плюс криптография и довольно сложный протокол, все же.

Насчет низкоуровневого кода — если не на ассемблере, то 64к довольно быстро забиваются.

Ужасно, и как только людям удаётся умещать это всё в ESP8266 и всякие WiFi-шилды для Arduino? Нет там ничего сложного, ну будет у вас кода условно в два раза больше, чем для Ethernet, ну и всё. Та же крипта вообще уместилась в загрузчик на ESP, там даже поддержка SSL есть в каком-то виде.

Ну что спорить… Я же и говорил, что предзагрузчик — простая программа.
Кстати, минимальный размер Flash, с которой ESP8266 будет работать — 512к…

А по поводу WiFi — в Raspberry разве процессор со встроенным радиомодулем? Нет? Тогда велкам поддерживать все варианты подключения внешнего радиомодуля и все варианты самих модулей. То есть — и варианты подключения по SDIO к разным портам, и всякие SPI. Посмотрите на вполне классический bcm4330, сколько там нужно подключений.
Речь идет ведь о включении в масочный ROM, который должен подходить максимально для всех. Если это ESP8266, то там все понятно, из чипа торчит уже антенна. А если мы говорим о MPU/MCU общего применения, то это далеко не так.
А по поводу WiFi — в Raspberry разве процессор со встроенным радиомодулем? Нет? Тогда велкам поддерживать все варианты подключения внешнего радиомодуля и все варианты самих модулей.

И встроенного Ethernet-модуля на Raspberry Pi 3 тоже нет. Он подключен по USB, хоть и распаян на плате. Но это же не помешало реализовать поддержку этого модуля?


Речь идет ведь о включении в масочный ROM, который должен подходить максимально для всех.

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

Да, создатели малинки молодцы. Я не хочу даже с этим спорить. И не хочу провоцировать вас на спор.
Просто скажите, сколько примерно, по вашему опыту, стоит заказать у Broadcom чип типа BCM2837 с нужным содержимым масочного ROM? Просто у меня есть свой опыт в этом вопросе, хочу сравнить.

Не люблю вот этих смелых предположений, основанных ни на чём, так что не могу ответить на этот вопрос. Могу только сказать, что профит масочного ROM в том, что для изготовления вариации чипа нужно переделать одну (или несколько, для сложных тех.процессов) маску, что значительно дешевле переделывания всех масок. А для вариаций EPROM так вообще ничего переделывать не нужно (ну, кроме прошивки).


И да, про масочный ROM в BCM2837 сказали вы, а не я. Есть ли какие-нибудь подтверждения этому?

UFO just landed and posted this here
Спасибо, вот это ценно! Малинка огонь, рвет шаблоны…
У вас информация уже устарела на 5 лет

Prior to 19th October 2012, there was previously also a third stage bootloader (loader.bin) but this is no longer required.
Эксплойт TrustZone

USENIX Security '17 — CLKSCREW: Exposing the Perils of Security-Oblivious Energy Management www.youtube.com/watch?v=vI3GRCgThxE

www.usenix.org/conference/usenixsecurity17/technical-sessions/presentation/tang

CLKSCREW: Exposing the perils of security-oblivious energy management blog.acolyer.org/2017/09/21/clkscrew-exposing-the-perils-of-security-oblivious-energy-management

Example attack: loading self-signed apps
In section 5 of the paper the authors show how CLKSCREW can subvert RSA signature chain verification used in loading firmware images into Trustzone.
Эту атаку можно использовать не только для TrustZone. Просто TrustZone в действительности довольно классно защищает доверенную зону и поэтому атаковать TrustZone — это очень эффектно. Еще уместно вспомнить Row Hammer.

Вообще, это вопрос модели угроз и дефект дизайна устройства, а не TrustZone, как технологии. Как раз TZ позволяет ограничить доступ почти к любым устройствам из Normal World. Поэтому, будь в модели угроз устройства предположение о манипуляции рабочей точкой CPU (напряжение, частота), эта атака легко была бы предотвращена. То есть, закрываем от Normal World эту функциональность и делаем вызов TEE для этой операции. Linux/Android будет вызывать TEE для изменения режима, что при нормальном функционировании не будет влиять на производительность. А на момент, когда TEE что-то вычисляет, вызовы по изменению рабочей точки будут задерживаться или блокироваться. Можно еще ограничить частоту вызовов или выполнять их со случайной задержкой.

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

Но в любом случае, все тайное становится явным, и в TrustZone не стоит хранить, конечно, самый главный ключ, который нельзя знать никому. Рано или поздно девайс подключат к внешним источникам питания, генераторам частоты, нагреют, охладят, просверлят отверстия, придумают еще одну атаку и достанут ключик. Поэтому наши регуляторы очень мудро ограничивают сроки жизни ключей в устройствах 1-3 годами, в зависимости от применения.
Андрей!
Спасибо за статью! Наконец-то я осмыслил что собой являет TrustZone.
Sign up to leave a comment.