Как сохранить образ PCI-пространства в двоичный файл?

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

Как со­хра­нить главный про­филь со­вре­мен­ной плат­фор­мы — об­раз кон­фи­гу­ра­ци­он­но­го PCI-про­ст­ран­ст­ва — в дво­ич­ный файл? Ар­хи­тек­ту­ра ны­не­ш­них PC-плат­форм та­ко­ва, что для это­го тре­бу­ет­ся до­с­туп к me­mo­ry-mapp­ed ди­а­па­зо­ну, ба­зо­вый ад­рес и раз­мер ко­то­ро­го де­кла­ри­ру­ет­ся в ACPI-таб­ли­це с сиг­на­ту­рой «MCFG». По­ста­ра­ем­ся вы­пол­нить этот эк­с­пе­ри­мент на стен­де, где хо­зяй­ни­ча­ет ма­те­рин­ская пла­та ASUS TUF Gaming X570-Plus, ко­то­рая ос­на­ще­на сис­тем­ной ло­ги­кой AMD X570. По­смот­рим за­од­но, что там ин­те­рес­но­го, за­гля­нув в ре­гист­ро­вые по­ля с по­мо­щью RW­Everything.

Установив RWEverything, открываем два ее окна: «ACPI» (отмечено красным) и «Memory» (если что — третья слева). В ок­не ACPI переходим на закладку MCFG (выделена розовым цветом), а в Memory кли­ка­ем на вто­рую сле­ва икон­ку «Sa­ve as bi­na­ry» (она у нас на розовом фоне).

ddd

 

Осталась пара пустяков: ввести стартовый и конечный адреса нужного нам региона памяти. Первый из них нам по­мо­жет оп­ре­де­лить закладка MCFG в окне ACPI — он там указан, как базовый и равен F8000000h (крас­ное под­чер­ки­ва­ние).

Размер диапазона равен количеству шин, умноженному на 1 MB — для пред­став­ле­ния кон­фи­гу­ра­ци­он­ной ин­фор­ма­ции ис­поль­зу­ет­ся имен­но 1 MB данных на каждую PCIe-шину. Значение 3Fh соответствует шине 63. С учетом то­го, что ну­ме­р­а­ция вы­пол­ня­ет­ся с 0, мак­си­маль­ное ко­ли­че­ст­во шин равно 64.

Диапазон размером в 64 MB адресуется от 00000000h до 03FFFFFFh, всего — 4000000h байт. Это шест­над­ца­те­рич­ное чис­ло и со­от­вет­ст­ву­ет объему нашего 64MB-пространства. Сложив его с базовым адресом ди­а­па­зо­на, получим:

End Address = F8000000h + 03FFFFFFh = FBFFFFFFh

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

В типовой системе количество реально ис­поль­зу­е­мых номеров шин значительно меньше ог­ра­ни­че­ния, об­ус­лов­лен­но­го раз­ме­ром ди­а­па­зо­на. Мак­си­маль­ное количество устройств на шину (32) и функций на уст­рой­ст­во (8) так­же, как пра­ви­ло, не ис­поль­зу­ет­ся. Это оз­на­ча­ет, что двоичный файл содержит раз­ре­жен­ные дан­ные и мо­жет быть эф­фек­тив­но упа­ко­ван ар­хи­ва­то­ром.

По­лу­чен­ный дамп мож­но про­а­на­ли­зи­ро­вать с по­мо­щью про­г­рам­мно­го обес­пе­че­ния Java­Cross­Plat­form­Pci­Dump.

Замечания и уточнения

Численные значения базового адреса ди­а­па­зо­на и ко­ли­че­ст­во шин являются параметрами, за­ви­ся­щи­ми от кон­фи­гу­ра­ции плат­фор­мы. Обновление UEFI, из­ме­не­ния в состоянии опций CMOS Setup, добавление или уда­ле­ние обо­ру­до­ва­ния может привести к другому результату. Об этом стоит помнить пе­ред каж­дой опе­ра­ци­ей со­хра­не­ния об­ра­за кон­фи­гу­ра­ци­он­но­го PCI-прост­ран­ст­ва.

Системы с несколькими сегментами PCI Express шин (например, Intel VMD/VROC) оп­ци­о­наль­но ­мо­гут со­дер­жать не­сколь­ко ди­а­па­зо­нов MCFG — по одному диапазону на шинный сегмент. Описанная методика под­дер­жи­ва­ет­ся для сис­тем­ных плат не только с шинами PCI Express, но также и с PCI-X то­по­ло­ги­ей. Ра­зу­ме­ет­ся, речь идет о под­дер­ж­ке кон­фи­гу­ра­ци­он­ных ме­ха­низ­мов, а не о наличии фи­зи­че­ских слотов.

Для платформ более ранних поколений, не использующих диапазон MCFG, один из ва­ри­ан­тов ре­ше­ния мо­жет со­сто­ять в на­пи­са­нии прог­рам­мы, по­сле­до­ва­тель­но счи­ты­ва­ю­щей ин­фор­ма­цию, ис­поль­зуя порты:

  • 0CF8h = CONFIGURATION ADDRESS
  • 0CFCh = CONFIGURATION DATA

Код, осуществляющий данную операцию, должен иметь привилегии Ring 0 в операционной системе — вы­пол­нять­ся в ре­жи­ме Kernel Mode драйвера, либо запускаться в среде DOS или UEFI. Вместо не­по­сред­ст­вен­но­го доступа к портам, в за­ви­си­мос­ти от контекста, можно использовать функции Legacy PCI BIOS или EFI PCI I/O Protocol. Удачи!