=== 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 */