lkml.org 
[lkml]   [2012]   [Mar]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH] ACPI: Implement overriding of arbitrary ACPI tables via initrd
    On 03/25/2012 01:54 AM, Borislav Petkov wrote:
    >
    > One other downside for this approach would be the need to have
    > initrd/initramfs support always compiled into the kernel in order to do
    > all those things but, hey, distro kernels already have that so we're
    > probably stuck with it anyway.
    >

    In theory we could make the early stuff independent of the initramfs
    code in the kernel -- just like we always build in an initramfs.

    Not that it matters much, at this point the no-initramfs configurations
    are mostly theoretical.

    I was able to shave a bit more off the code... optimizing for size can
    be fun sometimes. The code is now 442 bytes on x86-64 and 413 on i386
    when compiled with -O2 -fomit-frame-pointer; with -Os
    -fomit-frame-pointer it is 372/410... all of that without any library
    calls or relocations of any kind (which means it should be safe to call
    from the prepaging environment.)

    -hpa
    /*
    * findcpio.c
    *
    * Find a specific cpio member; must precede any compressed content.
    */

    #include <stddef.h>
    #include <stdbool.h>

    struct cpio_data {
    void *data;
    unsigned long size;
    };

    enum cpio_fields {
    C_MAGIC,
    C_INO,
    C_MODE,
    C_UID,
    C_GID,
    C_NLINK,
    C_MTIME,
    C_FILESIZE,
    C_MAJ,
    C_MIN,
    C_RMAJ,
    C_RMIN,
    C_NAMESIZE,
    C_CHKSUM,
    C_NFIELDS
    };

    #if defined(__i386__) || defined(__x86_64__)
    static size_t strlen(const char *name)
    {
    size_t n = -1;

    asm("repne; scasb"
    : "+D" (name), "+c" (n)
    : "a" (0));

    return -2 - n;
    }

    static int memcmp(const void *p1, const void *p2, size_t n)
    {
    unsigned char rv;

    asm("repe; cmpsb; setne %0"
    : "=r" (rv), "+S" (p1), "+D" (p2), "+c" (n));

    return rv;
    }
    #else
    static size_t strlen(const char *name)
    {
    size_t n = 0;

    while (*name++)
    n++;

    return n;
    }

    static int memcmp(const void *p1, const void *p2, size_t n)
    {
    const unsigned char *u1 = p1;
    const unsigned char *u2 = p2;
    int d;

    while (n--) {
    d = *u2++ - *u1++;
    if (d)
    return d;
    }
    return 0;
    }
    #endif

    #define ALIGN4(p) ((void *)(((size_t)p + 3) & ~3))

    struct cpio_data find_cpio_data(const char *name, const void *data, size_t len)
    {
    const size_t cpio_header_len = 8*C_NFIELDS - 2;
    struct cpio_data cd = { NULL, 0 };
    const char *p, *dptr, *nptr;
    unsigned int ch[C_NFIELDS], *chp, v;
    unsigned char c, x;
    size_t mynamesize = strlen(name) + 1;
    int i, j;

    p = data;

    while (len > cpio_header_len) {
    if (!*p) {
    /* All cpio headers need to be 4-byte aligned */
    p += 4;
    len -= 4;
    continue;
    }

    j = 6; /* The magic field is only 6 characters */
    chp = ch;
    for (i = C_NFIELDS; i; i--) {
    v = 0;
    while (j--) {
    v <<= 4;
    c = *p++;

    x = c - '0';
    if (x < 10) {
    v += x;
    continue;
    }

    x = (c | 0x20) - 'a';
    if (x < 6) {
    v += x + 10;
    continue;
    }

    goto quit; /* Invalid hexadecimal */
    }
    *chp++ = v;
    j = 8; /* All other fields are 8 characters */
    }

    if ((ch[C_MAGIC] - 0x070701) > 1)
    goto quit; /* Invalid magic */

    len -= cpio_header_len;

    dptr = ALIGN4(p + ch[C_NAMESIZE]);
    nptr = ALIGN4(dptr + ch[C_FILESIZE]);

    if (nptr > p + len || dptr < p || nptr < dptr)
    goto quit; /* Buffer overrun */

    if ((ch[C_MODE] & 0170000) == 0100000 &&
    ch[C_NAMESIZE] == mynamesize &&
    !memcmp(p, name, mynamesize)) {
    cd.data = (void *)dptr;
    cd.size = ch[C_FILESIZE];
    return cd; /* Found it! */
    }

    len -= (nptr - p);
    p = nptr;
    }

    quit:
    return cd;
    }

    \
     
     \ /
      Last update: 2012-03-26 03:39    [W:0.031 / U:0.196 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site