grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] new (mmap support and x86_64 detection)


From: Ruslan Nikolaev
Subject: Re: [PATCH] new (mmap support and x86_64 detection)
Date: Tue, 16 Aug 2005 15:25:24 -0700 (PDT)

OK.

I've changed it to grub_multiboot_detect_x86_64().
I'll busy for a week or even more. Please say if
something wrong.

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-02-01 00:40:25.000000000 +0300
+++ new/grub-1.90/include/grub/i386/pc/init.h
2005-08-17 02:16:05.987721056 +0400
@@ -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 19:56:54.000000000 +0400
+++ new/grub-1.90/loader/i386/pc/multiboot.c
2005-08-17 02:17:47.771247608 +0400
@@ -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_multiboot_detect_x86_64
(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_multiboot_detect_x86_64 () < 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);
     }



                
____________________________________________________
Start your day with Yahoo! - make it your home page 
http://www.yahoo.com/r/hs 
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]