Поддавшись общей волне энтузиазма относительно систем «Умный дом», а также имея профильное образование инженера АСУ ТП, с удовольствием занимаюсь данной темой в виде хобби. В этой статье поделюсь с вами своим опытом реверс-инжиниринга популярного модуля ESP8266.
![](https://habrastorage.org/r/w1560/files/58b/045/331/58b045331d9d43f99a8d2e8811508cc1.png)
В основном меня интересовали внутреннее устройство SoC, архитектура и система команд процессора, процедура старта и загрузки прошивки и другие не менее интересные вещи. Начав изучение данного модуля, я столкнулся с тем, что нужной информации по нему не много, и зачастую она достаточно противоречива. Поэтому многое приходилось перепроверять, что-то выяснять опытным путем, а о чем-то просто догадываться. Буду рад вашим комментариям и дополнениям.
Чтобы систематизировать всю полученную информацию и была написана эта статья.
Не буду приводить технические характеристики, про это уже много написано, в том числе и на Хабре. Желающие могут ознакомиться, например, здесь.
![](https://habrastorage.org/r/w1560/files/ec0/ba9/119/ec0ba91196d941ab97ffa89a29ab280f.png)
Начнем с общей архитектуры системы. Модуль представляет собой Soc, в основе которого лежит процессор семейства Xtensa – Tensilica’s L106 Diamond series производства американской компании Cadence, а также микросхему флеш-памяти на 512кБ. Сам модуль разработан китайской компанией Espressif Systems. Таким образом, основная официальная информация по ESP8266 поступает от Espressif (на китайском языке и в переводе), а некоторые общие данные можно получать от Cadence.
Особенностью данного семейства процессоров является то, что они представляют собой конструктор, из которого заказчик с помощью предлагаемого инструмента Xtensa Processor Generator может собрать чип с нужными ему характеристиками и заказать его у производителя. Поэтому различные модификации могут сильно отличаться, например, количеством ядер, дополнительными инструкциями, модулями DSP и так далее.
Как я уже говорил выше, модель состоит из flash ROM размером 512 КБ и SoC, который, по неподтвержденным данным имеет RAM до 248 КБ.
Вообще все, что касается памяти – расположения, свойств и атрибутов сегментов – это изыскания сообщества. В оригинальной китайской документации этот вопрос почему-то обойден стороной.
Один из вариантов (имеются противоречия с другими источниками) известной на сегодняшний день карты памяти можно посмотреть здесь. Приведу лишь наиболее интересные адреса:
Внутренняя память:
Различные сегменты адресного пространства могут быть RAM, ROM или подмаплены непосредственно к flash. Подмапленные области кэшируются для скорости работы.
Flash:
Теперь, перед тем, как перейти к процессу запуска модуля, рассмотрим формат прошивки. Для загрузки пользовательской прошивки обычно достаточно записать 2 блока данных: по адресу 00000h и 40000h. Остальные блоки могут потребовать перепрошивки для сброса конфигурации, например, при заливке новой прошивки с несовместимым форматом данных.
Блок, начинающийся с 40000h содержит простой бинарный код, который загружается и работает в неизменном виде. А вот блок, начинающийся с 00000h, представляет собой структурированные данные о находящихся в нем сегментах и выглядит следующим образом:
Структура сегмента:
Завершающий блок:
Заполнен нулями для выравнивания до границы 16 байт минус 1 байт. После этого добавляется последний байт, представляющий собой контрольную сумму данных всех сегментов, вычисляемая функцией xor над всеми байтами и константой `0xEF`.
Формат прошивки взят из описания к утилите esptool.
Теперь, вооружившись этими знаниями, рассмотрим процесс старта модуля ESP8266 с точки зрения инициализации и запуска прошивки.
При подаче питания или поступлении сигнала сброса процессор начинает выполнение инструкций с адреса 40000080h (системный ROM). По адресу 40001308h располагается процедура, которая считывает блок 00000h flash и копирует сегменты, хранящиеся в ней по заданным адресам.
![](https://habrastorage.org/r/w1560/files/1f7/03b/c22/1f703bc2284440fcbbb933746288ea4b.png)
На схеме этот процесс показан фиолетовым цветом. Здесь видно, что часть прошивки является исполняемым кодом, а часть инициализирует данные в ОЗУ. Зеленым обозначен блок, напрямую подмапленный в адресное пространство процессора.
После всех инициализаций управление передается по адресу, указанному в заголовке прошивки. Обычно это адрес пользовательского кода 40100000h.
Что ж, теперь, когда мы разобрались с архитектурой и процедурой старта модуля ESP8266, давайте перейдем к изучению его программного кода. Какие ресурсы и инструменты у нас есть для этого?
Для проектирования, разработки и отладки продуктов на базе SoC Xtensa существует пакет Xtensa Xplorer от производителя процессора, в состав которого входит множество утилит, включая TurboXIM – симулятор SoC. Теоретически, эта утилита могла бы быть полезной, но даже бесплатная версия требует лицензионных ключей, выдаваемых по запросу. Написав такой запрос я не получил ответа, поэтому воспользоваться симулятором не удалось. Скачать весь набор инструментов можно здесь, возможно, вам повезет больше.
Для разработки, сборки прошивок и выгрузки отладочной информации нам будет полезно развернуть среду разработки, как описано здесь.
Из традиционных инструментов воспользуемся IDA Pro и HIEW.
Для изучения кода процессора Xtensa необходимо использовать IDA Pro версии 6.6 и выше со встроенным интерпретатором питона для выполнения скриптов. В перечень стандартно поддерживаемых процессоров Xtensa не входит, поэтому каждый раз при запуске IDA Pro перед открытием исследуемого файла необходимо загружать скрипт “xtensa.py”, который можно взять здесь.
Также для автоматического создания сегментов и наименования функций системного ROM нам понадобится скрипт для IDA Pro. Скрипт и дамп системной прошивки можно скачать здесь.
HIEW будет полезен для исследования структуры ELF- и готовых двоичных файлов прошивки.
В следующей части мы рассмотрим процесс загрузки прошивки для исследования.
Update. Продолжение здесь.
![](https://habrastorage.org/files/58b/045/331/58b045331d9d43f99a8d2e8811508cc1.png)
Содержание
- Введение
- Архитектура ESP8266
- Инструменты
- Загрузка прошивки для исследования
- ELF
- Системная прошивка модуля
- Пользовательская прошивка
- Ассемблер Xtensa
- Регистры
- Базовые операторы
- Функции
- Условные переходы
- Заключение
- Ссылки
1. Введение
В основном меня интересовали внутреннее устройство SoC, архитектура и система команд процессора, процедура старта и загрузки прошивки и другие не менее интересные вещи. Начав изучение данного модуля, я столкнулся с тем, что нужной информации по нему не много, и зачастую она достаточно противоречива. Поэтому многое приходилось перепроверять, что-то выяснять опытным путем, а о чем-то просто догадываться. Буду рад вашим комментариям и дополнениям.
Чтобы систематизировать всю полученную информацию и была написана эта статья.
2. Архитектура ESP8266
Не буду приводить технические характеристики, про это уже много написано, в том числе и на Хабре. Желающие могут ознакомиться, например, здесь.
![](https://habrastorage.org/files/ec0/ba9/119/ec0ba91196d941ab97ffa89a29ab280f.png)
Начнем с общей архитектуры системы. Модуль представляет собой Soc, в основе которого лежит процессор семейства Xtensa – Tensilica’s L106 Diamond series производства американской компании Cadence, а также микросхему флеш-памяти на 512кБ. Сам модуль разработан китайской компанией Espressif Systems. Таким образом, основная официальная информация по ESP8266 поступает от Espressif (на китайском языке и в переводе), а некоторые общие данные можно получать от Cadence.
Особенностью данного семейства процессоров является то, что они представляют собой конструктор, из которого заказчик с помощью предлагаемого инструмента Xtensa Processor Generator может собрать чип с нужными ему характеристиками и заказать его у производителя. Поэтому различные модификации могут сильно отличаться, например, количеством ядер, дополнительными инструкциями, модулями DSP и так далее.
Карта памяти (адресного пространства)
Как я уже говорил выше, модель состоит из flash ROM размером 512 КБ и SoC, который, по неподтвержденным данным имеет RAM до 248 КБ.
Вообще все, что касается памяти – расположения, свойств и атрибутов сегментов – это изыскания сообщества. В оригинальной китайской документации этот вопрос почему-то обойден стороной.
Один из вариантов (имеются противоречия с другими источниками) известной на сегодняшний день карты памяти можно посмотреть здесь. Приведу лишь наиболее интересные адреса:
Внутренняя память:
Диапазон | Описание |
---|---|
3FFE8000h — 3FFFBFFFh | оперативная память для пользовательских приложений. При старте модуля может инициализироваться значениями из пользовательской прошивки. |
3FFFC000h — 3FFFFFFFh | системная оперативная память |
40000000h — 4000FFFFh | системный ROM. Отсюда стартует процессор, загружается пользовательская прошивка и здесь находятся основные системные библиотеки. |
40100000h — 4010FFFFh | оперативная память, содержит пользовательскую прошивку |
40240000h — 40271FFFh | вторая часть пользовательской прошивки. Здесь находятся код подключенных библиотек и SDK. Подмаплено к flash по адресу 40000h. |
Различные сегменты адресного пространства могут быть RAM, ROM или подмаплены непосредственно к flash. Подмапленные области кэшируются для скорости работы.
Flash:
Диапазон | Описание |
---|---|
00000h — 3DFFFh | адрес загрузки пользовательской прошивки |
40000h — 7BFFFh | адрес загрузки библиотек SDK (также может являться частью пользовательской прошивки) |
Формат прошивки
Теперь, перед тем, как перейти к процессу запуска модуля, рассмотрим формат прошивки. Для загрузки пользовательской прошивки обычно достаточно записать 2 блока данных: по адресу 00000h и 40000h. Остальные блоки могут потребовать перепрошивки для сброса конфигурации, например, при заливке новой прошивки с несовместимым форматом данных.
Блок, начинающийся с 40000h содержит простой бинарный код, который загружается и работает в неизменном виде. А вот блок, начинающийся с 00000h, представляет собой структурированные данные о находящихся в нем сегментах и выглядит следующим образом:
Смещение | Описание |
---|---|
0 | идентификатор прошивки, всегда `0xE9` |
1 | количество сегментов в прошивке |
2,3 | параметры SPI Flash |
4-7 | адрес запуска прошивки (Entry Point) |
8... | далее идут данные сегментов |
Структура сегмента:
Смещение | Описание |
---|---|
0-3 | адрес для загрузки сегмента |
4-7 | размер сегмента |
8... | далее идут данные сегмента |
Завершающий блок:
Заполнен нулями для выравнивания до границы 16 байт минус 1 байт. После этого добавляется последний байт, представляющий собой контрольную сумму данных всех сегментов, вычисляемая функцией xor над всеми байтами и константой `0xEF`.
Формат прошивки взят из описания к утилите esptool.
Процесс запуска
Теперь, вооружившись этими знаниями, рассмотрим процесс старта модуля ESP8266 с точки зрения инициализации и запуска прошивки.
При подаче питания или поступлении сигнала сброса процессор начинает выполнение инструкций с адреса 40000080h (системный ROM). По адресу 40001308h располагается процедура, которая считывает блок 00000h flash и копирует сегменты, хранящиеся в ней по заданным адресам.
![](https://habrastorage.org/files/1f7/03b/c22/1f703bc2284440fcbbb933746288ea4b.png)
На схеме этот процесс показан фиолетовым цветом. Здесь видно, что часть прошивки является исполняемым кодом, а часть инициализирует данные в ОЗУ. Зеленым обозначен блок, напрямую подмапленный в адресное пространство процессора.
После всех инициализаций управление передается по адресу, указанному в заголовке прошивки. Обычно это адрес пользовательского кода 40100000h.
3. Инструменты
Что ж, теперь, когда мы разобрались с архитектурой и процедурой старта модуля ESP8266, давайте перейдем к изучению его программного кода. Какие ресурсы и инструменты у нас есть для этого?
Для проектирования, разработки и отладки продуктов на базе SoC Xtensa существует пакет Xtensa Xplorer от производителя процессора, в состав которого входит множество утилит, включая TurboXIM – симулятор SoC. Теоретически, эта утилита могла бы быть полезной, но даже бесплатная версия требует лицензионных ключей, выдаваемых по запросу. Написав такой запрос я не получил ответа, поэтому воспользоваться симулятором не удалось. Скачать весь набор инструментов можно здесь, возможно, вам повезет больше.
Для разработки, сборки прошивок и выгрузки отладочной информации нам будет полезно развернуть среду разработки, как описано здесь.
Из традиционных инструментов воспользуемся IDA Pro и HIEW.
Для изучения кода процессора Xtensa необходимо использовать IDA Pro версии 6.6 и выше со встроенным интерпретатором питона для выполнения скриптов. В перечень стандартно поддерживаемых процессоров Xtensa не входит, поэтому каждый раз при запуске IDA Pro перед открытием исследуемого файла необходимо загружать скрипт “xtensa.py”, который можно взять здесь.
Также для автоматического создания сегментов и наименования функций системного ROM нам понадобится скрипт для IDA Pro. Скрипт и дамп системной прошивки можно скачать здесь.
HIEW будет полезен для исследования структуры ELF- и готовых двоичных файлов прошивки.
В следующей части мы рассмотрим процесс загрузки прошивки для исследования.
Update. Продолжение здесь.