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

Re: [Xen-devel] [PATCHv3] xen: Add EFI_LOAD_OPTION support



On Tue, May 22, 2018 at 6:24 AM, Jan Beulich <JBeulich@xxxxxxxx> wrote:
>>>> On 21.05.18 at 18:59, <tamas@xxxxxxxxxxxxx> wrote:
>> After closer inspection the problem is with the following line here:
>>
>>>>          for ( i = 1; i < argc; ++i )
>>
>> This assumes that argv[0] is the EFI executable filename, which is not
>> true when EFI_LOAD_OPTION is used. That's why in my v3 patch I had the
>> "elo_active" variable to determine whether to start the iteration from
>> 0 or from 1.
>
> How about this one then?
>

Success! Although I have to say it's pretty hard to follow the code
and what it's actually doing. Perhaps adding more comments would be
helpful.

Tamas

>
>
> EFI: add EFI_LOAD_OPTION support
>
> When booting Xen via UEFI the Xen config file can contain multiple
> sections each describing different boot options. It is currently only
> possible to choose which section to boot with if the buffer contains a
> string. UEFI provides a different standard to pass optional arguments
> to an application, and in this patch we make Xen properly parse this
> buffer, thus making it possible to have separate EFI boot options
> present for the different config sections.
>
> Signed-off-by: Tamas K Lengyel <tamas@xxxxxxxxxxxxx>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> ---
> v4: Address my own review comments.
>
> --- unstable.orig/xen/common/efi/boot.c
> +++ unstable/xen/common/efi/boot.c
> @@ -88,6 +88,14 @@ typedef struct _EFI_APPLE_PROPERTIES {
>      EFI_APPLE_PROPERTIES_GETALL GetAll;
>  } EFI_APPLE_PROPERTIES;
>
> +typedef struct _EFI_LOAD_OPTION {
> +    UINT32 Attributes;
> +    UINT16 FilePathListLength;
> +    CHAR16 Description[];
> +} EFI_LOAD_OPTION;
> +
> +#define LOAD_OPTION_ACTIVE              0x00000001
> +
>  union string {
>      CHAR16 *w;
>      char *s;
> @@ -275,6 +283,16 @@ static int __init wstrncmp(const CHAR16
>      return n ? *s1 - *s2 : 0;
>  }
>
> +static const CHAR16 *__init wmemchr(const CHAR16 *s, CHAR16 c, UINTN n)
> +{
> +    while ( n && *s != c )
> +    {
> +        --n;
> +        ++s;
> +    }
> +    return n ? s : NULL;
> +}
> +
>  static CHAR16 *__init s2w(union string *str)
>  {
>      const char *s = str->s;
> @@ -374,14 +392,58 @@ static void __init PrintErrMesg(const CH
>  }
>
>  static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv,
> -                                    CHAR16 *cmdline, UINTN cmdsize,
> +                                    VOID *data, UINTN size, UINTN *offset,
>                                      CHAR16 **options)
>  {
> -    CHAR16 *ptr = (CHAR16 *)(argv + argc + 1), *prev = NULL;
> +    CHAR16 *ptr = (CHAR16 *)(argv + argc + 1), *prev = NULL, *cmdline = NULL;
>      bool prev_sep = true;
>
> -    for ( ; cmdsize > sizeof(*cmdline) && *cmdline;
> -            cmdsize -= sizeof(*cmdline), ++cmdline )
> +    if ( argc )
> +    {
> +        cmdline = data + *offset;
> +        /* EFI_LOAD_OPTION does not supply an image name as first component. 
> */
> +        if ( *offset )
> +            *argv++ = NULL;
> +    }
> +    else if ( size > sizeof(*cmdline) && !(size % sizeof(*cmdline)) &&
> +              (wmemchr(data, 0, size / sizeof(*cmdline)) ==
> +               data + size - sizeof(*cmdline)) )
> +    {
> +        *offset = 0;
> +        cmdline = data;
> +    }
> +    else if ( size > sizeof(EFI_LOAD_OPTION) )
> +    {
> +        const EFI_LOAD_OPTION *elo = data;
> +        /* The minimum size the buffer needs to be. */
> +        size_t elo_min = offsetof(EFI_LOAD_OPTION, Description[1]) +
> +                         elo->FilePathListLength;
> +
> +        if ( (elo->Attributes & LOAD_OPTION_ACTIVE) && size > elo_min &&
> +             !((size - elo_min) % sizeof(*cmdline)) )
> +        {
> +            const CHAR16 *desc = elo->Description;
> +            const CHAR16 *end = wmemchr(desc, 0,
> +                                        (size - elo_min) / sizeof(*desc) + 
> 1);
> +
> +            if ( end )
> +            {
> +                *offset = elo_min + (end - desc) * sizeof(*desc);
> +                if ( (size -= *offset) > sizeof(*cmdline) )
> +                {
> +                    cmdline = data + *offset;
> +                    /* Cater for the image name as first component. */
> +                    ++argc;
> +                }
> +            }
> +        }
> +    }
> +
> +    if ( !cmdline )
> +        return 0;
> +
> +    for ( ; size > sizeof(*cmdline) && *cmdline;
> +            size -= sizeof(*cmdline), ++cmdline )
>      {
>          bool cur_sep = *cmdline == L' ' || *cmdline == L'\t';
>
> @@ -1095,15 +1157,17 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
>
>      if ( use_cfg_file )
>      {
> +        UINTN offset = 0;
> +
>          argc = get_argv(0, NULL, loaded_image->LoadOptions,
> -                        loaded_image->LoadOptionsSize, NULL);
> +                        loaded_image->LoadOptionsSize, &offset, NULL);
>          if ( argc > 0 &&
>               efi_bs->AllocatePool(EfiLoaderData,
>                                    (argc + 1) * sizeof(*argv) +
>                                        loaded_image->LoadOptionsSize,
>                                    (void **)&argv) == EFI_SUCCESS )
>              get_argv(argc, argv, loaded_image->LoadOptions,
> -                     loaded_image->LoadOptionsSize, &options);
> +                     loaded_image->LoadOptionsSize, &offset, &options);
>          else
>              argc = 0;
>          for ( i = 1; i < argc; ++i )
> @@ -1244,6 +1308,15 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
>              efi_bs->FreePool(name.w);
>          }
>
> +        if ( argc && !*argv )
> +        {
> +            EFI_FILE_HANDLE handle = get_parent_handle(loaded_image,
> +                                                       &file_name);
> +
> +            handle->Close(handle);
> +            *argv = file_name;
> +        }
> +
>          name.s = get_value(&cfg, section.s, "options");
>          efi_arch_handle_cmdline(argc ? *argv : NULL, options, name.s);
>

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.