Page 3 of 3

Re: Emulating BIOS for VBE

Posted: Mon Dec 30, 2013 7:00 am
by Brendan
Hi,
rdos wrote:
Owen wrote:For those machines which no option ROM in PCI space (but instead one at 0xC0000), do they have PCI expansion headers? If so, that would seem like a good cross check (you might also want to scan the entire option ROM space).
No. When I read PCI register 0x30, it always returns 0. This is regardless of what I write to it, like 0xFFFFF000 or 0xFFFFF001 to detect depth. On the machine that does support register 0x30, it returns 0xFFFE0000.
For systems that have video built into the motherboard or CPU (lots of them), it's relatively normal for the PCI device itself to have no ROM at all. In this case the code that would've been in the video device's ROM is normally in the system's flash memory somewhere instead (possibly anywhere, and possibly compressed somehow).
rdos wrote:Given this, I think the algorithm will be to first search for option ROMs, and if those are found, map them to physical address 0xC0000, allocate space for the RAM copy, and copy contents of the BIOS ROM version. Then map this RAM copy to 0xC0000 linear. If an option ROM is not found, map physical address 0xC0000 to linear address 0xC0000. After that, check for a value AA55 signature, and if found, do the VBE initialization.
No.

If the device does have a ROM, then you map that option ROM anywhere you like (typically somewhere in the "PCI hole") and search for the "ROM image" you want. Then (if the "ROM image" you want exists) you need to:
  • Ensure the "fixed range MTTRs" (in all CPUs) have the area from 0x000A0000 configured as "uncached". For a pure UEFI system there's no guarantee that this area isn't normal RAM configured as "write-back" caching.
  • Mess with the memory controller to configure the area at 0x000C0000 as "reads and writes go to RAM". Note that the PCI specification will tell you that the option ROM's code will expect to be able to write to itself (which is why you can't just map the ROM itself at 0x000C0000). For a "BIOS system" this area will probably be left as "reads go to RAM, writes go to PCI" by the firmware, which isn't what you need.
  • Mess with the memory controller again to configure the area from 0x000A0000 to 0x00BFFFF as "reads and writes go to PCI". Be warned that in a lot of systems the firmware hides the "SMM RAM" underneath this area (so that when the CPU is in SMM mode reads and writes to this area go to RAM, and when the CPU is not in SMM mode reads and writes go to wherever the memory controller says). Accidentally messing up the firmware's ability to access its own SMM code would be very bad; so don't be too surprised if your ability to mess with the memory controller is hampered by "write once" chipset lock/s.
  • Copy the "ROM image" to the RAM at 0x000C0000, so it is where it expects to be
  • Make sure the "VGA enable" bit is set in the configuration space for all PCI bridges in the path from the host controller to the video device; and make sure the "VGA enable" bit is clear for any bridges that aren't on this path (otherwise the same IO port or memory access can get forwarded to multiple different video cards and cause large quantities of confusion).
  • Reset the video device to its "power on" state. If the video device has already been configured by firmware during boot, then it may be in a "native mode" state (e.g. where memory mapped registers are enabled and "legacy VGA IO port registers" are disabled) and no longer compatible with its own VBE ROM.
  • Call the "ROM image" entry point.
  • After this, you should reconfigure the RAM at 0x000C0000 as "reads go to RAM and writes go to PCI". I'm not sure that this is strictly required for your case (where you hopefully don't need to worry about other code trashing the video ROM), but it's at least theoretically possible for the video ROM to contain code that does an "am I being called during ROM initialisation test" where the same code behaves differently depending on if the ROM can modify itself or not.
Of course there's no sane way to test that any of the steps above will work correctly on every single computer - there's far too many different permutations of video cards, motherboard/chipsets, firmware versions, etc. For this reason, if you do all this work and test that it works on your computers (e.g. 4 permutations out of a total of many million permutations), you should still disable it all by default because (assuming the hardware supports everything it requires) you'll never be able to guarantee it works on other people's computers.

Please note that you may be lazy and skip some or all of the steps above (e.g. merely hope that the firmware left various things in various states). This will significantly increase the risk of it not working (especially for future UEFI systems).

Also note that the amount of work involved to make it "hopefully reliable maybe (if hardware supports it at all)" is mostly wasted effort. It doesn't get you any closer to having "video mode switching only" native video drivers (which are a necessary first step towards "full function" native video drivers, which should be the long term goal).


Cheers,

Brendan

Re: Emulating BIOS for VBE

Posted: Mon Dec 30, 2013 2:13 pm
by Owen
Brendan,

Let us ignore the matter of onboard graphics for a second. Let us look at just the case when there is a valid option ROM on the PCI graphics card.

You keep on asserting that this option ROM requires all sorts of legacy compatibility infrastructure - e.g. legacy PCI MMIO forwarding - except this isn't true. It is demonstrably not true, because X.Org has been doing this - with surprisingly high reliability - for over a decade on systems which don't even run x86 processors and don't have any legacy backwards compatibility crud because there isn't a legacy to be backwards compatible with!

Lets dismantle some of the assertions:
Brendan wrote:Ensure the "fixed range MTTRs" (in all CPUs) have the area from 0x000A0000 configured as "uncached". For a pure UEFI system there's no guarantee that this area isn't normal RAM configured as "write-back" caching.
You're running the video BIOS under an emulator. You don't need to map the legacy VGA MMIO range at 0xA0000. Map it in a hole anywhere you want and use paging to make it visible to your emulator.
Brendan wrote:Mess with the memory controller to configure the area at 0x000C0000 as "reads and writes go to RAM". Note that the PCI specification will tell you that the option ROM's code will expect to be able to write to itself (which is why you can't just map the ROM itself at 0x000C0000). For a "BIOS system" this area will probably be left as "reads go to RAM, writes go to PCI" by the firmware, which isn't what you need.
Pick some random pages of memory and stick the video BIOS ROM there. Again, the video BIOS doesn't care about its' actual physical address.
Brendan wrote:Make sure the "VGA enable" bit is set in the configuration space for all PCI bridges in the path from the host controller to the video device; and make sure the "VGA enable" bit is clear for any bridges that aren't on this path (otherwise the same IO port or memory access can get forwarded to multiple different video cards and cause large quantities of confusion).
Map it somewhere inside the bridge's normal addressing range and ignore the legacy shenanigans (note: the legacy bit is to support legacy operating systems)
Brendan wrote:Reset the video device to its "power on" state. If the video device has already been configured by firmware during boot, then it may be in a "native mode" state (e.g. where memory mapped registers are enabled and "legacy VGA IO port registers" are disabled) and no longer compatible with its own VBE ROM.
Conveniently, video BIOSes normally have device reinitialization entry points for exactly this purpose! They even work! (Because otherwise the Windows bluescreen doesn't)

I don't claim its' the most preferable (far from it - VBE is after all not a good interface) method, but its' certainly workable as one fallback, with less complexity than might be imagined.

And indeed, you'll find it works more often than you might expect - because its' the normal method Windows uses to switch to the correct mode for the BSOD.

Re: Emulating BIOS for VBE

Posted: Tue Dec 31, 2013 2:47 pm
by Brendan
Hi,
Owen wrote:Let us ignore the matter of onboard graphics for a second. Let us look at just the case when there is a valid option ROM on the PCI graphics card.

You keep on asserting that this option ROM requires all sorts of legacy compatibility infrastructure - e.g. legacy PCI MMIO forwarding - except this isn't true.
Um, you're saying that the option ROM requires all sorts of legacy compatibility infrastructure too. The only difference is that you're proposing "whole system emulation" as a work-around for missing legacy compatibility infrastructure.
Owen wrote:It is demonstrably not true, because X.Org has been doing this - with surprisingly high reliability - for over a decade on systems which don't even run x86 processors and don't have any legacy backwards compatibility crud because there isn't a legacy to be backwards compatible with!
X.Org does still have a dodgy old "VBE fallback driver" that nobody uses anymore. Attempting to pretend that it's used for everything (and is 100% reliable in all cases) is extremely dishonest.
Owen wrote:Conveniently, video BIOSes normally have device reinitialization entry points for exactly this purpose! They even work! (Because otherwise the Windows bluescreen doesn't)
I can't find anything to confirm this. All of the information I do find suggests that the video driver is responsible for providing a "safe" video mode (using whatever method it likes), and that (for 8-bpp or higher video modes) Windows expects the framebuffer to be in a certain format (specific endianness with specific "B, G then R" component ordering) to ensure that the OS can use the framebuffer in "basic failure modes" (whatever that means).
Owen wrote:I don't claim its' the most preferable (far from it - VBE is after all not a good interface) method, but its' certainly workable as one fallback, with less complexity than might be imagined.

And indeed, you'll find it works more often than you might expect - because its' the normal method Windows uses to switch to the correct mode for the BSOD.
I'm not saying that VBE doesn't work on old systems (especially systems that boot using BIOS) and I'm not saying that it won't work on current "BIOS + UEFI hybrid" systems. What I'm saying is that it is deprecated (replaced by UEFI and GOP) and that there is no guarantee that it will exist or continue to work in future; and that it'd be extremely stupid for a modern OS to require deprecated functionality that probably won't exist by the time the OS is "finished" (even if that deprecated functionality exists now).

If you are able to travel forward in time to the year 2025 and check that VBE will continue to exist (and is therefore still a sane/viable option now), then please do so. If you are unable to do this, then you are unable to show that relying on the VBE now is a sane idea.


Cheers,

Brendan