Как процессор считывает BIOS с флэш-памяти SPI?

В типичных системах x86 встроенное ПО (также известное как BIOS или UEFI) хранится во флэш-чипе на основе SPI. Когда происходит включение питания, процессор начинает выполнение с вектора сброса, который указывает на микросхему SPI с отображением памяти, где хранится BIOS. С этого момента начальная загрузка происходит, когда BIOS завершает инициализацию платформы, загружает загрузчик, который затем загружает ядро.

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


person Insane Coder    schedule 13.02.2020    source источник
comment
Аппаратное обеспечение (в южном мосту), которое сопоставляет физические адреса с различными устройствами, знает, как общаться с устройствами SPI. Я предполагаю, что у производителя мобильных устройств есть какой-то способ установить начальное состояние диапазонов адресов при включении питания или это жестко зашито в чипсете. Контроллер адресного пространства X86? может иметь значение.   -  person Peter Cordes    schedule 13.02.2020
comment
Как сказал Питер, PCH управляет окном памяти для SPI с субтрактивным декодированием. Может быть, позже я найду время, чтобы написать правильный ответ.   -  person Margaret Bloom    schedule 13.02.2020


Ответы (1)


Первое, что делает ЦП Haswell+ при включении питания (после встроенного самотестирования BIST), — это выполнение микропрограммы, являющейся частью технология Intel TXT для получения FIT на 4GiB-40h и выполняет BIOS ACM (модуль кода с проверкой подлинности) и, в конечном итоге, продолжает измеренная загрузка или возврат к устаревшему вектору сброса на 4 ГБ — 10 часов.

В любом случае ЦП должен извлекать инструкции из окна памяти размером в несколько МиБ чуть меньше 4ГиБ.
ЦП не имеет интерфейса SPI, запросы к этому окну всегда перенаправляются на интерфейс DMI из соображений безопасности.
> Вы можете найти следующую карту в главе 2.6 Техническое описание 8-9 поколения Vol. 2 (правда даже в предыдущих поколениях, AFAIK):

Карта памяти

что актуально в связи с этим абзацем:

Из соображений безопасности процессор положительно декодирует этот диапазон [High BIOS] в DMI. Это положительное декодирование гарантирует, что любые перекрывающиеся диапазоны будут проигнорированы. Это гарантирует, что вектор загрузки и BIOS будут выполняться вне PCH.

Таким образом, ЦП загружается с интерфейса DMI, и, следовательно, PCH (концентратор контроллера платформы) обрабатывает запросы.
Обратите внимание, что даже в старых системах, где это окно размером почти 4 ГиБ было субтрактивно декодировано в Интерфейс DMI (т. е. отправка на интерфейс DMI только в том случае, если никакое другое устройство не заявило об этом), загрузка почти всегда происходила с самого интерфейса DMI.
Новое поведение с положительным декодированием является мерой защиты от атак с загрузкой.

Если вы посмотрите на техническое описание относительно современного PCH, т.е. pch-datasheet-vol-2.pdf" rel="noreferrer">series 200 видно, что он поддерживает флэш-ПЗУ либо за мостом LPC, либо за интерфейсами SPI.

Мы ограничимся последним.
В этом чипсете мостом SPI является устройство PCI 31, функция 15.
В его конфигурационном пространстве PCI находятся стандартные регистры и:

  • BAR (регистр базового адреса) для отображения окна регистра MMIO размером 4 КиБ для управления самим интерфейсом SPI.
  • Регистр BIOS Decode Enable, который включает или отключает восстановление доступа к памяти в определенных окнах.
  • Управляющий регистр для включения различных функций безопасности (включая загрузку с интерфейса SPI или LPC).

Остановимся на втором пункте:

«Регистр

Следует отметить две вещи: во-первых, этот регистр разрешает или запрещает отправку обращений к памяти от ЦП в области 4 МиБ ниже 4 ГиБ и других в SPI.
Во-вторых, значение по умолчанию — 0ffcfh, это означает, что по умолчанию все окна сопоставляются с SPI.
Регистр управления BIOS также выбирает SPI в качестве загрузочного интерфейса по умолчанию, но это также можно настроить с помощью контактов softstrap/bootstrap. , IIRC.

И последнее, но не менее важное: когда PCH видит доступ к адресу, подобному 4GiB-10h, он не может отправить его во флэш-память, поскольку он находится за пределами досягаемости самой флэш-памяти.
Сначала он должен его декодировать, вычитание смещения. Однако это смещение зависит от размера Flash ROM.

До появления PCH (думаю, в наборе микросхем ICH8 и в некоторых не слишком новых наборах микросхем Atom) флэш-ПЗУ использовалось без дескрипторов.
Набор микросхем просто сопоставлял ПЗУ из 4GiB до 4GiB-16MiB с псевдонимом, что означает, что адрес 4GiB - X будет сопоставлен с Размером флэш-памяти - (X % размера флэш-памяти).
Эффект заключался в том, что, например, флэш-память объемом 2 МиБ отображалась 8 раз в окнах размером 16 МиБ ниже предела в 4 ГиБ.
В этих чипсетах были контакты начальной загрузки для настройки размера флэш-памяти.

Сегодняшние флэш-ПЗУ для PCH использовать дескрипторы, где флэш-память разделена на регионы (BIOS, ME, GbE и т. д.).
В адресном пространстве ЦП отображается только регион BIOS. Существует система дескрипторов безопасности, основанная на идентификаторе отправителя запроса (данном его PCI-идентификацией).
Введение в эту тему см. на странице это или лучше это для более полного описания (немного устаревшего, но все еще актуального).
Регионы важны здесь, потому что они перечислены в дескрипторе флэш-памяти со своим смещением и размером, поэтому PCH может знать, как преобразовать адреса ЦП в линейные адреса флэш-памяти.

Наконец, регистры MMIO интерфейса SPI обеспечивают непосредственный доступ к флэш-ПЗУ. Можно синтезировать команды для отправки по шине SPI, что позволяет перепрограммировать флэш-ПЗУ (например).
На них по-прежнему распространяются различные контрмеры безопасности, которые должны быть перечислены в техническом описании IIRC.

person Margaret Bloom    schedule 13.02.2020
comment
trmm.net/Bootguard вам это может понравиться. Я проверил -18h в своем дампе физической памяти, и указателя там не было, поэтому, вероятно, он находится в xxC0, как он говорит. Мне нужно проверить позже. xxF0 имел относительный переход к FFFFFFF5 - 3BD со следующим кодом: imgur.com/a/vy0LT5s - person Lewis Kelsey; 02.05.2020
comment
Хорошо, это было на FFFFFFC0. Указатель на FFD90100. imgur.com/a/V5zhRS9 - person Lewis Kelsey; 02.05.2020
comment
@LewisKelsey Спасибо, я нашел источники с -18h и -40h, проверил, какой из них правильный, но потом забыл об этом. Я редактирую ответ. - person Margaret Bloom; 03.05.2020
comment
в документе SGX было написано FFFFFFE8, я думаю, но я не видел его в другом месте. Во всяком случае, я только что понял, что область F0000–FFFFF не отображается на ту же часть ПЗУ SPI, что и FFFF0000–FFFFFFFF, что не проясняет ни одна диаграмма карты памяти, которую я видел, и я уверен, что видел ' псевдоним» и тому подобное, но на самом деле подпрограмма, к которой перешел FFFFFFF0, ожидает, что es:[ffff0] (es = f000, где дескриптор сегмента имеет основание 0) будет содержать другой вектор сброса, который в моей системе является абсолютным 16 битовая память прямой прямой безусловный дальний переход (код операции EA) - person Lewis Kelsey; 03.05.2020
comment
Я не помню ничего, что могло бы позволить выбрать способ сопоставления FFFF0 с SPI ROM (но может быть что-то либо в дескрипторе FLASH, либо в каком-то флаге начальной загрузки). Механизм TOS Swap используется для чего-то подобного, мне нужно освежить в памяти это. Если вы сбросили память в работающей системе, возможно, вы сбрасываете теневую прошивку. Вы пробовали перевести цель прыжка в FFFFFFF0 в соответствующее место в верхнем SPI ROM? Это стоит исследовать, как только я найду немного времени, я посмотрю на это. Но я бы хотел реальный дамп SPI с программатором :/ - person Margaret Bloom; 03.05.2020
comment
Регистр включения декодирования BIOS для SPI и LPC имеет бит BIOS_LEGACY_F_EN для диапазона F0000-FFFFF. Я предположил, что причина разницы в том, что я мог читать затененный код на этом этапе, но затем я увидел код, который я отправил по ссылке выше, и он проверяет последовательность 0xeaf000e05b в es:[ffff0] и если она соответствует он отправляет код отладки «1» на порт POST-кода 0x80, пропуская проверку бита BSP в MSR APIC_base. Я не совсем уверен, какова цель этого, но, возможно, он проверяет, не было ли оно уже затенено. - person Lewis Kelsey; 03.05.2020
comment
Но это не имеет смысла, потому что на данном этапе этого не будет. Вот почему я начал думать, что, возможно, это проверка правильности фактической карты памяти. - person Lewis Kelsey; 03.05.2020
comment
@LewisKelsey Это может быть просто обработка теплого сброса или проверка из-за того, как прошивка разрабатывается sw house. - person Margaret Bloom; 03.05.2020
comment
Ты прав. Я просто запустил код через поиск Google. github.com/andreiw/lampone-edk2-platforms/blob/master/Platform/ - person Lewis Kelsey; 03.05.2020
comment
Я видел байт префикса 67, но я не уверен, почему он используется здесь. (Я не уверен, расширяет ли знак 67h или ноль расширяет moffs; я бы подумал, что он расширен до нуля, так что это кажется бессмысленным). Так что здесь может быть загрузка с 0xffffffff0h, но я так не думаю, и я думаю, что 32-битное смещение не может превышать 64k в реальном режиме, так что опять же, бессмысленно. - person Lewis Kelsey; 03.05.2020
comment
@LewisKelsey Хорошая находка! Префикс 67h не расширяется (ни знаком, ни нулем), он увеличивает ширину смещения в кодировке инструкции. Вы можете видеть, что FFF0 на самом деле использует четыре байта. Я думаю, это связано с тем, что разработчики использовали 32-битную константу (а ассемблер либо не жаловался и выдал 67h, либо предупредил и все равно выдал). - person Margaret Bloom; 03.05.2020
comment
О, да. Там было в инструкции. Я разобрался частично. Если EA находится в FFFF0h, то он проверяет FFFF1h для этого ptr16:16. Если он есть, то он знает, что затененное ПЗУ присутствует (т.е. произошел какой-то программный сброс, например, INIT#, который не повлиял на флэш-память SPI), затем он проверяет флаг BSP, и если это BSP, он переходит к затененное ПЗУ в FFFF0h. Если ptr16:16 там нет, он переходит к настройке 16-битного + 32-битного защищенного режима (называемой «nowarmstart»), которая затем переходит к реализации PEI с 32-битным плоским защищенным режимом по адресу 0x18:0xffffff6e. - person Lewis Kelsey; 04.05.2020
comment
Я не знаю, почему EA должен быть там, а этот конкретный ptr16:16 не может быть, но, по-видимому, это приводит к правильной загрузке (переход к nowarmstart). Если EA отсутствует, он проверяет бит 3 0xcf9 на «Проверка INIT# подтверждена». Если он подтвержден, он выполняет полный сброс, записывая 0x6, что приводит к PLTRST #, причина «выполнить теплый сброс, поскольку, если выдается только сброс ЦП, не все MSR восстанавливаются до значений по умолчанию». Если он не утвержден, он переходит к «nowarmstart». типы сброса: chromium.googlesource .com/chromiumos/ Third_Party/coreboot/+/ - person Lewis Kelsey; 04.05.2020
comment
Я не уверен, что понимаю этот сценарий, в котором INIT# будет утверждаться в это конкретное время. Нет такой документации по чтению из 0xcf9. Я объединяю ответ UEFI, чтобы ответить на то, что я знаю до сих пор - person Lewis Kelsey; 04.05.2020
comment
stackoverflow.com/questions/54274221/ Я только что нашел это .. (другие предложения по этому вопросу) Я думаю, что моя работа вырезана - person Lewis Kelsey; 05.05.2020