On 03/27/15 16:07, Gordan Bobic wrote:
> On 2015-03-27 12:58, Laszlo Ersek wrote:
>> On 03/27/15 13:27, Gordan Bobic wrote:
>>> On 2015-03-27 09:39, Laszlo Ersek wrote:
>>>>>
>>>>> Return (VROM)
>>>>> }
>>>>> }
>>>>> }
>>>>
>>>> The end result is that the caller should call _ROM in a loop, updating
>>>> the start offset, and stop when the returned buffer size is smaller
>>>> (potentially: zero) than the requested read size. This _ROM loop
>>>> will be
>>>> served from the memory range starting at (0x9CF9C018 + 4), for the
>>>> number of bytes that can be read from the UINT32 at 0x9CF9C018.
>>>>
>>>> If a copy of the actual ROM in question is available, then one might be
>>>> able reimplement the _ROM method: define a Buffer of bytes, listing the
>>>> actual bytes comprising the ROM image, and then serve the _ROM
>>>> invocations from *that*, instead of the VBOR operation region's VBSx
>>>> fields. And the RVBS references can be replaced with a known constant.
>>>
>>> Right. So what would be the correct way to embed a 103936 byte BIOS
>>> payload inside the _ROM method?
>>
>> Please consult the ACPI spec. You should create a named Buffer object
>> with open-coded byte contents (*), then rebase the existing _ROM logic
>> on top of that object. Build the new SSDT with iasl, then pass it to
>> qemu with the -acpitable switch, as Gerd recommended. QEMU should then
>> expose that custom table too to OVMF, and OVMF should install it for the
>> guest OS.
>>
>> ((*) As an example, refer to
>>
>> Name (VROM, Buffer (Local1)
>> {
>> 0x00
>> })
>>
>> in the iasl output. See also "19.5.10 Buffer (Declare Buffer Object)" in
>> the ACPI spec.)
>>
>> I'm not suggesting this is easy -- to the contrary. In particular
>> because the SSDT that you decompiled has a bunch of other code in it,
>> with many OperationRegions and Externals.
>>
>> In particular, there's a whole bunch of open-coded address constants in
>> the SSDT. One of those is
>>
>> OperationRegion (VBOR, SystemMemory, 0x9CF9C018, 0x00019604)
>
> I was rather hoping, as a first pass, to simply statically encode the
> payload into a binary string
Yes, indeed, that is part of the idea. And, as I said below, the VBOR
opregion would actually be obviated (removed) by implementing the idea.
(But, there are other opregions with hard-coded addresses that would
remain!)
> and have the _ROM method simply return
> that. Would that not work?
No, this part would not. You can't return the *entire* expansion ROM in
one _ROM method invocation. _ROM basically corresponds to pread(), in
POSIX speak. You must take an offset to read from, and a target buffer
size that the caller wants to get in return. (Obviously the analogy is
very incomplete, but the point is that _ROM needs to take start offset
and buffer size parameters.)
What you could do is embed the full ROM as *another* named Buffer object
in the SSDT, and then serve the _ROM invocations (which are basically
pread() calls) from that buffer, instead of the VBSx arrays.
>> itself, which you would replace with the explicit Buffer object.
>> However, there are others, for example:
>>
>> OperationRegion (SGOP, SystemMemory, 0x9CFBBE98, 0x00000054)
>>
>> The hardcoded address constant in the AML code very strongly suggests
>> that this AML payload was entirely composed, or partially patched, by
>> the laptop vendor's firmware *dynamically* during boot, dependent on
>> system RAM size, video card characteristics, PCI window characteristics,
>> whatever. To replay that in the guest, you'd probably have to
>> reimplement most of that logic in OVMF and/or qemu. '-acpitable' is good
>> only if you have a static AML blob.
>
> I am 99% certain it is not being patched at runtime, because what
> nouveau pulls out and makes available as
> /sys/kernel/debug/dri/<id>/vbios.rom
> is exactly identical to the firmware blob I pulled out of the
> system firmware.
I don't know how that tool that you used to pull the firmware blob out
of the system firmware works. If it is reading live tables from system
memory, then it doesn't prove anything. The patching could happen inside
the system firmware before even grub is booted.
The only way this method would prove anything is if you had the entire
system firmware *as a file* on your host (from some reliable source),
and the extractor fetched this exact ROM image from that static file.
(Alternatively, if the extractor fetched the embedded ROM image directly
from read-only flash.)
> Having said that, the system firmware does include no fewer than 3
> Nvidia BIOS-es with different version numbers, so I suspect what is
> happening there is the firmware figuring out which of the three it
> should use for the card that is present.
>
>> So, I think your card is simply unusable for passthrough. It is strongly
>> tied to your proprietary system firmware, instead of carrying its own,
>> well-isolated option ROM.
>
> Which does kind of present another possibility. Nvidia cards, according
> to what nouveau driver does, offer 3 methods of getting the VBIOS out:
> 1) PRAMIN (read it from the particular place in VRAM)
If it can be just read from the video RAM, then why doesn't that work in
a guest? It doesn't seem to be much different from reading the ROM image
from the dedicated PCI ROM bar.
> It has been suggested that if I use a driver to initialize the RAM,
> then use nvafakebios to load the BIOS blob into the PRAMIN, and then
> start the VM.
I have no clue what nvafakebios does. I found the source but none of it
is documented.
> But it doesn't appear to have worked - seems something
> seems to clobber the BIOS payload along the way.
>
> 2) PROM (read it from the supported PROM)
> Short of writing a qemu emulation for one, I'm not sure there's a
> way to make use of this.
>
> 3) ACPI
>
>> With a separate add-on card, the vendor simply can't put the option ROM
>> anywhere else than on the card itself, but with an integrated card, they
>> can apparently pull sh*t like this.
>
> See above - it isn't all that messed up, the output is completely
> clean.
Fine. Then you can start hacking the SSDT, as discussed before :)
Laszlo
------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel