Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 26 Feb 2013 03:24:45 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r247301 - head/sys/boot/common
Message-ID:  <201302260324.r1Q3Oj56039626@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Tue Feb 26 03:24:45 2013
New Revision: 247301
URL: http://svnweb.freebsd.org/changeset/base/247301

Log:
  Adjust the arm kernel entry point address properly regardless of whether the
  e_entry field holds a physical or a virtual address.  Add a comment block
  that explains the assumptions being made by the adjustment code.

Modified:
  head/sys/boot/common/load_elf.c

Modified: head/sys/boot/common/load_elf.c
==============================================================================
--- head/sys/boot/common/load_elf.c	Tue Feb 26 02:13:02 2013	(r247300)
+++ head/sys/boot/common/load_elf.c	Tue Feb 26 03:24:45 2013	(r247301)
@@ -290,14 +290,25 @@ __elfN(loadimage)(struct preloaded_file 
 	} else
 	    off = 0;
 #elif defined(__arm__)
-	if (off & 0xf0000000u) {
-	    off = -(off & 0xf0000000u);
-	    ehdr->e_entry += off;
+	/*
+	 * The elf headers in some kernels specify virtual addresses in all
+	 * header fields.  More recently, the e_entry and p_paddr fields are the
+	 * proper physical addresses.  Even when the p_paddr fields are correct,
+	 * the MI code below uses the p_vaddr fields with an offset added for
+	 * loading (doing so is arguably wrong).  To make loading work, we need
+	 * an offset that represents the difference between physical and virtual
+	 * addressing.  ARM kernels are always linked at 0xC0000000.  Depending
+	 * on the headers, the offset value passed in may be physical or virtual
+	 * (because it typically comes from e_entry), but we always replace
+	 * whatever is passed in with the va<->pa offset.  On the other hand, we
+	 * only adjust the entry point if it's a virtual address to begin with.
+	 */
+	off = -0xc0000000u;
+	if ((ehdr->e_entry & 0xc0000000u) == 0xc000000u)
+		ehdr->e_entry += off;
 #ifdef ELF_VERBOSE
-	    printf("Converted entry 0x%08x\n", ehdr->e_entry);
+	printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n", ehdr->e_entry, off);
 #endif
-	} else
-	    off = 0;
 #else
 	off = 0;		/* other archs use direct mapped kernels */
 #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201302260324.r1Q3Oj56039626>