Работа с MDL

Тема в разделе "WASM.WIN32", создана пользователем LightElf, 24 фев 2005.

  1. LightElf

    LightElf New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2005
    Сообщения:
    13
    Люди добрые, сами мы не местные, помогите кто чем сможет...



    Вводная часть: имеются страницы физической памяти (то есть locked, fixed, etc), заполненные некоторой сигнатурой. Задача: из драйвера найти все эти страницы (количество заранее известно) и построить из них буфер для дальнейшего использования драйвером.



    Теперь вопросы:

    1) как из драйвера узнать общий объем физической памяти на данном компьютере? Вопрос не самый важный, но желательный.

    Можно конечно перебирать все страницы памяти начиная с нулевой и пока не будут найдены все нужные страницы. Но на всякий случай хотелось бы иметь верхний предел поиска.



    2) Как построить буфер из произвольного списка страниц? Чего-то я не пойму, как создать пустой MDL, то есть не связанный с какой-либо памятью.



    3) как привязать MDL к виртуальному адресу?



    Заранее прошу прощения, если вопросы глупые. Опыт написания драйверов у меня есть, но вот только не под Windows. Чтение MSDN просветления не вызвало :)

    на всякий случай: Дело происходит под XP.
     
  2. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    <font color="gray][ LightElf</font><!--color--><font color="gray]: как из драйвера узнать общий объем физической памяти на данном компьютере? ]</font><!--color-->


    Код (Text):
    1. ZwQuerySystemInformation, SystemBasicInformation,...
    2.  
    3. typedef struct _SYSTEM_BASIC_INFORMATION {
    4.     ULONG Unknown;
    5.     ULONG MaximumIncrement;
    6.     ULONG PhysicalPageSize;
    7.     ULONG NumberOfPhysicalPages;
    8.     ULONG LowestPhysicalPage;
    9.     ULONG HighestPhysicalPage;
    10.     ULONG AllocationGranularity;
    11.     ULONG LowestUserAddress;
    12.     ULONG HighestUserAddress;
    13.     ULONG ActiveProcessors;
    14.     UCHAR NumberProcessors;
    15. }SYSTEM_BASIC_INFORMATION,*PSYSTEM_BASIC_INFORMATION;


    <font color="gray][ LightElf</font><!--color--><font color="gray]: Как построить буфер из произвольного списка страниц? ]</font><!--color-->



    Скорее всего никак, в смысле с помощью экспортируемых ядром функций. Тебе придется разобраться как IoAllocateMdl, MmCreateMdl и т.п. это делают.





    <font color="gray][ LightElf</font><!--color--><font color="gray]: как создать пустой MDL, то есть не связанный с какой-либо памятью. ]</font><!--color-->



    Тоже скорее всего никак, ибо MDL есть описание некоторого кол-ва страниц памяти, а если этого кол-ва нет, то и описывать нечего.





    <font color="gray][ LightElf</font><!--color--><font color="gray]: как привязать MDL к виртуальному адресу? ]</font><!--color-->



    Привязка происходит в момент формирования MDL.
     
  3. LightElf

    LightElf New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2005
    Сообщения:
    13
    [Four-F: ZwQuerySystemInformation, SystemBasicInformation,...]



    А оно разве из драйвера доступно? Или "Нельзя, но если очень хочется, то можно..."?



    А по сути: ни фига не понимаю, чего делает IoAllocateMdl.

    Делаем такое: IoAllocMdl(NULL, 16384, FALSE, FALSE, NULL)

    получаем MDL, у которой в таблице страниц загадочные числа, а-ля 80c1a178, 80c15318, 00002501, 00001d42...

    Что это, Бэрримор?

    Первые два числа никак не тянут на физический адрес страницы, ибо у компа всего 64мега памяти. Последние два тоже какие-то странные... При этом в заголовке MDL, как и положено, лежат внятные числа, все пучком...
     
  4. TarasCo

    TarasCo New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2005
    Сообщения:
    106
    IoAllocMdl не выделяет память под буфер.

    Она

    1. Выделяет память под дескриптор буфера (MDL) с учетом его страничной организации. Минимальный размер этого буфера - sizeof(MDL) + 4 * 0x17 (жуткий хардкод :) ).

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



    Чтобы выделить буфер и получить дескриптор, можно действовать примерно так:

    PVOID p = ExAllocatePool(NonPagedPool, 4 * PAGE_SIZE );

    PMDL mdl = IoAllocateMdl(p, 4 * PAGE_SIZE, 0, 0, 0);

    MmBuildMdlForNonPagedPool(mdl);
     
  5. LightElf

    LightElf New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2005
    Сообщения:
    13
    Спасибо TarasCo за пояснение.

    Мне не нужно выделять буфер - он уже выделен и сделан non-pageble. Но: я не знаю его линейный адрес (такое вот хреновое лето), но знаю что в нем будет лежать сигнатура. Поэтому я хочу:

    1) мапя по одной страничке (с помощью MmMapIoSpace/ MmUnmapIoSpace) просмотреть всю физическую память в поисках страниц с сигнатурой.

    2) создать MDL, руками заполнить ее номерами физических страниц, найденных на предыдущем этапе.

    3) прикрутить полученную MDL к некоторому линейному адресу.



    Пока вытанцовывается такая картина:

    1) через MmAllocateMappingAddress резервируем кусок адресного пространства нужного размера.

    2) через IoAllocateMdl создаем для него MDL, заполняем его ручками

    3) с помощью MmMapLockedPagesWithReservedMapping прикручиваем страницы MDL к зарезервированному на первом этапе адресному пространству.



    Осталось разобраться с содержимым MDL :)
     
  6. TarasCo

    TarasCo New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2005
    Сообщения:
    106
    А зачем такие сложности?

    Если ты пробежишь по памяти и выяснишь номера физическиз страниц, где лежит твой буфер, а затем сам создашь MDL, то дальше можно пойти документированным путем:

    MmMapLockedPages - система сама найдет диапазон виртуальных адресов, куда можно отобразить твой набор и проделает это. Зачем делать чужую работу?



    Кроме того, просмотреть физическую память можно без MmMapIoSpace. Есть секция //Device//PhysicalMemory - туда замеплена физическая память и смещение от начала секции соответсвует смещению от 0 линейного адреса.
     
  7. LightElf

    LightElf New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2005
    Сообщения:
    13




    От 0 физического адреса наверно?







    Как? Просто выделить место из nonpageble pool нужного размера и руками создать заголовок?
     
  8. TarasCo

    TarasCo New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2005
    Сообщения:
    106
    Чето мой пост не дошел или меня забанили?



    От 0 физического адреса наверно?

    так точно



    Как? Просто выделить место из nonpageble pool нужного размера и руками создать заголовок?

    MDL можешь как хочешь сляпать. Но таблицу PFN нужно руками заполнять. Нужно заметить, PFN - это не физический адрес страницы. Вычисляется он примерно так:

    #define PHYSICAL_ADDRESS_TO_PFN(addr)(((ULONG)addr << 3) >> 15)

    на других платформах, возможно, по другому
     
  9. LightElf

    LightElf New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2005
    Сообщения:
    13




    Вот! Это собственно и есть ключевой аспект :) Теперича я знаю кто есть ху. Спасибо!

    Я еще приду с новыми вопросами :)
     
  10. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    <font color="gray][ LightElf</font><!--color--><font color="gray]: ZwQuerySystemInformation... А оно разве из драйвера доступно? ]</font><!--color-->



    Да. Без проблем.





    <font color="gray][ TarasCo</font><!--color--><font color="gray]: на других платформах, возможно, по другому ]</font><!--color-->



    #define MI_CONVERT_PHYSICAL_TO_PFN(Va) (((ULONG)Va << 2) >> (PAGE_SHIFT + 2))





    <font color="gray][ LightElf</font><!--color--><font color="gray]: Как? Просто выделить место из nonpageble pool нужного размера и руками создать заголовок? ]</font><!--color-->



    Вобщем да.


    Код (Text):
    1.     PMDL   MDL,
    2.     PVOID  Base,
    3.     SIZE_T Length
    4.     SIZE_T MdlSize;
    5.  
    6.     MdlSize = MmSizeOfMdl( Base, Length );
    7.  
    8.     MDL = (PMDL) ExAllocatePoolWithTag( NonPagedPool, MdlSize, 'ldmM' );
    9.  
    10.     MmInitializeMdl( MDL, Base, Length );


    В качестве Base указываешь любой адрес, в качестве Length - кол-во твоих страниц * PAGE_SIZE. Дальше в массив страниц заносишь номера твоих физических страниц, т.е. PFN = физический адрес >> PAGE_SHIFT. Это практически тоже самое, что делает MmCreateMdl .



    Но ты так не делай ;) Ибо как система будет воспринимать такой МДЛ я не знаю. Ведь эти страницы на самом деле отображены на другие виртуальные адреса и что ты будешь указывать в качестве Base? И что будет в случае если страницы будут маленькие и большие?
     
  11. LightElf

    LightElf New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2005
    Сообщения:
    13




    Ну спасибо ;)

    Я собственно потому и хочу использовать MmAllocateMappingAddress чтобы иметь виртуальный адрес за которым заведомо нет никакой памяти. Тогда я смогу его использовать как Base направо-налево. Ну а то, что физические страницы имеют несколько алиасных виртуальных адресов - на то вроде бы и сделана виртуальная память.





    А вот этого точно не будет. Все страницы будут по 4кб.
     
  12. TarasCo

    TarasCo New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2005
    Сообщения:
    106
    Но ты так не делай ;) Ибо как система будет воспринимать такой МДЛ я не знаю. Ведь эти страницы на самом деле отображены на другие виртуальные адреса и что ты будешь указывать в качестве Base? И что будет в случае если страницы будут маленькие и большие?



    А чего такого то?

    Физические страницы можно отобразить хоть на (ну не знаю... ) ну хоть на 2 :) Различных адресных диапазона.

    Им то по барабану.



    2 LightElf:

    Напиши о результатах, интересно ж :)
     
  13. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    <font color="gray][ TarasCo</font><!--color--><font color="gray]: Физические страницы можно отобразить хоть на... ]</font><!--color-->



    Отобразить то можно, но они же не отображены, когда мы МДЛ руками делаем. Система то его делает из уже отображенных страниц. Вобщем, всё это очень сильный хак, а сильно думать лень, что будет. Вот поэтому "ты так не делай" ;)
     
  14. TarasCo

    TarasCo New Member

    Публикаций:
    0
    Регистрация:
    2 фев 2005
    Сообщения:
    106
    По идее, если для MDL, у которого BaseVa = 0 и все (в том числе таблица PFN) будет верно заполнена, вызвать MmMapLockedPages (2 Four-F: взгляни туда же, откуда определение MI_CONVERT_PHYSICAL_TO_PFN :) ), то ядро само ваыделит достаточный непрерывный диапазон виртуальной памяти для отображения физических страниц. Это конечно хак, но не такой уж сильный :). А вот использование MmAllocateMappingAddress на мой взгляд лдишнее ( и по сути тот же хак и андок)
     
  15. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    <font color="gray][ TarasCo</font><!--color--><font color="gray]: 2 Four-F: взгляни туда же... ]</font><!--color-->



    Да хрен с ним. Своего геморра хватает ;)
     
  16. LightElf

    LightElf New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2005
    Сообщения:
    13
    В общем всем спасибо. Похоже что метода работает. На реальном драйвере пока не проверял, наваял кролика простейшего (через один IOCTL выделяет locked буфер и заполняет его сигнатурой, через другой - сканит физпамять и создает искомый маппинг). Посмотрим потом, как себя это будет вести на боевой системе - может в стрессе система подлянку какую выкинет.



    последовательность действий такая:

    ptr = MmAllocateMappingAddress(size, tag);

    pMdl = IoAllocateMdl(ptr, size, FALSE, FALSE, NULL);



    Дальше заполняем PFN и делаем MmMapLockedPages.



    Так что вот такие извращения для тривиальной вроде бы задачи.
     
  17. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    LightElf, если не секрет, как ты определяешь что пейдж локед аль нет?
     
  18. LightElf

    LightElf New Member

    Публикаций:
    0
    Регистрация:
    24 фев 2005
    Сообщения:
    13
    Никак не определяю - я заведомо это знаю. То есть в моем случае я точно знаю, что страницы, составляющие искомый буфер, локед :)