Re: Fill Frame Buffer in Video Driver Initialization

Tech Tip: Click here to run a free scan for Windows Errors and optimize PC performance



OK Lucio,

lsimoni a écrit :
Remi,

Thanks for you patience. I'm obviously lacking in understanding the fundamentals of my BSP. I"m using an ETX module with an AMD GeodeLx processor, so the display should be a PCI device. There was very little documentation that came with the board, and the manufacturer has been of no help in this matter. Microcontrollers are so much easier to understand...


I agree with you that the display should be a PCI device.
I guess that the right hardware documentation should be found at AMD's but I am definitely not a Geode expert.

So bootloader's buffer is located at physical address 0x6E000000 and is 128 KB large. Does it make sense with your hardware?

This doesn't make sense, there is only 512Mb of memory, giving an address limit of 0x20000000.

0x6E000000 could be the address of an intermediate PCI window used to 'cleverly' access the actual RAM where the frame buffer lays. On Intel's modern graphics controller, this is quite common. So the actual RAM buffer may be somewhere else (0xA0000-0xBFFFF ?), even if access to this RAM should be done through the PCI window.
BTW, are you sure that the video resolution used by the bootloader is the same that the one your driver will use?

I guess since it's a virtual mapping, the system could be mapping this from anywhere, right? I just don't see any references in the bootloader. It gets the memory map from the Vesa settings, does that come straight from the BIOS?


It looks like the bootloader gets the buffer address here
pBootArgs->pvFlatFrameBuffer = vesaModeInfo.dwPhysBasePtr;
and then assigns the Framebuffer here
FlatFrameBuffer = (PBYTE)TempBootArgs.pvFlatFrameBuffer;

When it draws the splash screen, it references the FlatFrameBuffer.


It is interesting to see that the flat physical address is given by the BIOS and passed to the BootArgs: this means that you should be able to use the VGA Flat display driver just as it.



You can't copy things this way. memcpy uses virtual addresses and both source and destination must be accessible as virtual addresses. I don't know for 0xD2BF0000 (which really looks like a virtual address!) but at least 0x6E000000 (IF it is a physical address!) has to be mapped into the virtual address space of the driver.
This is where I should use the VirtualAlloc in the video driver, right? Once I allocte the memory, I can then copy it. However, in the MSDN documentation for VirtualAlloc, it says that memory allocated will be initialized to zero. Wouldn't that clear the bitmap that I'm trying to copy to the video driver buffer?

Used with the MEM_RESERVE flag, VirtualAlloc does not actually allocate physical memory but simply reserve virtual space (page table entries.) The VirtualCopy that follows writes the actual physical addresses into the PTE, doing the virtal to physical mapping.

From VGAFLAT driver:
m_VirtualFrameBuffer = (DWORD)VirtualAlloc(0, fbSize, MEM_RESERVE, PAGE_NOACCESS);
VirtualCopy((void *)m_VirtualFrameBuffer, (void *)(m_pvFlatFrameBuffer >> 8), fbSize, PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL);

MmMapIoSpace does this in a single operation.


I'll start digging in the Bios and see if I can see any mappings there. If I can't find anything there, I'll try to dig up the hardware datasheets.

If I were you, I'd begin by the datasheets :o)

Good luck.
Remi



Thanks again,
Lucio

"R. de Gravelaine" wrote:

Hi,

lsimoni a écrit :
I found that the Bootloader is using address 0xEE000000 for it's framebuffer. I've added this address to the config.bib:

FRAMEBUF 800A0000 00020000 RESERVED
DOSBUF EE000000 00020000 RESERVED

So bootloader's buffer is located at physical address 0x6E000000 and is 128 KB large. Does it make sense with your hardware?

And I've tried to do a memcpy in the display driver to copy the contents from the DOSBUF (bootloader) to the FRAMEBUF (windows buffer) and it still doesn't work.

Display driver copy memory code:

*DestBuffer=0xD2BF0000; //Address of windows framebuffer
*SourceBuffer=0xEE000000; //Address of bootloader framebuffer
memcpy(DestBuffer,SourceBuffer,0x00600000); // transfer bootloader buffer to windows

You can't copy things this way. memcpy uses virtual addresses and both source and destination must be accessible as virtual addresses. I don't know for 0xD2BF0000 (which really looks like a virtual address!) but at least 0x6E000000 (IF it is a physical address!) has to be mapped into the virtual address space of the driver.

The part that's confusing now is that the bootloader is using 0xEE000000 for it's buffer, but how can that be a physical memory address? There's only 512M available in the system, limiting the address range to 0x20000000. Even if we clear bit 31, that still makes it 0x6E000000, over the range of the physical memory.

So you have the answer: 0xEE000000 is not a physical address, unless you have a dedicated frame buffer mapped at physical 0x6E000000, or it is a window in PCI space. I don't know about your hardware but you should really focus on the way the display controller works, and specially on the way it maps the frame buffer.

I've been under the assumption that only windows knows about virtual memory and the booloader would be forced to use physical memory.


Am I on the right track?

Don't make such assumptions. Some bootloaders do their memory mappings late, some others do it earlier. The only way to understand what actually happens is to read the source code of the bootloader, and the documentation for your hardware.

HTH
Remi

Thanks again for your help. "R. de Gravelaine" wrote:

lsimoni a écrit :
I thought of the same thing, seemed easy. But when I changed the bootloader's frame buffer to what windows was using, there was nothing on the screen foor the bootloader.

For the windows video driver, the debug output is:
LX Graphics: FB Virtual = 0xD2BF0000
Which means that I need to find out the physical address of this virtual mapping, right? How do I translate from virtual memory back to physical memory? I'm guessing that the bootloader knows nothing about virtual memory and is strictly using a physical addresses.
If you want to copy into driver's frame buffer the contents of the boot frame buffer, you need to map boot physical frame buffer address (might be 0x7E000000 - see how memory is mapped in your bootloader) into something virtual that can be accessed at driver time. To achieve this, you can use VirtualAlloc/VirtualCopy or MmMapIoSpace.
Of course, the frame buffer layout must be identical in both contexts.
Another problem may come from the fact that memory used by the bootloader has been used by the system, which is not supposed to preserve it if it has not been reserved in config.bib.

I tried to use some of the remote tools like the Process viewer, and I can see the video driver Lxvideo.dll at Base Addr C09E0000, but that's the driver address, not the buffer. Plus, that's probably another virtual address.

In my config.bib I see an entry of FRAMEBUF 800a0000 00020000
Is this a physical address?
This is the physical address for 0x000A0000, where the legacy VGA frame buffer lays. Under CE, kernel addresses have bit 31 set.

So first check the physical location of the frame buffer used by the bootloader. Once you got it, reserve it in config.bib then make the physical to virtual translation in the display driver, initialize the hardware and make the memcpy. Don't try to use what will be drivers frame buffer in the bootloader, as it is probably dynamically allocated and may change from one image to an other.

HTH
Remi

.


Quantcast