grub-devel
[Top][All Lists]
Advanced

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

Re: [PATCH V2 3/3] Update Linux loader to follow the kernel's preference


From: Keshav P R
Subject: Re: [PATCH V2 3/3] Update Linux loader to follow the kernel's preferences
Date: Mon, 6 Feb 2012 21:58:55 +0530

On Mon, Feb 6, 2012 at 21:23, Matthew Garrett <address@hidden> wrote:
> We should attempt to load the kernel at its preferred address, and if we
> can't do that then we should at lesat align it correctly. When doing so
> we should also make sure to avoid putting the kernel on top of any regions
> being used by the firmware.
> ---
>
> I managed to screw up the rebase, so this is a fixed version. Also, the code
> now follows the old path if the kernel isn't relocatable - we can't move it,
> so better to try it and just hope that everything works out.
>
>  ChangeLog                     |    8 +++++
>  grub-core/loader/i386/linux.c |   67 ++++++++++++++++++++++++++++++++++------
>  2 files changed, 65 insertions(+), 10 deletions(-)
>
> diff --git a/ChangeLog b/ChangeLog
> index 33e5dda..aedf4bc 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,5 +1,13 @@
>  2012-02-06  Matthew Garrett  <address@hidden>
>
> +       * grub-core/loader/i386/linux.c (allocate_pages): Attempt to obtain
> +       appropriately aligned memory if the desired target is unavailable
> +       (grub_cmd_linux): Update to match newer Linux boot protocols, and
> +       attempt to load the kernel at its preferred address rather than
> +       hardcoding.
> +
> +2012-02-06  Matthew Garrett  <address@hidden>
> +
>        * grub-core/lib/efi/relocator.c (grub_relocator_alloc_chunk_addr):
>        Add argument to fail allocation when target address overlaps
>        firmware regions. All users updated.
> diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
> index 67a4533..3eb8fa0 100644
> --- a/grub-core/loader/i386/linux.c
> +++ b/grub-core/loader/i386/linux.c
> @@ -183,13 +183,14 @@ free_pages (void)
>   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;
> +  real_mode_target = initrd_mem_target = 0;
>  }
>
>  /* Allocate pages for the real mode code and the protected mode code
>    for linux as well as a memory map buffer.  */
>  static grub_err_t
> -allocate_pages (grub_size_t prot_size)
> +allocate_pages (grub_size_t prot_size, grub_size_t *align,
> +               grub_size_t min_align, int relocatable)
>  {
>   grub_size_t real_size, mmap_size;
>   grub_err_t err;
> @@ -269,18 +270,38 @@ allocate_pages (grub_size_t prot_size)
>                                            + efi_mmap_size), 0);
>     if (err)
>       goto fail;
> +
> +    grub_errno = GRUB_ERR_NONE;
>     real_mode_mem = get_virtual_current_address (ch);
>   }
>   efi_mmap_buf = (grub_uint8_t *) real_mode_mem + real_size + mmap_size;
>
> -  prot_mode_target = GRUB_LINUX_BZIMAGE_ADDR;
> -
>   {
>     grub_relocator_chunk_t ch;
>     err = grub_relocator_alloc_chunk_addr (relocator, &ch,
> -                                          prot_mode_target, prot_size, 0);
> +                                          prot_mode_target, prot_size,
> +                                          relocatable);
> +    if (err)
> +      {
> +       unsigned int i;
> +       for (i = *align; i >= min_align; i--)
> +         {
> +           err = grub_relocator_alloc_chunk_align (relocator, &ch,
> +                                                   0x1000000, 0xffffffff,
> +                                                   prot_size, 1 << i,
> +                                                   
> GRUB_RELOCATOR_PREFERENCE_LOW);
> +           if (!err)
> +             {
> +               *align = i;
> +               prot_mode_target = get_physical_target_address (ch);
> +               break;
> +             }
> +         }
> +      }
> +
>     if (err)
>       goto fail;
> +
>     prot_mode_mem = get_virtual_current_address (ch);
>   }
>
> @@ -631,8 +652,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
> ((unused)),
>   struct linux_kernel_header lh;
>   struct linux_kernel_params *params;
>   grub_uint8_t setup_sects;
> -  grub_size_t real_size, prot_size;
> +  grub_size_t real_size, prot_size, prot_file_size, align = 0, min_align = 0;
>   grub_ssize_t len;
> +  int relocatable = 0;
>   int i;
>
>   grub_dl_ref (my_mod);
> @@ -705,9 +727,32 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
> ((unused)),
>     setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
>
>   real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
> -  prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
>
> -  if (allocate_pages (prot_size))
> +  if (grub_le_to_cpu16 (lh.version) >= 0x205)
> +    {
> +      for (align = 0; align < 32; align++)
> +       {
> +         if (grub_le_to_cpu32 (lh.kernel_alignment) & (1 << align))
> +           break;
> +       }
> +      relocatable = grub_le_to_cpu32 (lh.relocatable);
> +    }
> +
> +  if (grub_le_to_cpu16 (lh.version) >= 0x020a)
> +    {
> +      min_align = lh.min_alignment;
> +      prot_size = grub_le_to_cpu32 (lh.init_size);
> +      prot_mode_target = grub_le_to_cpu64 (lh.pref_address);
> +    }
> +  else
> +    {
> +      min_align = 0;
> +      prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
> +      prot_mode_target = grub_le_to_cpu32 (lh.code32_start);
> +    }
> +
> +  prot_file_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
> +  if (allocate_pages (prot_size, &align, min_align, relocatable))
>     goto fail;
>
>   params = (struct linux_kernel_params *) real_mode_mem;
> @@ -715,6 +760,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
> ((unused)),
>   grub_memcpy (&params->setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
>
>   params->ps_mouse = params->padding10 =  0;
> +  params->code32_start = prot_mode_target;
> +  params->kernel_alignment = (1 << align);
>
>   len = 0x400 - sizeof (lh);
>   if (grub_file_read (file, (char *) real_mode_mem + sizeof (lh), len) != len)
> @@ -774,7 +821,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
> ((unused)),
>   grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
>
>   grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
> -               (unsigned) real_size, (unsigned) prot_size);
> +               (unsigned) real_size, (unsigned) prot_file_size);
>
>   /* Look for memory size and video mode specified on the command line.  */
>   linux_mem_size = 0;
> @@ -911,7 +958,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
> ((unused)),
>                              maximal_cmdline_size
>                              - (sizeof (LINUX_IMAGE) - 1));
>
> -  len = prot_size;
> +  len = prot_file_size;
>   if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno)
>     grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
>                argv[0]);
> --
> 1.7.7.6
>
>
> _______________________________________________
> Grub-devel mailing list
> address@hidden
> https://lists.gnu.org/mailman/listinfo/grub-devel

Boot fine in VirtualBox X64 UEFI (UEFI 2.1 Tianocore OVMF). Patch V1
3/3 failed with premature end of file error.

Regards.

Keshav



reply via email to

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