Эх сурвалжийг харах

Merge tag 'efi-urgent' into x86/urgent

 * Remove a duplicate copy of linux_banner from the arm64 EFI stub
   which, apart from reducing code duplication also stops the arm64 stub
   being rebuilt every time make is invoked - Ard Biesheuvel

 * Fix the EFI fdt code to not report a boot error if UEFI is
   unavailable since booting without UEFI parameters is a valid use case
   for non-UEFI platforms - Catalin Marinas

 * Include a .bss section in the EFI boot stub PE/COFF headers to fix a
   memory corruption bug - Michael Brown

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
H. Peter Anvin 11 жил өмнө
parent
commit
e0463e42d7

+ 0 - 2
arch/arm64/kernel/efi-stub.c

@@ -12,8 +12,6 @@
 #include <linux/efi.h>
 #include <linux/efi.h>
 #include <linux/libfdt.h>
 #include <linux/libfdt.h>
 #include <asm/sections.h>
 #include <asm/sections.h>
-#include <generated/compile.h>
-#include <generated/utsrelease.h>
 
 
 /*
 /*
  * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from
  * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from

+ 22 - 4
arch/x86/boot/header.S

@@ -91,10 +91,9 @@ bs_die:
 
 
 	.section ".bsdata", "a"
 	.section ".bsdata", "a"
 bugger_off_msg:
 bugger_off_msg:
-	.ascii	"Direct floppy boot is not supported. "
-	.ascii	"Use a boot loader program instead.\r\n"
+	.ascii	"Use a boot loader.\r\n"
 	.ascii	"\n"
 	.ascii	"\n"
-	.ascii	"Remove disk and press any key to reboot ...\r\n"
+	.ascii	"Remove disk and press any key to reboot...\r\n"
 	.byte	0
 	.byte	0
 
 
 #ifdef CONFIG_EFI_STUB
 #ifdef CONFIG_EFI_STUB
@@ -108,7 +107,7 @@ coff_header:
 #else
 #else
 	.word	0x8664				# x86-64
 	.word	0x8664				# x86-64
 #endif
 #endif
-	.word	3				# nr_sections
+	.word	4				# nr_sections
 	.long	0 				# TimeDateStamp
 	.long	0 				# TimeDateStamp
 	.long	0				# PointerToSymbolTable
 	.long	0				# PointerToSymbolTable
 	.long	1				# NumberOfSymbols
 	.long	1				# NumberOfSymbols
@@ -250,6 +249,25 @@ section_table:
 	.word	0				# NumberOfLineNumbers
 	.word	0				# NumberOfLineNumbers
 	.long	0x60500020			# Characteristics (section flags)
 	.long	0x60500020			# Characteristics (section flags)
 
 
+	#
+	# The offset & size fields are filled in by build.c.
+	#
+	.ascii	".bss"
+	.byte	0
+	.byte	0
+	.byte	0
+	.byte	0
+	.long	0
+	.long	0x0
+	.long	0				# Size of initialized data
+						# on disk
+	.long	0x0
+	.long	0				# PointerToRelocations
+	.long	0				# PointerToLineNumbers
+	.word	0				# NumberOfRelocations
+	.word	0				# NumberOfLineNumbers
+	.long	0xc8000080			# Characteristics (section flags)
+
 #endif /* CONFIG_EFI_STUB */
 #endif /* CONFIG_EFI_STUB */
 
 
 	# Kernel attributes; used by setup.  This is part 1 of the
 	# Kernel attributes; used by setup.  This is part 1 of the

+ 30 - 8
arch/x86/boot/tools/build.c

@@ -143,7 +143,7 @@ static void usage(void)
 
 
 #ifdef CONFIG_EFI_STUB
 #ifdef CONFIG_EFI_STUB
 
 
-static void update_pecoff_section_header(char *section_name, u32 offset, u32 size)
+static void update_pecoff_section_header_fields(char *section_name, u32 vma, u32 size, u32 datasz, u32 offset)
 {
 {
 	unsigned int pe_header;
 	unsigned int pe_header;
 	unsigned short num_sections;
 	unsigned short num_sections;
@@ -164,10 +164,10 @@ static void update_pecoff_section_header(char *section_name, u32 offset, u32 siz
 			put_unaligned_le32(size, section + 0x8);
 			put_unaligned_le32(size, section + 0x8);
 
 
 			/* section header vma field */
 			/* section header vma field */
-			put_unaligned_le32(offset, section + 0xc);
+			put_unaligned_le32(vma, section + 0xc);
 
 
 			/* section header 'size of initialised data' field */
 			/* section header 'size of initialised data' field */
-			put_unaligned_le32(size, section + 0x10);
+			put_unaligned_le32(datasz, section + 0x10);
 
 
 			/* section header 'file offset' field */
 			/* section header 'file offset' field */
 			put_unaligned_le32(offset, section + 0x14);
 			put_unaligned_le32(offset, section + 0x14);
@@ -179,6 +179,11 @@ static void update_pecoff_section_header(char *section_name, u32 offset, u32 siz
 	}
 	}
 }
 }
 
 
+static void update_pecoff_section_header(char *section_name, u32 offset, u32 size)
+{
+	update_pecoff_section_header_fields(section_name, offset, size, size, offset);
+}
+
 static void update_pecoff_setup_and_reloc(unsigned int size)
 static void update_pecoff_setup_and_reloc(unsigned int size)
 {
 {
 	u32 setup_offset = 0x200;
 	u32 setup_offset = 0x200;
@@ -203,9 +208,6 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
 
 
 	pe_header = get_unaligned_le32(&buf[0x3c]);
 	pe_header = get_unaligned_le32(&buf[0x3c]);
 
 
-	/* Size of image */
-	put_unaligned_le32(file_sz, &buf[pe_header + 0x50]);
-
 	/*
 	/*
 	 * Size of code: Subtract the size of the first sector (512 bytes)
 	 * Size of code: Subtract the size of the first sector (512 bytes)
 	 * which includes the header.
 	 * which includes the header.
@@ -220,6 +222,22 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz)
 	update_pecoff_section_header(".text", text_start, text_sz);
 	update_pecoff_section_header(".text", text_start, text_sz);
 }
 }
 
 
+static void update_pecoff_bss(unsigned int file_sz, unsigned int init_sz)
+{
+	unsigned int pe_header;
+	unsigned int bss_sz = init_sz - file_sz;
+
+	pe_header = get_unaligned_le32(&buf[0x3c]);
+
+	/* Size of uninitialized data */
+	put_unaligned_le32(bss_sz, &buf[pe_header + 0x24]);
+
+	/* Size of image */
+	put_unaligned_le32(init_sz, &buf[pe_header + 0x50]);
+
+	update_pecoff_section_header_fields(".bss", file_sz, bss_sz, 0, 0);
+}
+
 static int reserve_pecoff_reloc_section(int c)
 static int reserve_pecoff_reloc_section(int c)
 {
 {
 	/* Reserve 0x20 bytes for .reloc section */
 	/* Reserve 0x20 bytes for .reloc section */
@@ -259,6 +277,8 @@ static void efi_stub_entry_update(void)
 static inline void update_pecoff_setup_and_reloc(unsigned int size) {}
 static inline void update_pecoff_setup_and_reloc(unsigned int size) {}
 static inline void update_pecoff_text(unsigned int text_start,
 static inline void update_pecoff_text(unsigned int text_start,
 				      unsigned int file_sz) {}
 				      unsigned int file_sz) {}
+static inline void update_pecoff_bss(unsigned int file_sz,
+				     unsigned int init_sz) {}
 static inline void efi_stub_defaults(void) {}
 static inline void efi_stub_defaults(void) {}
 static inline void efi_stub_entry_update(void) {}
 static inline void efi_stub_entry_update(void) {}
 
 
@@ -310,7 +330,7 @@ static void parse_zoffset(char *fname)
 
 
 int main(int argc, char ** argv)
 int main(int argc, char ** argv)
 {
 {
-	unsigned int i, sz, setup_sectors;
+	unsigned int i, sz, setup_sectors, init_sz;
 	int c;
 	int c;
 	u32 sys_size;
 	u32 sys_size;
 	struct stat sb;
 	struct stat sb;
@@ -376,7 +396,9 @@ int main(int argc, char ** argv)
 	buf[0x1f1] = setup_sectors-1;
 	buf[0x1f1] = setup_sectors-1;
 	put_unaligned_le32(sys_size, &buf[0x1f4]);
 	put_unaligned_le32(sys_size, &buf[0x1f4]);
 
 
-	update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz));
+	update_pecoff_text(setup_sectors * 512, i + (sys_size * 16));
+	init_sz = get_unaligned_le32(&buf[0x260]);
+	update_pecoff_bss(i + (sys_size * 16), init_sz);
 
 
 	efi_stub_entry_update();
 	efi_stub_entry_update();
 
 

+ 15 - 7
drivers/firmware/efi/efi.c

@@ -346,6 +346,7 @@ static __initdata struct {
 
 
 struct param_info {
 struct param_info {
 	int verbose;
 	int verbose;
+	int found;
 	void *params;
 	void *params;
 };
 };
 
 
@@ -362,16 +363,12 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
 	    (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
 	    (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
 		return 0;
 		return 0;
 
 
-	pr_info("Getting parameters from FDT:\n");
-
 	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
 	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
 		prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
 		prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
-		if (!prop) {
-			pr_err("Can't find %s in device tree!\n",
-			       dt_params[i].name);
+		if (!prop)
 			return 0;
 			return 0;
-		}
 		dest = info->params + dt_params[i].offset;
 		dest = info->params + dt_params[i].offset;
+		info->found++;
 
 
 		val = of_read_number(prop, len / sizeof(u32));
 		val = of_read_number(prop, len / sizeof(u32));
 
 
@@ -390,10 +387,21 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
 int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
 int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
 {
 {
 	struct param_info info;
 	struct param_info info;
+	int ret;
+
+	pr_info("Getting EFI parameters from FDT:\n");
 
 
 	info.verbose = verbose;
 	info.verbose = verbose;
+	info.found = 0;
 	info.params = params;
 	info.params = params;
 
 
-	return of_scan_flat_dt(fdt_find_uefi_params, &info);
+	ret = of_scan_flat_dt(fdt_find_uefi_params, &info);
+	if (!info.found)
+		pr_info("UEFI not found.\n");
+	else if (!ret)
+		pr_err("Can't find '%s' in device tree!\n",
+		       dt_params[info.found].name);
+
+	return ret;
 }
 }
 #endif /* CONFIG_EFI_PARAMS_FROM_FDT */
 #endif /* CONFIG_EFI_PARAMS_FROM_FDT */

+ 0 - 10
drivers/firmware/efi/fdt.c

@@ -23,16 +23,6 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
 	u32 fdt_val32;
 	u32 fdt_val32;
 	u64 fdt_val64;
 	u64 fdt_val64;
 
 
-	/*
-	 * Copy definition of linux_banner here.  Since this code is
-	 * built as part of the decompressor for ARM v7, pulling
-	 * in version.c where linux_banner is defined for the
-	 * kernel brings other kernel dependencies with it.
-	 */
-	const char linux_banner[] =
-	    "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
-	    LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
-
 	/* Do some checks on provided FDT, if it exists*/
 	/* Do some checks on provided FDT, if it exists*/
 	if (orig_fdt) {
 	if (orig_fdt) {
 		if (fdt_check_header(orig_fdt)) {
 		if (fdt_check_header(orig_fdt)) {