lpc frame что это
Lpc frame что это
LPC (Low Pin Count, малое число контактов) — шина, разработанная компанией Intel и предназначенная главным образом для подключения стандартных устройств, доставшихся современным персональным компьютерам «в наследство» от ранних ПК и обычно называемых унаследованными (legacy). Раньше такие устройства подключались к шине ISA.
Целесообразность разработки новой шины объясняется следующими основными причинами:
Шина LPC имеет всего 7 обязательных и 6 необязательных сигналов. Обмен данными по ней идёт в синхронном режиме с частотой 33 МГц (шина ISA является асинхронной, что также усложняет работающее с ней оборудование), причём каждый так передаётся 4 информационных или управляющих бита. Разрядность адреса увеличена до 32 бит, что позволяет задатчикам шины прямо обращаться к адресному пространству памяти объёмом 4 Гбайта (у шины ISA разрядность адреса составляла 24 бита, что ограничивало возможности адресации величиной 16 Мбайт). Реальная пропускная способность LPC, составляющая 6,7 Мбайт/с, ненамного уступает таковой у ISA (до 8 Мбайт/с) и совершенно достаточна для одновременной работы всех подключенных к ней устройств (по расчётам Intel, они используют порядка 75% максимальной пропускной способности).
С точки зрения программиста шина LPC как бы отсутствует: программы просто работают с регистрами подключенных к ней устройств. Хотя у LPC отсутствуют традиционные сигналы запросов прерываний и прямого доступа к памяти, эти возможности поддерживаются, причём создаётся иллюзия применения обычной шины ISA. Например, с точки зрения программиста подключенные к LPC порты и контроллер интерфейса PS/2 генерируют обычные для них запросы прерываний IRQ1, IRQ3, IRQ4, IRQ12, хотя физически эти линии отсутствуют. Определять наличие или отсутствие тех или иных устройств, подключенных к LPC, необходимо соответствующими функциями BIOS. Зачастую информация о них содержится в таблицах ACPI, поэтому анализ конфигурации обычно целесообразно начинать именно с их разбора.
Корзина
Сборник околотехнических статей.
LPC Debug, один из вариантов..
Один из вариантов диагностики материнских плат компьютеров — использование POSTкарт… Не буду описывать историю развития средств диагностики и их современные разновидности, рассмотрим частный случай — использование LPC. Интерфейс LPC (Low pin count) — использует, как видно из названия, уменьшенное количество линий для передачи информации. Для DEBUG-целей используется по-сути 7 линий: D0-D3, Frame, RST, CLK.
Некоторые производители матплат выводят эти линии (плюс землю и питание) на отдельный разъем (часто DEBUG-разъем есть в ноутбуках ASUS, Samsung). Некоторые выводят на неиспользуемые пины разъемов mini-pci, некоторые не выводят никуда — в таком случае для получения отладочной информации приходится припаивать эти самые 7 (с общим и питанием — 9) линий непосредственно к выводам мультиконтроллера (задача весьма непростая, требующая аккуратности), либо флешки БИОСа (да, были флешки которые подключались к мультиконтроллеру тоже при помощи LPC-интерфейса, т.е. он не только диагностический, а вполне себе полноценный интерфейс обмена данными). К флешке припаяться было легче, но такие флешки уже почти не встречаются, а вытеснены SPI-собратьями.
Я упоминал уже что иногда все нужные сигналы присутствуют на mini-pci разъеме — меняем вай-фай платку на post-карту и всё видим.. Но бывают еще варианты. Один из которых, достаточно простой, но судя по вопросам на форумах почему-то не всем очевидный, рассмотрю здесь подробно и с картинками.
В качестве примера подвернулся Lenovo G555, платформа COMPAL LA-5972P. Схема без труда гуглится. Смотрим на стр. 31 и видим (выделил куда именно смотреть):
Итого как бы всё есть — D0-D3 на выводах 16, 14, 12, 10; frame — 8; RST — 17; CLC — 19.
Вставляем карту, включаем питание — и ничего: ни клок не мигает на карте, ни коды не идут…. Смотрим на ту же страницу схемы но в другое место:
Значек «@» возле элемента на схемах обычно обозначает что элемент на плате не установлен… То есть в схеме есть, а на плате нет 🙂 Смотрим на плату — и «таки да», напротив контактов 8, 10, 12, 14, 16 видим пустые места под резисторы…
Берем указанные на схеме резисторы с нулевым сопротивлением с 5%-й точностью, и впаиваем. Если таких резисторов у вас нет (как и у меня), то можно обойтись «соплями» припоя, либо тонкими проводочками. Должно получиться примерно так:
Возле 17-го контакта (там у нас сигнал RESET) тоже видим площадки, поступаем аналогично:
А вот с 19-м немного засада…. Площадок возле разъема нет, а если посмотреть на схему — то резистора R973 нам тоже не хватает чтобы увидеть сигнал наличия тактовой частоты на пост-карте…. Не буду томить — площадка под него находится на другой стороне платы, найдена мультиметром.
Впаиваем резитор-перемычку, вставляем пост-карту в слот от вайфая, нажимаем кнопку включения питания — и всё работает: видим POST-код 76, обозначающий в данном случае отсутствие оперативной памяти (не вставил):
Как бы и всё.. Ну, если уже рассказывать о конкретно этом случае, то кодов сначала у меня не было — был мертв 216-0752001. Поменял его на 216-0752003, коды пошли, всё заработало, клиент счастлив.
PS: Еще маленький «хинт», очевидный для тех кто смотрит схемы, но к сожалению это делают не все… Чтобы нажать на этой плате кнопку включения — необязательно подключать панель с кнопкой, что есть не очень удобно в разобранном состоянии… На плате такие вот площадки (J5):
Просто коротим их подручным токопроводящим предметом — и плата должна стартануть. Нарисовано это на 35-й странице схемы. В принципе в этой статье всё взято из схемы — как говорит детский стишок: «как хорошо уметь читать…».
990x.top
Простой компьютерный блог для души)
LPC_DEBUG на материнской плате — что это такое?
LPC_DEBUG — разьем, к которому подключается специальное устройство для получения POST-кодов, при помощи которых можно выяснить неисправность материнской платы.
Вот собственно сам разьем:
Вообще какие разьемы и для чего они — должно быть описано в инструкции, если ее нет, то стоит посмотреть мануалы в интернете (правда обычно они на английском идут).
POST-коды уже давно используются для анализа материнки, если она вышла из строя. Как все примерно работает — к материнке подключается устройство, которое может выводить POST-коды. Потом включается материнка и по коду определяется в каком узле неисправность.
Чаще всего для таких целей используется специальная PCI-карта, которая имеет небольшой экран для отображения кода ошибки:
На некоторых игровых платах или платах класса премиум такой индикатор может быть встроенным:
Но карты были даже во времена шины ISA — она была еще до простой PCI, а это на минуточку еще до выхода Pentium 4, то есть очень давно. Вот собственно карта для ISA:
Надеюсь информация оказалась помогла. Удачи и добра, до новых встреч, друзья!
ISA умер! Да здравствует LPC?
Сегодня в персональном компьютере осталось только одно функциональное устройство, по которому можно проследить его генеалогию, — это интерфейс ISA, доставшийся ему по наследству от IBM PC AT. Большинство карт расширения выполняется по стандарту PCI, многие видеокарты подключаются по AGP. Однако производители карт расширения и материнских плат кивают друг на друга: если стандарт существует, то под него должны выпускаться карты; если выпускаются карты с интерфейсом ISA, то материнские платы должны его поддерживать. В спецификации PC98 наличие разъемов расширения стандарта ISA признается нежелательным. Однако для подсоединения таких устройств, как параллельные и последовательные порты, клавиатура, флоппи-диск, какой-нибудь интерфейс все же необходим. Поэтому разработчики микросхем для материнских плат вынуждены разводить ISA на кристалле, а чтобы добро не пропадало зря, — и выводить его наружу. Что же придет ему на смену?
Наименование | Направление | Назначение | |
---|---|---|---|
Периферия | Основной задатчик | ||
LAD[3:0] | I/O | I/O | Мультиплексированные команды, адреса и данные |
LFRAME# | I | O | Фрейм, указывает на начало новой команды |
LRESET# | I | I | Сброс, те же функции, что PCI Reset. При наличии PCIRST# необязателен |
LCLC | I | I | Тактовая частота 33 МГц, те же функции, что PCICLK |
Для подключения перечисленных выше устройств Intel предлагает новый стандарт — LPC (Low Pin Count, Малое Количество Контактов). Этот интерфейс, по утверждению представителей корпорации, будет встраиваться в будущие чипсеты для материнских плат. Такие намерения Intel означают, что, вероятнее всего, мы вскоре сможем в добровольно-принудительном порядке ознакомиться со стандартом LPC. Попробуем сделать это заранее и по собственной воле.
Введение нового стандарта преследует следующие цели:
Контактов действительно очень мало: семь обязательных (для передачи информации) и шесть дополнительных (для подключения устройств, выполняющих функцию задатчика и управления мощностью). Названия и функции обязательных сигналов интерфейса LPC приведены в табл. 1. Команды, адреса и данные передаются по линиям LAD[3:0] тетрадами-нибблами последовательно по четыре бита за один раз. Подобно PCI интерфейс синхронный, каждый цикл состоит из нескольких полей, каждое из которых имеет длительность в один период тактовой частоты 33 МГц. Любой цикл обмена по интерфейсу LPC начинается с того, что основной задатчик на шине (обычно чипсет) устанавливает активный уровень на линии LFRAME#. При этом все периферийные устройства переходят в состояние «начало цикла» и анализируют состояние линий LAD[3:0]. Если устройства передавали информацию по линиям LAD[3:0], то они немедленно их освобождают. Таким образом, этот сигнал может использоваться для прекращения затянувшихся циклов, например, при сбоях и зависаниях. То есть при достаточно интеллектуальном основном задатчике зависшее периферийное устройство не сможет подвесить всю систему. Сигнал LFRAME# может быть активным более одного периода тактовой частоты 33 МГц. В этом случае действительной считается информация, имевшаяся на LAD[3:0] во время последнего периода тактовой частоты. Первое поле — START — определяет тип операции, его возможные значения приведены в табл. 2.
Значение LAD[3:0] | Тип операции |
---|---|
0 | Начало ввода/вывода или чтения/записи |
1 | Зарезервировано для последующего расширения |
10 | Разрешение для задатчика номер 1 |
11 | Разрешение для задатчика номер 2 |
0100-1110 | Зарезервировано для последующего расширения |
1111 | Принудительное прекращение цикла |
Следующее поле — CYCTYPE + DIR (Cycle Type / Direction, тип цикла и направление передачи), определяется текущим задатчиком. Это поле может иметь значения, указанные в табл. 3. Значение бита LAD[0] зарезервировано, и он всегда должен быть равен 0.
Поле SIZE (Размер) может принимать значения 00 при передаче 1 байта, 01 при передаче 2 байт и 11 при передаче 4 байт. Значение 10 зарезервировано. Это поле используется только при операциях прямого доступа; ввод/вывод и чтение/запись осуществляются побайтно. Поле ADDR имеет длину четыре периода тактовой частоты для операций ввода/вывода и восемь периодов для циклов обращения к памяти. Адреса передаются начиная со старшей тетрады, то есть при обращении к памяти первыми передаются биты 31:28, а последними — 3:0.
LAD[3:2] | LAD[1] | Тип операции |
---|---|---|
0 | 0 | Чтение из внешнего устройства |
0 | 1 | Запись во внешнее устройство |
1 | 0 | Чтение из памяти |
1 | 1 | Запись в память |
10 | 0 | Прямой доступ к памяти для чтения |
10 | 1 | Прямой доступ к памяти для записи |
11 | Х | Зарезервировано. Периферия должна игнорировать это значение, а основной задатчик, обнаружив его, прерывает цикл установкой LFRAME# в активное состояние |
Поле CHANNEL используется в операциях прямого доступа к памяти и содержит в битах 0:2 номер канала, а в бите 3 — аналог сигнала Terminal Count шины ISA.
Поле DATA (Данные) имеет длину два периода тактовой частоты и содержит данные, передаваемые младшей тетрадой вперед. В одном цикле может содержаться одно, два или четыре поля DATA.
Поле передачи управления Turn Around, TAR, используется для передачи контроля над линиями LAD [3:0] второму участнику данного цикла, что необходимо при операциях чтения. Оно имеет продолжительность два периода тактовой частоты, на первом периоде текущий задатчик устанавливает на линиях LAD[3:0] значение 1111, на втором отключается, ожидая информацию от второго участника диалога.
Поле SYNC служит для синхронизации источника и приемника данных. Его вставляет ведомый участник цикла для того, чтобы подготовить для передачи запрошенные данные, или для размещения полученной информации. Полей SYNC в одном цикле может быть несколько, фактически столько, сколько нужно для подготовки. Значения поля SYNC приведены в табл. 4.
LAD[3:0] | |
---|---|
0 | Синхронизация достигнута |
0001-0100 | Зарезервировано |
101 | Короткое ожидание |
110 | Длительное ожидание, будет добавлено много полей SYNC |
0111-1000 | Зарезервировано |
1001 | Синхронизация достигнута, передача будет продолжена в следующем цикле (только при прямом доступе к памяти) |
1010 | Ошибка. В переданных данных содержится ошибка |
1011 — 1111 | Зарезервировано |
Значение 1010 — Ошибка необходимо потому, что все циклы должны иметь определенную длину, так что периферийное устройство обязано передать требуемое для данного цикла количество данных, но перед этим оно честно предупреждает задатчика о том, что эти данные имеют чисто фиктивный характер.
Ознакомившись с типами полей, можно более подробно рассмотреть механизмы начала, окончания и принудительного прекращения цикла. Цикл начинается с того, что основной задатчик устанавливает активный уровень на линии LFRAME#. С этого момента периферийные устройства только анализируют состояние линий LAD[3:0], прервав любую операцию на шине (если она проводилась). Задатчик может удерживать LFRAME# в активном состоянии более одного периода частоты синхронизации, при этом он даже может произвольно менять состояние LAD[3:0]. Действительным значением поля START будет то, которое имелось на этих линиях перед переходом LFRAME# в пассивное состояние. Если считанное поле START распознается периферийными устройствами, то они должны декодировать весь цикл, а в противном случае — просто дожидаться следующей активации LFRAME# (например, устройства ввода/вывода, не использующие циклы прямого доступа или захвата шины, могут их просто игнорировать). Принудительное прекращение цикла является специальным циклом, так как начинается с установки LFRAME# в активное состояние, а заканчивается установкой поля START со значением 1111. При этом для более уверенного распознавания линия LFRAME# находится в активном состоянии не менее четырех периодов тактовой частоты.
Поле | Значение | Источник | Число тактов |
---|---|---|---|
START | 0 | Основной задатчик | 1 |
CYCTYPE+DIR | 100 | Основной задатчик | 1 |
ADDR | ХХХХ | Основной задатчик | 8 |
TAR | 1111 | Основной задатчик | 2 |
SYNC | 101 | Периферийное устройство | 3 |
SYNC | 0 | Периферийное устройство | 1 |
DATA | ХХХХ | Периферийное устройство | 2 |
TAR | 1111 | Периферийное устройство | 2 |
Всего тактов | 20 | ||
Время доступа | 0,66 мкс | ||
Скорость передачи | 1,5 Мбайт/с |
В табл. 5 приведены последовательность и характеристики полей в цикле чтения из памяти. Основной задатчик инициирует цикл, определяет тип цикла и направление передачи (чтение из памяти), адрес памяти и информирует об освобождении линий LAD[3:0]. Периферийное устройство во время подготовки данных передает поля SYNC со значением 0101. Когда данные готовы для передачи, устройство передает поле SYNC со значением 0000, две тетрады данных и информирует основного задатчика об освобождении линий LAD[3:0].
Количество полей синхронизации соответствует быстродействию памяти и может изменяться. В данном примере предполагалось наличие ППЗУ с временем доступа 120 нс (4*33 нс = 132 нс). Цикл записи построен примерно так же, но данные передает основной задатчик, а периферийное устройство — только поля SYNC и TAR. В поле SYNC устройство помещает значение либо 0000 (успешная запись), либо 1010 (ошибка при записи). Соответственно возможны варианты, когда устройство не буферизует данные, а выдает поля SYNC до момента реальной записи.
Поле | Значение | Источник | Число тактов |
---|---|---|---|
START | 0 | Основной задатчик | 1 |
CYCTYPE+DIR | 110 | Основной задатчик | 1 |
ADDR | ХХХХ | Основной задатчик | 8 |
DATA | ХХХХ | Основной задатчик | 2 |
TAR | 1111 | Основной задатчик | 2 |
SYNC | 0 | Периферийное устройство | 1 |
TAR | 1111 | Периферийное устройство | 2 |
Всего тактов | 17 | ||
Время доступа | 0,56 мкс | ||
Скорость передачи | 1,8 Мбайт/с |
В табл. 6 приведены последовательность и характеристики полей в цикле чтения из памяти. Совершенно аналогично происходит ввод/вывод при работе с портами, отличие состоит лишь в других значениях полей CYCTYPE+DIR. Для ознакомления с функциями работы с прямым доступом к памяти и управления потребляемой мощностью в табл. 7 приведены необязательные линии интерфейса LPC.
Наименование | Направление | Назначение | |
---|---|---|---|
Периферия | Основной задатчик | ||
LDRQ# | O | I | Запрос на прямой доступ к памяти или захват шины. Каждому устройству, обладающему этими функциями, требуется отдельная линия LDRQ# |
SERIRQ | I/O | I/O | Последовательный запрос на прерывание |
CLKRUN# | OD I/OD | OD I/OD | То же, что и PCI CLKRUN# |
PME# | OD | I/OD | То же, что и PCI PME# |
LPCPD# | I O | I O | Отключение, указывает, что периферия должна подготовиться к отключению |
LSMI# | O/D I | O/D I | Как и PCI SMI#, нужен для повторных попыток |
При запросе прямого доступа к памяти (ПДП) или захвата шины используется линия LDRQ#. В первом случае по ней передается номер канала ПДП, во втором — зарезервированное значение 100. При благоприятном для данного запроса исходе арбитража основной задатчик начинает производить циклы ПДП. Бит LAD[3] в поле CHANNEL играет специальную роль и соответствует линии шины ISA TC (Terminal Count). В случае передачи последней порции данных (1, 2, 4 байт) этот бит устанавливается в 1, сигнализируя о том, что текущий сеанс ПДП закончен. Также сеанс ПДП может быть завершен установкой поля SYNC=0000 (синхронизация достигнута) или SYNC=1010 (ошибка), так как при циклах ПДП для индикации готовности данных используется значение SYNC=1001 (синхронизация достигнута; в следующем цикле будут еще данные). Последовательность полей и другие характеристики цикла ПДП при 8-битном чтении внешним устройством из основной памяти приведены в табл. 8. В зависимости от типа ПДП (8, 16 или 32 разряда) последние четыре поля передаются один, два или четыре раза соответственно. Соответственно будут меняться время доступа и скорость передачи.
Цикл захвата шины, как и все остальные, инициируется основным задатчиком после получения запроса по линии LDRQ#. Основной задатчик, как и при всех других циклах, формирует поле START, имеющее значение 0010 или 0011 (разрешение для задатчика 1 или задатчика 2; в настоящее время поддерживается не более двух задатчиков). После этого основной задатчик передает управление шиной при помощи поля TAR. Далее все протекает как при описанных выше циклах, за одним исключением: поля SYCTYPE+DIR и последующие, которые определяют тип цикла и направление передачи, формируются устройством, получившим право на захват шины.
Наименование | Направление | Назначение | |
---|---|---|---|
Периферия | Основной задатчик | ||
LDRQ# | O | I | Запрос на прямой доступ к памяти или захват шины. Каждому устройству, обладающему этими функциями, требуется отдельная линия LDRQ# |
SERIRQ | I/O | I/O | Последовательный запрос на прерывание |
CLKRUN# | OD I/OD | OD I/OD | То же, что и PCI CLKRUN# |
PME# | OD | I/OD | То же, что и PCI PME# |
LPCPD# | I O | I O | Отключение, указывает, что периферия должна подготовиться к отключению |
LSMI# | O/D I | O/D I | Как и PCI SMI#, нужен для повторных попыток |
Для работы с устройствами, использующими прерывания, используется линия SERIRQ# и одноименный протокол, описанный в спецификации шины PCI «PCI Local Bus Specification, Rev 2.1». Управление включением/выключением периферийных устройств осуществляется при помощи линий LPCPD# и LRST#. При выключении первая из них устанавливается основным задатчиком в низкий уровень, при этом в течение еще не менее 30 мкс на шину подается сигнал тактовой частоты LCLC. Все периферийные устройства при обнаружении низкого уровня на линии LPCPD# обязаны прекратить любую активность на шине и перейти в режим пониженного энергопотребления. Переход к работе происходит при подаче основным задатчиком на линию LPCPD# высокого уровня. Подача тактового сигнала осуществляется заранее, не менее чем за 100 мкс перед установкой высокого уровня LPCPD#. Для правильного перехода внешних устройств в начальное состояние на линии LRST# поддерживается низкий (активный) уровень еще в течение 60 мкс.
Встроенный контроллер одного ноутбука и его наследство
В этом материале я хочу немного рассказать о том, что происходит во встроенном контроллере (Embedded Controller, EC) моего ноутбука. Речь идёт о мультиконтроллере IT8586E, основанном на Intel 8051. Он встроен в ноутбук Lenovo Ideapad 310-15IKB. Но, прежде чем переходить к деталям, полагаю, нелишним будет поговорить о том, что это вообще такое — встроенные контроллеры.
Краткая история встроенных контроллеров на платформах x86
Сначала был создан компьютер IBM PC. Многих это возмутило, данный шаг компании IBM был широко признан неразумным.
В материнскую плату этого компьютера было встроено множество периферийных устройств, вроде Intel 8259 (программируемый контроллер прерываний) или Intel 8253 (программируемый таймер). Обращаться к этим контроллерам можно было, пользуясь инструкциями in/out ядра x86 (и, на самом деле, к контроллерам 8259 и 8253 всё ещё можно обращаться на современных x86-процессоров, но теперь они входят в состав кристалла CPU). Один из контроллеров IBM PC, Intel 8255 (программируемый контроллер интерфейса периферийных устройств), отвечал за взаимодействие с клавиатурой.
Где-то в конце 1980-х периферийные устройства всё чаще и чаще объединяли, включая в состав одной микросхемы несколько таких устройств. Например — это чипы северного моста и южного моста. Один из таких чипов, Super I/O-контроллер, отвечал за взаимодействие с низкоскоростными устройствами, вроде последовательных портов, параллельных портов и контроллеров дисководов гибких дисков. В состав этого чипа часто входил и контроллер клавиатуры.
Ноутбукам, кроме прочего, требовалась особая система управления питанием. Производители портативных компьютеров взглянули на контроллер клавиатуры, на то, что он способен перезагружать компьютер, и сказали: «На самом деле — это замечательно. Давайте сделаем то, что нам нужно, по похожей схеме». В результате к контроллеру клавиатуры были добавлены два порта с похожим интерфейсом, позволяющим отправлять на устройства команды и получать от них данные. И, фактически, во многих платформах эта возможность реализована в том же самом контроллере, который входит в состав Super I/O-чипа.
В середине 1990-х заметным явлением стал стандарт ACPI (Advanced Configuration and Power Interface, усовершенствованный интерфейс управления конфигурацией и питанием). Он определял стандартизированный интерфейс для EC. А именно, через его командный интерфейс можно было обращаться к 8-битному адресному пространству переменных, определяемых производителями оборудования. Эти переменные можно было описывать с помощью языка AML (ACPI Machine Language), средствами AML можно было описывать и код, позволяющий воздействовать на эти переменные.
В конце 2000-х годов микросхемы южного и северного мостов были объединены с CPU. Правда, надо отметить, что интеграция южного моста (PCH, Platform Controller Hub) в CPU, по всей видимости, имеет место лишь на мобильных платформах. Но в ноутбуках EC всё ещё представлен отдельным чипом, который, кроме того, реализует функционал Super I/O-контроллера и контроллера клавиатуры. Он, например, решает следующие задачи:
Схема материнской платы моего ноутбука
Так как EC интенсивно взаимодействует с разными устройствами — неплохо было бы знать о том, что это за устройства. Мне в решении этой задачи повезло — кто-то выложил в интернет так называемые boardview-файлы к интересующей меня плате. В таких файлах содержатся схемы печатных плат, в частности, сведения о компонентах, расположенных на плате, и о том, как они связаны. Между компонентами материнских плат имеется так много соединений, что анализ схемы их связей может оказаться весьма сложной задачей. Я попытался представить связи между компонентами платы в упрощённой форме, результат моих трудов показан на следующей схеме (тут нет большинства линий, имеющих отношение к питанию).
Схема связей компонентов платы (оригинал)
CPU соединён с EC с использованием шины LPC (Low Pin Count), которая, по сути, представляет собой замену шины ISA, применявшейся в более старых компьютерах, в физической реализации которой используется меньше линий связи. Процессор и контроллер взаимодействуют, в основном, по LPC. Но между EC и CPU имеется множество соединений (показанных синими линиями без стрелок), используемых в особых целях. Например — это линия SCI, предназначенная для вызова прерывания от EC в CPU.
Прошивка EC
Раздобыть прошивку контроллера несложно. Я уже извлекал образ BIOS раньше, для других нужд. После его обработки с помощью утилиты cpu_rec в моём распоряжении оказалось примерно 160 Кб 8051-кода из самого начала образа, расположенного до кода, имеющего отношения к UEFI. Контроллер 8051 имеет 16-битное адресное пространство, а значит 160 Кб кода ему не соответствуют. Получается, что речь идёт о так называемой banked-прошивке. То есть — одни части («блоки» или «банки») прошивки в адресном пространстве подвергаются динамической замене на другие части путём воздействия на некие регистры.
Размеры блоков прошивки обычно, в большинстве контроллеров 8051, составляют либо 32, либо 64 Кб. Выяснить их размер при работе с конкретным контроллером можно, поискав повторяющиеся фрагменты кода. Дело в том, что в разных блоках прошивки обычно имеются одинаковые фрагменты, представляющие код общего назначения (быстро найти такие фрагменты можно попробовать, прибегнув к автокорреляции). Оказалось, что в моём случае речь идёт о блоках кода размером 32 Кб.
После того, как я всё это выяснил, меня посетила блестящая идея, которая заключалась в том, чтобы посмотреть даташит исследуемого компонента. Даташит на мой контроллер найти не удалось, но мне попались документы на IT8502E, описывающие устройство достаточно близкое к тому, которое было у меня. В нём, что было очень кстати, подробно описывалось большинство I/O-механизмов и, похоже, описание функционирования прошивки, в основном, соответствовало той прошивке, что была у меня.
При просмотре даташита я наткнулся на упоминание отладочного интерфейса I2C, но он, правда, не был документирован. После некоторых изысканий я нашёл проект ECSpy, который представляет собой Rust-реализацию отладчика для EC, созданную силами компании System76, которая работает над собственной прошивкой для EC.
Отладчик даёт доступ на чтение и запись к оперативной памяти и регистрам ввода/вывода EC. Доступ к регистрам отличается дополнительным ограничением, которое заключается в том, что операция записи чётко определена лишь для триггерных регистров (в результате, например, операция, вызывающая изменение состояния конечного автомата, не сработает).
Ещё в даташите сказано, что возможность отладки нужно включать с помощью регистра, но она и так включена. Доступ к ней осуществляется посредством I/O-портов x86 через Super I/O-чип, поэтому ей можно пользоваться из пользовательского пространства, без необходимости писать драйвер.
Для реверс-инжиниринга тех частей прошивки, которые отвечают за взаимодействие с различными устройствами, могут пригодиться спецификации этих устройств. Я, работая над этим проектом, прочитал часть спецификаций ACPI, SMBus и Smart Battery. В процессе исследования кода прошивки используются следующие ресурсы и инструменты: boardview-файлы, даташиты, спецификации компонентов, отладчик Ghidra, обычный браузер, применяемый для поиска дополнительных сведений вроде скан-кодов, исходный код Linux-драйвера для EC, дизассемблированный машинный ACPI-код, отладчик для EC и его исходный код. В таких делах весьма кстати могут оказаться несколько мониторов, использование которых позволяет ускорить сопоставление информации, полученной из разных источников.
Большой объём работы выполняется в коде главного цикла, ответственном за обработку событий таймера. Таймер в EC запрограммирован так, что он выдаёт прерывание раз в одну миллисекунду. Потом, на основе прерываний таймера, формируются события, которые происходят, например, каждые 10, 50, 100 мс. Обновление ACPI-переменных выполняется, в основном, в этом контексте.
POST-карты в современных ноутбуках
Затем, вместе с тактовыми импульсами, осуществляется последовательный вывод результирующего значения на GPIO-пины.
Вышеприведённая поисковая таблица может показаться вам знакомой. Дело в том, что она позволяет преобразовывать полубайты в шестнадцатеричные числа для их вывода на 7-сегментном дисплее. Если взглянуть на схему материнской платы, там можно увидеть две линии — EC_TX и EC_RX (эти названия, вероятно, не очень удачны, так как одна из них — это линия данных, а другая — тактовая линия, обе они используются лишь для отправки данных). Они ведут к Wi-Fi-чипу, который подключён к плате через разъём M.2. Но эти линии, на самом деле, ни к чему на Wi-Fi-карте не присоединены.
Это наводит на мысль о том, что существуют некие POST-платы, которые можно подключать к разъёму M.2 для решения проблем, возникающих в ходе загрузки ноутбуков. Так как я знаком с протоколом обмена данными, используемым в M.2-картах, я попытался сделать собственный вариант такой платы (она, в целом, представляет собой два последовательно соединённых сдвиговых регистра, подключённых к 7-сегментным дисплеям). Посмотрите — какая симпатичная у меня получилась штука.
Самодельная POST-плата для разъёма M.2
Но я, к сожалению, видимо что-то напутал, так как эта плата, в итоге, так и не заработала, а мне не очень-то хотелось тратить время на поиск и исправление ошибок, допущенных при её создании.
Клавиатурные механизмы
Можно подумать, что вышеописанная задача решается очень легко, что заключается она в просмотре некоей поисковой таблицы и в отправке хосту результатов. Но, увы, скан-коды PS/2 — это настоящий бардак.
Существует три различных набора скан-кодов, между которыми нет ничего общего. EC использует набор №2. Одиночное нажатие и отпускание клавиши не всегда приводит к генерированию одного байта скан-кода.
Если промежуточное значение меньше 0x80, это значит, что оно просто соответствует обычному однобайтовому PS/2 скан-коду. А если говорить о других значениях, то они, по уже рассмотренной нами схеме, используются в роли индексов в поисковой таблице. Результирующее значение определяет функцию, которая используется для обработки скан-кода. Полученные скан-коды затем помещают в 16-байтовый кольцевой буфер, байты, содержащиеся в котором, если это возможно, потом отправляют хосту.
Таинственный фрагмент кода
Зачем встроенному контроллеру SHA-1? Если посмотреть на то, что именно вызывает SHA1-код, то окажется, что он используется при взаимодействии с батареей по SMBus:
Где хранится код?
Во многих прошивках для 8051 обычно имеется код, реализующий возможности отладки, и мой — не исключение. Перед функциями, имеющими отношение к контроллеру клавиатуры и к EC, имеется множество функций, которые явно реализуют отладочные возможности. Одна из них — это команда контроллера клавиатуры, предназначенная для чтения из EC данных с адресов флеш-памяти с применением регистра.
Если сделать оттуда дамп прошивки, то получится образ, который отличается от оригинала. Изначально я предполагал, что EC использует образ из флеш-памяти BIOS, так как он хранится в этой памяти, и EC к этой памяти подключён. Но оказалось, что это, на самом деле, не так. К этой памяти напрямую подключены и CPU, и EC. В результате, в том случае, если и тот и другой одновременно попытаются прочесть из неё данные, на шине неизбежно возникнет конфликт. Прошивка, на самом деле, хранится в самом EC. В IT8502 этой возможности не было (это запутало меня ещё сильнее, так как я пользовался даташитом именно для такого контроллера).
Запуск моего собственного кода в EC
Вероятно, стоит сказать о том, что у 8051 имеется некоторое количество различных адресных пространств:
Я этого делать не собирался, так как подобные действия несут в себе риск «окирпичивания» устройства. EC можно перепрограммировать, используя входы/выходы клавиатурной матрицы в роли параллельного порта, но я не собирался заниматься и этим.
Ещё одна проблема, связанная с записью данных во флеш-память, заключается в том, что её содержимое проверяется с использованием контрольной суммы. В прошивке имеется сигнатура, которая указывает на то, где начинается контрольная сумма, и в ней имеются два байта, которые различаются в разных редакциях прошивки. Подобное характерно для контрольных сумм. Если дело обстоит именно так — то неясно, где именно начинается и заканчивается контрольная сумма, и то, как именно она вычисляется.
Правда, для выполнения собственного кода нет нужды выполнять запись данных во флеш-память. В EC для этого имеется другой механизм. А именно — адреса 0x0000-0x1000 в адресном пространстве XDATA — это обычная оперативная память, которую можно отобразить на произвольную область адресного пространства CODE, изменив содержимое кое-каких регистров.
Схема из даташита, на которой показано 5 областей, пронумерованных от 0 до 4, которые могут быть отображены на адресное пространство кода. А именно, речь идёт об областях 0x0000-0x0800, 0x0800-0x0c00, 0x0c00-0x0e00, 0x0e00-0x0f00 и 0x0f00-0x1000
В результате для выполнения собственного кода достаточно лишь выполнить отображение одного из этих фрагментов на память с кодом. Оперативная память в диапазоне 0x0000-0x0e00 используется самой прошивкой, в результате остаются блоки 3 и 4, размер каждого из которых составляет 256 байт.
Правда, чтобы осуществить отображение этой памяти на память с кодом, нужно выполнить запись в регистры и в оперативную память из пространства XDATA. Есть одна отладочная функция, позволяющая писать данные в XDATA, но она содержит ошибки и может писать данные только по адресам, где байт из верхней части адреса является таким же, как и байт из его нижней части. Тут имеется ещё и интерфейс I2C, который достаточно хорошо подходит для решения задачи записи данных в SRAM.
Я сомневался по поводу записи данных в порты ввода/вывода, так как было сказано, что это подходит лишь для триггерных регистров. Но в регистрах, используемых для отображения памяти, имеется ещё и бит для запуска DMA-транзакции (так как этот чип, конечно, поддерживает DMA). В любом случае, не было способа проверить то, что отображение памяти осуществляется именно так, как мне нужно, так как нет отладочной функции, позволяющей читать данные из адресного пространства CODE.
К счастью, был и другой путь: функционал отображения памяти используется для перезаписи флеш-памяти (так как никто не заинтересован в том, чтобы работа программы завершилась бы с ошибкой, когда будет достигнута область с кодом, выполняющим запись данных). Используя I2C можно отредактировать содержимое SRAM в адресном пространстве XDATA, поместив туда отладочный код, и подстроить механизм записи данных во флеш-память так, чтобы он обращался бы к этому отладочному коду.
В любом случае, эту проблему легко обойти, так как между адресами, всё равно, имеется взаимно однозначное соответствие, а значит — код можно просто записать в те места пространства XDATA, которые будут соответствовать нужным местам памяти. Оказалось, что I2C-запись в регистры, отвечающие за отображение памяти, тоже работает. В результате для выполнения отладочного кода с его последующей записью мне не нужно было бы прибегать к режиму перезаписи флеш-памяти.
Итоги
На сегодня это всё, а в следующий раз я расскажу об исследовании прошивки ноутбучного Wi-Fi-модуля (RTL8821AE) и о разработке небольшого кейлоггера, основанного исключительно на возможностях Intel 8051.
Занимались ли вы разработкой прошивок для контроллеров, основанных на Intel 8051?