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 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel