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

Re: [Xen-devel] [PATCH v2 21/23] x86/boot: implement early command line parser in C



>>> On 20.07.15 at 16:29, <daniel.kiper@xxxxxxxxxx> wrote:
> Current early command line parser implementation in assembler
> is very difficult to change to relocatable stuff using segment
> registers. This requires a lot of changes in very weird and
> fragile code. So, reimplement this functionality in C. This
> way code will be relocatable out of the box and much easier
> to maintain.

All appreciated and nice, but the goal of making the code
relocatable by playing with segment registers sounds fragile:
This breaks assumptions the compiler may validly make.

>  xen/arch/x86/boot/cmdline.S    |  367 -------------------------------------
>  xen/arch/x86/boot/cmdline.c    |  396 
> ++++++++++++++++++++++++++++++++++++++++

A fundamental expectation I would have had is for the C file to be
noticeably smaller than the assembly file.

> --- /dev/null
> +++ b/xen/arch/x86/boot/cmdline.c
>[...]
> +#define VESA_WIDTH   0
> +#define VESA_HEIGHT  1
> +#define VESA_DEPTH   2
> +
> +#define VESA_SIZE    3

These should go away in favor of using individual (sub)structure fields.

> +#define __cdecl              __attribute__((__cdecl__))

???

> +#define __packed     __attribute__((__packed__))
> +#define __text               __attribute__((__section__(".text")))
> +#define __used               __attribute__((__used__))

Likely better to include compiler.h instead.

> +#define max(x,y) ({ \
> +        const typeof(x) _x = (x);       \
> +        const typeof(y) _y = (y);       \
> +        (void) (&_x == &_y);            \
> +        _x > _y ? _x : _y; })

I also wonder whether -imacros .../xen/kernel.h wouldn't be a better
approach here. Please really think hard on how to avoid duplications
like these.

> +#define strlen_static(s) (sizeof(s) - 1)

What is this good for? A decent compiler should be able to deal with
strlen("..."). Plus your macro is longer that what it tries to "abbreviate".

> +static const char empty_chars[] __text = " \n\r\t";

What is empty about them? DYM blank or (white) space or separator
or delimiter? I also wonder whether \n and \r are actually usefully here,
as they should (if at all) only end the line.

> +/**
> + * strlen - Find the length of a string
> + * @s: The string to be sized
> + */
> +static size_t strlen(const char *s)

Comments are certainly nice, but in this special case I'd rather suggest
against bloating the code by commenting standard library functions.

> +static int strtoi(const char *s, const char *stop, const char **next)
> +{
> +    int base = 10, i, ores = 0, res = 0;
> +
> +    if ( *s == '0' )
> +      base = (tolower(*++s) == 'x') ? (++s, 16) : 8;
> +
> +    for ( ; *s != '\0'; ++s )
> +    {
> +        for ( i = 0; stop && stop[i] != '\0'; ++i )
> +            if ( *s == stop[i] )
> +                goto out;
> +
> +        if ( *s < '0' || (*s > '7' && base == 8) )
> +        {
> +            res = -1;
> +            goto out;
> +        }
> +
> +        if ( *s > '9' && (base != 16 || tolower(*s) < 'a' || tolower(*s) > 
> 'f') )
> +        {
> +            res = -1;
> +            goto out;
> +        }
> +
> +        res *= base;
> +        res += (tolower(*s) >= 'a') ? (tolower(*s) - 'a' + 10) : (*s - '0');
> +
> +        if ( ores > res )
> +        {
> +            res = -1;
> +            goto out;
> +        }
> +
> +        ores = res;
> +    }
> +
> +out:

C labels intended by at least one space please.

> +static const char *find_opt(const char *cmdline, const char *opt, int arg)
> +{
> +    size_t lc, lo;
> +    static const char mm[] __text = "--";

I'd be surprised if there weren't compiler/assembler versions
complaining about a section type conflict here. I can see why you
want everything in one section, but I'd rather suggest achieving
this at the linking step (which I would suppose to already be taking
care of this).

> +static u8 skip_realmode(const char *cmdline)
> +{
> +    static const char nrm[] __text = "no-real-mode";
> +    static const char tboot[] __text = "tboot=";
> +
> +    if ( find_opt(cmdline, nrm, 0) || find_opt(cmdline, tboot, 1) )
> +        return 1;
> +
> +    return 0;

return find_opt(cmdline, nrm, 0) || find_opt(cmdline, tboot, 1);

> +static u8 edd_parse(const char *cmdline)
> +{
> +    const char *c;
> +    size_t la;
> +    static const char edd[] __text = "edd=";
> +    static const char edd_off[] __text = "off";
> +    static const char edd_skipmbr[] __text = "skipmbr";
> +
> +    c = find_opt(cmdline, edd, 1);
> +
> +    if ( !c )
> +        return 0;
> +
> +    c += strlen_static(edd);
> +    la = strcspn(c, empty_chars);
> +
> +    if ( !strncmp(c, edd_off, max(la, strlen_static(edd_off))) )
> +        return 2;
> +    else if ( !strncmp(c, edd_skipmbr, max(la, strlen_static(edd_skipmbr))) )

Pointless else.

> +        return 1;
> +
> +    return 0;

And the last two returns can be folded again anyway.

> +static void __cdecl __used cmdline_parse_early(const char *cmdline, 
> early_boot_opts_t *ebo)

I don't see the point of the __cdecl, and (as said before) dislike the
static __used pair.

> --- a/xen/arch/x86/boot/head.S
> +++ b/xen/arch/x86/boot/head.S
> @@ -429,8 +429,24 @@ trampoline_setup:
>          cmp     $sym_phys(__trampoline_seg_stop),%edi
>          jb      1b
>  
> +        /* Do not parse command line on EFI platform here. */
> +        cmpb    $1,sym_phys(skip_realmode)

Is there a reason you can't look at efi.flags instead here (and in
the other case you abuse skip_realmode as meaning EFI)?

> --- a/xen/arch/x86/boot/trampoline.S
> +++ b/xen/arch/x86/boot/trampoline.S
> @@ -1,3 +1,5 @@
> +#include "video.h"

Please move this farther down, making invisible all its definitions to
code not supposed to use them.

Jan

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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