Hi!
 
OK, I rewrote the patch. Now it uses inline assembly and memory map function name was changed. I also add "ebx" to clobbered registers list because I have recently found that it also can be clobbered (it marked as "Reserverd" in documentation => it can be clobbered).
 
Is it good now? What do you think?
 
Ruslan.
 
ChangeLog:
 
2005-08-16  Ruslan Nikolaev  <[EMAIL PROTECTED]>
 * loader/i386/pc/multiboot.c (grub_multiboot_mmap): New function.
 (grub_x86_64_cpu): Likewise.
 (grub_multiboot_load_elf64): Make sure that we have deal with x86_64 CPU.
 (grub_rescue_cmd_multiboot): Added mmap support.
 * include/grub/i386/pc/init.h: Function grub_get_mmap_entry is exportable now.
PATCH:
 
diff -urN old/grub-1.90/include/grub/i386/pc/init.h new/grub-1.90/include/grub/i386/pc/init.h
--- old/grub-1.90/include/grub/i386/pc/init.h 2005-01-31 21:40:25.000000000 +0000
+++ new/grub-1.90/include/grub/i386/pc/init.h 2005-08-16 03:58:23.000000000 +0000
@@ -48,7 +48,7 @@
 
 /* Get a memory map entry. Return next continuation value. Zero means
    the end.  */
-grub_uint32_t grub_get_mmap_entry (struct grub_machine_mmap_entry *entry,
+grub_uint32_t EXPORT_FUNC (grub_get_mmap_entry) (struct grub_machine_mmap_entry *entry,
        grub_uint32_t cont);
 
 /* Turn on/off Gate A20.  */
diff -urN old/grub-1.90/loader/i386/pc/multiboot.c new/grub-1.90/loader/i386/pc/multiboot.c
--- old/grub-1.90/loader/i386/pc/multiboot.c 2005-07-31 15:56:54.000000000 +0000
+++ new/grub-1.90/loader/i386/pc/multiboot.c 2005-08-16 04:22:35.939871456 +0000
@@ -25,7 +25,6 @@
  *  - a.out support
  *  - boot device
  *  - symbol table
- *  - memory map
  *  - drives table
  *  - ROM configuration table
  *  - APM table
@@ -35,6 +34,7 @@
 #include <grub/machine/loader.h>
 #include <grub/machine/multiboot.h>
 #include <grub/machine/init.h>
+#include <grub/machine/memory.h>
 #include <grub/elf.h>
 #include <grub/file.h>
 #include <grub/err.h>
@@ -81,6 +81,42 @@
   return GRUB_ERR_NONE;
 }
 
+/* Detect x86_64 CPU */
+static __inline__ int grub_x86_64_cpu (void)
+{
+  int res;
+
+  __asm__ __volatile__ (
+    "pushf;"                    /* Save EFLAGS */
+    "pushf;"
+    "popl %%eax;"
+    "xorl $0x200000, %%eax;"    /* Change ID(21) bit */
+    "pushl %%eax;"
+    "popf;"
+    "pushf;"
+    "popl %%edx;"
+    "popf;"                     /* Restore EFLAGS */
+    "xorl %%edx, %%edx;"
+    "jnz 1f;"
+    "movl $0x80000000, %%eax;"  /* Any function > 0x80000000? */
+    "cpuid;"
+    "cmpl $0x80000000, %%eax;"
+    "jbe 1f;"
+    "movl $0x80000001, %%eax;"  /* Does CPU supports long mode? */
+    "cpuid;"
+    "xorl %%eax, %%eax;"
+    "btl $29, %%edx;"
+    "jc 2f;"
+    "1: movl $0xFFFFFFFF, %%eax;"
+    "2:"
+    : "=a" (res)
+    :
+    : "%ebx", "%ecx", "%edx"
+  );
+
+  return res;
+}
+
 /* Check if BUFFER contains ELF32.  */
 static int
 grub_multiboot_is_elf32 (void *buffer)
@@ -172,6 +208,10 @@
       || ehdr->e_machine != EM_X86_64)
     return grub_error(GRUB_ERR_UNKNOWN_OS, "no valid ELF header found");
 
+  /* First we must ensure that we have deal with x86_64 processor */
+  if (grub_x86_64_cpu () < 0)
+    return grub_error (GRUB_ERR_UNKNOWN_OS, "you have a pure x86 system but the kernel requires x86_64 one");
+
   if (ehdr->e_type != ET_EXEC)
     return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type");
 
@@ -233,11 +273,77 @@
   return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
 }
 
+/* Get memory map */
+static grub_err_t
+grub_multiboot_get_memmap(void **mmap_addr, grub_uint32_t *mmap_length)
+{
+  char *addr, *old_addr;
+  grub_size_t buf_size = 4096;
+  grub_uint32_t length = 0;
+  grub_uint32_t cont, entry_size;
+  struct grub_machine_mmap_entry *mmap_entry
+    = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
+
+  /* Check if grub_get_mmap_entry works. */
+  cont = grub_get_mmap_entry (mmap_entry, 0);
+  if (mmap_entry->size)
+    {
+ /* Allocate buffer for memory map */
+ addr = grub_malloc (4096);
+ if (! addr)
+   return grub_errno;
+
+      do
+      {
+ entry_size = mmap_entry->size + sizeof(mmap_entry->size);
+ /* If buffer is small then reallocate it */
+ if (length + entry_size > buf_size)
+         {
+     buf_size += 4096;
+        old_addr = addr;
+        addr = grub_realloc(old_addr, buf_size);
+        if (! addr)
+          goto mem_out;
+   }
+
+ grub_memcpy (addr + length, mmap_entry, entry_size);
+ length += entry_size;
+
+ if (! cont)
+   break;
+
+        /* Get next entry */
+        cont = grub_get_mmap_entry (mmap_entry, cont);
+      } while (mmap_entry->size);
+
+ /* Truncate buffer to apropriate size */
+ old_addr = addr;
+ addr = grub_realloc (old_addr, length);
+ if (! addr)
+   {
+     mem_out:
+     grub_free(old_addr);
+     return grub_errno;
+      }
+
+      *mmap_addr = addr;
+      *mmap_length = length;
+    }
+  else
+    {
+      *mmap_addr = 0;
+      *mmap_length = 0;
+    }
+
+  return GRUB_ERR_NONE;
+}
+
 void
 grub_rescue_cmd_multiboot (int argc, char *argv[])
 {
   grub_file_t file = 0;
   char buffer[GRUB_MB_SEARCH], *cmdline = 0, *p;
+  void *mmap_addr = 0;
   struct grub_multiboot_header *header;
   grub_ssize_t len;
   int i;
@@ -297,12 +403,27 @@
   if (! mbi)
     goto fail;
 
-  mbi->flags = GRUB_MB_INFO_MEMORY;
+  mbi->flags = 0;
+
+  if (header->flags & GRUB_MB_MEMORY_INFO)
+    {
+
+  mbi->flags |= GRUB_MB_INFO_MEMORY;
 
   /* Convert from bytes to kilobytes.  */
   mbi->mem_lower = grub_lower_mem / 1024;
   mbi->mem_upper = grub_upper_mem / 1024;
 
+  /* Get memory map */
+  if (grub_multiboot_get_memmap (&mmap_addr, &mbi->mmap_length) != GRUB_ERR_NONE)
+    goto fail;
+
+  mbi->mmap_addr = (grub_uint32_t) mmap_addr;
+  if (mmap_addr)
+    mbi->flags |= GRUB_MB_INFO_MEM_MAP;
+
+    }
+
   for (i = 0, len = 0; i < argc; i++)
     len += grub_strlen (argv[i]) + 1;
  
@@ -334,6 +455,7 @@
   if (grub_errno != GRUB_ERR_NONE)
     {
       grub_free (cmdline);
+      grub_free (mmap_addr);
       grub_free (mbi);
       grub_dl_unref (my_mod);
     }
 

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to