svn commit: r246608 - projects/uefi/sys/boot/i386/efi

Benno Rice benno at FreeBSD.org
Sun Feb 10 04:17:43 UTC 2013


Author: benno
Date: Sun Feb 10 04:17:41 2013
New Revision: 246608
URL: http://svnweb.freebsd.org/changeset/base/246608

Log:
  Rework copy routines to ensure we always use memory allocated via EFI.
  
  The previous code assumed it could copy wherever it liked. This is not the
  case. The approach taken by this code is pretty ham-fisted in that it simply
  allocates a large (32MB) buffer area and stages into that, then copies the
  whole area into place when it's time to execute. A more elegant solution could
  be used but this works for now.
  
  Sponsored by:	FreeBSD Foundation

Added:
  projects/uefi/sys/boot/i386/efi/x86_efi_copy.c
  projects/uefi/sys/boot/i386/efi/x86_efi_copy.h
Deleted:
  projects/uefi/sys/boot/i386/efi/i386_copy.c
Modified:
  projects/uefi/sys/boot/i386/efi/Makefile
  projects/uefi/sys/boot/i386/efi/bootinfo.c
  projects/uefi/sys/boot/i386/efi/bootinfo64.c
  projects/uefi/sys/boot/i386/efi/elf64_freebsd.c
  projects/uefi/sys/boot/i386/efi/main.c

Modified: projects/uefi/sys/boot/i386/efi/Makefile
==============================================================================
--- projects/uefi/sys/boot/i386/efi/Makefile	Sun Feb 10 04:14:25 2013	(r246607)
+++ projects/uefi/sys/boot/i386/efi/Makefile	Sun Feb 10 04:17:41 2013	(r246608)
@@ -11,7 +11,7 @@ INTERNALPROG=
 
 # architecture-specific loader code
 SRCS=	main.c exec.c conf.c vers.c reloc.c elf32_freebsd.c elf64_freebsd.c
-SRCS+=	i386_copy.c bootinfo.c bootinfo64.c autoload.c devicename.c efimd.c
+SRCS+=	x86_efi_copy.c bootinfo.c bootinfo64.c autoload.c devicename.c efimd.c
 
 .PATH:	${.CURDIR}/${MACHINE_CPUARCH}
 SRCS+=	start.S

Modified: projects/uefi/sys/boot/i386/efi/bootinfo.c
==============================================================================
--- projects/uefi/sys/boot/i386/efi/bootinfo.c	Sun Feb 10 04:14:25 2013	(r246607)
+++ projects/uefi/sys/boot/i386/efi/bootinfo.c	Sun Feb 10 04:17:41 2013	(r246608)
@@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$");
 #include "libi386.h"
 #include <machine/bootinfo.h>
 
+#include "x86_efi_copy.h"
+
 /*
  * Return a 'boothowto' value corresponding to the kernel arguments in
  * (kargs) and any relevant environment variables.
@@ -120,24 +122,24 @@ bi_copyenv(vm_offset_t start)
 	/* Traverse the environment. */
 	for (ep = environ; ep != NULL; ep = ep->ev_next) {
 		len = strlen(ep->ev_name);
-		if (i386_copyin(ep->ev_name, addr, len) != len)
+		if (x86_efi_copyin(ep->ev_name, addr, len) != len)
 			break;
 		addr += len;
-		if (i386_copyin("=", addr, 1) != 1)
+		if (x86_efi_copyin("=", addr, 1) != 1)
 			break;
 		addr++;
 		if (ep->ev_value != NULL) {
 			len = strlen(ep->ev_value);
-			if (i386_copyin(ep->ev_value, addr, len) != len)
+			if (x86_efi_copyin(ep->ev_value, addr, len) != len)
 				break;
 			addr += len;
 		}
-		if (i386_copyin("", addr, 1) != 1)
+		if (x86_efi_copyin("", addr, 1) != 1)
 			break;
 		last = ++addr;
 	}
 
-	if (i386_copyin("", last++, 1) != 1)
+	if (x86_efi_copyin("", last++, 1) != 1)
 		last = start;
 	return(last);
 }
@@ -160,14 +162,14 @@ bi_copyenv(vm_offset_t start)
  */
 #define COPY32(v, a) {				\
     u_int32_t	x = (v);			\
-    i386_copyin(&x, a, sizeof(x));		\
+    x86_efi_copyin(&x, a, sizeof(x));		\
     a += sizeof(x);				\
 }
 
 #define MOD_STR(t, a, s) {			\
     COPY32(t, a);				\
     COPY32(strlen(s) + 1, a);			\
-    i386_copyin(s, a, strlen(s) + 1);		\
+    x86_efi_copyin(s, a, strlen(s) + 1);		\
     a += roundup(strlen(s) + 1, sizeof(u_int64_t));\
 }
 
@@ -178,7 +180,7 @@ bi_copyenv(vm_offset_t start)
 #define MOD_VAR(t, a, s) {			\
     COPY32(t, a);				\
     COPY32(sizeof(s), a);			\
-    i386_copyin(&s, a, sizeof(s));		\
+    x86_efi_copyin(&s, a, sizeof(s));		\
     a += roundup(sizeof(s), sizeof(u_int64_t));	\
 }
 
@@ -188,7 +190,7 @@ bi_copyenv(vm_offset_t start)
 #define MOD_METADATA(a, mm) {			\
     COPY32(MODINFO_METADATA | mm->md_type, a);	\
     COPY32(mm->md_size, a);			\
-    i386_copyin(mm->md_data, a, mm->md_size);	\
+    x86_efi_copyin(mm->md_data, a, mm->md_size);	\
     a += roundup(mm->md_size, sizeof(u_int64_t));\
 }
 

Modified: projects/uefi/sys/boot/i386/efi/bootinfo64.c
==============================================================================
--- projects/uefi/sys/boot/i386/efi/bootinfo64.c	Sun Feb 10 04:14:25 2013	(r246607)
+++ projects/uefi/sys/boot/i386/efi/bootinfo64.c	Sun Feb 10 04:17:41 2013	(r246608)
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
 #include <machine/specialreg.h>
 #include "bootstrap.h"
 #include "libi386.h"
+#include "x86_efi_copy.h"
 
 /*
  * Copy module-related data into the load area, where it can be
@@ -57,7 +58,7 @@ __FBSDID("$FreeBSD$");
 #define COPY32(v, a, c) {			\
     u_int32_t	x = (v);			\
     if (c)					\
-	i386_copyin(&x, a, sizeof(x));		\
+	x86_efi_copyin(&x, a, sizeof(x));	\
     a += sizeof(x);				\
 }
 
@@ -65,7 +66,7 @@ __FBSDID("$FreeBSD$");
     COPY32(t, a, c);				\
     COPY32(strlen(s) + 1, a, c);		\
     if (c)					\
-	i386_copyin(s, a, strlen(s) + 1);	\
+	x86_efi_copyin(s, a, strlen(s) + 1);	\
     a += roundup(strlen(s) + 1, sizeof(u_int64_t));\
 }
 
@@ -77,7 +78,7 @@ __FBSDID("$FreeBSD$");
     COPY32(t, a, c);				\
     COPY32(sizeof(s), a, c);			\
     if (c)					\
-	i386_copyin(&s, a, sizeof(s));		\
+	x86_efi_copyin(&s, a, sizeof(s));	\
     a += roundup(sizeof(s), sizeof(u_int64_t));	\
 }
 
@@ -88,7 +89,7 @@ __FBSDID("$FreeBSD$");
     COPY32(MODINFO_METADATA | mm->md_type, a, c); \
     COPY32(mm->md_size, a, c);			\
     if (c)					\
-	i386_copyin(mm->md_data, a, mm->md_size); \
+	x86_efi_copyin(mm->md_data, a, mm->md_size); \
     a += roundup(mm->md_size, sizeof(u_int64_t));\
 }
 

Modified: projects/uefi/sys/boot/i386/efi/elf64_freebsd.c
==============================================================================
--- projects/uefi/sys/boot/i386/efi/elf64_freebsd.c	Sun Feb 10 04:14:25 2013	(r246607)
+++ projects/uefi/sys/boot/i386/efi/elf64_freebsd.c	Sun Feb 10 04:17:41 2013	(r246608)
@@ -49,6 +49,8 @@ __FBSDID("$FreeBSD$");
 #include "actypes.h"
 #include "actbl.h"
 
+#include "x86_efi_copy.h"
+
 static EFI_GUID acpi_guid = ACPI_TABLE_GUID;
 static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID;
 
@@ -155,6 +157,8 @@ elf64_exec(struct preloaded_file *fp)
 
     dev_cleanup();
 
+    x86_efi_copy_finish();
+
     mp = modulep & 0xffffffff;
     ke = kernend & 0xffffffff;
     pagetable = (uintptr_t)PT4;

Modified: projects/uefi/sys/boot/i386/efi/main.c
==============================================================================
--- projects/uefi/sys/boot/i386/efi/main.c	Sun Feb 10 04:14:25 2013	(r246607)
+++ projects/uefi/sys/boot/i386/efi/main.c	Sun Feb 10 04:17:41 2013	(r246608)
@@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$");
 #include <bootstrap.h>
 #include "../libi386/libi386.h"
 
+#include "x86_efi_copy.h"
+
 extern char bootprog_name[];
 extern char bootprog_rev[];
 extern char bootprog_date[];
@@ -69,6 +71,11 @@ main(int argc, CHAR16 *argv[])
 	 */
 	cons_probe();
 
+	if (x86_efi_copy_init()) {
+		printf("failed to allocate staging area\n");
+		return (EFI_BUFFER_TOO_SMALL);
+	}
+
 	/*
 	 * March through the device switch probing for things.
 	 */
@@ -115,9 +122,9 @@ main(int argc, CHAR16 *argv[])
     
 	archsw.arch_autoload = i386_autoload;
 	archsw.arch_getdev = i386_getdev;
-	archsw.arch_copyin = i386_copyin;
-	archsw.arch_copyout = i386_copyout;
-	archsw.arch_readin = i386_readin;
+	archsw.arch_copyin = x86_efi_copyin;
+	archsw.arch_copyout = x86_efi_copyout;
+	archsw.arch_readin = x86_efi_readin;
 
 	interact();			/* doesn't return */
 

Added: projects/uefi/sys/boot/i386/efi/x86_efi_copy.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/uefi/sys/boot/i386/efi/x86_efi_copy.c	Sun Feb 10 04:17:41 2013	(r246608)
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Benno Rice under sponsorship from
+ * the FreeBSD Foundation.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stand.h>
+#include <bootstrap.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#define	STAGE_PAGES	8000	/* 32MB */
+
+EFI_PHYSICAL_ADDRESS	staging;
+int			stage_offset_set = 0;
+ssize_t			stage_offset;
+
+int
+x86_efi_copy_init(void)
+{
+	EFI_STATUS	status;
+
+	status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
+	    STAGE_PAGES, &staging);
+	if (EFI_ERROR(status)) {
+		printf("failed to allocate staging area: %d\n",
+		    status & EFI_ERROR_MASK);
+		return (status);
+	}
+
+	printf("x86_efi_copyinit>>> staging=0x%016x\n", staging);
+	return (0);
+}
+
+ssize_t
+x86_efi_copyin(const void *src, vm_offset_t dest, const size_t len)
+{
+
+	if (!stage_offset_set) {
+		stage_offset = (vm_offset_t)staging - dest;
+		stage_offset_set = 1;
+	}
+
+	bcopy(src, (void *)(dest + stage_offset), len);
+	return (len);
+}
+
+ssize_t
+x86_efi_copyout(const vm_offset_t src, void *dest, const size_t len)
+{
+
+	bcopy((void *)(src + stage_offset), dest, len);
+	return (len);
+}
+
+
+ssize_t
+x86_efi_readin(const int fd, vm_offset_t dest, const size_t len)
+{
+
+	return (read(fd, (void *)(dest + stage_offset), len));
+}
+
+void
+x86_efi_copy_finish(void)
+{
+
+	bcopy((void *)staging, (void *)(staging - stage_offset),
+	    STAGE_PAGES * EFI_PAGE_SIZE);
+}

Added: projects/uefi/sys/boot/i386/efi/x86_efi_copy.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/uefi/sys/boot/i386/efi/x86_efi_copy.h	Sun Feb 10 04:17:41 2013	(r246608)
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Benno Rice under sponsorship from
+ * the FreeBSD Foundation.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef	_X86_EFI_COPY_H_
+#define	_X86_EFI_COPY_H_
+
+int	x86_efi_copy_init(void);
+void	x86_efi_copy_finish(void);
+
+ssize_t	x86_efi_copyin(const void *src, vm_offset_t dest, const size_t len);
+ssize_t	x86_efi_copyout(const vm_offset_t src, void *dest, const size_t len);
+ssize_t	x86_efi_readin(const int fd, vm_offset_t dest, const size_t len);
+
+#endif	/* _X86_EFI_COPY_H_ */


More information about the svn-src-projects mailing list