socsvn commit: r237877 - in soc2012/emc2: experimental head/sys/boot/efi/include head/sys/boot/efi/include/i386

emc2 at FreeBSD.org emc2 at FreeBSD.org
Mon Jun 18 04:42:41 UTC 2012


Author: emc2
Date: Mon Jun 18 04:42:39 2012
New Revision: 237877
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=237877

Log:
  Very hard-won progress.  Due to a bug in stdint.h, uint64_t (and by
  extension, UINT64) was being typedef'ed to unsigned long, but when compiling
  with -m32, this meant sizeof(uint64_t) == 4.  This ultimately caused the
  EFI_SYSTEM_TABLE and others to have the wrong offsets, which caused the
  errors I'd been seeing.
  
  I added a temporary fix to detect when compiling for i386 vs amd64, and to
  select the proper UINT64.

Added:
  soc2012/emc2/experimental/reloc.c
Modified:
  soc2012/emc2/experimental/Makefile
  soc2012/emc2/experimental/helloworld.c
  soc2012/emc2/experimental/start.S
  soc2012/emc2/head/sys/boot/efi/include/efiapi.h
  soc2012/emc2/head/sys/boot/efi/include/i386/efibind.h

Modified: soc2012/emc2/experimental/Makefile
==============================================================================
--- soc2012/emc2/experimental/Makefile	Mon Jun 18 04:31:15 2012	(r237876)
+++ soc2012/emc2/experimental/Makefile	Mon Jun 18 04:42:39 2012	(r237877)
@@ -1,13 +1,23 @@
-CC=gcc
-CFLAGS=-O2 -m32 -I../head/sys/boot/efi/include/ -I../head/sys/boot/efi/include/i386 -fPIC
-OBJCOPY=objcopy
+GCCPREFIX=
+#GCCPREFIX=/usr/local/mingw32/bin
+CC=${GCCPREFIX}gcc
+INCLUDEFLAGS=-I../head/sys/boot/efi/include/ -I../head/sys/boot/efi/include/i386 -I../head/sys/boot/common
+CFLAGS=-O2 -m32 ${INCLUDEFLAGS}
+#CFLAGS = -g -Os -fshort-wchar -fno-strict-aliasing -Wall -Werror -Wno-missing-braces -Wno-array-bounds -c -m32 -malign-double -freorder-blocks -freorder-blocks-and-partition -O2 -mno-stack-arg-probe ${INCLUDEFLAGS}
+OBJCOPY=${GCCPREFIX}objcopy
+
 EFIFORMAT=efi-app-ia32
 LDSCRIPT=ldscript.i386
 
+CLEANFILES=helloworld.dll helloworld.obj helloworld.o helloworld helloworld.efi start.o reloc.o
+
 all: helloworld.efi
 
 clean:
-	rm -f helloworld.o helloworld helloworld.efi start.o
+	rm -rf ${CLEANFILES}
+
+reloc.o: reloc.c
+	${CC} -c ${CFLAGS} reloc.c
 
 start.o: start.S
 	${CC} -c ${CFLAGS} start.S
@@ -15,8 +25,9 @@
 helloworld.o: helloworld.c
 	${CC} -c ${CFLAGS} helloworld.c
 
-helloworld: helloworld.o start.o
-	${CC} -nostdlib -o helloworld -Wl,-T ${LDSCRIPT} -shared -symbolic helloworld.o start.o
+helloworld: helloworld.o start.o reloc.o
+	${CC} -nostdlib -o helloworld -Wl,-T ${LDSCRIPT} -shared -symbolic helloworld.o start.o reloc.o
+# libefi.a
 
 helloworld.efi: helloworld
 	${OBJCOPY} -j .data -j .dynamic -j .dynstr -j .dynsym -j .hash \

Modified: soc2012/emc2/experimental/helloworld.c
==============================================================================
--- soc2012/emc2/experimental/helloworld.c	Mon Jun 18 04:31:15 2012	(r237876)
+++ soc2012/emc2/experimental/helloworld.c	Mon Jun 18 04:42:39 2012	(r237877)
@@ -1,12 +1,55 @@
+#include <stdlib.h>
 #include <efi.h>
-
+#include <efiapi.h>
+/*
+int main(int argc, char** argv) {
+  return -1;
+}
+*/
 static unsigned short str[] =
   { 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\n', '\r', 0 };
 
+
 EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE* systab)
 {
+  /*
+  sig = systab->Hdr.Signature;
+  rev = systab->Hdr.Revision;
+  hdrsize = systab->Hdr.HeaderSize;
+  CRC32 = systab->Hdr.CRC32;
+  reserved = systab->Hdr.Reserved;
+  vendor = systab->FirmwareVendor;
+  revision = systab->FirmwareRevision;
+  coninhandle = systab->ConsoleInHandle;
+  ConIn = systab->ConIn;
+  conouthandle = systab->ConsoleOutHandle;
+  ConOut = systab->ConOut;
+  */
+  systab->ConOut->OutputString(systab->ConOut, str);
+  /*
+  EFI_STATUS status;
+
+  IH = image;
+  ST = systab;
+  BS = ST->BootServices;
+  RS = ST->RuntimeServices;
+
+  heapsize = 2 * 1024 * 1024;
+  status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
+			     EFI_SIZE_TO_PAGES(heapsize), &heap);
+
+  if(NULL == ST->ConOut->Reset)
+    return -1;
+  else
+    return EFI_SUCCESS;
+  */
+  return sizeof(UINT64);
+  //return (EFI_STATUS)systab->ConOut;
+}
 
-  systab->ConOut->ClearScreen(systab->ConOut);
+#include <stdio.h>
 
-  return EFI_SUCCESS;
+main() {
+  printf("%d\n", sizeof(uint64_t));
+  return 0;
 }

Added: soc2012/emc2/experimental/reloc.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2012/emc2/experimental/reloc.c	Mon Jun 18 04:42:39 2012	(r237877)
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 2008-2010 Rui Paulo <rpaulo at FreeBSD.org>
+ * All rights reserved.
+ *
+ * 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: soc2012/emc2/head/sys/boot/i386/efi/reloc.c 235458 2012-05-09 07:55:42Z avg $");
+
+#include <sys/types.h>
+#include <sys/elf32.h>
+#include <efi.h>
+#include <bootstrap.h>
+
+/*
+ * A simple relocator for IA32 EFI binaries.
+ */
+EFI_STATUS
+_reloc(unsigned long ImageBase, Elf32_Dyn *dynamic, EFI_HANDLE image_handle,
+    EFI_SYSTEM_TABLE *system_table)
+{
+	unsigned long relsz, relent;
+	unsigned long *newaddr;
+	Elf32_Rel *rel;
+	Elf32_Dyn *dynp;
+
+	/*
+	 * Find the relocation address, its size and the relocation entry.
+	 */
+	relsz = 0;
+	relent = 0;
+	for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) {
+		switch (dynp->d_tag) {
+		case DT_REL:
+			rel = (Elf32_Rel *) ((unsigned long) dynp->d_un.d_ptr +
+			    ImageBase);
+			break;
+		case DT_RELSZ:
+			relsz = dynp->d_un.d_val;
+			break;
+		case DT_RELENT:
+			relent = dynp->d_un.d_val;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/*
+	 * Perform the actual relocation.
+	 * XXX: We are reusing code for the amd64 version of this, but
+	 * we must make sure the relocation types are the same.
+	 */
+	CTASSERT(R_386_NONE == R_X86_64_NONE);
+	CTASSERT(R_386_RELATIVE == R_X86_64_RELATIVE);
+	for (; relsz > 0; relsz -= relent) {
+		switch (ELF32_R_TYPE(rel->r_info)) {
+		case R_386_NONE:
+			/* No relocation needs be performed. */
+			break;
+		case R_386_RELATIVE:
+			/* Address relative to the base address. */
+			newaddr = (unsigned long *)(ImageBase + rel->r_offset);
+			*newaddr += ImageBase;
+			break;
+		default:
+			/* XXX: do we need other relocations ? */
+			return (EFI_LOAD_ERROR);
+		}
+		rel = (Elf32_Rel *) ((caddr_t) rel + relent);
+	}
+
+	return (EFI_SUCCESS);
+}

Modified: soc2012/emc2/experimental/start.S
==============================================================================
--- soc2012/emc2/experimental/start.S	Mon Jun 18 04:31:15 2012	(r237876)
+++ soc2012/emc2/experimental/start.S	Mon Jun 18 04:42:39 2012	(r237877)
@@ -46,8 +46,20 @@
 
 	pushl	12(%ebp)	/* image_handle */
 	pushl	8(%ebp)		/* system_table */
+	call	0f
+0:	popl	%eax
+	movl	%eax, %ebx
+	addl	$ImageBase-0b, %eax
+	addl	$_DYNAMIC-0b, %ebx
+	pushl	%ebx		/* dynamic */
+	pushl	%eax		/* ImageBase */
+	call	_reloc
+	cmpl	$EFI_SUCCESS, %eax
+	jne	1f
+	popl	%ebx		/* remove ImageBase from the stack */
+	popl	%ebx		/* remove dynamic from the stack */
 	call	efi_main
-	leave
+1:	leave
 	ret
 END(_start)
 

Modified: soc2012/emc2/head/sys/boot/efi/include/efiapi.h
==============================================================================
--- soc2012/emc2/head/sys/boot/efi/include/efiapi.h	Mon Jun 18 04:31:15 2012	(r237876)
+++ soc2012/emc2/head/sys/boot/efi/include/efiapi.h	Mon Jun 18 04:42:39 2012	(r237877)
@@ -666,7 +666,7 @@
 // Standard EFI table header
 //
 
-typedef struct _EFI_TABLE_HEARDER {
+typedef struct _EFI_TABLE_HEADER {
   UINT64                      Signature;
   UINT32                      Revision;
   UINT32                      HeaderSize;

Modified: soc2012/emc2/head/sys/boot/efi/include/i386/efibind.h
==============================================================================
--- soc2012/emc2/head/sys/boot/efi/include/i386/efibind.h	Mon Jun 18 04:31:15 2012	(r237876)
+++ soc2012/emc2/head/sys/boot/efi/include/i386/efibind.h	Mon Jun 18 04:42:39 2012	(r237877)
@@ -84,9 +84,13 @@
 //
 // Basic EFI types of various widths
 //
-
-typedef uint64_t   UINT64;
-typedef int64_t    INT64;
+#if defined(__amd64)
+typedef unsigned long   UINT64;
+typedef long    INT64;
+#elif defined(__i386)
+typedef unsigned long long UINT64;
+typedef long long INT64;
+#endif
 
 #ifndef _BASETSD_H_
     typedef uint32_t   UINT32;


More information about the svn-soc-all mailing list