1. 30 11月, 2018 1 次提交
    • E
      x86/efi: Allocate e820 buffer before calling efi_exit_boot_service · b84a64fa
      Eric Snowberg 提交于
      The following commit:
      
        d6493401 ("x86/efi: Use efi_exit_boot_services()")
      
      introduced a regression on systems with large memory maps causing them
      to hang on boot. The first "goto get_map" that was removed from
      exit_boot() ensured there was enough room for the memory map when
      efi_call_early(exit_boot_services) was called. This happens when
      (nr_desc > ARRAY_SIZE(params->e820_table).
      
      Chain of events:
      
        exit_boot()
          efi_exit_boot_services()
            efi_get_memory_map                  <- at this point the mm can't grow over 8 desc
            priv_func()
              exit_boot_func()
                allocate_e820ext()              <- new mm grows over 8 desc from e820 alloc
            efi_call_early(exit_boot_services)  <- mm key doesn't match so retry
            efi_call_early(get_memory_map)      <- not enough room for new mm
            system hangs
      
      This patch allocates the e820 buffer before calling efi_exit_boot_services()
      and fixes the regression.
      
       [ mingo: minor cleanliness edits. ]
      Signed-off-by: NEric Snowberg <eric.snowberg@oracle.com>
      Signed-off-by: NArd Biesheuvel <ard.biesheuvel@linaro.org>
      Cc: <stable@vger.kernel.org>
      Cc: Andy Lutomirski <luto@kernel.org>
      Cc: Arend van Spriel <arend.vanspriel@broadcom.com>
      Cc: Bhupesh Sharma <bhsharma@redhat.com>
      Cc: Borislav Petkov <bp@alien8.de>
      Cc: Dave Hansen <dave.hansen@intel.com>
      Cc: Hans de Goede <hdegoede@redhat.com>
      Cc: Joe Perches <joe@perches.com>
      Cc: Jon Hunter <jonathanh@nvidia.com>
      Cc: Julien Thierry <julien.thierry@arm.com>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Marc Zyngier <marc.zyngier@arm.com>
      Cc: Matt Fleming <matt@codeblueprint.co.uk>
      Cc: Nathan Chancellor <natechancellor@gmail.com>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>
      Cc: Sedat Dilek <sedat.dilek@gmail.com>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: YiFei Zhu <zhuyifei1999@gmail.com>
      Cc: linux-efi@vger.kernel.org
      Link: http://lkml.kernel.org/r/20181129171230.18699-2-ard.biesheuvel@linaro.orgSigned-off-by: NIngo Molnar <mingo@kernel.org>
      b84a64fa
  2. 26 9月, 2018 1 次提交
    • H
      efi/x86: Call efi_parse_options() from efi_main() · c33ce984
      Hans de Goede 提交于
      Before this commit we were only calling efi_parse_options() from
      make_boot_params(), but make_boot_params() only gets called if the
      kernel gets booted directly as an EFI executable. So when booted through
      e.g. grub we ended up not parsing the commandline in the boot code.
      
      This makes the drivers/firmware/efi/libstub code ignore the "quiet"
      commandline argument resulting in the following message being printed:
      "EFI stub: UEFI Secure Boot is enabled."
      
      Despite the quiet request. This commits adds an extra call to
      efi_parse_options() to efi_main() to make sure that the options are
      always processed. This fixes quiet not working.
      
      This also fixes the libstub code ignoring nokaslr and efi=nochunk.
      Reported-by: NPeter Robinson <pbrobinson@redhat.com>
      Signed-off-by: NHans de Goede <hdegoede@redhat.com>
      Signed-off-by: NArd Biesheuvel <ard.biesheuvel@linaro.org>
      c33ce984
  3. 22 7月, 2018 6 次提交
  4. 16 7月, 2018 1 次提交
  5. 11 7月, 2018 1 次提交
    • A
      efi/x86: Fix mixed mode reboot loop by removing pointless call to PciIo->Attributes() · e2967018
      Ard Biesheuvel 提交于
      Hans de Goede reported that his mixed EFI mode Bay Trail tablet
      would not boot at all any more, but enter a reboot loop without
      any logs printed by the kernel.
      
      Unbreak 64-bit Linux/x86 on 32-bit UEFI:
      
      When it was first introduced, the EFI stub code that copies the
      contents of PCI option ROMs originally only intended to do so if
      the EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM attribute was *not* set.
      
      The reason was that the UEFI spec permits PCI option ROM images
      to be provided by the platform directly, rather than via the ROM
      BAR, and in this case, the OS can only access them at runtime if
      they are preserved at boot time by copying them from the areas
      described by PciIo->RomImage and PciIo->RomSize.
      
      However, it implemented this check erroneously, as can be seen in
      commit:
      
        dd5fc854 ("EFI: Stash ROMs if they're not in the PCI BAR")
      
      which introduced:
      
          if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
                  continue;
      
      and given that the numeric value of EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
      is 0x4000, this condition never becomes true, and so the option ROMs
      were copied unconditionally.
      
      This was spotted and 'fixed' by commit:
      
        886d751a ("x86, efi: correct precedence of operators in setup_efi_pci")
      
      but inadvertently inverted the logic at the same time, defeating
      the purpose of the code, since it now only preserves option ROM
      images that can be read from the ROM BAR as well.
      
      Unsurprisingly, this broke some systems, and so the check was removed
      entirely in the following commit:
      
        73970188 ("x86, efi: remove attribute check from setup_efi_pci")
      
      It is debatable whether this check should have been included in the
      first place, since the option ROM image provided to the UEFI driver by
      the firmware may be different from the one that is actually present in
      the card's flash ROM, and so whatever PciIo->RomImage points at should
      be preferred regardless of whether the attribute is set.
      
      As this was the only use of the attributes field, we can remove
      the call to PciIo->Attributes() entirely, which is especially
      nice because its prototype involves uint64_t type by-value
      arguments which the EFI mixed mode has trouble dealing with.
      
      Any mixed mode system with PCI is likely to be affected.
      Tested-by: NWilfried Klaebe <linux-kernel@lebenslange-mailadresse.de>
      Tested-by: NHans de Goede <hdegoede@redhat.com>
      Signed-off-by: NArd Biesheuvel <ard.biesheuvel@linaro.org>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Matt Fleming <matt@codeblueprint.co.uk>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: linux-efi@vger.kernel.org
      Link: http://lkml.kernel.org/r/20180711090235.9327-2-ard.biesheuvel@linaro.orgSigned-off-by: NIngo Molnar <mingo@kernel.org>
      e2967018
  6. 24 6月, 2018 1 次提交
    • A
      efi/x86: Fix incorrect invocation of PciIo->Attributes() · 2e6eb40c
      Ard Biesheuvel 提交于
      The following commit:
      
        2c3625cb ("efi/x86: Fold __setup_efi_pci32() and __setup_efi_pci64() into one function")
      
      ... merged the two versions of __setup_efi_pciXX(), without taking into
      account that the 32-bit version used a rather dodgy trick to pass an
      immediate 0 constant as argument for a uint64_t parameter.
      
      The issue is caused by the fact that on x86, UEFI protocol method calls
      are redirected via struct efi_config::call(), which is a variadic function,
      and so the compiler has to infer the types of the parameters from the
      arguments rather than from the prototype.
      
      As the 32-bit x86 calling convention passes arguments via the stack,
      passing the unqualified constant 0 twice is the same as passing 0ULL,
      which is why the 32-bit code in __setup_efi_pci32() contained the
      following call:
      
        status = efi_early->call(pci->attributes, pci,
                                 EfiPciIoAttributeOperationGet, 0, 0,
                                 &attributes);
      
      to invoke this UEFI protocol method:
      
        typedef
        EFI_STATUS
        (EFIAPI *EFI_PCI_IO_PROTOCOL_ATTRIBUTES) (
          IN  EFI_PCI_IO_PROTOCOL                     *This,
          IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
          IN  UINT64                                  Attributes,
          OUT UINT64                                  *Result OPTIONAL
          );
      
      After the merge, we inadvertently ended up with this version for both
      32-bit and 64-bit builds, breaking the latter.
      
      So replace the two zeroes with the explicitly typed constant 0ULL,
      which works as expected on both 32-bit and 64-bit builds.
      
      Wilfried tested the 64-bit build, and I checked the generated assembly
      of a 32-bit build with and without this patch, and they are identical.
      Reported-by: NWilfried Klaebe <linux-kernel@lebenslange-mailadresse.de>
      Tested-by: NWilfried Klaebe <linux-kernel@lebenslange-mailadresse.de>
      Signed-off-by: NArd Biesheuvel <ard.biesheuvel@linaro.org>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Matt Fleming <matt@codeblueprint.co.uk>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: hdegoede@redhat.com
      Cc: linux-efi@vger.kernel.org
      Signed-off-by: NIngo Molnar <mingo@kernel.org>
      2e6eb40c
  7. 14 5月, 2018 4 次提交
  8. 12 3月, 2018 1 次提交
  9. 09 3月, 2018 1 次提交
  10. 22 2月, 2018 1 次提交
    • I
      treewide/trivial: Remove ';;$' typo noise · ed7158ba
      Ingo Molnar 提交于
      On lkml suggestions were made to split up such trivial typo fixes into per subsystem
      patches:
      
        --- a/arch/x86/boot/compressed/eboot.c
        +++ b/arch/x86/boot/compressed/eboot.c
        @@ -439,7 +439,7 @@ setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
                struct efi_uga_draw_protocol *uga = NULL, *first_uga;
                efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
                unsigned long nr_ugas;
        -       u32 *handles = (u32 *)uga_handle;;
        +       u32 *handles = (u32 *)uga_handle;
                efi_status_t status = EFI_INVALID_PARAMETER;
                int i;
      
      This patch is the result of the following script:
      
        $ sed -i 's/;;$/;/g' $(git grep -E ';;$'  | grep "\.[ch]:"  | grep -vwE 'for|ia64' | cut -d: -f1 | sort | uniq)
      
      ... followed by manual review to make sure it's all good.
      
      Splitting this up is just crazy talk, let's get over with this and just do it.
      Reported-by: NPavel Machek <pavel@ucw.cz>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: linux-kernel@vger.kernel.org
      Signed-off-by: NIngo Molnar <mingo@kernel.org>
      ed7158ba
  11. 08 1月, 2018 1 次提交
  12. 29 8月, 2017 1 次提交
    • T
      x86/idt: Unify gate_struct handling for 32/64-bit kernels · 64b163fa
      Thomas Gleixner 提交于
      The first 32 bits of gate struct are the same for 32 and 64 bit kernels.
      
      The 32-bit version uses desc_struct and no designated data structure,
      so we need different accessors for 32 and 64 bit kernels.
      
      Aside of that the macros which are necessary to build the 32-bit
      gate descriptor are horrible to read.
      
      Unify the gate structs and switch all code fiddling with it over.
      Signed-off-by: NThomas Gleixner <tglx@linutronix.de>
      Cc: Andy Lutomirski <luto@kernel.org>
      Cc: Borislav Petkov <bp@alien8.de>
      Cc: Brian Gerst <brgerst@gmail.com>
      Cc: Denys Vlasenko <dvlasenk@redhat.com>
      Cc: H. Peter Anvin <hpa@zytor.com>
      Cc: Josh Poimboeuf <jpoimboe@redhat.com>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Steven Rostedt <rostedt@goodmis.org>
      Link: http://lkml.kernel.org/r/20170828064957.861974317@linutronix.deSigned-off-by: NIngo Molnar <mingo@kernel.org>
      64b163fa
  13. 26 8月, 2017 1 次提交
  14. 17 8月, 2017 1 次提交
    • B
      efi: Introduce efi_early_memdesc_ptr to get pointer to memmap descriptor · 02e43c2d
      Baoquan He 提交于
      The existing map iteration helper for_each_efi_memory_desc_in_map can
      only be used after the kernel initializes the EFI subsystem to set up
      struct efi_memory_map.
      
      Before that we also need iterate map descriptors which are stored in several
      intermediate structures, like struct efi_boot_memmap for arch independent
      usage and struct efi_info for x86 arch only.
      
      Introduce efi_early_memdesc_ptr() to get pointer to a map descriptor, and
      replace several places where that primitive is open coded.
      Signed-off-by: NBaoquan He <bhe@redhat.com>
      [ Various improvements to the text. ]
      Acked-by: NMatt Fleming <matt@codeblueprint.co.uk>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: ard.biesheuvel@linaro.org
      Cc: fanc.fnst@cn.fujitsu.com
      Cc: izumi.taku@jp.fujitsu.com
      Cc: keescook@chromium.org
      Cc: linux-efi@vger.kernel.org
      Cc: n-horiguchi@ah.jp.nec.com
      Cc: thgarnie@google.com
      Link: http://lkml.kernel.org/r/20170816134651.GF21273@x1Signed-off-by: NIngo Molnar <mingo@kernel.org>
      02e43c2d
  15. 13 6月, 2017 3 次提交
  16. 07 2月, 2017 2 次提交
  17. 01 2月, 2017 2 次提交
  18. 29 1月, 2017 2 次提交
    • I
      x86/boot/e820: Separate the E820 ABI structures from the in-kernel structures · 7410aa1c
      Ingo Molnar 提交于
      Linus pointed out that relying on the compiler to pack structures with
      enums is fragile not just for the kernel, but for external tooling as
      well which might rely on our UAPI headers.
      
      So separate the two from each other: introduce 'struct boot_e820_entry',
      which is the boot protocol entry format.
      
      This actually simplifies the code, as e820__update_table() is now never
      called directly with boot protocol table entries - we can rely on
      append_e820_table() and do a e820__update_table() call afterwards.
      
      ( This will allow further simplifications of __e820__update_table(),
        but that will be done in a separate patch. )
      
      This change also has the side effect of not modifying the bootparams structure
      anymore - which might be useful for debugging. In theory we could even constify
      the boot_params structure - at least from the E820 code's point of view.
      
      Remove the uapi/asm/e820/types.h file, as it's not used anymore - all
      kernel side E820 types are defined in asm/e820/types.h.
      Reported-by: NLinus Torvalds <torvalds@linux-foundation.org>
      Cc: Alex Thorlton <athorlton@sgi.com>
      Cc: Andy Lutomirski <luto@kernel.org>
      Cc: Borislav Petkov <bp@alien8.de>
      Cc: Brian Gerst <brgerst@gmail.com>
      Cc: Dan Williams <dan.j.williams@intel.com>
      Cc: Denys Vlasenko <dvlasenk@redhat.com>
      Cc: H. Peter Anvin <hpa@zytor.com>
      Cc: Huang, Ying <ying.huang@intel.com>
      Cc: Josh Poimboeuf <jpoimboe@redhat.com>
      Cc: Juergen Gross <jgross@suse.com>
      Cc: Paul Jackson <pj@sgi.com>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Rafael J. Wysocki <rjw@sisk.pl>
      Cc: Tejun Heo <tj@kernel.org>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: Wei Yang <richard.weiyang@gmail.com>
      Cc: Yinghai Lu <yinghai@kernel.org>
      Cc: linux-kernel@vger.kernel.org
      Signed-off-by: NIngo Molnar <mingo@kernel.org>
      7410aa1c
    • I
      x86/boot/e820: Prefix the E820_* type names with "E820_TYPE_" · 09821ff1
      Ingo Molnar 提交于
      So there's a number of constants that start with "E820" but which
      are not types - these create a confusing mixture when seen together
      with 'enum e820_type' values:
      
      	E820MAP
      	E820NR
      	E820_X_MAX
      	E820MAX
      
      To better differentiate the 'enum e820_type' values prefix them
      with E820_TYPE_.
      
      No change in functionality.
      
      Cc: Alex Thorlton <athorlton@sgi.com>
      Cc: Andy Lutomirski <luto@kernel.org>
      Cc: Borislav Petkov <bp@alien8.de>
      Cc: Brian Gerst <brgerst@gmail.com>
      Cc: Dan Williams <dan.j.williams@intel.com>
      Cc: Denys Vlasenko <dvlasenk@redhat.com>
      Cc: H. Peter Anvin <hpa@zytor.com>
      Cc: Huang, Ying <ying.huang@intel.com>
      Cc: Josh Poimboeuf <jpoimboe@redhat.com>
      Cc: Juergen Gross <jgross@suse.com>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Paul Jackson <pj@sgi.com>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Rafael J. Wysocki <rjw@sisk.pl>
      Cc: Tejun Heo <tj@kernel.org>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: Wei Yang <richard.weiyang@gmail.com>
      Cc: Yinghai Lu <yinghai@kernel.org>
      Cc: linux-kernel@vger.kernel.org
      Signed-off-by: NIngo Molnar <mingo@kernel.org>
      09821ff1
  19. 28 1月, 2017 4 次提交
    • I
      x86/boot/e820: Rename everything to e820_table · 61a50101
      Ingo Molnar 提交于
      No change in functionality.
      
      Cc: Alex Thorlton <athorlton@sgi.com>
      Cc: Andy Lutomirski <luto@kernel.org>
      Cc: Borislav Petkov <bp@alien8.de>
      Cc: Brian Gerst <brgerst@gmail.com>
      Cc: Dan Williams <dan.j.williams@intel.com>
      Cc: Denys Vlasenko <dvlasenk@redhat.com>
      Cc: H. Peter Anvin <hpa@zytor.com>
      Cc: Huang, Ying <ying.huang@intel.com>
      Cc: Josh Poimboeuf <jpoimboe@redhat.com>
      Cc: Juergen Gross <jgross@suse.com>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Paul Jackson <pj@sgi.com>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Rafael J. Wysocki <rjw@sisk.pl>
      Cc: Tejun Heo <tj@kernel.org>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: Wei Yang <richard.weiyang@gmail.com>
      Cc: Yinghai Lu <yinghai@kernel.org>
      Cc: linux-kernel@vger.kernel.org
      Signed-off-by: NIngo Molnar <mingo@kernel.org>
      61a50101
    • I
      x86/boot/e820: Rename 'e820_map' variables to 'e820_array' · acd4c048
      Ingo Molnar 提交于
      In line with the rename to 'struct e820_array', harmonize the naming of common e820
      table variable names as well:
      
       e820          =>  e820_array
       e820_saved    =>  e820_array_saved
       e820_map      =>  e820_array
       initial_e820  =>  e820_array_init
      
      This makes the variable names more consistent  and easier to grep for.
      
      No change in functionality.
      
      Cc: Alex Thorlton <athorlton@sgi.com>
      Cc: Andy Lutomirski <luto@kernel.org>
      Cc: Borislav Petkov <bp@alien8.de>
      Cc: Brian Gerst <brgerst@gmail.com>
      Cc: Dan Williams <dan.j.williams@intel.com>
      Cc: Denys Vlasenko <dvlasenk@redhat.com>
      Cc: H. Peter Anvin <hpa@zytor.com>
      Cc: Huang, Ying <ying.huang@intel.com>
      Cc: Josh Poimboeuf <jpoimboe@redhat.com>
      Cc: Juergen Gross <jgross@suse.com>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Paul Jackson <pj@sgi.com>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Rafael J. Wysocki <rjw@sisk.pl>
      Cc: Tejun Heo <tj@kernel.org>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: Wei Yang <richard.weiyang@gmail.com>
      Cc: Yinghai Lu <yinghai@kernel.org>
      Cc: linux-kernel@vger.kernel.org
      Signed-off-by: NIngo Molnar <mingo@kernel.org>
      acd4c048
    • I
      x86/boot/e820: Rename the basic e820 data types to 'struct e820_entry' and 'struct e820_array' · 8ec67d97
      Ingo Molnar 提交于
      The 'e820entry' and 'e820map' names have various annoyances:
      
       - the missing underscore departs from the usual kernel style
         and makes the code look weird,
      
       - in the past I kept confusing the 'map' with the 'entry', because
         a 'map' is ambiguous in that regard,
      
       - it's not really clear from the 'e820map' that this is a regular
         C array.
      
      Rename them to 'struct e820_entry' and 'struct e820_array' accordingly.
      
      ( Leave the legacy UAPI header alone but do the rename in the bootparam.h
        and e820/types.h file - outside tools relying on these defines should
        either adjust their code, or should use the legacy header, or should
        create their private copies for the definitions. )
      
      No change in functionality.
      
      Cc: Alex Thorlton <athorlton@sgi.com>
      Cc: Andy Lutomirski <luto@kernel.org>
      Cc: Borislav Petkov <bp@alien8.de>
      Cc: Brian Gerst <brgerst@gmail.com>
      Cc: Dan Williams <dan.j.williams@intel.com>
      Cc: Denys Vlasenko <dvlasenk@redhat.com>
      Cc: H. Peter Anvin <hpa@zytor.com>
      Cc: Huang, Ying <ying.huang@intel.com>
      Cc: Josh Poimboeuf <jpoimboe@redhat.com>
      Cc: Juergen Gross <jgross@suse.com>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Paul Jackson <pj@sgi.com>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Rafael J. Wysocki <rjw@sisk.pl>
      Cc: Tejun Heo <tj@kernel.org>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: Wei Yang <richard.weiyang@gmail.com>
      Cc: Yinghai Lu <yinghai@kernel.org>
      Cc: linux-kernel@vger.kernel.org
      Signed-off-by: NIngo Molnar <mingo@kernel.org>
      8ec67d97
    • I
      x86/boot/e820: Remove spurious asm/e820/api.h inclusions · 5520b7e7
      Ingo Molnar 提交于
      A commonly used lowlevel x86 header, asm/pgtable.h, includes asm/e820/api.h
      spuriously, without making direct use of it.
      
      Removing it is not simple: over the years various .c code learned to rely
      on this indirect inclusion.
      
      Remove the unnecessary include - this should speed up the kernel build a bit,
      as a large header is not included anymore in totally unrelated code.
      
      Cc: Alex Thorlton <athorlton@sgi.com>
      Cc: Andy Lutomirski <luto@kernel.org>
      Cc: Borislav Petkov <bp@alien8.de>
      Cc: Brian Gerst <brgerst@gmail.com>
      Cc: Dan Williams <dan.j.williams@intel.com>
      Cc: Denys Vlasenko <dvlasenk@redhat.com>
      Cc: H. Peter Anvin <hpa@zytor.com>
      Cc: Huang, Ying <ying.huang@intel.com>
      Cc: Josh Poimboeuf <jpoimboe@redhat.com>
      Cc: Juergen Gross <jgross@suse.com>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Paul Jackson <pj@sgi.com>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Rafael J. Wysocki <rjw@sisk.pl>
      Cc: Tejun Heo <tj@kernel.org>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: Wei Yang <richard.weiyang@gmail.com>
      Cc: Yinghai Lu <yinghai@kernel.org>
      Cc: linux-kernel@vger.kernel.org
      Signed-off-by: NIngo Molnar <mingo@kernel.org>
      5520b7e7
  20. 13 11月, 2016 1 次提交
    • L
      x86/efi: Retrieve and assign Apple device properties · 58c5475a
      Lukas Wunner 提交于
      Apple's EFI drivers supply device properties which are needed to support
      Macs optimally. They contain vital information which cannot be obtained
      any other way (e.g. Thunderbolt Device ROM). They're also used to convey
      the current device state so that OS drivers can pick up where EFI
      drivers left (e.g. GPU mode setting).
      
      There's an EFI driver dubbed "AAPL,PathProperties" which implements a
      per-device key/value store. Other EFI drivers populate it using a custom
      protocol. The macOS bootloader /System/Library/CoreServices/boot.efi
      retrieves the properties with the same protocol. The kernel extension
      AppleACPIPlatform.kext subsequently merges them into the I/O Kit
      registry (see ioreg(8)) where they can be queried by other kernel
      extensions and user space.
      
      This commit extends the efistub to retrieve the device properties before
      ExitBootServices is called. It assigns them to devices in an fs_initcall
      so that they can be queried with the API in <linux/property.h>.
      
      Note that the device properties will only be available if the kernel is
      booted with the efistub. Distros should adjust their installers to
      always use the efistub on Macs. grub with the "linux" directive will not
      work unless the functionality of this commit is duplicated in grub.
      (The "linuxefi" directive should work but is not included upstream as of
      this writing.)
      
      The custom protocol has GUID 91BD12FE-F6C3-44FB-A5B7-5122AB303AE0 and
      looks like this:
      
      typedef struct {
      	unsigned long version; /* 0x10000 */
      	efi_status_t (*get) (
      		IN	struct apple_properties_protocol *this,
      		IN	struct efi_dev_path *device,
      		IN	efi_char16_t *property_name,
      		OUT	void *buffer,
      		IN OUT	u32 *buffer_len);
      		/* EFI_SUCCESS, EFI_NOT_FOUND, EFI_BUFFER_TOO_SMALL */
      	efi_status_t (*set) (
      		IN	struct apple_properties_protocol *this,
      		IN	struct efi_dev_path *device,
      		IN	efi_char16_t *property_name,
      		IN	void *property_value,
      		IN	u32 property_value_len);
      		/* allocates copies of property name and value */
      		/* EFI_SUCCESS, EFI_OUT_OF_RESOURCES */
      	efi_status_t (*del) (
      		IN	struct apple_properties_protocol *this,
      		IN	struct efi_dev_path *device,
      		IN	efi_char16_t *property_name);
      		/* EFI_SUCCESS, EFI_NOT_FOUND */
      	efi_status_t (*get_all) (
      		IN	struct apple_properties_protocol *this,
      		OUT	void *buffer,
      		IN OUT	u32 *buffer_len);
      		/* EFI_SUCCESS, EFI_BUFFER_TOO_SMALL */
      } apple_properties_protocol;
      
      Thanks to Pedro Vilaça for this blog post which was helpful in reverse
      engineering Apple's EFI drivers and bootloader:
      https://reverse.put.as/2016/06/25/apple-efi-firmware-passwords-and-the-scbo-myth/
      
      If someone at Apple is reading this, please note there's a memory leak
      in your implementation of the del() function as the property struct is
      freed but the name and value allocations are not.
      
      Neither the macOS bootloader nor Apple's EFI drivers check the protocol
      version, but we do to avoid breakage if it's ever changed. It's been the
      same since at least OS X 10.6 (2009).
      
      The get_all() function conveniently fills a buffer with all properties
      in marshalled form which can be passed to the kernel as a setup_data
      payload. The number of device properties is dynamic and can change
      between a first invocation of get_all() (to determine the buffer size)
      and a second invocation (to retrieve the actual buffer), hence the
      peculiar loop which does not finish until the buffer size settles.
      The macOS bootloader does the same.
      
      The setup_data payload is later on unmarshalled in an fs_initcall. The
      idea is that most buses instantiate devices in "subsys" initcall level
      and drivers are usually bound to these devices in "device" initcall
      level, so we assign the properties in-between, i.e. in "fs" initcall
      level.
      
      This assumes that devices to which properties pertain are instantiated
      from a "subsys" initcall or earlier. That should always be the case
      since on macOS, AppleACPIPlatformExpert::matchEFIDevicePath() only
      supports ACPI and PCI nodes and we've fully scanned those buses during
      "subsys" initcall level.
      
      The second assumption is that properties are only needed from a "device"
      initcall or later. Seems reasonable to me, but should this ever not work
      out, an alternative approach would be to store the property sets e.g. in
      a btree early during boot. Then whenever device_add() is called, an EFI
      Device Path would have to be constructed for the newly added device,
      and looked up in the btree. That way, the property set could be assigned
      to the device immediately on instantiation. And this would also work for
      devices instantiated in a deferred fashion. It seems like this approach
      would be more complicated and require more code. That doesn't seem
      justified without a specific use case.
      
      For comparison, the strategy on macOS is to assign properties to objects
      in the ACPI namespace (AppleACPIPlatformExpert::mergeEFIProperties()).
      That approach is definitely wrong as it fails for devices not present in
      the namespace: The NHI EFI driver supplies properties for attached
      Thunderbolt devices, yet on Macs with Thunderbolt 1 only one device
      level behind the host controller is described in the namespace.
      Consequently macOS cannot assign properties for chained devices. With
      Thunderbolt 2 they started to describe three device levels behind host
      controllers in the namespace but this grossly inflates the SSDT and
      still fails if the user daisy-chained more than three devices.
      
      We copy the property names and values from the setup_data payload to
      swappable virtual memory and afterwards make the payload available to
      the page allocator. This is just for the sake of good housekeeping, it
      wouldn't occupy a meaningful amount of physical memory (4444 bytes on my
      machine). Only the payload is freed, not the setup_data header since
      otherwise we'd break the list linkage and we cannot safely update the
      predecessor's ->next link because there's no locking for the list.
      
      The payload is currently not passed on to kexec'ed kernels, same for PCI
      ROMs retrieved by setup_efi_pci(). This can be added later if there is
      demand by amending setup_efi_state(). The payload can then no longer be
      made available to the page allocator of course.
      
      Tested-by: Lukas Wunner <lukas@wunner.de> [MacBookPro9,1]
      Tested-by: Pierre Moreau <pierre.morrow@free.fr> [MacBookPro11,3]
      Signed-off-by: NLukas Wunner <lukas@wunner.de>
      Signed-off-by: NMatt Fleming <matt@codeblueprint.co.uk>
      Cc: Andreas Noever <andreas.noever@gmail.com>
      Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Pedro Vilaça <reverser@put.as>
      Cc: Peter Jones <pjones@redhat.com>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: grub-devel@gnu.org
      Cc: linux-efi@vger.kernel.org
      Link: http://lkml.kernel.org/r/20161112213237.8804-9-matt@codeblueprint.co.ukSigned-off-by: NIngo Molnar <mingo@kernel.org>
      58c5475a
  21. 09 9月, 2016 3 次提交
    • L
      x86/efi: Allow invocation of arbitrary boot services · 0a637ee6
      Lukas Wunner 提交于
      We currently allow invocation of 8 boot services with efi_call_early().
      Not included are LocateHandleBuffer and LocateProtocol in particular.
      For graphics output or to retrieve PCI ROMs and Apple device properties,
      we're thus forced to use the LocateHandle + AllocatePool + LocateHandle
      combo, which is cumbersome and needs more code.
      
      The ARM folks allow invocation of the full set of boot services but are
      restricted to our 8 boot services in functions shared across arches.
      
      Thus, rather than adding just LocateHandleBuffer and LocateProtocol to
      struct efi_config, let's rework efi_call_early() to allow invocation of
      arbitrary boot services by selecting the 64 bit vs 32 bit code path in
      the macro itself.
      
      When compiling for 32 bit or for 64 bit without mixed mode, the unused
      code path is optimized away and the binary code is the same as before.
      But on 64 bit with mixed mode enabled, this commit adds one compare
      instruction to each invocation of a boot service and, depending on the
      code path selected, two jump instructions. (Most of the time gcc
      arranges the jumps in the 32 bit code path.) The result is a minuscule
      performance penalty and the binary code becomes slightly larger and more
      difficult to read when disassembled. This isn't a hot path, so these
      drawbacks are arguably outweighed by the attainable simplification of
      the C code. We have some overhead anyway for thunking or conversion
      between calling conventions.
      
      The 8 boot services can consequently be removed from struct efi_config.
      
      No functional change intended (for now).
      
      Example -- invocation of free_pool before (64 bit code path):
      0x2d4      movq  %ds:efi_early, %rdx          ; efi_early
      0x2db      movq  %ss:arg_0-0x20(%rsp), %rsi
      0x2e0      xorl  %eax, %eax
      0x2e2      movq  %ds:0x28(%rdx), %rdi         ; efi_early->free_pool
      0x2e6      callq *%ds:0x58(%rdx)              ; efi_early->call()
      
      Example -- invocation of free_pool after (64 / 32 bit mixed code path):
      0x0dc      movq  %ds:efi_early, %rax          ; efi_early
      0x0e3      cmpb  $0, %ds:0x28(%rax)           ; !efi_early->is64 ?
      0x0e7      movq  %ds:0x20(%rax), %rdx         ; efi_early->call()
      0x0eb      movq  %ds:0x10(%rax), %rax         ; efi_early->boot_services
      0x0ef      je    $0x150
      0x0f1      movq  %ds:0x48(%rax), %rdi         ; free_pool (64 bit)
      0x0f5      xorl  %eax, %eax
      0x0f7      callq *%rdx
      ...
      0x150      movl  %ds:0x30(%rax), %edi         ; free_pool (32 bit)
      0x153      jmp   $0x0f5
      
      Size of eboot.o text section:
      CONFIG_X86_32:                         6464 before, 6318 after
      CONFIG_X86_64 && !CONFIG_EFI_MIXED:    7670 before, 7573 after
      CONFIG_X86_64 &&  CONFIG_EFI_MIXED:    7670 before, 8319 after
      Signed-off-by: NLukas Wunner <lukas@wunner.de>
      Signed-off-by: NMatt Fleming <matt@codeblueprint.co.uk>
      0a637ee6
    • L
      x86/efi: Remove unused find_bits() function · 15cf7cae
      Lukas Wunner 提交于
      Left behind by commit fc372064 ("efi/libstub: Move Graphics Output
      Protocol handling to generic code").
      Signed-off-by: NLukas Wunner <lukas@wunner.de>
      Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
      Signed-off-by: NMatt Fleming <matt@codeblueprint.co.uk>
      15cf7cae
    • C
      x86/efi: Initialize status to ensure garbage is not returned on small size · ac0e94b6
      Colin Ian King 提交于
      Although very unlikey, if size is too small or zero, then we end up with
      status not being set and returning garbage. Instead, initializing status to
      EFI_INVALID_PARAMETER to indicate that size is invalid in the calls to
      setup_uga32 and setup_uga64.
      Signed-off-by: NColin Ian King <colin.king@canonical.com>
      Cc: "H. Peter Anvin" <hpa@zytor.com>
      Cc: Thomas Gleixner <tglx@linutronix.de>
      Cc: Ingo Molnar <mingo@kernel.org>
      Signed-off-by: NMatt Fleming <matt@codeblueprint.co.uk>
      ac0e94b6
  22. 05 9月, 2016 1 次提交
    • J
      x86/efi: Use efi_exit_boot_services() · d6493401
      Jeffrey Hugo 提交于
      The eboot code directly calls ExitBootServices.  This is inadvisable as the
      UEFI spec details a complex set of errors, race conditions, and API
      interactions that the caller of ExitBootServices must get correct.  The
      eboot code attempts allocations after calling ExitBootSerives which is
      not permitted per the spec.  Call the efi_exit_boot_services() helper
      intead, which handles the allocation scenario properly.
      Signed-off-by: NJeffrey Hugo <jhugo@codeaurora.org>
      Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
      Cc: Mark Rutland <mark.rutland@arm.com>
      Cc: Leif Lindholm <leif.lindholm@linaro.org>
      Cc: Ingo Molnar <mingo@kernel.org>
      Cc: <stable@vger.kernel.org>
      Signed-off-by: NMatt Fleming <matt@codeblueprint.co.uk>
      d6493401