Allocating memory below 1MB

I have a real mode component (integrated into the BIOS) that I need to allocate memory below 1MB boundary for from my Windows OS driver. It needs to be 1 page size (actually less than that). The driver and the real mode component basically use this memory block as a scratchpad

I see the call MmAllocateContiguousMemorySpecifyCacheNode. Will this work?. I will try this out but I am just curious. I need this to work on both 32-bit and 64-bit environments (only x86 class processors)

Under what conditions (beyond memory intensive conditions I guess) can this fail?.

Thanks,
Ramakrishna Saripalli

What is the nature of your device? In particular, does ACPI know about it and must the region be < 1MB?

Also, what verisons of the OS must this run on. Windows 7+ (I think Vista as well) no longer use this area of memory (< 1MB) for OS storage due to corruption issues upon resuming from sleep.

mm

wrote in message news:xxxxx@ntdev…
> I have a real mode component (integrated into the BIOS) that I need to
> allocate memory below 1MB boundary for from my Windows OS driver. It needs
> to be 1 page size (actually less than that). The driver and the real mode
> component basically use this memory block as a scratchpad

??? What is realmode component?
Windows runs in protected mode, so while it is up, no real mode components
can run.
Do you mean SMM or a boot ROM?
–pa

> I see the call MmAllocateContiguousMemorySpecifyCacheNode. Will this
> work?. I will try this out but I am just curious. I need this to work on
> both 32-bit and 64-bit environments (only x86 class processors)
>
> Under what conditions (beyond memory intensive conditions I guess) can
> this fail?.
>
> Thanks,
> Ramakrishna Saripalli
>

> What is the nature of your device?

Unless the OP happens to be OEM (which I seriously doubt) I just wonder how it may be possibly “integrated into the BIOS”. To be honest, it looks pretty much like a rootkit that operates
at the sub-OS level - driver is a channel via which rootkit communicates with the system, and the page he asks about. is meant to be a container for messages that rootkit and driver pass to one another…

In particular, does ACPI know about it

Apparently, not - if its services were available via ACPI tables it would not be “a real mode component”, in the first place. …

Anton Bassov

This is a typical preboot authentication issue, e.g. for software-based disk encryption.
You need some memory space to pass authentication data from realmode to protected mode.
I guess that “integrated into the BIOS” simply means that the memory range is set by Int15h.

Else

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.com
Sent: Dienstag, 8. Dezember 2009 05:26
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Allocating memory below 1MB

What is the nature of your device?

Unless the OP happens to be OEM (which I seriously doubt) I just wonder how it may be possibly “integrated into the BIOS”. To be honest, it looks pretty much like a rootkit that operates
at the sub-OS level - driver is a channel via which rootkit communicates with the system, and the page he asks about. is meant to be a container for messages that rootkit and driver pass to one another…

In particular, does ACPI know about it

Apparently, not - if its services were available via ACPI tables it would not be “a real mode component”, in the first place. …

Anton Bassov


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Utimaco Safeware AG
A member of the Sophos Group
Hohemarkstr. 22
61440 Oberursel
Germany

Registergericht Bad Homburg HRB 5302
WEEE-Reg.Nr.: DE39805015
Sitz: Oberursel
Vorstandsmitglieder: Steve Munford (Vorsitzender), Jeff Babka, Malte Pollmann, Olaf Siemens
Aufsichtsratsvorsitzender: Dr. Peter Lammer

> -----Original Message-----

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@hotmail.com
Sent: Tuesday, December 08, 2009 5:26 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Allocating memory below 1MB

Unless the OP happens to be OEM (which I seriously doubt) I
just wonder how it may be possibly “integrated into the
BIOS”.

Simply. You give your code to OEMs who integrate it to their BIOS. We’re
doing it with our PBA code.

Best regards,

Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]

> You need some memory space to pass authentication data from realmode to protected mode.

Please read his post carefully - he wants to allocate memory in a driver, i.e. when the CPU is already in protected mode, which somehow suggests that switching between real and protected modes is meant to take place while the OS is running. If the whole thing was unidirectional (i.e. real mode code passes parameters to the OS and never gets the CPU back) there would be no need to allocate memory in a driver, in the first place.

Furthermore, pay a special attention to his requirement of target range residing below 1M. Apparently, he wants to map this memory identically by modifying PTEs (this virtual range is unused anyway so that he is not going to get into a conflict with anyone), copy a code that disables paging and switches the CPU to the real mode into the target range, and jump to it…

Anton Bassov

>I have a real mode component (integrated into the BIOS) that I need to allocate memory below 1MB

boundary for from my Windows OS driver. It needs to be 1 page size (actually less than that).

Sorry, but, after Windows is booted, the real mode is dead forever and no code can be executed in real mode.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

>You need some memory space to pass authentication data from realmode to protected mode.

Correct, but the OP wants to do vice versa - pass data from Windows to real mode code.

For the task described by you, I would suggest to cut the low memory block a bit by hooking the real mode int 15h memory map call and returning the new memory map to the caller, with your memory being marked as a special block.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Maxim S. Shatskih wrote:

> I have a real mode component (integrated into the BIOS) that I need to allocate memory below 1MB
> boundary for from my Windows OS driver. It needs to be 1 page size (actually less than that).
>

Sorry, but, after Windows is booted, the real mode is dead forever and no code can be executed in real mode.

True, but it IS possible to drop into V86 mode. Many display driver
miniports do this to call their BIOS routines for mode setting. The
video port driver even has entry points to make it possible.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> True, but it IS possible to drop into V86 mode. Many display driver

miniports do this to call their BIOS routines for mode setting. The
video port driver even has entry points to make it possible.

OK, then allocating in real mode by hooking int 15h and returning the patched memory map to NTLDR/BootMgr is a good idea.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

> Sorry, but, after Windows is booted, the real mode is dead forever and no code can be

executed in real mode.

This is quite an exaggeration - what you should have said is “not supposed to be executed”, because, in actuality, as long as you run in the kernel mode nothing holds you back from switching into a real mode…

All you need to do to switch back to the real mode is to map some memory range identically. If you do it you will be able to disable paging while executing in the target range, effectively getting into a protected mode without paging, and, at this point, switching into a real mode is just trivial. Furthermore, as long as you don’t modify protected-mode selectors, i.e. the ones that point to flat 32-bit segments in GDT you will be able to address 4G of memory while running in real mode (this trick is known as so-called “unreal mode”). As long as you know what you are doing you will be able to do whatever you want transparently to the OS, and return back to the protected mode with paging enabled as if nothing had ever happened.

It is needless to say that one would not normally expect it from a “good” driver. This is why the very first thing that got into my head after I saw the original post is that the OP writes a rootkit…

Anton Bassov

> For the task described by you, I would suggest to cut the low memory block a bit by hooking

the real mode int 15h memory map call and returning the new memory map to the caller,
with your memory being marked as a special block.

If you mark a range as reserved by BIOS the OS is going to treat it as non-existing one. Therefore, once you driver happens to run within an OS it will be unable to access it by “proper” means - again, you need something “not-so-trivial” to make it work…

Anton Bassov

> If you mark a range as reserved by BIOS the OS is going to treat it as non-existing one. Therefore,

once you driver happens to run within an OS it will be unable to access it by “proper” means - again,
you need something “not-so-trivial” to make it work…

Like MmMapIoSpace, for instance.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

> Like MmMapIoSpace, for instance.

First of all, how are you going to pass the target physical address from real-mode component to a driver??? This is the first issue that you have to address.

Second,when it comes to mapping physical page(s) to virtual address I suspect that using any system-defined mapping mechanism may be problematic in our situation.

When you map physical range to the virtual one the system will, apparently, have to increment refcount in PFN database entries that correspond to the pages in the target physical range - otherwise the system will be unable to make any distinction between physical pages that are currently in use and unused ones. If the system believes that physical memory range is reserved by BIOS, it is probably just not going to set up valid PFN database entries for pages in this range - it may well happen that, from the system’s perspective, you are just passing an invalid physical address to MmMapIoSpace()…

Anton Bassov

>the system’s perspective, you are just passing an invalid physical address to MmMapIoSpace()…

MmMapIoSpace has nothing to do with PFN database - imagine your device’s PCI BARs, they have no PFN entries for sure.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

>imagine your device’s PCI BARs, they have no PFN entries for sure.

Fair point…

Anton Bassov

Maxim,

MmMapIoSpace has nothing to do with PFN database - imagine your device’s PCI BARs,
they have no PFN entries for sure.

Actually, after thinking a bit I realized that your argument about BARs strongly suggests that my reasoning that I stated earlier is, indeed, well-founded. Consider the case when you map RAM page with MmMapIoSpace(). In such case PFN refcount for the target page has to be incremented for the reason I stated earlier. However, in case of memory-mapped device there is no PFN involved
(the same holds true for ROM, local APIC , IOAPIC and whatever else that may appear as memory-mapped device).

Therefore, MmMapIoSpace() has to check whether your target address corresponds to system RAM or to some other addressable region - it obviously does not bluntly modify PTEs without any extra checking. Once it does some checks, it has all chances to see that you are trying to map a region that, from the OS’s perspective, just does not exist . Therefore, it may just return NULL…

If you don’t mind, could you please test it - just pass some plainly invalid address to MmMapIoSpace() and let’s see what happens next( I would do it myself but I haven’t got Windows machine anywhere around)

Anton Bassov

Anton, do we really have to go through this again?

When you run out of actual information, could you please just stop typing?
The people on this list would be happy to read your posts when you do have
the actual answer, which is actually quite frequently.

MmMapIoSpace will map any physical address. It doesn’t check the underlying
physical address before making a mapping. The only thing it does is chase
down any existing PTEs for the range to see if their cache mappings
conflict. Then it changes the cache attributes to something more or less
compatible with the existing mappings. (This is why you really shouldn’t
try to map anything you don’t own in your assigned resources.)

P.S. APICs, both local an I/O, are handled entirely separately, internally
by the HAL, from PTEs that the HAL owns, before the memory manager even
initializes.


Jake Oshins
Hyper-V I/O Architect
Windows Kernel Group

This post implies no warranties and confers no rights.


wrote in message news:xxxxx@ntdev…
>
>
> Maxim,
>
>>MmMapIoSpace has nothing to do with PFN database - imagine your device’s
>>PCI BARs,
>> they have no PFN entries for sure.
>
> Actually, after thinking a bit I realized that your argument about BARs
> strongly suggests that my reasoning that I stated earlier is, indeed,
> well-founded. Consider the case when you map RAM page with MmMapIoSpace().
> In such case PFN refcount for the target page has to be incremented for
> the reason I stated earlier. However, in case of memory-mapped device
> there is no PFN involved
> (the same holds true for ROM, local APIC , IOAPIC and whatever else that
> may appear as memory-mapped device).
>
> Therefore, MmMapIoSpace() has to check whether your target address
> corresponds to system RAM or to some other addressable region - it
> obviously does not bluntly modify PTEs without any extra checking. Once it
> does some checks, it has all chances to see that you are trying to map a
> region that, from the OS’s perspective, just does not exist . Therefore,
> it may just return NULL…
>
> If you don’t mind, could you please test it - just pass some plainly
> invalid address to MmMapIoSpace() and let’s see what happens next( I
> would do it myself but I haven’t got Windows machine anywhere around)
>
>
> Anton Bassov
>
>

Since it maps memory, any idea why it is called MmMapIoSpace?

x86 processors have both a memory space and an IO space.

Mike Loving


From: Jake Oshins
To: Windows System Software Devs Interest List
Sent: Thu, December 10, 2009 10:08:58 AM
Subject: Re:[ntdev] Allocating memory below 1MB

Anton, do we really have to go through this again?

When you run out of actual information, could you please just stop typing? The people on this list would be happy to read your posts when you do have the actual answer, which is actually quite frequently.

MmMapIoSpace will map any physical address. It doesn’t check the underlying physical address before making a mapping. The only thing it does is chase down any existing PTEs for the range to see if their cache mappings conflict. Then it changes the cache attributes to something more or less compatible with the existing mappings. (This is why you really shouldn’t try to map anything you don’t own in your assigned resources.)

P.S. APICs, both local an I/O, are handled entirely separately, internally by the HAL, from PTEs that the HAL owns, before the memory manager even initializes.

– Jake Oshins
Hyper-V I/O Architect
Windows Kernel Group

This post implies no warranties and confers no rights.

--------------------------------------------------------------

wrote in message news:xxxxx@ntdev…
>
>
> Maxim,
>
>> MmMapIoSpace has nothing to do with PFN database - imagine your device’s PCI BARs,
>> they have no PFN entries for sure.
>
> Actually, after thinking a bit I realized that your argument about BARs strongly suggests that my reasoning that I stated earlier is, indeed, well-founded. Consider the case when you map RAM page with MmMapIoSpace(). In such case PFN refcount for the target page has to be incremented for the reason I stated earlier. However, in case of memory-mapped device there is no PFN involved
> (the same holds true for ROM, local APIC , IOAPIC and whatever else that may appear as memory-mapped device).
>
> Therefore, MmMapIoSpace() has to check whether your target address corresponds to system RAM or to some other addressable region - it obviously does not bluntly modify PTEs without any extra checking. Once it does some checks, it has all chances to see that you are trying to map a region that, from the OS’s perspective, just does not exist . Therefore, it may just return NULL…
>
> If you don’t mind, could you please test it - just pass some plainly invalid address to MmMapIoSpace() and let’s see what happens next( I would do it myself but I haven’t got Windows machine anywhere around)
>
>
> Anton Bassov
>
>


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit: http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer