grub-devel
[Top][All Lists]
Advanced

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

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


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

Tested with bzr r3856

On 06/02/2012, Keshav P R <address@hidden> wrote:
> Fails to boot x86_64 Archlinux kernels 3.2.2 and 3.3-rc2 - premature
> end of file error. The first 2 patches work fine (no noticable
> difference). Only this patch leads to boot failure. Tested in
> Tianocore UDK DuetPkg 64-bit firmware. Also a syntax error (missing
> comma) in the very last change in this patch.
>
> - Keshav
>
> PS: Sent from my mobile. Pls ignore top posting.
>
> On 04/02/2012, 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 least 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.
>>
>> ---
>>  ChangeLog                     |    8 +++++
>>  grub-core/loader/i386/linux.c |   67
>> +++++++++++++++++++++++++++++++++++-----
>>  2 files changed, 66 insertions(+), 9 deletions(-)
>>
>> diff --git a/ChangeLog b/ChangeLog
>> index 0a94fc0..1e0270b 100644
>> --- a/ChangeLog
>> +++ b/ChangeLog
>> @@ -1,5 +1,13 @@
>>  2012-02-03  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-03  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..b61749d 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)
>>  {
>>    grub_size_t real_size, mmap_size;
>>    grub_err_t err;
>> @@ -269,18 +270,37 @@ 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, 1);
>> +    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,7 +651,7 @@ 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 i;
>>
>> @@ -705,9 +725,31 @@ 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;
>> +    }
>> +    }
>> +
>> +  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))
>>      goto fail;
>>
>>    params = (struct linux_kernel_params *) real_mode_mem;
>> @@ -715,6 +757,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 +818,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;
>> @@ -916,6 +960,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__
>> ((unused)),
>>      grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file
>> %s"),
>>              argv[0]);
>>
>> +  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]);
>> +
>>    if (grub_errno == GRUB_ERR_NONE)
>>      {
>>        grub_loader_set (grub_linux_boot, grub_linux_unload,
>> --
>> 1.7.7.6
>>
>>
>> _______________________________________________
>> Grub-devel mailing list
>> address@hidden
>> https://lists.gnu.org/mailman/listinfo/grub-devel
>>
>



reply via email to

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