grub-devel
[Top][All Lists]
Advanced

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

[PATCH] mmap support and x86_64 CPU detection


From: Ruslan Nikolaev
Subject: [PATCH] mmap support and x86_64 CPU detection
Date: Sat, 13 Aug 2005 18:27:03 -0700 (PDT)

Hi!

I made a patch. Now you can use MMAP for multiboot and also during loading ELF64 (x86_64) check for x86_64 performs. I've tested it with gnu sample from multiboot.html.

You can say that it will be better to have separte cpuid feauture detection function, but please note that some 486 processor needs kludge code for CPUID detection while it always works for x86_64. Briefly: some 486 processor actually has CPUID but this code says that they don't (they need kludge code for detection). => In that case I think that it is clear to have CPUID detection within grub_x86_64_cpu function :)

P.S. It seems that grub_disk_read works (at least for grub-1.90 version) works incorrectly when you specify 0 as read data size. It returns something strange. This bug for both ext2 and dos. I've found this bug when tried to load multiboot file (it fails in one place). I comment readed data size checking (just for testing my patch).

ChangeLog:

ChangeLog:

2005-08-13  Ruslan Nikolaev  <address@hidden>

 * kern/i386/pc/startup.S (grub_x86_64_cpu): New function.

 * loader/i386/pc/multiboot.c (grub_multiboot_mmap): New function.
 (grub_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.

 * include/grub/i386/pc/loader.h: Added prototype for grub_x86_64_cpu.

 

PATCH:

diff -urN old/include/grub/i386/pc/init.h new/include/grub/i386/pc/init.h
--- old/include/grub/i386/pc/init.h 2005-01-31 21:40:25.000000000 +0000
+++ new/include/grub/i386/pc/init.h 2005-08-13 22:35:59.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/include/grub/i386/pc/loader.h new/include/grub/i386/pc/loader.h
--- old/include/grub/i386/pc/loader.h 2004-09-12 12:20:52.000000000 +0000
+++ new/include/grub/i386/pc/loader.h 2005-08-13 14:55:23.000000000 +0000
@@ -38,6 +38,7 @@
 void EXPORT_FUNC(grub_multiboot_real_boot) (grub_addr_t entry,
          struct grub_multiboot_info *mbi)
      __attribute__ ((noreturn));
+int EXPORT_FUNC(grub_x86_64_cpu) (void);
 
 /* It is necessary to export these functions, because normal mode commands
    reuse rescue mode commands.  */
diff -urN old/kern/i386/pc/startup.S new/kern/i386/pc/startup.S
--- old/kern/i386/pc/startup.S 2005-08-06 15:40:00.000000000 +0000
+++ new/kern/i386/pc/startup.S 2005-08-13 22:50:34.000000000 +0000
@@ -1684,3 +1684,32 @@
  popl %ebx
  popl %ebp
  ret
+
+/*
+ * int grub_x86_64_cpu (void)
+ */
+FUNCTION(grub_x86_64_cpu)
+ pushf      /* Save EFLAGS */
+ pushf
+ popl %eax
+ xorl $0x200000, %eax  /* Change ID(21) bit */
+ pushl %eax
+ popf
+ pushf
+ popl %edx
+ popf      /* Restore EFLAGS */
+ xorl %edx, %eax
+ jnz  1f
+ movl $0x80000000, %eax /* Does CPU supports 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:
+ ret
diff -urN old/loader/i386/pc/multiboot.c new/loader/i386/pc/multiboot.c
--- old/loader/i386/pc/multiboot.c 2005-07-31 15:56:54.000000000 +0000
+++ new/loader/i386/pc/multiboot.c 2005-08-14 04:44:32.282230288 +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>
@@ -172,6 +172,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 +237,77 @@
   return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
 }
 
+/* Get MMAP */
+static grub_err_t
+grub_multiboot_mmap(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 mmap */
+ 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 +367,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 MMAP */
+  if (grub_multiboot_mmap (&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 +419,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


reply via email to

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