Geoff Chappell - Software Analyst
A possibly useful demonstration of the x86 BIOS emulator is to have a driver execute int 15h function E820h on a running system in order to discover the memory map that the loader will have worked from in deciding what memory Windows can use.
The value of such a map is increased beyond mere curiosity now that computers typically have gigabytes of RAM. Indeed, many computers are now sold with more RAM than can fit in what’s left of the first 4GB of physical address space after an increasing number of increasingly greedy peripheral devices each take their cut. Some chipsets, perhaps many, deal with this reasonably elegantly by remapping much of the excess RAM to the end of all other RAM that is anyway addressable above 4GB. Some don’t. Either way, since Microsoft does not license 32-bit Windows Vista to use physical memory above 4GB, most users just end up wondering where the missing part of their 4GB has gone, manufacturers have to warn that not all the 4GB will be usable, and the Internet gets to show how very good it is at propagating all manner of supposed explanations.
If you’re using 32-bit Windows Vista on a computer that has 4GB or more of RAM fitted, and you wonder what your options are for getting all that memory into use, then you might benefit from knowing whether any RAM that doesn’t show below 4GB is remapped above 4GB. The Firmware Memory Map Tool presented on this page will give you this information. If you find that no RAM is reported above 4GB, then the RAM that is overridden below 4GB is truly lost. Even installing 64-bit Windows will not help, and you are clearly better off to know before trying. If you do have RAM above 4GB, then you can know how much you stand to gain from getting a Windows that isn’t limited to 4GB.
Three options would seem to be possible from Microsoft:
Unfortunately, Microsoft shows no sign of offering the last despite its being obviously the least costly (by far) to users who have perfectly adequate computers and applications and have no wish to be mucked around with installing an operating system, even as an upgrade, and possibly also reinstalling their software. Since Microsoft seems nowhere to say directly that the restriction of 32-bit Windows Vista to 4GB is a licensing issue, it seems unlikely that a license upgrade will ever be offered. Even so, the driver and utility program presented below does at least give users the means to know that their computer with 4GB of RAM has 768MB (or whatever) sitting above the 4GB address, and they can then ask Microsoft for permission to have Windows use that extra memory. How much does Microsoft think this permission should cost a customer, I wonder, not just in money paid to Microsoft but in the customer’s time which is lost to nobody’s benefit?
The FWMEMMAP.SYS driver exists just to reproduce the loader’s memory map by calling int 15h function E820h enough times to retrieve the whole memory map and then to make the result accessible from user mode via a Device I/O Control interface. The FWMEMMAP.EXE utility is a console application that exists just to load the driver, ask it for the map, show the map to you, and then unload the driver.
The driver calls the BIOS by using the HAL’s real-mode emulator, which is conveniently new for Windows Vista. One of the points to this introduction of BIOS support through an emulator is presumably that it should work for both the x86 and x64 architectures, without Microsoft having to build into 64-bit Windows all the support needed for getting the processor to execute 16-bit real-mode code in a virtual-8086 task. So that you may see this works, I provide x64 builds of the driver and program, even though I do not imagine they are much use in practice. After all, if you have 64-bit Windows, you do not need this utility to tell you whether any RAM is remapped to be addressable above 4GB.
You should be aware that the driver uses five undocumented kernel-mode functions:
If you are troubled about software using features that the manufacturer does not disclose, then do not use this driver.
Now, I should point out that there are some risks with the BIOS emulation on a running system. The HAL interprets the real-mode code that would execute if an interrupt actually were called in real mode, e.g., by a DOS program running on a machine that has booted DOS, or indeed by the Windows loaders (both BOOTMGR and WINLOAD) before the kernel runs. Wherever the real-mode code would execute port I/O instructions, the HAL actually may read from or write to the port. There is at least some potential that port I/O for the emulator interferes with port I/O being performed concurrently by drivers. Except for CMOS and PCI ports, there seems to be no means of synchronisation. Though conflict over port I/O seems highly improbable for int 15h function E820h, it perhaps is not impossible.
The following example should be typical of the tool’s output. The machine in question is fitted with 4GB of RAM (as four 1GB chips). Much of the address space immediately below 4GB is not usable for RAM, but 768MB is remapped to be usable above 4GB.
Map of firmware memory ranges (from int 15h function E820h)
Address Size Type
=================== =================== =================
0x00000000`00000000 0x00000000`0009E800 1 (memory)
0x00000000`0009E800 0x00000000`00001800 2 (reserved)
0x00000000`000F0000 0x00000000`00010000 2 (reserved)
0x00000000`00100000 0x00000000`CFD90000 1 (memory)
0x00000000`CFE90000 0x00000000`00053000 4 (ACPI NVS)
0x00000000`CFEE3000 0x00000000`0000D000 3 (ACPI Reclaim)
0x00000000`CFEF0000 0x00000000`00010000 2 (reserved)
0x00000000`E0000000 0x00000000`10000000 2 (reserved)
0x00000000`FEC00000 0x00000000`01400000 2 (reserved)
0x00000001`00000000 0x00000000`30000000 1 (memory)
Summary (in MB, ignoring partial MB):
Total memory: 4094
Memory above 4GB: 768
Ranges that are addressable as RAM are marked “memory”. To interpret other values in the Type column, refer to the definition of int 15h function E820h in the Advanced Configuration and Power Interface (ACPI) Specification, Section 14, System Address Map Interfaces. Note that the map has holes: int 15h function E820h does not report “standard PC address ranges” or areas of address space that are used “for the memory mapping of PCI devices, ISA Option ROMs, and ISA Plug and Play cards”.
For distribution, the Firmware Memory Map Tool is compressed into zip files:
The driver and the program must be in the same directory. Just run the program from a Command Prompt. You will need administrative privilege. On an x64 system, you will need to start Windows in Test Mode, i.e., with testsigning enabled in the Boot Configuration Data (BCD). For 32-bit Windows, Test Mode is merely optional but it does spare you from a warning in the event log (specifically in Microsoft-Windows-CodeIntegrity/Operational). On both architectures, loading the driver will typically cause warnings in the System log from the Windows Defender.
The restriction to Test Mode on x64 systems is because the executables are signed with a root certificate only. I am not a software manufacturer and do not have a Software Publishing Certificate (SPC) for signing kernel-mode drivers. Yes, I am a specialist in kernel-mode drivers, but I write them for other people to publish, and the release-signing of the products they sell is done by them, not by me. Getting an SPC is a lot of trouble to go to for a simple utility that will likely be run only once on any one machine. Test Mode seems perfectly reasonable to me. If you don’t like Test Mode but do have an SPC, then re-sign the driver as your own.
Source code is provided as a root directory and three subdirectories:
The code is written for use with the Windows Driver Kit (WDK). To build the executables, open one of the WDK’s build environments for Windows Vista, change to the root directory of this source tree, and run the WDK’s BUILD utility.
To have the binaries and symbol files be collected in a tree beneath a subdirectory named BIN, undefine the environment variable NO_BINPLACE before running BUILD. For details, refer to the PROJECT.MK file in the root directory of the source tree.
The executables are not signed unless you define one or more environment variables before building. If you are happy for test-signing with a root certificate named My Own Testing Authority which you have already created and imported into your personal certificate store, then define the environment variable SIGNCODE. Otherwise, describe your certificate by defining environment variables SIGNCODE_CERTIFICATE_STORE and SIGNCODE_CERTIFICATE_NAME, and optionally SIGNCODE_CROSS_CERTIFICATE and SIGNCODE_TIME_STAMPER. For details, refer to the PROJECT.MK file in the root directory of the source tree.