[1802] 2008-08-12 Robert Millan <[email protected]>

Robert Millan <[email protected]>
Newsgroups gmane.comp.boot-loaders.grub.cvs
Message-ID <[email protected]>
Revision: 1802
          http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=1802
Author:   robertmh
Date:     2008-08-12 15:40:26 +0000 (Tue, 12 Aug 2008)

Log Message:
-----------
2008-08-12  Robert Millan  <[email protected]>

        * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Move part
        of the relocation code from here ...
        (grub_multiboot): ... to here.
        (forward_relocator, backward_relocator): Move from here ...
        * kern/i386/loader.S (grub_multiboot_forward_relocator)
        (grub_multiboot_backward_relocator): ... to here.
        (grub_multiboot_real_boot): Use %edx for entry offset.  Put Multiboot
        magic in %eax.  Use %ebp for jumping (so %edx is not trashed).
        * include/grub/i386/loader.h (grub_multiboot_forward_relocator)
        (grub_multiboot_forward_relocator_end)
        (grub_multiboot_backward_relocator)
        (grub_multiboot_backward_relocator_end): New variables.

Modified Paths:
--------------
    trunk/grub2/ChangeLog
    trunk/grub2/include/grub/i386/loader.h
    trunk/grub2/kern/i386/loader.S
    trunk/grub2/loader/i386/pc/multiboot.c

Modified: trunk/grub2/ChangeLog
===================================================================
--- trunk/grub2/ChangeLog	2008-08-12 13:58:29 UTC (rev 1801)
+++ trunk/grub2/ChangeLog	2008-08-12 15:40:26 UTC (rev 1802)
@@ -1,3 +1,18 @@
+2008-08-12  Robert Millan  <[email protected]>
+
+	* loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Move part
+	of the relocation code from here ...
+	(grub_multiboot): ... to here.
+	(forward_relocator, backward_relocator): Move from here ...
+	* kern/i386/loader.S (grub_multiboot_forward_relocator)
+	(grub_multiboot_backward_relocator): ... to here.
+	(grub_multiboot_real_boot): Use %edx for entry offset.  Put Multiboot
+	magic in %eax.  Use %ebp for jumping (so %edx is not trashed).
+	* include/grub/i386/loader.h (grub_multiboot_forward_relocator)
+	(grub_multiboot_forward_relocator_end)
+	(grub_multiboot_backward_relocator)
+	(grub_multiboot_backward_relocator_end): New variables.
+
 2008-08-12  Bean  <[email protected]>
 
 	* disk/raid.c (grub_raid_read): Fix a bug in raid0 code.

Modified: trunk/grub2/include/grub/i386/loader.h
===================================================================
--- trunk/grub2/include/grub/i386/loader.h	2008-08-12 13:58:29 UTC (rev 1801)
+++ trunk/grub2/include/grub/i386/loader.h	2008-08-12 15:40:26 UTC (rev 1802)
@@ -53,4 +53,11 @@
 void grub_rescue_cmd_linux (int argc, char *argv[]);
 void grub_rescue_cmd_initrd (int argc, char *argv[]);
 
+extern grub_uint8_t EXPORT_VAR(grub_multiboot_forward_relocator);
+extern grub_uint8_t EXPORT_VAR(grub_multiboot_forward_relocator_end);
+extern grub_uint8_t EXPORT_VAR(grub_multiboot_backward_relocator);
+extern grub_uint8_t EXPORT_VAR(grub_multiboot_backward_relocator_end);
+
+#define RELOCATOR_SIZEOF(x)	(&grub_multiboot_##x##_relocator_end - &grub_multiboot_##x##_relocator)
+
 #endif /* ! GRUB_LOADER_CPU_HEADER */

Modified: trunk/grub2/kern/i386/loader.S
===================================================================
--- trunk/grub2/kern/i386/loader.S	2008-08-12 13:58:29 UTC (rev 1801)
+++ trunk/grub2/kern/i386/loader.S	2008-08-12 15:40:26 UTC (rev 1802)
@@ -132,6 +132,36 @@
 VARIABLE(grub_multiboot_payload_entry_offset)
 	.long	0
 
+/*
+ * The relocators below understand the following parameters:
+ * ecx:	Size of the block to be copied.
+ * esi:	Where to copy from (always lowest address, even if we're relocating
+ *      backwards).
+ * edi:	Where to copy to (likewise).
+ * edx:	Offset of the entry point (relative to the beginning of the block).
+ */
+VARIABLE(grub_multiboot_forward_relocator)
+	cld
+	addl	%edi, %edx
+	rep
+	movsb
+	jmp	*%edx
+VARIABLE(grub_multiboot_forward_relocator_end)
+
+VARIABLE(grub_multiboot_backward_relocator)
+	std
+	addl	%ecx, %esi
+	addl	%ecx, %edi
+	/* backward movsb is implicitly off-by-one.  compensate that. */
+	incl	%ecx
+	rep
+	movsb
+	/* same problem again. */
+	incl	%edi
+	addl	%edi, %edx
+	jmp	*%edx
+VARIABLE(grub_multiboot_backward_relocator_end)
+
 FUNCTION(grub_multiboot_real_boot)
 	/* Push the entry address on the stack.  */
 	pushl	%eax
@@ -149,11 +179,14 @@
 	movl	EXT_C(grub_multiboot_payload_size), %ecx
 	movl	EXT_C(grub_multiboot_payload_orig), %esi
 	movl	EXT_C(grub_multiboot_payload_dest), %edi
-	movl	EXT_C(grub_multiboot_payload_entry_offset), %eax
-			
+	movl	EXT_C(grub_multiboot_payload_entry_offset), %edx
+
+	/* Move the magic value into eax.  */
+	movl	$MULTIBOOT_MAGIC2, %eax
+				
 	/* Jump to the relocator.  */
-	popl	%edx
-	jmp 	*%edx
+	popl	%ebp
+	jmp 	*%ebp
 	
 /*
  * This starts the multiboot 2 kernel.

Modified: trunk/grub2/loader/i386/pc/multiboot.c
===================================================================
--- trunk/grub2/loader/i386/pc/multiboot.c	2008-08-12 13:58:29 UTC (rev 1801)
+++ trunk/grub2/loader/i386/pc/multiboot.c	2008-08-12 15:40:26 UTC (rev 1802)
@@ -52,31 +52,6 @@
 
 static char *playground = NULL;
 
-static grub_uint8_t forward_relocator[] =
-{
-  0xfc,				/* cld */
-  0x89, 0xf2,			/* movl %esi, %edx */
-  0xf3, 0xa4,			/* rep movsb */
-  0x01, 0xc2,			/* addl %eax, %edx */
-  0xb8, 0x02, 0xb0, 0xad, 0x2b,	/* movl $MULTIBOOT_MAGIC2, %eax */
-  0xff, 0xe2,			/* jmp *%edx */
-};
-
-static grub_uint8_t backward_relocator[] =
-{
-  0xfd,				/* std */
-  0x01, 0xce,			/* addl %ecx, %esi */
-  0x01, 0xcf,			/* addl %ecx, %edi */
-				/* backward movsb is implicitly off-by-one.  compensate that. */
-  0x41,				/* incl %ecx */
-  0xf3, 0xa4,			/* rep movsb */
-				/* same problem again. */
-  0x47,				/* incl %edi */
-  0x01, 0xc7,			/* addl %eax, %edi */
-  0xb8, 0x02, 0xb0, 0xad, 0x2b,	/* movl $MULTIBOOT_MAGIC2, %eax */
-  0xff, 0xe7,			/* jmp *%edi */
-};
-
 static grub_err_t
 grub_multiboot_boot (void)
 {
@@ -155,17 +130,12 @@
   grub_multiboot_payload_size = (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr;
   grub_multiboot_payload_dest = phdr(lowest_segment)->p_paddr;
 
-  if (playground)
-    grub_free (playground);
-  playground = grub_malloc (sizeof (forward_relocator) + grub_multiboot_payload_size + sizeof (backward_relocator));
+  playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
   if (! playground)
     return grub_errno;
 
-  grub_multiboot_payload_orig = (long) playground + sizeof (forward_relocator);
+  grub_multiboot_payload_orig = (long) playground + RELOCATOR_SIZEOF(forward);
 
-  grub_memmove (playground, forward_relocator, sizeof (forward_relocator));
-  grub_memmove ((char *) (grub_multiboot_payload_orig + grub_multiboot_payload_size), backward_relocator, sizeof (backward_relocator));
-
   /* Load every loadable segment in memory.  */
   for (i = 0; i < ehdr->e_phnum; i++)
     {
@@ -196,16 +166,6 @@
 
 #undef phdr
 
-  if (grub_multiboot_payload_dest >= grub_multiboot_payload_orig)
-    entry = (grub_addr_t) playground;
-  else
-    entry = (grub_addr_t) grub_multiboot_payload_orig + grub_multiboot_payload_size;
-
-  grub_dprintf ("multiboot_loader", "dest=%p, size=0x%x, entry_offset=0x%x\n",
-		(void *) grub_multiboot_payload_dest,
-		grub_multiboot_payload_size,
-		grub_multiboot_payload_entry_offset);
-
   return grub_errno;
 }
 
@@ -413,24 +373,66 @@
       goto fail;
     }
 
+  if (playground)
+    {
+      grub_free (playground);
+      playground = NULL;
+    }
+
   if (header->flags & MULTIBOOT_AOUT_KLUDGE)
     {
-      int ofs;
+      int offset = ((char *) header - buffer -
+		    (header->header_addr - header->load_addr));
+      int load_size = ((header->load_end_addr == 0) ? file->size - offset :
+		       header->load_end_addr - header->load_addr);
 
-      ofs = (char *) header - buffer -
-            (header->header_addr - header->load_addr);
-      if ((grub_aout_load (file, ofs, header->load_addr,
-                           ((header->load_end_addr == 0) ? 0 :
-                            header->load_end_addr - header->load_addr),
-                           header->bss_end_addr))
-          !=GRUB_ERR_NONE)
-        goto fail;
+      if (header->bss_end_addr)
+	grub_multiboot_payload_size = (header->bss_end_addr - header->load_addr);
+      else
+	grub_multiboot_payload_size = load_size;
+      grub_multiboot_payload_dest = header->load_addr;
 
-      entry = header->entry_addr;
+      playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
+      if (! playground)
+	goto fail;
+
+      grub_multiboot_payload_orig = (long) playground + RELOCATOR_SIZEOF(forward);
+
+      if ((grub_file_seek (file, offset)) == (grub_off_t) - 1)
+	goto fail;
+
+      grub_file_read (file, grub_multiboot_payload_orig, load_size);
+      if (grub_errno)
+	goto fail;
+      
+      if (header->bss_end_addr)
+	grub_memset (grub_multiboot_payload_orig + load_size, 0,
+		     header->bss_end_addr - header->load_addr - load_size);
+      
+      grub_multiboot_payload_entry_offset = header->entry_addr - header->load_addr;
+
     }
   else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
     goto fail;
 
+      
+  if (grub_multiboot_payload_dest >= grub_multiboot_payload_orig)
+    {
+      grub_memmove (playground, &grub_multiboot_forward_relocator, RELOCATOR_SIZEOF(forward));
+      entry = (grub_addr_t) playground;
+    }
+  else
+    {
+      grub_memmove ((char *) (grub_multiboot_payload_orig + grub_multiboot_payload_size),
+		    &grub_multiboot_backward_relocator, RELOCATOR_SIZEOF(backward));
+      entry = (grub_addr_t) grub_multiboot_payload_orig + grub_multiboot_payload_size;
+    }
+  
+  grub_dprintf ("multiboot_loader", "dest=%p, size=0x%x, entry_offset=0x%x\n",
+		(void *) grub_multiboot_payload_dest,
+		grub_multiboot_payload_size,
+		grub_multiboot_payload_entry_offset);
+
   mbi = grub_malloc (sizeof (struct grub_multiboot_info));
   if (! mbi)
     goto fail;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.