On Sat, Aug 18, 2012 at 01:15:20AM -0700, Fenghua Yu wrote: > From: Fenghua Yu <fenghua...@intel.com> > > Given a file's name, find its starting point in a cpio formated area. This > will
s/file's/file/ cpio-formatted > be used to find microcode in combined initrd image. But this function is > generic and could be used in other places. > > Signed-off-by: Fenghua Yu <fenghua...@intel.com> > --- > arch/x86/include/asm/cpio.h | 10 +++ > arch/x86/lib/Makefile | 2 + > arch/x86/lib/cpio.c | 179 > +++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 191 insertions(+), 0 deletions(-) > create mode 100644 arch/x86/include/asm/cpio.h > create mode 100644 arch/x86/lib/cpio.c > > diff --git a/arch/x86/include/asm/cpio.h b/arch/x86/include/asm/cpio.h > new file mode 100644 > index 0000000..26a4333 > --- /dev/null > +++ b/arch/x86/include/asm/cpio.h > @@ -0,0 +1,10 @@ > +#include <stddef.h> > +#include <stdbool.h> > + > +struct cpio_data { > + void *data; > + unsigned long size; > +}; > + > +extern struct cpio_data > +find_cpio_data(const char *name, const void *data, size_t len); > diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile > index b00f678..452a4b5 100644 > --- a/arch/x86/lib/Makefile > +++ b/arch/x86/lib/Makefile > @@ -45,3 +45,5 @@ else > lib-y += copy_user_64.o copy_user_nocache_64.o > lib-y += cmpxchg16b_emu.o > endif > + > +obj-y += cpio.o > diff --git a/arch/x86/lib/cpio.c b/arch/x86/lib/cpio.c > new file mode 100644 > index 0000000..70ac474 > --- /dev/null > +++ b/arch/x86/lib/cpio.c > @@ -0,0 +1,179 @@ > +/* > + * findcpio.c > + * > + * Find a specific cpio member; must precede any compressed content. > + * > + * Copyright (C) 2012 H Peter Anvin" <h...@zytor.com> stray " > + * Fenghua Yu <fenghua...@intel.com> > + */ > +#include <linux/module.h> > +#include <linux/mm.h> > +#include <linux/swap.h> > +#include <linux/slab.h> > +#include <linux/sysctl.h> > +#include <linux/bitmap.h> > +#include <linux/signal.h> > +#include <linux/printk.h> > +#include <linux/proc_fs.h> > +#include <linux/security.h> > +#include <linux/ctype.h> > +#include <linux/kmemcheck.h> > +#include <linux/fs.h> > +#include <linux/init.h> > +#include <linux/kernel.h> > +#include <linux/kobject.h> > +#include <linux/net.h> > +#include <linux/sysrq.h> > +#include <linux/highuid.h> > +#include <linux/writeback.h> > +#include <linux/ratelimit.h> > +#include <linux/compaction.h> > +#include <linux/hugetlb.h> > +#include <linux/initrd.h> > +#include <linux/key.h> > +#include <linux/times.h> > +#include <linux/limits.h> > +#include <linux/dcache.h> > +#include <linux/dnotify.h> > +#include <linux/syscalls.h> Why all those includes? > +#include <asm/cpio.h> > + > +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 cpio_strlen(const char *name) > +{ > + size_t n = -1; > + > + asm("repne; scasb" > + : "+D" (name), "+c" (n) > + : "a" (0)); > + > + return -2 - n; > +} > + > +static int cpio_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; > +} I guess those are speed optimizations on x86, right? In any case, can we reuse some of the already present ones like memcmp in <arch/x86/boot/compressed/string.c> and strlen in <arch/x86/lib/string_32.c>... > +#else > +static size_t cpio_strlen(const char *name) > +{ > + size_t n = 0; > + > + while (*name++) > + n++; > + > + return n; > +} > + > +static int cpio_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 and, similarly the generic ones in lib/string.c? > + > +#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 = cpio_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 */ Maybe put all comments above the line they refer to, like above instead of them trailing? > + 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 && > + !cpio_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; > +} > -- > 1.7.2 > > -- Regards/Gruss, Boris. Advanced Micro Devices GmbH Einsteinring 24, 85609 Dornach GM: Alberto Bozzo Reg: Dornach, Landkreis Muenchen HRB Nr. 43632 WEEE Registernr: 129 19551 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/