On 02/13/18 15:17, Igor Mammedov wrote: > On Tue, 13 Feb 2018 14:31:41 +0100 > Laszlo Ersek <ler...@redhat.com> wrote: > >> On 02/13/18 13:57, Igor Mammedov wrote: >>> On Mon, 12 Feb 2018 15:17:21 -0500 >>> Stefan Berger <stef...@linux.vnet.ibm.com> wrote: >>> >>>> On 02/12/2018 02:45 PM, Kevin O'Connor wrote: >>>>> On Fri, Feb 09, 2018 at 03:19:31PM -0500, Stefan Berger wrote: >>>>>> I have played around with this patch and some modifications to EDK2. >>>>>> Though >>>>>> for EDK2 the question is whether to try to circumvent their current >>>>>> implementation that uses SMM or use SMM. With this patch so far I >>>>>> circumvent >>>>>> it, which is maybe not a good idea. >>>>>> >>>>>> The facts for EDK2's PPI: >>>>>> >>>>>> - from within the OS a PPI code is submitted to ACPI and ACPI enters SMM >>>>>> via >>>>>> an SMI and the PPI code is written into a UEFI variable. For this ACPI >>>>>> uses >>>>>> the memory are at 0xFFFF 0000 to pass parameters from the OS (via ACPI) >>>>>> to >>>>>> SMM. This is declared in ACPI with an OperationRegion() at that address. >>>>>> Once the machine is rebooted, UEFI reads the variable and finds the PPI >>>>>> code >>>>>> and reacts to it. >>>>> I'm a bit confused by this. The top 1M of the first 4G of ram is >>>>> generally mapped to the flash device on real machines. Indeed, this >>>>> is part of the mechanism used to boot an X86 machine - it starts >>>>> execution from flash at 0xfffffff0. This is true even on modern >>>>> machines. >>>>> >>>>> So, it seems strange that UEFI is pushing a code through a memory >>>>> device at 0xffff0000. I can't see how that would be portable. Are >>>>> you sure the memory write to 0xffff0000 is not just a trigger to >>>>> invoke the SMI? >>>> >>>> I base this on the code here: >>>> >>>> https://github.com/tianocore/edk2/blob/master/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl#L81 >>>> >>>> OperationRegion (TNVS, SystemMemory, 0xFFFF0000, 0xF0) >>> Is the goal to reuse EDK PPI impl. including ASL? >> >> Right, that is one important question. Some code in edk2 is meant only >> as example code (so actual firmware platforms are encouraged to copy & >> customize the code, or use similar or dissimilar alternatives). Some >> modules are meant for inclusion "as-is" in the platform description >> files (~ makefiles). There are so many edk2 modules related to TPM >> (several versions of the specs even) that it's hard to say what is meant >> for what usage type. (By my earlier count, there are 19 modules.) >> >>> If it's so, then perhaps we only need to write address into QEMU >>> and let OVMF to discard PPI SSDT from QEMU. >> >> That's something I would not like. When running on QEMU, it's OK for >> some edk2 modules to install their own ACPI tables, but only if they are >> "software" tables, such as the IBFT for iSCSI booting, BGRT (boot >> graphics table) for the boot logo / splash screen, etc. For ACPI tables >> that describe hardware (data tables) or carry out actions related to >> hardware (DefinitionBlocks / AML), I much prefer QEMU to generate all >> the stuff. >> >> If there is a conflict between hardware-related tables that QEMU >> generates and similar tables that pre-exist in edk2, I prefer working >> with the edk2 maintainers to customize their subsystems, so that a >> concrete firmware platform, such as OvmfPkg and ArmVirtPkg, can >> conditionalize / exclude those preexistent ACPI tables, while benefiting >> from the rest of the code. Then the ACPI linker/loader client used in >> both OvmfPkg and ArmVirtPkg can remain dumb and process & expose >> whatever tables QEMU generates. >> >> We could control the AML payload for TPM and/or TPM PPI -- e.g. whether >> it should raise an SMI -- via "-device tpm2,smi=on", for example. (Just >> making up the syntax, but you know what I mean.) >> >> We could go one step further, "-device tpm2,acpi=[on|off]". acpi=on >> would make QEMU generate the TPM related tables (perhaps targeting only >> SeaBIOS, if that makes sense), acpi=off would leave the related tables >> to the firmware. >> >> This is just speculation on my part; the point is I'd like to avoid any >> more "intelligent filtering" regarding ACPI tables in OVMF. What we have >> there is terrible enough already. > If we could discard EDK's generated tables, it's fine as well, > but we would need to model TPM device model to match EDK's one > (risk here is that implementation goes of sync, if it's not spec > dictated). Then SeaBIOS side could 're-implement' it using > the same set of tables from QEMU. > > I wonder if we could somehow detect firmware flavor we are > running on from ASL /wrt [no]using SMI/? > * I don't really like idea but we can probably detect > in QEMU if firmware is OVMF or not and generate extra SMI hunk > based on that. > * or we could always generate SMI code and probe for some > EDK specific SSDT code to see in AML to enable it. > Maybe OVMF could inject such table.
There are already several QEMU artifacts that are specific to OVMF, but none of them is a full match for this purpose: * "-machine smm=on" means that SMM emulation is enabled. However, this is automatically done for Q35, and it happens regardless of firmware. So basing the decision on this is no good. * One (or much more frequently, two) pflash devices usually indicate OVMF (as opposed to SeaBIOS, which is selected with -L, or with -bios, or by default). However, the same pflash setup is appropriate for i440fx machine types too, which lack SMM emulation. * The "-global driver=cfi.pflash01,property=secure,value=on" flag means that QEMU should restrict pflash write access to guest code that runs in SMM. This is required for making the UEFI variable store actually secure, but a user might have any reason for *not* specifying this flag (while keeping SMM emulation generally enabled, with "-machine smm=on"). This looks like the closest match, but still not a 100% match. * OVMF generally negotiates "SMI broadcast", but the user can prevent that too on the QEMU command line. ... I really think SMM is a red herring here. We've established several times that the PPI opcodes need no protection. SMM is an implementation detail in edk2, and it is used *only* because there is no other way for AML code to enter (invoke) the firmware. In other words, this is simply a "firmware calling convention" for AML code -- prepare a request buffer and raise an SMI. A valid alternative would be if we provided native OS drivers for a new ACPI device (both for Windows and Linux), and used Notify() in the TPM-related AML. Then the ACPI code could call back into the native OS driver, and *that* driver could then use the regular interface to the UEFI variable services (for example), without having to care about SMM explicitly. (Note that I'm not actually suggesting this; I'd just like to show that SMM is accidental here, not inherent.) Thanks Laszlo