lkml.org 
[lkml]   [2012]   [Mar]   [24]   [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/24/2012 03:21 PM, H. Peter Anvin wrote:
    > The attached cpio-parsing code compiles to 458 bytes on x86-64 and 476
    > bytes on i386, and that is without any library dependencies at all.
    > Again, it will completely stop at the first compressed data item, so any
    > such kernel objects absolutely will have to be first. In good Linux
    > tradition, it is also completely untested.
    >
    > However, given that very reasonable size I would think that this is a
    > reasonable approach. Anyone who has a better suggestion for the
    > namespace than "kernel/"?
    >

    Slightly improved version with actually working memcmp()...

    -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_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
    };

    /* Return true if this field is composed of valid hex digits */
    static bool validhex(const char *ptr, int len)
    {
    unsigned char c, x;

    while (len--) {
    c = *ptr++;

    x = c - '0';
    if (x < 10)
    continue;

    x = (c | 0x20) - 'a' + 10;
    if (x < 16)
    continue;

    return false;
    }

    return true;
    }

    /* Return the value of an already validated field */
    static unsigned int hexval(const char *ptr, int len)
    {
    unsigned int v = 0;
    unsigned char c, x;

    while (len--) {
    v <<= 4;
    c = *ptr++;

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

    x = (c | 0x20) - 'a' + 10;
    v += x;
    }

    return v;
    }

    #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 = 6 + 8*C_NFIELDS;
    struct cpio_data cd = { NULL, 0 };
    const char *p, *dptr, *nptr;
    unsigned int magic, ch[C_NFIELDS], *chp;
    size_t mynamesize = strlen(name) + 1;
    int i;

    p = data;

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

    if (!validhex(p, cpio_header_len))
    break; /* Not a valid cpio header */

    magic = hexval(p, 6);
    if ((magic - 0x070701) > 1)
    break; /* Not a valid cpio magic */

    p += 6;
    chp = ch;
    for (i = 0; i < C_NFIELDS; i++) {
    *chp++ = hexval(p, 8);
    p += 8;

    }

    len -= cpio_header_len;

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

    if (nptr > p + len)
    break; /* 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];
    break;
    }

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

    return cd;
    }

    \
     
     \ /
      Last update: 2012-03-24 23:47    [W:0.025 / U:29.244 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site