From patchwork Tue Sep 27 08:58:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 609809 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 86745C6FA83 for ; Tue, 27 Sep 2022 08:58:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229633AbiI0I65 (ORCPT ); Tue, 27 Sep 2022 04:58:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41400 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230168AbiI0I64 (ORCPT ); Tue, 27 Sep 2022 04:58:56 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 75A957E303 for ; Tue, 27 Sep 2022 01:58:55 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 0D7C761750 for ; Tue, 27 Sep 2022 08:58:55 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id ACA59C433C1; Tue, 27 Sep 2022 08:58:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664269134; bh=EUvMUA6prcrkqn0Th8aDLSdQCn7i50Mc6uVnZ1xVHho=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QM87R5d5wZEF1i9bvPdmJd3VIskLaMFhgtMTwd96M/ZekACq1wQ3ciMgH4dRRBLFj F3GhfpZhgIjksIybsPOCnAByqMz0zQ6ujYeBS3dqGidFCV4nUfFVWzi684Q8KY7PdY o6wXAseb343tvwsBV3Hmdo/eVJdrnk3Frt8XTdTjTN2cdd6Ysv4dXC9D/gRcH6HFnx fXGOJY5Aq8zUjyTuqJ/NDjpvE96jG65d8vucbGUEceWMY92oFmIexSJMCOHskMXDKH wMPhJdjAlACTzZCZuzaqDJQDxcZoiIIAHYz/CKdOmoaTPg6DhEiiFQ3mHLU5T5+yJ1 LkxmUln63ImnA== From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , Huacai Chen , Palmer Dabbelt , Jeremy Linton , Atish Patra , Lennart Poettering , Ilias Apalodimas Subject: [PATCH 1/4] efi: libstub: Implement devicepath support for initrd commandline loader Date: Tue, 27 Sep 2022 10:58:39 +0200 Message-Id: <20220927085842.2860715-2-ardb@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220927085842.2860715-1-ardb@kernel.org> References: <20220927085842.2860715-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=7551; i=ardb@kernel.org; h=from:subject; bh=EUvMUA6prcrkqn0Th8aDLSdQCn7i50Mc6uVnZ1xVHho=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBjMrs+9poQAhTp1VrbueTY2LVcMrxX6r9ukppJt/J4 9Oth5mqJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYzK7PgAKCRDDTyI5ktmPJNmSDA CdA1TgjanE49wWechQXrIt6mapXhV1wgOGAXsBpDFn82VUXFzhDdmndSqYzPwUuTNJb4GzvmJ3YQ9Q K15Vr0oskk+uLAJDL11+sNokVrlzNmu5CwhTueYSCAhFcsVuunJPDmZd8SjwMYDOiWJheNsSoKQgtv 3GORNFpfOdnHIKgDYvsfEkXa8aBIruLTXlm+c+B9LJdKFxZxDjyu8oVm0/C+/JhjBUSjlWGJUGpEeo 5nxCI7yB48tyAICCbbVL3OhdcYwSdBkGrfZ3FN3afTRiUc7vfyY05XL5PKoPnjGWbV8BIfzLVv97FV 0W5yazk8xJhCEESwmNBTyD5OGsUpnG6qsiz9ctlYwQb31OVNth/Tqc+jZvxGobyFJ6MtQI/Wvtd/KB 7+Z7ONoe5JhnDxsCJPMjpl5DY6oQUOooUp5OdQzwQMDgQ8AEzg6AfVNK2TOs2gW9QtTGYZlyPXJ+/z q392sUOnjtPukBJFP6Dngksf/tZm9IPuHp0EncZJpAgOg= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Currently, the initrd= command line option to the EFI stub only supports loading files that reside on the same volume as the loaded image, which is not workable for loaders like GRUB that don't even implement the volume abstraction (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL), and load the kernel from an anonymous buffer in memory. For this reason, another method was devised that relies on the LoadFile2 protocol. However, the command line loader is rather useful when using the UEFI shell or other generic loaders that have no awareness of Linux specific protocols so let's make it a bit more flexible, by permitting textual device paths to be provided to initrd= as well, provided that they refer to a file hosted on a EFI_SIMPLE_FILE_SYSTEM_PROTOCOL volume. E.g., initrd=PciRoot(0x0)/Pci(0x3,0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/rootfs.cpio.gz Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/libstub/efistub.h | 15 ++++ drivers/firmware/efi/libstub/file.c | 77 +++++++++++++++++--- include/linux/efi.h | 6 ++ 3 files changed, 87 insertions(+), 11 deletions(-) diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 7e619f7ad438..f403aebf0182 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -179,6 +179,21 @@ union efi_device_path_to_text_protocol { typedef union efi_device_path_to_text_protocol efi_device_path_to_text_protocol_t; +union efi_device_path_from_text_protocol { + struct { + efi_device_path_protocol_t * + (__efiapi *convert_text_to_device_node)(const efi_char16_t *); + efi_device_path_protocol_t * + (__efiapi *convert_text_to_device_path)(const efi_char16_t *); + }; + struct { + u32 convert_text_to_device_node; + u32 convert_text_to_device_path; + } mixed_mode; +}; + +typedef union efi_device_path_from_text_protocol efi_device_path_from_text_protocol_t; + typedef void *efi_event_t; /* Note that notifications won't work in mixed mode */ typedef void (__efiapi *efi_event_notify_t)(efi_event_t, void *); diff --git a/drivers/firmware/efi/libstub/file.c b/drivers/firmware/efi/libstub/file.c index bf133d39a543..972ecc97b1d1 100644 --- a/drivers/firmware/efi/libstub/file.c +++ b/drivers/firmware/efi/libstub/file.c @@ -43,6 +43,13 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume, efi_file_protocol_t *fh; unsigned long info_sz; efi_status_t status; + efi_char16_t *c; + + /* Replace UNIX dir separators with EFI standard ones */ + for (c = fi->filename; *c != L'\0'; c++) { + if (*c == L'/') + *c = L'\\'; + } status = volume->open(volume, &fh, fi->filename, EFI_FILE_MODE_READ, 0); if (status != EFI_SUCCESS) { @@ -129,16 +136,61 @@ static int find_file_option(const efi_char16_t *cmdline, int cmdline_len, if (c == L'\0' || c == L'\n' || c == L' ') break; - else if (c == L'/') - /* Replace UNIX dir separators with EFI standard ones */ - *result++ = L'\\'; - else - *result++ = c; + *result++ = c; } *result = L'\0'; return i; } +static efi_status_t efi_open_device_path(efi_file_protocol_t **volume, + struct finfo *fi) +{ + efi_guid_t text_to_dp_guid = EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID; + static efi_device_path_from_text_protocol_t *text_to_dp = NULL; + efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; + efi_device_path_protocol_t *initrd_dp; + efi_simple_file_system_protocol_t *io; + struct efi_file_path_dev_path *fpath; + efi_handle_t handle; + efi_status_t status; + + /* See if the text to device path protocol exists */ + if (!text_to_dp && + efi_bs_call(locate_protocol, &text_to_dp_guid, NULL, + (void **)&text_to_dp) != EFI_SUCCESS) + return EFI_UNSUPPORTED; + + + /* Convert the filename wide string into a device path */ + initrd_dp = text_to_dp->convert_text_to_device_path(fi->filename); + + /* Check whether the device path in question implements simple FS */ + if ((efi_bs_call(locate_device_path, &fs_proto, &initrd_dp, &handle) ?: + efi_bs_call(handle_protocol, handle, &fs_proto, (void **)&io)) + != EFI_SUCCESS) + return EFI_NOT_FOUND; + + /* Check whether the remaining device path is a file device path */ + if (initrd_dp->type != EFI_DEV_MEDIA || + initrd_dp->sub_type != EFI_DEV_MEDIA_FILE) { + efi_warn("Unexpected device path node type: (%x, %x)\n", + initrd_dp->type, initrd_dp->sub_type); + return EFI_LOAD_ERROR; + } + + /* Copy the remaining file path into the fi structure */ + fpath = (struct efi_file_path_dev_path *)initrd_dp; + memcpy(fi->filename, fpath->filename, + min(sizeof(fi->filename), + fpath->header.length - sizeof(fpath->header))); + + status = io->open_volume(io, volume); + if (status != EFI_SUCCESS) + efi_err("Failed to open volume\n"); + + return status; +} + /* * Check the cmdline for a LILO-style file= arguments. * @@ -188,11 +240,13 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, cmdline += offset; cmdline_len -= offset; - if (!volume) { + status = efi_open_device_path(&volume, &fi); + if (status == EFI_UNSUPPORTED || status == EFI_NOT_FOUND) + /* try the volume that holds the kernel itself */ status = efi_open_volume(image, &volume); - if (status != EFI_SUCCESS) - return status; - } + + if (status != EFI_SUCCESS) + goto err_free_alloc; status = efi_open_file(volume, &fi, &file, &size); if (status != EFI_SUCCESS) @@ -249,13 +303,12 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, size -= chunksize; } file->close(file); + volume->close(volume); } while (offset > 0); *load_addr = alloc_addr; *load_size = alloc_size; - if (volume) - volume->close(volume); return EFI_SUCCESS; err_close_file: @@ -263,6 +316,8 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, err_close_volume: volume->close(volume); + +err_free_alloc: efi_free(alloc_size, alloc_addr); return status; } diff --git a/include/linux/efi.h b/include/linux/efi.h index da3974bf05d3..e739196ce9b2 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -371,6 +371,7 @@ void efi_native_runtime_setup(void); #define LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID EFI_GUID(0xbc62157e, 0x3e33, 0x4fec, 0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf) #define EFI_DEVICE_PATH_PROTOCOL_GUID EFI_GUID(0x09576e91, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) #define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID EFI_GUID(0x8b843e20, 0x8132, 0x4852, 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c) +#define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID EFI_GUID(0x05c99a21, 0xc70f, 0x4ad2, 0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e) #define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID EFI_GUID(0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a) #define EFI_UGA_PROTOCOL_GUID EFI_GUID(0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39) #define EFI_PCI_IO_PROTOCOL_GUID EFI_GUID(0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x02, 0x9a) @@ -1011,6 +1012,11 @@ struct efi_mem_mapped_dev_path { u64 ending_addr; } __packed; +struct efi_file_path_dev_path { + struct efi_generic_dev_path header; + efi_char16_t filename[]; +} __packed; + struct efi_dev_path { union { struct efi_generic_dev_path header; From patchwork Tue Sep 27 08:58:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 610367 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0877BC54EE9 for ; Tue, 27 Sep 2022 08:59:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230347AbiI0I67 (ORCPT ); Tue, 27 Sep 2022 04:58:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41408 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230168AbiI0I66 (ORCPT ); Tue, 27 Sep 2022 04:58:58 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 92E847CAA9 for ; Tue, 27 Sep 2022 01:58:57 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 2E3EA61628 for ; Tue, 27 Sep 2022 08:58:57 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D6C96C433B5; Tue, 27 Sep 2022 08:58:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664269136; bh=mGT8IYCiIqJ+xhweRLSyCgqFOtdB7hNQ8qX9oeqmvaM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kRNfD7Ca/q2InMGXBQ5ID1+Bzk0QIMzUneUO2ZdnLF7+RXvvZatW+KrsycE29vq1C RZPMJxZpE1rY025CSq+zPEKo/HS4NCTTlhvWMjPpuuf+yGFXM7cw2qJuzPlVGXhiqd NjtCPYlvpOAFyl56PBgZ5KSKYlYHLza6dPI7AEwzwbTDDuyw5svdev3BpVT6wwFR20 wID4QJByROEBcJ0TzWxq+82rXafo9qzjwAcD9jAVIf+eXIe0CXXWNSk7q/fs6adM5z R66a2pfzhq5ITs4VdoMm2RTgts09qOs/7pljqnMLiw8OsY4wlMMtCT/UEAYWgZPHs+ CMUE1LFkLXSVg== From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , Huacai Chen , Palmer Dabbelt , Jeremy Linton , Atish Patra , Lennart Poettering , Ilias Apalodimas Subject: [PATCH 2/4] efi: libstub: Permit mixed mode return types other than efi_status_t Date: Tue, 27 Sep 2022 10:58:40 +0200 Message-Id: <20220927085842.2860715-3-ardb@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220927085842.2860715-1-ardb@kernel.org> References: <20220927085842.2860715-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4690; i=ardb@kernel.org; h=from:subject; bh=mGT8IYCiIqJ+xhweRLSyCgqFOtdB7hNQ8qX9oeqmvaM=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBjMrs/srtA86IP6E/BjEJyORs1wz2TGOR/Efs856XT PK77hTSJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYzK7PwAKCRDDTyI5ktmPJOfYDA CqBmIwdRDH8ULp4IMQioXsf+J+8UVdvukYgBgZn/Xh7yTQrPxqmMVazTp7nZ2ISWMoMwngXplWHx6O av9LpUVe4DW2GWpyGEuwVAbrGa5IcM7Rh12SKYgfUq1xsdPiYNmNOdAocjKMDhUij8+mQUXPIh2PTs lKOdOb0oJlNaRSUpsja5Zw1kmpiA+4t7tWHoxaEiQ4zqsCJs9WzaKorzH2JTdIsUs9h84+emvttIwr ya1C3/VdPzFrJcQm96S2H7TXZMn5vZeftIgxvjcqfznE1Hj7A0Ac3dTB37VwM4Cq7F5SHpqMT7O9Rs /t99sYfaBh9uvMI8V2Gs9Uiw5mf6o9Us5lbxHN0VcDr5CfNR1GGsQ8TXpoaVQZ7HvSIMCXaAdEwOoW d0qCxJiJy3KbzoRi1mvFPBntAc8VaeyjgWJmIXp3zO/QkHuK+j8LWnduN2HMjODdNi8kST2ExIFB52 ibA+/sBr7coY0D7DNojRf4DuSsZsFpZY2arCQNd3vTDqw= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Rework the EFI stub macro wrappers around protocol method calls and other indirect calls in order to allow return types other than efi_status_t. This means the widening should be conditional on whether or not the return type is efi_status_t, and should be omitted otherwise. Note that this does not take into account that unsigned long types might exist that are not efi_status_t, but that can be addressed when it becomes an issue. Signed-off-by: Ard Biesheuvel --- arch/x86/boot/compressed/efi_thunk_64.S | 6 ---- arch/x86/include/asm/efi.h | 38 ++++++++------------ drivers/firmware/efi/libstub/efistub.h | 16 ++++++--- 3 files changed, 26 insertions(+), 34 deletions(-) diff --git a/arch/x86/boot/compressed/efi_thunk_64.S b/arch/x86/boot/compressed/efi_thunk_64.S index 67e7edcdfea8..0c988f2a1243 100644 --- a/arch/x86/boot/compressed/efi_thunk_64.S +++ b/arch/x86/boot/compressed/efi_thunk_64.S @@ -93,12 +93,6 @@ SYM_FUNC_START(__efi64_thunk) movl %ebx, %fs movl %ebx, %gs - /* - * Convert 32-bit status code into 64-bit. - */ - roll $1, %eax - rorq $1, %rax - pop %rbx pop %rbp RET diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 233ae6986d6f..8edead8568ec 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -178,7 +178,7 @@ struct efi_setup_data { extern u64 efi_setup; #ifdef CONFIG_EFI -extern efi_status_t __efi64_thunk(u32, ...); +extern u64 __efi64_thunk(u32, ...); #define efi64_thunk(...) ({ \ u64 __pad[3]; /* must have space for 3 args on the stack */ \ @@ -344,31 +344,23 @@ static inline u32 efi64_convert_status(efi_status_t status) #define __efi_eat(...) #define __efi_eval(...) __VA_ARGS__ -/* The three macros below handle dispatching via the thunk if needed */ - -#define efi_call_proto(inst, func, ...) \ - (efi_is_native() \ - ? inst->func(inst, ##__VA_ARGS__) \ - : __efi64_thunk_map(inst, func, inst, ##__VA_ARGS__)) - -#define efi_bs_call(func, ...) \ - (efi_is_native() \ - ? efi_system_table->boottime->func(__VA_ARGS__) \ - : __efi64_thunk_map(efi_table_attr(efi_system_table, \ - boottime), \ - func, __VA_ARGS__)) +static inline efi_status_t __efi64_widen_efi_status(u64 status) +{ + return status ? status ^ 0x8000000080000000ULL : 0; +} -#define efi_rt_call(func, ...) \ - (efi_is_native() \ - ? efi_system_table->runtime->func(__VA_ARGS__) \ - : __efi64_thunk_map(efi_table_attr(efi_system_table, \ - runtime), \ - func, __VA_ARGS__)) +/* The macro below handles dispatching via the thunk if needed */ -#define efi_dxe_call(func, ...) \ +#define efi_fn_call(inst, func, ...) \ (efi_is_native() \ - ? efi_dxe_table->func(__VA_ARGS__) \ - : __efi64_thunk_map(efi_dxe_table, func, __VA_ARGS__)) + ? inst->func(__VA_ARGS__) \ + : __builtin_choose_expr( \ + __builtin_types_compatible_p(efi_status_t, \ + __typeof__(inst->func(__VA_ARGS__))), \ + __efi64_widen_efi_status( \ + __efi64_thunk_map(inst, func, ##__VA_ARGS__)), \ + (__typeof__(inst->func(__VA_ARGS__))) \ + __efi64_thunk_map(inst, func, ##__VA_ARGS__))) #else /* CONFIG_EFI_MIXED */ diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index f403aebf0182..d26d3d7b99c0 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -44,15 +44,21 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, #ifndef ARCH_HAS_EFISTUB_WRAPPERS -#define efi_is_native() (true) -#define efi_bs_call(func, ...) efi_system_table->boottime->func(__VA_ARGS__) -#define efi_rt_call(func, ...) efi_system_table->runtime->func(__VA_ARGS__) -#define efi_dxe_call(func, ...) efi_dxe_table->func(__VA_ARGS__) +#define efi_is_native() (true) #define efi_table_attr(inst, attr) (inst->attr) -#define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__) +#define efi_fn_call(inst, func, ...) inst->func(__VA_ARGS__) #endif +#define efi_call_proto(inst, func, ...) \ + efi_fn_call(inst, func, inst, ##__VA_ARGS__) +#define efi_bs_call(func, ...) \ + efi_fn_call(efi_table_attr(efi_system_table, boottime), func, ##__VA_ARGS__) +#define efi_rt_call(func, ...) \ + efi_fn_call(efi_table_attr(efi_system_table, runtime), func, ##__VA_ARGS__) +#define efi_dxe_call(func, ...) \ + efi_fn_call(efi_dxe_table, func, ##__VA_ARGS__) + #define efi_info(fmt, ...) \ efi_printk(KERN_INFO fmt, ##__VA_ARGS__) #define efi_warn(fmt, ...) \ From patchwork Tue Sep 27 08:58:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 610366 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE8AEC6FA92 for ; Tue, 27 Sep 2022 08:59:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231149AbiI0I7F (ORCPT ); Tue, 27 Sep 2022 04:59:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41438 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231181AbiI0I7C (ORCPT ); Tue, 27 Sep 2022 04:59:02 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 78ED77E33A for ; Tue, 27 Sep 2022 01:59:01 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 0E876B81A9C for ; Tue, 27 Sep 2022 08:59:00 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0D11BC433C1; Tue, 27 Sep 2022 08:58:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664269138; bh=m+x57A0P1GfwYS7XLRrN6i3hk+eSrpUKLsEtMpPA90s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y4S37wp5iQ6nhNqXy/6RpF+aNV2gdEgiKPOFYVRLcWwT0EiDM++L5KN3RGsI3zfa3 +sScj2nsxycN6iOunlhwYhbfW+419y78zgYd6v1yrVmxM8wmlU5Onf8V5/L414LO7P bRiJSyeM2/MZFKM5SUdXeHV2Q1GJBiPOvdNfyBCO/E4Pc3pa3gF7sAAot0MLdf/Eau 0EzKtq0Z+BL/9WdOzzfAAy0spZAT2NGhi90A7tEZQEPgQsFMKtrK/170ILxTmd1Orf RnAVo+0+ACqSK+OYd9fWHbC6ELA6qxkuuiKjNk6A3hM0JQrLjjA3qrwmwV0U7MESmD Rfy8OH3XaX1Vg== From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , Huacai Chen , Palmer Dabbelt , Jeremy Linton , Atish Patra , Lennart Poettering , Ilias Apalodimas Subject: [PATCH 3/4] efi: libstub: Add mixed mode support to command line initrd loader Date: Tue, 27 Sep 2022 10:58:41 +0200 Message-Id: <20220927085842.2860715-4-ardb@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220927085842.2860715-1-ardb@kernel.org> References: <20220927085842.2860715-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=9611; i=ardb@kernel.org; h=from:subject; bh=m+x57A0P1GfwYS7XLRrN6i3hk+eSrpUKLsEtMpPA90s=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBjMrtALcOPOqpyKufl6npYzc4ubyLBaVrTcPAz5xEe G8t2kVmJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYzK7QAAKCRDDTyI5ktmPJD+XC/ 9m6XSJ1JzWyPJqGE4BaLLILpqjImNksJvFZwH9QoQQfXNIcEVY2AnPW2Y58/5NNglkJVExecZudYcq uY9CXAqufqMjj/DzKxa6j8PLK/5M+gk9P7H40LCrjifeLY1YqUXasRTLa3/e2EoMXV2ny5ImF7+jxy Y4laQyhCKnV6W6WunpCeSxN/toQyCwuUllKg9N8gu9MIRxaBIqWdBqd34PI6qoPNXDuEuMfkvS//GO NnibDqgOZZKOGqbl3yjn3ufiC6E9xL5/DmPEm/wCs+A3vTphD6AOoYlJfLIQng89tMl3AJz1slj466 HyovXy+Vxf/Amd3RlivK/ND/D8WE3s+j3xmgk2NvHsPszw2a7Wya3/Bf9r2FwV4XNihBHqGjRRwSy4 IxN7MxVUDRtc3CRoOPmkojSdNtnXhuq1VH/PGPSUMVw4XjSLnCCd8WPLCCA/CVJk+th+UKQ16HBYe1 tCPYbcpNDKu+Z5gsicyUZF4Ds7XqFJ/ujTyzhBfcy9UIQ= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org Now that we have support for calling protocols that need additional marshalling for mixed mode, wire up the initrd command line loader. Signed-off-by: Ard Biesheuvel --- arch/x86/include/asm/efi.h | 11 +++ drivers/firmware/efi/libstub/efi-stub-helper.c | 2 +- drivers/firmware/efi/libstub/efistub.h | 81 +++++++++++++------- drivers/firmware/efi/libstub/file.c | 34 ++++---- 4 files changed, 84 insertions(+), 44 deletions(-) diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 8edead8568ec..9e56bd489b29 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -325,6 +325,17 @@ static inline u32 efi64_convert_status(efi_status_t status) #define __efi64_argmap_set_memory_space_attributes(phys, size, flags) \ (__efi64_split(phys), __efi64_split(size), __efi64_split(flags)) +/* file protocol */ +#define __efi64_argmap_open(prot, newh, fname, mode, attr) \ + ((prot), efi64_zero_upper(newh), (fname), __efi64_split(mode), \ + __efi64_split(attr)) + +#define __efi64_argmap_set_position(pos) (__efi64_split(pos)) + +/* file system protocol */ +#define __efi64_argmap_open_volume(prot, file) \ + ((prot), efi64_zero_upper(file)) + /* * The macros below handle the plumbing for the argument mapping. To add a * mapping for a specific EFI method, simply define a macro diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 3249d7927c88..37f42a1d1777 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -682,7 +682,7 @@ efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image, unsigned long hard_limit) { if (!IS_ENABLED(CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER) || - (IS_ENABLED(CONFIG_X86) && (!efi_is_native() || image == NULL))) + (IS_ENABLED(CONFIG_X86) && image == NULL)) return EFI_UNSUPPORTED; return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2, diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index d26d3d7b99c0..23b7880be11a 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -593,36 +593,63 @@ typedef struct { efi_char16_t filename[]; } efi_file_info_t; -typedef struct efi_file_protocol efi_file_protocol_t; - -struct efi_file_protocol { - u64 revision; - efi_status_t (__efiapi *open) (efi_file_protocol_t *, - efi_file_protocol_t **, - efi_char16_t *, u64, u64); - efi_status_t (__efiapi *close) (efi_file_protocol_t *); - efi_status_t (__efiapi *delete) (efi_file_protocol_t *); - efi_status_t (__efiapi *read) (efi_file_protocol_t *, - unsigned long *, void *); - efi_status_t (__efiapi *write) (efi_file_protocol_t *, - unsigned long, void *); - efi_status_t (__efiapi *get_position)(efi_file_protocol_t *, u64 *); - efi_status_t (__efiapi *set_position)(efi_file_protocol_t *, u64); - efi_status_t (__efiapi *get_info) (efi_file_protocol_t *, - efi_guid_t *, unsigned long *, - void *); - efi_status_t (__efiapi *set_info) (efi_file_protocol_t *, - efi_guid_t *, unsigned long, - void *); - efi_status_t (__efiapi *flush) (efi_file_protocol_t *); +typedef union efi_file_protocol efi_file_protocol_t; + +union efi_file_protocol { + struct { + u64 revision; + efi_status_t (__efiapi *open) (efi_file_protocol_t *, + efi_file_protocol_t **, + efi_char16_t *, u64, + u64); + efi_status_t (__efiapi *close) (efi_file_protocol_t *); + efi_status_t (__efiapi *delete) (efi_file_protocol_t *); + efi_status_t (__efiapi *read) (efi_file_protocol_t *, + unsigned long *, + void *); + efi_status_t (__efiapi *write) (efi_file_protocol_t *, + unsigned long, void *); + efi_status_t (__efiapi *get_position)(efi_file_protocol_t *, + u64 *); + efi_status_t (__efiapi *set_position)(efi_file_protocol_t *, + u64); + efi_status_t (__efiapi *get_info) (efi_file_protocol_t *, + efi_guid_t *, + unsigned long *, + void *); + efi_status_t (__efiapi *set_info) (efi_file_protocol_t *, + efi_guid_t *, + unsigned long, + void *); + efi_status_t (__efiapi *flush) (efi_file_protocol_t *); + }; + struct { + u64 revision; + u32 open; + u32 close; + u32 delete; + u32 read; + u32 write; + u32 get_position; + u32 set_position; + u32 get_info; + u32 set_info; + u32 flush; + } mixed_mode; }; -typedef struct efi_simple_file_system_protocol efi_simple_file_system_protocol_t; +typedef union efi_simple_file_system_protocol efi_simple_file_system_protocol_t; -struct efi_simple_file_system_protocol { - u64 revision; - int (__efiapi *open_volume)(efi_simple_file_system_protocol_t *, - efi_file_protocol_t **); +union efi_simple_file_system_protocol { + struct { + u64 revision; + efi_status_t (__efiapi *open_volume)(efi_simple_file_system_protocol_t *, + efi_file_protocol_t **); + }; + struct { + u64 revision; + u32 open_volume; + } mixed_mode; }; #define EFI_FILE_MODE_READ 0x0000000000000001 diff --git a/drivers/firmware/efi/libstub/file.c b/drivers/firmware/efi/libstub/file.c index 972ecc97b1d1..b16c6bdc9359 100644 --- a/drivers/firmware/efi/libstub/file.c +++ b/drivers/firmware/efi/libstub/file.c @@ -51,17 +51,18 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume, *c = L'\\'; } - status = volume->open(volume, &fh, fi->filename, EFI_FILE_MODE_READ, 0); + status = efi_call_proto(volume, open, &fh, fi->filename, + EFI_FILE_MODE_READ, 0); if (status != EFI_SUCCESS) { efi_err("Failed to open file: %ls\n", fi->filename); return status; } info_sz = sizeof(struct finfo); - status = fh->get_info(fh, &info_guid, &info_sz, fi); + status = efi_call_proto(fh, get_info, &info_guid, &info_sz, fi); if (status != EFI_SUCCESS) { efi_err("Failed to get file info\n"); - fh->close(fh); + efi_call_proto(fh, close); return status; } @@ -73,7 +74,7 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume, static efi_status_t efi_open_volume(efi_loaded_image_t *image, efi_file_protocol_t **fh) { - struct efi_vendor_dev_path *dp = image->file_path; + struct efi_vendor_dev_path *dp = efi_table_attr(image, file_path); efi_guid_t li_proto = LOADED_IMAGE_PROTOCOL_GUID; efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; efi_simple_file_system_protocol_t *io; @@ -95,14 +96,14 @@ static efi_status_t efi_open_volume(efi_loaded_image_t *image, } } - status = efi_bs_call(handle_protocol, image->device_handle, &fs_proto, - (void **)&io); + status = efi_bs_call(handle_protocol, efi_table_attr(image, device_handle), + &fs_proto, (void **)&io); if (status != EFI_SUCCESS) { efi_err("Failed to handle fs_proto\n"); return status; } - status = io->open_volume(io, fh); + status = efi_call_proto(io, open_volume, fh); if (status != EFI_SUCCESS) efi_err("Failed to open volume\n"); @@ -162,7 +163,8 @@ static efi_status_t efi_open_device_path(efi_file_protocol_t **volume, /* Convert the filename wide string into a device path */ - initrd_dp = text_to_dp->convert_text_to_device_path(fi->filename); + initrd_dp = efi_fn_call(text_to_dp, convert_text_to_device_path, + fi->filename); /* Check whether the device path in question implements simple FS */ if ((efi_bs_call(locate_device_path, &fs_proto, &initrd_dp, &handle) ?: @@ -184,7 +186,7 @@ static efi_status_t efi_open_device_path(efi_file_protocol_t **volume, min(sizeof(fi->filename), fpath->header.length - sizeof(fpath->header))); - status = io->open_volume(io, volume); + status = efi_call_proto(io, open_volume, volume); if (status != EFI_SUCCESS) efi_err("Failed to open volume\n"); @@ -205,8 +207,8 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, unsigned long *load_addr, unsigned long *load_size) { - const efi_char16_t *cmdline = image->load_options; - u32 cmdline_len = image->load_options_size; + const efi_char16_t *cmdline = efi_table_attr(image, load_options); + u32 cmdline_len = efi_table_attr(image, load_options_size); unsigned long efi_chunk_size = ULONG_MAX; efi_file_protocol_t *volume = NULL; efi_file_protocol_t *file; @@ -294,7 +296,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, while (size) { unsigned long chunksize = min(size, efi_chunk_size); - status = file->read(file, &chunksize, addr); + status = efi_call_proto(file, read, &chunksize, addr); if (status != EFI_SUCCESS) { efi_err("Failed to read file\n"); goto err_close_file; @@ -302,8 +304,8 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, addr += chunksize; size -= chunksize; } - file->close(file); - volume->close(volume); + efi_call_proto(file, close); + efi_call_proto(volume, close); } while (offset > 0); *load_addr = alloc_addr; @@ -312,10 +314,10 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, return EFI_SUCCESS; err_close_file: - file->close(file); + efi_call_proto(file, close); err_close_volume: - volume->close(volume); + efi_call_proto(volume, close); err_free_alloc: efi_free(alloc_size, alloc_addr); From patchwork Tue Sep 27 08:58:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 609808 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1BFB3C54EE9 for ; Tue, 27 Sep 2022 08:59:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231381AbiI0I7E (ORCPT ); Tue, 27 Sep 2022 04:59:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41436 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231149AbiI0I7C (ORCPT ); Tue, 27 Sep 2022 04:59:02 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E84137E814 for ; Tue, 27 Sep 2022 01:59:01 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 8504561628 for ; Tue, 27 Sep 2022 08:59:01 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3785DC433D7; Tue, 27 Sep 2022 08:58:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1664269140; bh=2WDjuWY8H6VhypnxzBZn90dgORVmAVV9szyeN7i9MmA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SAlRbhqH7Ro71yDXynzwyxh3pGkipy+xf6EA5d0ooU6EqQOgh7r7QSwR0P13gjsfN HtUkUJ/J41BO7vkrWEDuQICUdZY1BlvLRFBxSJHI44I8cktBlBh9Vfrofu7Edsmf87 1c/S6tt7NOjv6kQ4FfeYBP8rbshIdSONws09NhFlhFM/dkxOSsOcGj0JzwdG3LEysp USLut1QUB+3c+SY59yGYXyTfaEnNs/NVn7XZK9THqD8eAE0dh00GSqTeST9Yl5ZAv/ MlGjkCHM1pycW9fFkolLMtwATxuXdq3f/SuqEtKg6+JsUoJdhkEBiC4Qr04aeVzrII fjaI5PFUflIAA== From: Ard Biesheuvel To: linux-efi@vger.kernel.org Cc: Ard Biesheuvel , Huacai Chen , Palmer Dabbelt , Jeremy Linton , Atish Patra , Lennart Poettering , Ilias Apalodimas Subject: [PATCH 4/4] efi: libstub: Undeprecate the command line initrd loader Date: Tue, 27 Sep 2022 10:58:42 +0200 Message-Id: <20220927085842.2860715-5-ardb@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220927085842.2860715-1-ardb@kernel.org> References: <20220927085842.2860715-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2002; i=ardb@kernel.org; h=from:subject; bh=2WDjuWY8H6VhypnxzBZn90dgORVmAVV9szyeN7i9MmA=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBjMrtCjfsTB5WZt0VCWFWtBGI58slNUjv3m1GaeLqb H3OURlmJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYzK7QgAKCRDDTyI5ktmPJFvvDA CQ9lhXJmW/sQit4UtoJcK7L3WXnvlNg1NiaXTmUwO9gE5WeS0qhc1VG0yJ9bL3gIxz6Ef/3aiaA3I7 Hr56A0HapdYFjGA2jPHOsNxmKJjlDeGa+lPf9qn1EfTnA6el8jB9qIodtyAYaWadDLwTD2FdBjl8n/ SoJlGGQFMuZpTJw087qt+s55l/46twcf9VSUl7wbqKmEpsQm02SxAAVsLuPO9LcffU2d9xEHh632GM lVrh9XDHb2uDldC34wBrVe5WmWGsq/SO9cjH7zrMHp2VVUsUW/hi6s9ZKur8TPPXfeNPpUa7Jeg1WE wYWFCjJZGcpcoi5vdOV4ZUicKAU4OHUq41rj9lS5dgU0CNSPptTyLHGO4h7iu9bBT2vYBqfw60Pj7/ O050RJIHak3A5Wb27e/GAqHF+FeO6rrN1biH+zefXx5pkotPU/0VOPHU5TqxZAcQ9Bz7RYOyxnauow U+bFIdMq46xDeJRbausxxNOkmONSYOXtmB/rbgKHBu9yw= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org The initrd= command line loader can be useful for development, but it was limited to loading files from the same file system as the loaded kernel (and it didn't work on x86 mixed mode). As both issues have been fixed, and the initrd= can now be used with files residing on any simply file system exposed by the EFI firmware, let's permit it to be enabled on RISC-V and LoongArch, which did not support it up to this point. Note that LoadFile2 remains the preferred option, as it is much simpler to use and implement, but generic loaders (including the UEFI shell) may not implement this so there, initrd= can now be used as well (if enabled in the build) Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/Kconfig | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 5b79a4a4a88d..4f7e65293297 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -165,13 +165,16 @@ config EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER bool "Enable the command line initrd loader" if !X86 depends on EFI_STUB && (EFI_GENERIC_STUB || X86) default y if X86 - depends on !RISCV && !LOONGARCH help Select this config option to add support for the initrd= command - line parameter, allowing an initrd that resides on the same volume - as the kernel image to be loaded into memory. - - This method is deprecated. + line parameter, allowing an initrd to be loaded into memory that + resides on a file system backed by an implementation of + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. + + This method has been superseded by the simpler LoadFile2 based + initrd loading method, but the initrd= loader is retained as it + can be used from the UEFI Shell or other generic loaders that + don't implement the Linux specific LoadFile2 method. config EFI_BOOTLOADER_CONTROL tristate "EFI Bootloader Control"