Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp3462901iob; Sun, 1 May 2022 18:53:08 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyiDkn0pFBOQyN/UOOUMuicPlYKWcWxds2IeYq05ihQBA9KgEeIe63C+CyEtFYT00SDUkjh X-Received: by 2002:a17:902:b78c:b0:15d:2431:a806 with SMTP id e12-20020a170902b78c00b0015d2431a806mr9840044pls.77.1651456387985; Sun, 01 May 2022 18:53:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651456387; cv=none; d=google.com; s=arc-20160816; b=SPDS5DJTnY3Brrcis4NBKd4obAJ9NAnwu+cPSyYEN9Ua/7A6st2YMndCz9oAKmUzU1 0J8L2NfXqWXgBPPjjPOh5fdrPNJCFlPL/JCcoMiE1Ya69MzUKpueLvSbbdgGBemGUy/y fi/lOSAoHpmAN5EkR4yP2hLIeH1oDi52Xew/uPD2UfqnKBCuMatpJiXzwIZ8KoHqRRlF F5eFQ52Pt5cFLr9lZ8O9kGn65btL4tPcEqL/eAipudMxnSM4zu7hJMMmB7sXwZZbPg5X wrtWCLnyANNekreCLzJxy8nJzYCJWrjfPF/n6okI3QufrOUapQRnyHKLbDmvfVK5lkKn xZTA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:dkim-signature; bh=Jk4ENjMS6b/JGdHH18p0Ub4VmpGav+yxuvj4NCL+dBQ=; b=LoaNLn5hpd1szQUZW+no7rmVANVvCvArzFNTW9AoU8pzznz/5gYGkDfguj+hOL9IaI +MSYc0yhlNwY55TzfzV72HdjVNG+OHbaTWhTqQzYhPQwfbHs0Nn4c1eGZjJ0glZGf19Z ybJK1b0xJoOEiw+kxBfmGPhGxdXdvS2bWFHpoMKZ4xC7Lf+R8vALqRtvv+sjzUNhiyne Mp250RDGRUhYV/TNOJcC/8ybI1eXAP0ZirHcdCs3vyz1/XsBZODelc6nkqcdvzrPeREr 2b4kcDEnJWj1LuvqeDmHaY9j9HOANVSby9YDWqn4lK51Mg98HEZzN7zw9lmDQXGJNmkM Vm4A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=dQ6QkrGL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id g67-20020a636b46000000b003c20fe7a159si1730517pgc.563.2022.05.01.18.52.51; Sun, 01 May 2022 18:53:07 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=dQ6QkrGL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1356910AbiD3KFv (ORCPT + 99 others); Sat, 30 Apr 2022 06:05:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38338 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237334AbiD3KFt (ORCPT ); Sat, 30 Apr 2022 06:05:49 -0400 Received: from mail-ua1-x930.google.com (mail-ua1-x930.google.com [IPv6:2607:f8b0:4864:20::930]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 10184DF2B; Sat, 30 Apr 2022 03:02:27 -0700 (PDT) Received: by mail-ua1-x930.google.com with SMTP id x11so1537488uao.2; Sat, 30 Apr 2022 03:02:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=Jk4ENjMS6b/JGdHH18p0Ub4VmpGav+yxuvj4NCL+dBQ=; b=dQ6QkrGLA6VGv7UOrGNxOYCJjtwuRU3qtb4x9JOkEAO9RNOY1dUUBeqPU4NyasqM+g W1+8i8+W6XV2nw7pcX7wQ2oxBCWGulJmlUwJA7vYS6jB91DWo/dbM7U5t/oBwHjfKiWY k2/jLPrtOEnv+Zj98ZG+Sb0rSYSuMRKEa9NglNJ5fmeZ/3nPJeRwk0qcfHz7twmpATsn OLxTopsBUpSGqdhR/eMI0JXqLd0X/2+UYsnT1Z0Rfp2lzEP0XSgWo4SEETtR6+v+DnzP QkgKZsDufPMP4XWrUeB1fRZt0eiN5hV7y71HxIYDCTQqrWeXZzEMzRc7v3Ol+JtoAcFc HVvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=Jk4ENjMS6b/JGdHH18p0Ub4VmpGav+yxuvj4NCL+dBQ=; b=k5Clh0uY1btmW+rHrIRLZFfUmmYup9snqmlsjRQe63eXvZ0KDs8Vw7EM3Ff5bT8nCK ztsWOYH8jKzqAg5qcF4LsQnsu47ND8OyVKSt2wtdKG4JEXLLOSEJWUT02sEUddGwoawn RCpE1CUW60vyvkQZ8RiqXMgWD3IQH22uaAEu18ICo0+v9r1qVWwcjnjpPcxI2JUWBpq3 oRhJ1wzlbEuXFMtJrdgH7hy8byYJaFWPZPk9+5midSYy1q80DOgWhbEQxNvz2kXwY2ah A7Xh27LE5y8AN1CRWznjH+wL5QWz21Q2ix4zSe6+wvI9PdnsRVVB0YZU53PMgUEE7HKa nJgQ== X-Gm-Message-State: AOAM530Odg+fkF9Lc3p3wiIA2+2uFo0bc4La6itJpzrrSsDHbjNLqRqr reoQsigktPktUkTFHz/gz6PJTlMkAizuNTZUK2s= X-Received: by 2002:ab0:2bc9:0:b0:362:8750:8032 with SMTP id s9-20020ab02bc9000000b0036287508032mr865008uar.118.1651312945860; Sat, 30 Apr 2022 03:02:25 -0700 (PDT) MIME-Version: 1.0 References: <20220430090518.3127980-1-chenhuacai@loongson.cn> <20220430090518.3127980-21-chenhuacai@loongson.cn> In-Reply-To: From: Huacai Chen Date: Sat, 30 Apr 2022 18:02:14 +0800 Message-ID: Subject: Re: [PATCH V9 20/24] LoongArch: Add efistub booting support To: Arnd Bergmann Cc: Huacai Chen , Andy Lutomirski , Thomas Gleixner , Peter Zijlstra , Andrew Morton , David Airlie , Jonathan Corbet , Linus Torvalds , linux-arch , "open list:DOCUMENTATION" , Linux Kernel Mailing List , Xuefeng Li , Yanteng Si , Guo Ren , Xuerui Wang , Jiaxun Yang , Ard Biesheuvel Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, Arnd, On Sat, Apr 30, 2022 at 5:56 PM Arnd Bergmann wrote: > > On Sat, Apr 30, 2022 at 11:05 AM Huacai Chen wrote: > > > > This patch adds efistub booting support, which is the standard UEFI boot > > protocol for us to use. > > > > Signed-off-by: Huacai Chen > > It's good to see that you completed this. Unfortunately you did not add Ard > Biesheuvel to Cc, he is the one who needs to review this code. Adding him > to Cc now, with the full patch quoted below for him (no more comments > from me there). I'm sorry I forgot that. Huacai > > Arnd > > > --- > > arch/loongarch/Kbuild | 3 + > > arch/loongarch/Kconfig | 8 + > > arch/loongarch/Makefile | 18 +- > > arch/loongarch/boot/Makefile | 23 + > > arch/loongarch/kernel/efi-header.S | 100 +++++ > > arch/loongarch/kernel/head.S | 44 +- > > arch/loongarch/kernel/image-vars.h | 30 ++ > > arch/loongarch/kernel/vmlinux.lds.S | 23 +- > > drivers/firmware/efi/Kconfig | 4 +- > > drivers/firmware/efi/libstub/Makefile | 14 +- > > drivers/firmware/efi/libstub/loongarch-stub.c | 425 ++++++++++++++++++ > > include/linux/pe.h | 1 + > > 12 files changed, 680 insertions(+), 13 deletions(-) > > create mode 100644 arch/loongarch/boot/Makefile > > create mode 100644 arch/loongarch/kernel/efi-header.S > > create mode 100644 arch/loongarch/kernel/image-vars.h > > create mode 100644 drivers/firmware/efi/libstub/loongarch-stub.c > > > > diff --git a/arch/loongarch/Kbuild b/arch/loongarch/Kbuild > > index 1ad35aabdd16..ab5373d0a24f 100644 > > --- a/arch/loongarch/Kbuild > > +++ b/arch/loongarch/Kbuild > > @@ -1,3 +1,6 @@ > > obj-y += kernel/ > > obj-y += mm/ > > obj-y += vdso/ > > + > > +# for cleaning > > +subdir- += boot > > diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig > > index 44b763046893..55225ee5f868 100644 > > --- a/arch/loongarch/Kconfig > > +++ b/arch/loongarch/Kconfig > > @@ -265,6 +265,14 @@ config EFI > > resultant kernel should continue to boot on existing non-EFI > > platforms. > > > > +config EFI_STUB > > + bool "EFI boot stub support" > > + default y > > + depends on EFI > > + help > > + This kernel feature allows the kernel to be loaded directly by > > + EFI firmware without the use of a bootloader. > > + > > config FORCE_MAX_ZONEORDER > > int "Maximum zone order" > > range 14 64 if PAGE_SIZE_64KB > > diff --git a/arch/loongarch/Makefile b/arch/loongarch/Makefile > > index c4b3f53cd276..d88a792dafbe 100644 > > --- a/arch/loongarch/Makefile > > +++ b/arch/loongarch/Makefile > > @@ -3,6 +3,14 @@ > > # Author: Huacai Chen > > # Copyright (C) 2020-2022 Loongson Technology Corporation Limited > > > > +boot := arch/loongarch/boot > > + > > +ifndef CONFIG_EFI_STUB > > +KBUILD_IMAGE = $(boot)/vmlinux > > +else > > +KBUILD_IMAGE = $(boot)/vmlinux.efi > > +endif > > + > > # > > # Select the object file format to substitute into the linker script. > > # > > @@ -30,8 +38,6 @@ ld-emul = $(64bit-emul) > > cflags-y += -mabi=lp64s > > endif > > > > -all-y := vmlinux > > - > > # > > # GCC uses -G0 -mabicalls -fpic as default. We don't want PIC in the kernel > > # code since it only slows down the whole thing. At some point we might make > > @@ -75,6 +81,7 @@ endif > > head-y := arch/loongarch/kernel/head.o > > > > libs-y += arch/loongarch/lib/ > > +libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a > > > > ifeq ($(KBUILD_EXTMOD),) > > prepare: vdso_prepare > > @@ -86,12 +93,13 @@ PHONY += vdso_install > > vdso_install: > > $(Q)$(MAKE) $(build)=arch/loongarch/vdso $@ > > > > -all: $(all-y) > > +all: $(KBUILD_IMAGE) > > > > -CLEAN_FILES += vmlinux > > +$(KBUILD_IMAGE): vmlinux > > + $(Q)$(MAKE) $(build)=$(boot) $(bootvars-y) $@ > > > > install: > > - $(Q)install -D -m 755 vmlinux $(INSTALL_PATH)/vmlinux-$(KERNELRELEASE) > > + $(Q)install -D -m 755 $(KBUILD_IMAGE) $(INSTALL_PATH)/vmlinux-$(KERNELRELEASE) > > $(Q)install -D -m 644 .config $(INSTALL_PATH)/config-$(KERNELRELEASE) > > $(Q)install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE) > > > > diff --git a/arch/loongarch/boot/Makefile b/arch/loongarch/boot/Makefile > > new file mode 100644 > > index 000000000000..66f2293c34b2 > > --- /dev/null > > +++ b/arch/loongarch/boot/Makefile > > @@ -0,0 +1,23 @@ > > +# > > +# arch/loongarch/boot/Makefile > > +# > > +# Copyright (C) 2020-2022 Loongson Technology Corporation Limited > > +# > > + > > +drop-sections := .comment .note .options .note.gnu.build-id > > +strip-flags := $(addprefix --remove-section=,$(drop-sections)) -S > > + > > +targets := vmlinux > > +quiet_cmd_strip = STRIP $@ > > + cmd_strip = $(STRIP) -s $@ > > + > > +$(obj)/vmlinux: vmlinux FORCE > > + $(call if_changed,copy) > > + $(call if_changed,strip) > > + > > +targets += vmlinux.efi > > +quiet_cmd_eficopy = OBJCOPY $@ > > + cmd_eficopy = $(OBJCOPY) -O binary $(strip-flags) $< $@ > > + > > +$(obj)/vmlinux.efi: $(obj)/vmlinux FORCE > > + $(call if_changed,eficopy) > > diff --git a/arch/loongarch/kernel/efi-header.S b/arch/loongarch/kernel/efi-header.S > > new file mode 100644 > > index 000000000000..ceb44524944a > > --- /dev/null > > +++ b/arch/loongarch/kernel/efi-header.S > > @@ -0,0 +1,100 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +/* > > + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited > > + */ > > + > > +#include > > +#include > > + > > + .macro __EFI_PE_HEADER > > + .long PE_MAGIC > > +coff_header: > > + .short IMAGE_FILE_MACHINE_LOONGARCH /* Machine */ > > + .short section_count /* NumberOfSections */ > > + .long 0 /* TimeDateStamp */ > > + .long 0 /* PointerToSymbolTable */ > > + .long 0 /* NumberOfSymbols */ > > + .short section_table - optional_header /* SizeOfOptionalHeader */ > > + .short IMAGE_FILE_DEBUG_STRIPPED | \ > > + IMAGE_FILE_EXECUTABLE_IMAGE | \ > > + IMAGE_FILE_LINE_NUMS_STRIPPED /* Characteristics */ > > + > > +optional_header: > > + .short PE_OPT_MAGIC_PE32PLUS /* PE32+ format */ > > + .byte 0x02 /* MajorLinkerVersion */ > > + .byte 0x14 /* MinorLinkerVersion */ > > + .long __inittext_end - efi_header_end /* SizeOfCode */ > > + .long _end - __initdata_begin /* SizeOfInitializedData */ > > + .long 0 /* SizeOfUninitializedData */ > > + .long __efistub_efi_pe_entry - _head /* AddressOfEntryPoint */ > > + .long efi_header_end - _head /* BaseOfCode */ > > + > > +extra_header_fields: > > + .quad 0 /* ImageBase */ > > + .long PECOFF_SEGMENT_ALIGN /* SectionAlignment */ > > + .long PECOFF_FILE_ALIGN /* FileAlignment */ > > + .short 0 /* MajorOperatingSystemVersion */ > > + .short 0 /* MinorOperatingSystemVersion */ > > + .short 0 /* MajorImageVersion */ > > + .short 0 /* MinorImageVersion */ > > + .short 0 /* MajorSubsystemVersion */ > > + .short 0 /* MinorSubsystemVersion */ > > + .long 0 /* Win32VersionValue */ > > + > > + .long _end - _head /* SizeOfImage */ > > + > > + /* Everything before the kernel image is considered part of the header */ > > + .long efi_header_end - _head /* SizeOfHeaders */ > > + .long 0 /* CheckSum */ > > + .short IMAGE_SUBSYSTEM_EFI_APPLICATION /* Subsystem */ > > + .short 0 /* DllCharacteristics */ > > + .quad 0 /* SizeOfStackReserve */ > > + .quad 0 /* SizeOfStackCommit */ > > + .quad 0 /* SizeOfHeapReserve */ > > + .quad 0 /* SizeOfHeapCommit */ > > + .long 0 /* LoaderFlags */ > > + .long (section_table - .) / 8 /* NumberOfRvaAndSizes */ > > + > > + .quad 0 /* ExportTable */ > > + .quad 0 /* ImportTable */ > > + .quad 0 /* ResourceTable */ > > + .quad 0 /* ExceptionTable */ > > + .quad 0 /* CertificationTable */ > > + .quad 0 /* BaseRelocationTable */ > > + > > + /* Section table */ > > +section_table: > > + .ascii ".text\0\0\0" > > + .long __inittext_end - efi_header_end /* VirtualSize */ > > + .long efi_header_end - _head /* VirtualAddress */ > > + .long __inittext_end - efi_header_end /* SizeOfRawData */ > > + .long efi_header_end - _head /* PointerToRawData */ > > + > > + .long 0 /* PointerToRelocations */ > > + .long 0 /* PointerToLineNumbers */ > > + .short 0 /* NumberOfRelocations */ > > + .short 0 /* NumberOfLineNumbers */ > > + .long IMAGE_SCN_CNT_CODE | \ > > + IMAGE_SCN_MEM_READ | \ > > + IMAGE_SCN_MEM_EXECUTE /* Characteristics */ > > + > > + .ascii ".data\0\0\0" > > + .long _end - __initdata_begin /* VirtualSize */ > > + .long __initdata_begin - _head /* VirtualAddress */ > > + .long _edata - __initdata_begin /* SizeOfRawData */ > > + .long __initdata_begin - _head /* PointerToRawData */ > > + > > + .long 0 /* PointerToRelocations */ > > + .long 0 /* PointerToLineNumbers */ > > + .short 0 /* NumberOfRelocations */ > > + .short 0 /* NumberOfLineNumbers */ > > + .long IMAGE_SCN_CNT_INITIALIZED_DATA | \ > > + IMAGE_SCN_MEM_READ | \ > > + IMAGE_SCN_MEM_WRITE /* Characteristics */ > > + > > + .org 0x20e > > + .word kernel_version - 512 - _head > > + > > + .set section_count, (. - section_table) / 40 > > +efi_header_end: > > + .endm > > diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S > > index b4a0b28da3e7..361b72e8bfc5 100644 > > --- a/arch/loongarch/kernel/head.S > > +++ b/arch/loongarch/kernel/head.S > > @@ -11,11 +11,53 @@ > > #include > > #include > > #include > > +#include > > +#include > > > > -SYM_ENTRY(_stext, SYM_L_GLOBAL, SYM_A_NONE) > > +#ifdef CONFIG_EFI_STUB > > + > > +#include "efi-header.S" > > + > > + __HEAD > > + > > +_head: > > + /* "MZ", MS-DOS header */ > > + .word MZ_MAGIC > > + .org 0x28 > > + .ascii "Loongson\0" > > + .org 0x3c > > + /* Offset to the PE header */ > > + .long pe_header - _head > > + > > +pe_header: > > + __EFI_PE_HEADER > > + > > +kernel_asize: > > + .long _end - _text > > + > > +kernel_fsize: > > + .long _edata - _text > > + > > +kernel_vaddr: > > + .quad VMLINUX_LOAD_ADDRESS > > + > > +kernel_offset: > > + .long kernel_offset - _text > > + > > +kernel_version: > > + .ascii UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") " UTS_VERSION "\0" > > + > > +SYM_L_GLOBAL(kernel_asize) > > +SYM_L_GLOBAL(kernel_fsize) > > +SYM_L_GLOBAL(kernel_vaddr) > > +SYM_L_GLOBAL(kernel_offset) > > + > > +#endif > > > > __REF > > > > +SYM_ENTRY(_stext, SYM_L_GLOBAL, SYM_A_NONE) > > + > > SYM_CODE_START(kernel_entry) # kernel entry point > > > > /* Config direct window and set PG */ > > diff --git a/arch/loongarch/kernel/image-vars.h b/arch/loongarch/kernel/image-vars.h > > new file mode 100644 > > index 000000000000..0162402b6212 > > --- /dev/null > > +++ b/arch/loongarch/kernel/image-vars.h > > @@ -0,0 +1,30 @@ > > +/* SPDX-License-Identifier: GPL-2.0-only */ > > +/* > > + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited > > + */ > > +#ifndef __LOONGARCH_KERNEL_IMAGE_VARS_H > > +#define __LOONGARCH_KERNEL_IMAGE_VARS_H > > + > > +#ifdef CONFIG_EFI_STUB > > + > > +__efistub_memcmp = memcmp; > > +__efistub_memcpy = memcpy; > > +__efistub_memmove = memmove; > > +__efistub_memset = memset; > > +__efistub_strcat = strcat; > > +__efistub_strcmp = strcmp; > > +__efistub_strlen = strlen; > > +__efistub_strncat = strncat; > > +__efistub_strnstr = strnstr; > > +__efistub_strnlen = strnlen; > > +__efistub_strpbrk = strpbrk; > > +__efistub_strsep = strsep; > > +__efistub_kernel_entry = kernel_entry; > > +__efistub_kernel_asize = kernel_asize; > > +__efistub_kernel_fsize = kernel_fsize; > > +__efistub_kernel_vaddr = kernel_vaddr; > > +__efistub_kernel_offset = kernel_offset; > > + > > +#endif > > + > > +#endif /* __LOONGARCH_KERNEL_IMAGE_VARS_H */ > > diff --git a/arch/loongarch/kernel/vmlinux.lds.S b/arch/loongarch/kernel/vmlinux.lds.S > > index 02abfaaa4892..7da4c4d7c50d 100644 > > --- a/arch/loongarch/kernel/vmlinux.lds.S > > +++ b/arch/loongarch/kernel/vmlinux.lds.S > > @@ -12,6 +12,14 @@ > > #define BSS_FIRST_SECTIONS *(.bss..swapper_pg_dir) > > > > #include > > +#include "image-vars.h" > > + > > +/* > > + * Max avaliable Page Size is 64K, so we set SectionAlignment > > + * field of EFI application to 64K. > > + */ > > +PECOFF_FILE_ALIGN = 0x200; > > +PECOFF_SEGMENT_ALIGN = 0x10000; > > > > OUTPUT_ARCH(loongarch) > > ENTRY(kernel_entry) > > @@ -27,6 +35,9 @@ SECTIONS > > . = VMLINUX_LOAD_ADDRESS; > > > > _text = .; > > + HEAD_TEXT_SECTION > > + > > + . = ALIGN(PECOFF_SEGMENT_ALIGN); > > .text : { > > TEXT_TEXT > > SCHED_TEXT > > @@ -38,11 +49,12 @@ SECTIONS > > *(.fixup) > > *(.gnu.warning) > > } :text = 0 > > + . = ALIGN(PECOFF_SEGMENT_ALIGN); > > _etext = .; > > > > EXCEPTION_TABLE(16) > > > > - . = ALIGN(PAGE_SIZE); > > + . = ALIGN(PECOFF_SEGMENT_ALIGN); > > __init_begin = .; > > __inittext_begin = .; > > > > @@ -51,6 +63,7 @@ SECTIONS > > EXIT_TEXT > > } > > > > + . = ALIGN(PECOFF_SEGMENT_ALIGN); > > __inittext_end = .; > > > > __initdata_begin = .; > > @@ -60,6 +73,10 @@ SECTIONS > > EXIT_DATA > > } > > > > + .init.bss : { > > + *(.init.bss) > > + } > > + . = ALIGN(PECOFF_SEGMENT_ALIGN); > > __initdata_end = .; > > > > __init_end = .; > > @@ -71,11 +88,11 @@ SECTIONS > > .sdata : { > > *(.sdata) > > } > > - > > - . = ALIGN(SZ_64K); > > + .edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGN); } > > _edata = .; > > > > BSS_SECTION(0, SZ_64K, 8) > > + . = ALIGN(PECOFF_SEGMENT_ALIGN); > > > > _end = .; > > > > diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig > > index 2c3dac5ecb36..ecb4e0b1295a 100644 > > --- a/drivers/firmware/efi/Kconfig > > +++ b/drivers/firmware/efi/Kconfig > > @@ -121,9 +121,9 @@ config EFI_ARMSTUB_DTB_LOADER > > > > 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 > > + depends on EFI_STUB && (EFI_GENERIC_STUB || X86 || LOONGARCH) > > + default y if (X86 || LOONGARCH) > > help > > Select this config option to add support for the initrd= command > > line parameter, allowing an initrd that resides on the same volume > > diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile > > index d0537573501e..663e9d317299 100644 > > --- a/drivers/firmware/efi/libstub/Makefile > > +++ b/drivers/firmware/efi/libstub/Makefile > > @@ -26,6 +26,8 @@ cflags-$(CONFIG_ARM) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ > > $(call cc-option,-mno-single-pic-base) > > cflags-$(CONFIG_RISCV) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ > > -fpic > > +cflags-$(CONFIG_LOONGARCH) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ > > + -fpic > > > > cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt > > > > @@ -55,7 +57,7 @@ KCOV_INSTRUMENT := n > > lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \ > > file.o mem.o random.o randomalloc.o pci.o \ > > skip_spaces.o lib-cmdline.o lib-ctype.o \ > > - alignedmem.o relocate.o vsprintf.o > > + alignedmem.o relocate.o string.o vsprintf.o > > > > # include the stub's generic dependencies from lib/ when building for ARM/arm64 > > efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c > > @@ -63,13 +65,15 @@ efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c > > $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE > > $(call if_changed_rule,cc_o_c) > > > > -lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o fdt.o string.o \ > > +lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o fdt.o \ > > $(patsubst %.c,lib-%.o,$(efi-deps-y)) > > > > lib-$(CONFIG_ARM) += arm32-stub.o > > lib-$(CONFIG_ARM64) += arm64-stub.o > > lib-$(CONFIG_X86) += x86-stub.o > > lib-$(CONFIG_RISCV) += riscv-stub.o > > +lib-$(CONFIG_LOONGARCH) += loongarch-stub.o > > + > > CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) > > > > # Even when -mbranch-protection=none is set, Clang will generate a > > @@ -125,6 +129,12 @@ STUBCOPY_FLAGS-$(CONFIG_RISCV) += --prefix-alloc-sections=.init \ > > --prefix-symbols=__efistub_ > > STUBCOPY_RELOC-$(CONFIG_RISCV) := R_RISCV_HI20 > > > > +# For LoongArch, keep all the symbols in .init section and make sure that no > > +# absolute symbols references doesn't exist. > > +STUBCOPY_FLAGS-$(CONFIG_LOONGARCH) += --prefix-alloc-sections=.init \ > > + --prefix-symbols=__efistub_ > > +STUBCOPY_RELOC-$(CONFIG_LOONGARCH) := R_LARCH_MARK_LA > > + > > $(obj)/%.stub.o: $(obj)/%.o FORCE > > $(call if_changed,stubcopy) > > > > diff --git a/drivers/firmware/efi/libstub/loongarch-stub.c b/drivers/firmware/efi/libstub/loongarch-stub.c > > new file mode 100644 > > index 000000000000..399641a0b0cb > > --- /dev/null > > +++ b/drivers/firmware/efi/libstub/loongarch-stub.c > > @@ -0,0 +1,425 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Author: Yun Liu > > + * Huacai Chen > > + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include "efistub.h" > > + > > +#define MAX_ARG_COUNT 128 > > +#define CMDLINE_MAX_SIZE 0x200 > > + > > +static int argc; > > +static char **argv; > > +const efi_system_table_t *efi_system_table; > > +static efi_guid_t screen_info_guid = LINUX_EFI_LARCH_SCREEN_INFO_TABLE_GUID; > > +static unsigned int map_entry[LOONGSON3_BOOT_MEM_MAP_MAX]; > > +static struct efi_mmap mmap_array[EFI_MAX_MEMORY_TYPE][LOONGSON3_BOOT_MEM_MAP_MAX]; > > + > > +struct exit_boot_struct { > > + struct boot_params *bp; > > + unsigned int *runtime_entry_count; > > +}; > > + > > +typedef void (*kernel_entry_t)(int argc, char *argv[], struct boot_params *boot_p); > > + > > +extern int kernel_asize; > > +extern int kernel_fsize; > > +extern int kernel_offset; > > +extern unsigned long kernel_vaddr; > > +extern kernel_entry_t kernel_entry; > > + > > +unsigned char efi_crc8(char *buff, int size) > > +{ > > + int sum, cnt; > > + > > + for (sum = 0, cnt = 0; cnt < size; cnt++) > > + sum = (char) (sum + *(buff + cnt)); > > + > > + return (char)(0x100 - sum); > > +} > > + > > +struct screen_info *alloc_screen_info(void) > > +{ > > + efi_status_t status; > > + struct screen_info *si; > > + > > + status = efi_bs_call(allocate_pool, > > + EFI_RUNTIME_SERVICES_DATA, sizeof(*si), (void **)&si); > > + if (status != EFI_SUCCESS) > > + return NULL; > > + > > + status = efi_bs_call(install_configuration_table, &screen_info_guid, si); > > + if (status == EFI_SUCCESS) > > + return si; > > + > > + efi_bs_call(free_pool, si); > > + > > + return NULL; > > +} > > + > > +static void setup_graphics(void) > > +{ > > + unsigned long size; > > + efi_status_t status; > > + efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; > > + void **gop_handle = NULL; > > + struct screen_info *si = NULL; > > + > > + size = 0; > > + status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, > > + &gop_proto, NULL, &size, gop_handle); > > + if (status == EFI_BUFFER_TOO_SMALL) { > > + si = alloc_screen_info(); > > + efi_setup_gop(si, &gop_proto, size); > > + } > > +} > > + > > +struct boot_params *bootparams_init(efi_system_table_t *sys_table) > > +{ > > + efi_status_t status; > > + struct boot_params *p; > > + unsigned char sig[8] = {'B', 'P', 'I', '0', '1', '0', '0', '2'}; > > + > > + status = efi_bs_call(allocate_pool, EFI_RUNTIME_SERVICES_DATA, SZ_64K, (void **)&p); > > + if (status != EFI_SUCCESS) > > + return NULL; > > + > > + memset(p, 0, SZ_64K); > > + memcpy(&p->signature, sig, sizeof(long)); > > + > > + return p; > > +} > > + > > +static unsigned long convert_priv_cmdline(char *cmdline_ptr, > > + unsigned long rd_addr, unsigned long rd_size) > > +{ > > + unsigned int rdprev_size; > > + unsigned int cmdline_size; > > + efi_status_t status; > > + char *pstr, *substr; > > + char *initrd_ptr = NULL; > > + char convert_str[CMDLINE_MAX_SIZE]; > > + static char cmdline_array[CMDLINE_MAX_SIZE]; > > + > > + cmdline_size = strlen(cmdline_ptr); > > + snprintf(cmdline_array, CMDLINE_MAX_SIZE, "kernel "); > > + > > + initrd_ptr = strstr(cmdline_ptr, "initrd="); > > + if (!initrd_ptr) { > > + snprintf(cmdline_array, CMDLINE_MAX_SIZE, "kernel %s", cmdline_ptr); > > + goto completed; > > + } > > + snprintf(convert_str, CMDLINE_MAX_SIZE, " initrd=0x%lx,0x%lx", rd_addr, rd_size); > > + rdprev_size = cmdline_size - strlen(initrd_ptr); > > + strncat(cmdline_array, cmdline_ptr, rdprev_size); > > + > > + cmdline_ptr = strnstr(initrd_ptr, " ", CMDLINE_MAX_SIZE); > > + strcat(cmdline_array, convert_str); > > + if (!cmdline_ptr) > > + goto completed; > > + > > + strcat(cmdline_array, cmdline_ptr); > > + > > +completed: > > + status = efi_allocate_pages((MAX_ARG_COUNT + 1) * (sizeof(char *)), > > + (unsigned long *)&argv, ULONG_MAX); > > + if (status != EFI_SUCCESS) { > > + efi_err("Alloc argv mmap_array error\n"); > > + return status; > > + } > > + > > + argc = 0; > > + pstr = cmdline_array; > > + > > + substr = strsep(&pstr, " \t"); > > + while (substr != NULL) { > > + if (strlen(substr)) { > > + argv[argc++] = substr; > > + if (argc == MAX_ARG_COUNT) { > > + efi_err("Argv mmap_array full!\n"); > > + break; > > + } > > + } > > + substr = strsep(&pstr, " \t"); > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +unsigned int efi_memmap_sort(struct loongsonlist_mem_map *memmap, > > + unsigned int index, unsigned int mem_type) > > +{ > > + unsigned int i, t; > > + unsigned long msize; > > + > > + for (i = 0; i < map_entry[mem_type]; i = t) { > > + msize = mmap_array[mem_type][i].mem_size; > > + for (t = i + 1; t < map_entry[mem_type]; t++) { > > + if (mmap_array[mem_type][i].mem_start + msize < > > + mmap_array[mem_type][t].mem_start) > > + break; > > + > > + msize += mmap_array[mem_type][t].mem_size; > > + } > > + memmap->map[index].mem_type = mem_type; > > + memmap->map[index].mem_start = mmap_array[mem_type][i].mem_start; > > + memmap->map[index].mem_size = msize; > > + memmap->map[index].attribute = mmap_array[mem_type][i].attribute; > > + index++; > > + } > > + > > + return index; > > +} > > + > > +static efi_status_t mk_mmap(struct efi_boot_memmap *map, struct boot_params *p) > > +{ > > + char checksum; > > + unsigned int i; > > + unsigned int nr_desc; > > + unsigned int mem_type; > > + unsigned long count; > > + efi_memory_desc_t *mem_desc; > > + struct loongsonlist_mem_map *mhp = NULL; > > + > > + memset(map_entry, 0, sizeof(map_entry)); > > + memset(mmap_array, 0, sizeof(mmap_array)); > > + > > + if (!strncmp((char *)p, "BPI", 3)) { > > + p->flags |= BPI_FLAGS_UEFI_SUPPORTED; > > + p->systemtable = (efi_system_table_t *)efi_system_table; > > + p->extlist_offset = sizeof(*p) + sizeof(unsigned long); > > + mhp = (struct loongsonlist_mem_map *)((char *)p + p->extlist_offset); > > + > > + memcpy(&mhp->header.signature, "MEM", sizeof(unsigned long)); > > + mhp->header.length = sizeof(*mhp); > > + mhp->desc_version = *map->desc_ver; > > + mhp->map_count = 0; > > + } > > + if (!(*(map->map_size)) || !(*(map->desc_size)) || !mhp) { > > + efi_err("get memory info error\n"); > > + return EFI_INVALID_PARAMETER; > > + } > > + nr_desc = *(map->map_size) / *(map->desc_size); > > + > > + /* > > + * According to UEFI SPEC, mmap_buf is the accurate Memory Map > > + * mmap_array now we can fill platform specific memory structure. > > + */ > > + for (i = 0; i < nr_desc; i++) { > > + mem_desc = (efi_memory_desc_t *)((void *)(*map->map) + (i * (*(map->desc_size)))); > > + switch (mem_desc->type) { > > + case EFI_RESERVED_TYPE: > > + case EFI_RUNTIME_SERVICES_CODE: > > + case EFI_RUNTIME_SERVICES_DATA: > > + case EFI_MEMORY_MAPPED_IO: > > + case EFI_MEMORY_MAPPED_IO_PORT_SPACE: > > + case EFI_UNUSABLE_MEMORY: > > + case EFI_PAL_CODE: > > + mem_type = ADDRESS_TYPE_RESERVED; > > + break; > > + > > + case EFI_ACPI_MEMORY_NVS: > > + mem_type = ADDRESS_TYPE_NVS; > > + break; > > + > > + case EFI_ACPI_RECLAIM_MEMORY: > > + mem_type = ADDRESS_TYPE_ACPI; > > + break; > > + > > + case EFI_LOADER_CODE: > > + case EFI_LOADER_DATA: > > + case EFI_PERSISTENT_MEMORY: > > + case EFI_BOOT_SERVICES_CODE: > > + case EFI_BOOT_SERVICES_DATA: > > + case EFI_CONVENTIONAL_MEMORY: > > + mem_type = ADDRESS_TYPE_SYSRAM; > > + break; > > + > > + default: > > + continue; > > + } > > + > > + mmap_array[mem_type][map_entry[mem_type]].mem_type = mem_type; > > + mmap_array[mem_type][map_entry[mem_type]].mem_start = > > + mem_desc->phys_addr & TO_PHYS_MASK; > > + mmap_array[mem_type][map_entry[mem_type]].mem_size = > > + mem_desc->num_pages << EFI_PAGE_SHIFT; > > + mmap_array[mem_type][map_entry[mem_type]].attribute = > > + mem_desc->attribute; > > + map_entry[mem_type]++; > > + } > > + > > + count = mhp->map_count; > > + /* Sort EFI memmap and add to BPI for kernel */ > > + for (i = 0; i < LOONGSON3_BOOT_MEM_MAP_MAX; i++) { > > + if (!map_entry[i]) > > + continue; > > + count = efi_memmap_sort(mhp, count, i); > > + } > > + > > + mhp->map_count = count; > > + mhp->header.checksum = 0; > > + > > + checksum = efi_crc8((char *)mhp, mhp->header.length); > > + mhp->header.checksum = checksum; > > + > > + return EFI_SUCCESS; > > +} > > + > > +static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv) > > +{ > > + efi_status_t status; > > + struct exit_boot_struct *p = priv; > > + > > + status = mk_mmap(map, p->bp); > > + if (status != EFI_SUCCESS) { > > + efi_err("Make kernel memory map failed!\n"); > > + return status; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +static efi_status_t exit_boot_services(struct boot_params *boot_params, void *handle) > > +{ > > + unsigned int desc_version; > > + unsigned int runtime_entry_count = 0; > > + unsigned long map_size, key, desc_size, buff_size; > > + efi_status_t status; > > + efi_memory_desc_t *mem_map; > > + struct efi_boot_memmap map; > > + struct exit_boot_struct priv; > > + > > + map.map = &mem_map; > > + map.map_size = &map_size; > > + map.desc_size = &desc_size; > > + map.desc_ver = &desc_version; > > + map.key_ptr = &key; > > + map.buff_size = &buff_size; > > + status = efi_get_memory_map(&map); > > + if (status != EFI_SUCCESS) { > > + efi_err("Unable to retrieve UEFI memory map.\n"); > > + return status; > > + } > > + > > + priv.bp = boot_params; > > + priv.runtime_entry_count = &runtime_entry_count; > > + > > + /* Might as well exit boot services now */ > > + status = efi_exit_boot_services(handle, &map, &priv, exit_boot_func); > > + if (status != EFI_SUCCESS) > > + return status; > > + > > + return EFI_SUCCESS; > > +} > > + > > +/* > > + * EFI entry point for the LoongArch EFI stub. > > + */ > > +efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, efi_system_table_t *sys_table) > > +{ > > + unsigned int cmdline_size = 0; > > + unsigned long kernel_addr = 0; > > + unsigned long initrd_addr = 0; > > + unsigned long initrd_size = 0; > > + enum efi_secureboot_mode secure_boot; > > + char *cmdline_ptr = NULL; > > + struct boot_params *boot_p; > > + efi_status_t status; > > + efi_loaded_image_t *image; > > + efi_guid_t loaded_image_proto; > > + kernel_entry_t real_kernel_entry; > > + > > + /* Config Direct Mapping */ > > + csr_writeq(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); > > + csr_writeq(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1); > > + > > + efi_system_table = sys_table; > > + loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; > > + kernel_addr = (unsigned long)&kernel_offset - kernel_offset; > > + real_kernel_entry = (kernel_entry_t) > > + ((unsigned long)&kernel_entry - kernel_addr + kernel_vaddr); > > + > > + /* Check if we were booted by the EFI firmware */ > > + if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) > > + goto fail; > > + > > + /* > > + * Get a handle to the loaded image protocol. This is used to get > > + * information about the running image, such as size and the command > > + * line. > > + */ > > + status = sys_table->boottime->handle_protocol(handle, > > + &loaded_image_proto, (void *)&image); > > + if (status != EFI_SUCCESS) { > > + efi_err("Failed to get loaded image protocol\n"); > > + goto fail; > > + } > > + > > + /* Get the command line from EFI, using the LOADED_IMAGE protocol. */ > > + cmdline_ptr = efi_convert_cmdline(image, &cmdline_size); > > + if (!cmdline_ptr) { > > + efi_err("Getting command line failed!\n"); > > + goto fail_free_cmdline; > > + } > > + > > +#ifdef CONFIG_CMDLINE_BOOL > > + if (cmdline_size == 0) > > + efi_parse_options(CONFIG_CMDLINE); > > +#endif > > + if (!IS_ENABLED(CONFIG_CMDLINE_OVERRIDE) && cmdline_size > 0) > > + efi_parse_options(cmdline_ptr); > > + > > + efi_info("Booting Linux Kernel...\n"); > > + > > + efi_relocate_kernel(&kernel_addr, kernel_fsize, kernel_asize, > > + PHYSADDR(kernel_vaddr), SZ_2M, PHYSADDR(kernel_vaddr)); > > + > > + setup_graphics(); > > + secure_boot = efi_get_secureboot(); > > + efi_enable_reset_attack_mitigation(); > > + > > + status = efi_load_initrd(image, &initrd_addr, &initrd_size, SZ_4G, ULONG_MAX); > > + if (status != EFI_SUCCESS) { > > + efi_err("Failed get initrd addr!\n"); > > + goto fail_free; > > + } > > + > > + status = convert_priv_cmdline(cmdline_ptr, initrd_addr, initrd_size); > > + if (status != EFI_SUCCESS) { > > + efi_err("Covert cmdline failed!\n"); > > + goto fail_free; > > + } > > + > > + boot_p = bootparams_init(sys_table); > > + if (!boot_p) { > > + efi_err("Create BPI struct error!\n"); > > + goto fail; > > + } > > + > > + status = exit_boot_services(boot_p, handle); > > + if (status != EFI_SUCCESS) { > > + efi_err("exit_boot services failed!\n"); > > + goto fail_free; > > + } > > + > > + real_kernel_entry(argc, argv, boot_p); > > + > > + return EFI_SUCCESS; > > + > > +fail_free: > > + efi_free(initrd_size, initrd_addr); > > + > > +fail_free_cmdline: > > + efi_free(cmdline_size, (unsigned long)cmdline_ptr); > > + > > +fail: > > + return status; > > +} > > diff --git a/include/linux/pe.h b/include/linux/pe.h > > index daf09ffffe38..f4bb0b6a416d 100644 > > --- a/include/linux/pe.h > > +++ b/include/linux/pe.h > > @@ -65,6 +65,7 @@ > > #define IMAGE_FILE_MACHINE_SH5 0x01a8 > > #define IMAGE_FILE_MACHINE_THUMB 0x01c2 > > #define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 > > +#define IMAGE_FILE_MACHINE_LOONGARCH 0x6264 > > > > /* flags */ > > #define IMAGE_FILE_RELOCS_STRIPPED 0x0001 > > -- > > 2.27.0 > >