From: "Vladimir 'φ-coder/phcoder' Serbinenko" <phcoder@gmail.com>
To: The development of GNU GRUB <grub-devel@gnu.org>
Subject: Re: [bug #36532] boot in EFI mode (x86_64) fails on some systems
Date: Sun, 27 May 2012 16:52:12 +0200 [thread overview]
Message-ID: <4FC23F9C.50000@gmail.com> (raw)
In-Reply-To: <959D45574D89AF41A9DADF6F446A2E9A2AE52B06DA@AUSX7MCPS310.AMER.DELL.COM>
[-- Attachment #1.1: Type: text/plain, Size: 283 bytes --]
On 24.05.2012 19:27, Stuart_Hayes@Dell.com wrote:
> Hello…
>
>
>
> I just submitted a grub2 bug, along with a patch, at
> <http://savannah.gnu.org/bugs/?36532>.
Could you test the attached patch on top of HEAD?
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: efi.diff --]
[-- Type: text/x-diff; name="efi.diff", Size: 12328 bytes --]
=== modified file 'grub-core/loader/efi/chainloader.c'
--- grub-core/loader/efi/chainloader.c 2012-03-10 19:41:28 +0000
+++ grub-core/loader/efi/chainloader.c 2012-05-27 14:29:35 +0000
@@ -111,14 +111,16 @@
fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE;
- size = len * sizeof (grub_efi_char16_t) + sizeof (*fp);
+
+ size = grub_utf8_to_utf16 (fp->path_name, len * GRUB_MAX_UTF16_PER_UTF8,
+ (const grub_uint8_t *) str, len, 0);
+ for (p = fp->path_name; p < fp->path_name + size; p++)
+ if (*p == '/')
+ *p = '\\';
+
+ size = size * sizeof (grub_efi_char16_t) + sizeof (*fp);
fp->header.length[0] = (grub_efi_uint8_t) (size & 0xff);
fp->header.length[1] = (grub_efi_uint8_t) (size >> 8);
- for (p = fp->path_name; len > 0; len--, p++, str++)
- {
- /* FIXME: this assumes that the path is in ASCII. */
- *p = (grub_efi_char16_t) (*str == '/' ? '\\' : *str);
- }
}
static grub_efi_device_path_t *
@@ -154,6 +156,7 @@
file_path = grub_malloc (size
+ ((grub_strlen (dir_start) + 1)
+ * GRUB_MAX_UTF16_PER_UTF8
* sizeof (grub_efi_char16_t))
+ sizeof (grub_efi_file_path_device_path_t) * 2);
if (! file_path)
=== modified file 'grub-core/loader/i386/linux.c'
--- grub-core/loader/i386/linux.c 2012-04-17 11:00:06 +0000
+++ grub-core/loader/i386/linux.c 2012-05-27 14:44:23 +0000
@@ -59,14 +59,10 @@
#define ACCEPTS_PURE_TEXT 1
#endif
-#define GRUB_LINUX_CL_OFFSET 0x1000
-
static grub_dl_t my_mod;
static grub_size_t linux_mem_size;
static int loaded;
-static void *real_mode_mem;
-static grub_addr_t real_mode_target;
static void *prot_mode_mem;
static grub_addr_t prot_mode_target;
static void *initrd_mem;
@@ -78,6 +74,8 @@
static struct grub_relocator *relocator = NULL;
static void *efi_mmap_buf;
static grub_size_t maximal_cmdline_size;
+static struct linux_kernel_params linux_params;
+static char *linux_cmdline;
#ifdef GRUB_MACHINE_EFI
static grub_efi_uintn_t efi_mmap_size;
#else
@@ -183,8 +181,8 @@
{
grub_relocator_unload (relocator);
relocator = NULL;
- real_mode_mem = prot_mode_mem = initrd_mem = 0;
- real_mode_target = prot_mode_target = initrd_mem_target = 0;
+ prot_mode_mem = initrd_mem = 0;
+ prot_mode_target = initrd_mem_target = 0;
}
/* Allocate pages for the real mode code and the protected mode code
@@ -194,31 +192,13 @@
grub_size_t min_align, int relocatable,
grub_uint64_t prefered_address)
{
- grub_size_t real_size, mmap_size;
grub_err_t err;
-
- /* Make sure that each size is aligned to a page boundary. */
- real_size = GRUB_LINUX_CL_OFFSET + maximal_cmdline_size;
- prot_size = page_align (prot_size);
- mmap_size = find_mmap_size ();
-
-#ifdef GRUB_MACHINE_EFI
- efi_mmap_size = find_efi_mmap_size ();
- if (efi_mmap_size == 0)
- return grub_errno;
-#endif
-
- grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n",
- (unsigned) real_size, (unsigned) prot_size, (unsigned) mmap_size);
-
- /* Calculate the number of pages; Combine the real mode code with
- the memory map buffer for simplicity. */
- real_mode_pages = ((real_size + mmap_size + efi_mmap_size) >> 12);
prot_mode_pages = (prot_size >> 12);
/* Initialize the memory pointers with NULL for convenience. */
free_pages ();
+ prot_size = page_align (prot_size);
relocator = grub_relocator_new ();
if (!relocator)
{
@@ -229,59 +209,6 @@
/* FIXME: Should request low memory from the heap when this feature is
implemented. */
- auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t,
- grub_memory_type_t);
- int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
- grub_memory_type_t type)
- {
- /* We must put real mode code in the traditional space. */
-
- if (type == GRUB_MEMORY_AVAILABLE
- && addr <= 0x90000)
- {
- if (addr < 0x10000)
- {
- size += addr - 0x10000;
- addr = 0x10000;
- }
-
- if (addr + size > 0x90000)
- size = 0x90000 - addr;
-
- if (real_size + mmap_size + efi_mmap_size > size)
- return 0;
-
- real_mode_target = ((addr + size) - (real_size + mmap_size + efi_mmap_size));
- return 1;
- }
-
- return 0;
- }
-#ifdef GRUB_MACHINE_EFI
- grub_efi_mmap_iterate (hook, 1);
- if (! real_mode_target)
- grub_efi_mmap_iterate (hook, 0);
-#else
- grub_mmap_iterate (hook);
-#endif
- if (! real_mode_target)
- {
- err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
- goto fail;
- }
-
- {
- grub_relocator_chunk_t ch;
- err = grub_relocator_alloc_chunk_addr (relocator, &ch,
- real_mode_target,
- (real_size + mmap_size
- + efi_mmap_size));
- if (err)
- goto fail;
- real_mode_mem = get_virtual_current_address (ch);
- }
- efi_mmap_buf = (grub_uint8_t *) real_mode_mem + real_size + mmap_size;
-
{
grub_relocator_chunk_t ch;
if (relocatable)
@@ -315,9 +242,6 @@
prot_mode_target = get_physical_target_address (ch);
}
- grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_target = %lx, real_mode_pages = %x\n",
- (unsigned long) real_mode_mem, (unsigned long) real_mode_target,
- (unsigned) real_mode_pages);
grub_dprintf ("linux", "prot_mode_mem = %lx, prot_mode_target = %lx, prot_mode_pages = %x\n",
(unsigned long) prot_mode_mem, (unsigned long) prot_mode_target,
(unsigned) prot_mode_pages);
@@ -335,12 +259,6 @@
{
int n = *e820_num;
- if (n >= GRUB_E820_MAX_ENTRY)
- {
- return grub_error (GRUB_ERR_OUT_OF_RANGE,
- "Too many e820 memory map entries");
- }
-
if ((n > 0) && (e820_map[n - 1].addr + e820_map[n - 1].size == start) &&
(e820_map[n - 1].type == type))
e820_map[n - 1].size += size;
@@ -462,9 +380,89 @@
const char *modevar;
char *tmp;
struct grub_relocator32_state state;
+ void *real_mode_mem;
+ grub_addr_t real_mode_target;
+ grub_size_t real_size, mmap_size;
+ grub_size_t cl_offset;
+
+ mmap_size = find_mmap_size ();
+ /* Make sure that each size is aligned to a page boundary. */
+ cl_offset = ALIGN_UP (mmap_size + sizeof (*params), 4096);
+ real_size = cl_offset + maximal_cmdline_size;
+
+#ifdef GRUB_MACHINE_EFI
+ efi_mmap_size = find_efi_mmap_size ();
+ if (efi_mmap_size == 0)
+ return grub_errno;
+#endif
+
+ grub_dprintf ("linux", "real_size = %x, mmap_size = %x\n",
+ (unsigned) real_size, (unsigned) mmap_size);
+
+ /* Calculate the number of pages; Combine the real mode code with
+ the memory map buffer for simplicity. */
+ real_mode_pages = ((real_size + efi_mmap_size) >> 12);
+
+ auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t,
+ grub_memory_type_t);
+ int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
+ grub_memory_type_t type)
+ {
+ /* We must put real mode code in the traditional space. */
+
+ if (type == GRUB_MEMORY_AVAILABLE
+ && addr <= 0x90000)
+ {
+ if (addr < 0x10000)
+ {
+ size += addr - 0x10000;
+ addr = 0x10000;
+ }
+
+ if (addr + size > 0x90000)
+ size = 0x90000 - addr;
+
+ if (real_size + efi_mmap_size > size)
+ return 0;
+
+ real_mode_target = ((addr + size) - (real_size + efi_mmap_size));
+ return 1;
+ }
+
+ return 0;
+ }
+#ifdef GRUB_MACHINE_EFI
+ grub_efi_mmap_iterate (hook, 1);
+ if (! real_mode_target)
+ grub_efi_mmap_iterate (hook, 0);
+#else
+ grub_mmap_iterate (hook);
+#endif
+ if (! real_mode_target)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
+
+ {
+ grub_relocator_chunk_t ch;
+ err = grub_relocator_alloc_chunk_addr (relocator, &ch,
+ real_mode_target,
+ (real_size + efi_mmap_size));
+ if (err)
+ return err;
+ real_mode_mem = get_virtual_current_address (ch);
+ }
+ efi_mmap_buf = (grub_uint8_t *) real_mode_mem + real_size;
+
+ grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_target = %lx, real_mode_pages = %x\n",
+ (unsigned long) real_mode_mem, (unsigned long) real_mode_target,
+ (unsigned) real_mode_pages);
params = real_mode_mem;
+ *params = linux_params;
+ params->cmd_line_ptr = real_mode_target + cl_offset;
+ grub_memcpy ((char *) params + cl_offset, linux_cmdline,
+ maximal_cmdline_size);
+
#ifdef GRUB_MACHINE_IEEE1275
{
const char *bootpath;
@@ -482,10 +480,10 @@
grub_dprintf ("linux", "code32_start = %x\n",
(unsigned) params->code32_start);
- auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t,
+ auto int NESTED_FUNC_ATTR hook_fill (grub_uint64_t, grub_uint64_t,
grub_memory_type_t);
- int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
- grub_memory_type_t type)
+ int NESTED_FUNC_ATTR hook_fill (grub_uint64_t addr, grub_uint64_t size,
+ grub_memory_type_t type)
{
grub_uint32_t e820_type;
switch (type)
@@ -517,7 +515,7 @@
}
e820_num = 0;
- if (grub_mmap_iterate (hook))
+ if (grub_mmap_iterate (hook_fill))
return grub_errno;
params->mmap_size = e820_num;
@@ -652,6 +650,8 @@
{
grub_dl_unref (my_mod);
loaded = 0;
+ grub_free (linux_cmdline);
+ linux_cmdline = 0;
return GRUB_ERR_NONE;
}
@@ -781,16 +781,16 @@
preffered_address))
goto fail;
- params = (struct linux_kernel_params *) real_mode_mem;
- grub_memset (params, 0, GRUB_LINUX_CL_OFFSET + maximal_cmdline_size);
+ params = (struct linux_kernel_params *) &linux_params;
+ grub_memset (params, 0, sizeof (*params));
grub_memcpy (¶ms->setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
params->code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR;
params->kernel_alignment = (1 << align);
params->ps_mouse = params->padding10 = 0;
- len = 0x400 - sizeof (lh);
- if (grub_file_read (file, (char *) real_mode_mem + sizeof (lh), len) != len)
+ len = sizeof (*params) - sizeof (lh);
+ if (grub_file_read (file, (char *) params + sizeof (lh), len) != len)
{
if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@@ -805,7 +805,6 @@
params->cl_magic = GRUB_LINUX_CL_MAGIC;
params->cl_offset = 0x1000;
- params->cmd_line_ptr = real_mode_target + 0x1000;
params->ramdisk_image = 0;
params->ramdisk_size = 0;
@@ -978,10 +977,12 @@
}
/* Create kernel command line. */
- grub_memcpy ((char *)real_mode_mem + GRUB_LINUX_CL_OFFSET, LINUX_IMAGE,
- sizeof (LINUX_IMAGE));
+ linux_cmdline = grub_malloc (maximal_cmdline_size);
+ if (!linux_cmdline)
+ goto fail;
+ grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
grub_create_loader_cmdline (argc, argv,
- (char *)real_mode_mem + GRUB_LINUX_CL_OFFSET
+ linux_cmdline
+ sizeof (LINUX_IMAGE) - 1,
maximal_cmdline_size
- (sizeof (LINUX_IMAGE) - 1));
@@ -1054,7 +1055,7 @@
initrd_pages = (page_align (size) >> 12);
- lh = (struct linux_kernel_header *) real_mode_mem;
+ lh = (struct linux_kernel_header *) &linux_params;
/* Get the highest address available for the initrd. */
if (grub_le_to_cpu16 (lh->version) >= 0x0203)
=== modified file 'include/grub/i386/linux.h'
--- include/grub/i386/linux.h 2012-03-04 11:13:05 +0000
+++ include/grub/i386/linux.h 2012-05-27 14:34:29 +0000
@@ -69,8 +69,6 @@
#define GRUB_E820_NVS 4
#define GRUB_E820_BADRAM 5
-#define GRUB_E820_MAX_ENTRY 128
-
struct grub_e820_mmap
{
grub_uint64_t addr;
@@ -298,7 +296,7 @@
grub_uint32_t payload_length;
grub_uint64_t setup_data;
grub_uint8_t pad2[120]; /* 258 */
- struct grub_e820_mmap e820_map[GRUB_E820_MAX_ENTRY]; /* 2d0 */
+ struct grub_e820_mmap e820_map[(0x400 - 0x2d0) / 20]; /* 2d0 */
} __attribute__ ((packed));
#endif /* ! ASM_FILE */
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]
next prev parent reply other threads:[~2012-05-27 14:52 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-24 17:27 [bug #36532] boot in EFI mode (x86_64) fails on some systems Stuart_Hayes
2012-05-26 10:18 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-05-27 14:52 ` Vladimir 'φ-coder/phcoder' Serbinenko [this message]
[not found] <20120523-193311.sv88235.49420@savannah.gnu.org>
[not found] ` <20120531-112908.sv72589.64321@savannah.gnu.org>
[not found] ` <959D45574D89AF41A9DADF6F446A2E9A2AE507A772@AUSX7MCPS310.AMER.DELL.COM>
[not found] ` <959D45574D89AF41A9DADF6F446A2E9A2AE55A707B@AUSX7MCPS310.AMER.DELL.COM>
[not found] ` <4FD1180B.8090709@gmail.com>
[not found] ` <959D45574D89AF41A9DADF6F446A2E9A2AE5668374@AUSX7MCPS310.AMER.DELL.COM>
[not found] ` <4FD646FE.4050301@gmail.com>
[not found] ` <959D45574D89AF41A9DADF6F446A2E9A2AE56AEA8E@AUSX7MCPS310.AMER.DELL.COM>
[not found] ` <4FD79D9E.6010702@gmail.com>
2012-06-27 19:59 ` Stuart_Hayes
2012-06-27 20:50 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-06-27 20:58 ` Stuart_Hayes
2012-06-28 21:39 ` Stuart_Hayes
2012-06-29 20:49 ` Stuart_Hayes
2012-06-29 21:14 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-07-02 17:49 ` Stuart_Hayes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4FC23F9C.50000@gmail.com \
--to=phcoder@gmail.com \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.