Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Linux: Kernel

[PATCH 02/11] x86/lib/cpio.c: Find cpio data by its file name

 

 

Linux kernel RSS feed   Index | Next | Previous | View Threaded


fenghua.yu at intel

Aug 18, 2012, 1:15 AM

Post #1 of 6 (79 views)
Permalink
[PATCH 02/11] x86/lib/cpio.c: Find cpio data by its file name

From: Fenghua Yu <fenghua.yu [at] intel>

Given a file's name, find its starting point in a cpio formated area. This will
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.yu [at] intel>
---
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" <hpa [at] zytor>
+ * Fenghua Yu <fenghua.yu [at] intel>
+ */
+#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>
+#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;
+}
+#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
+
+#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 */
+ 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

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo [at] vger
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/


hmh at hmh

Aug 18, 2012, 3:12 PM

Post #2 of 6 (69 views)
Permalink
Re: [PATCH 02/11] x86/lib/cpio.c: Find cpio data by its file name [In reply to]

On Sat, 18 Aug 2012, Fenghua Yu wrote:
> Given a file's name, find its starting point in a cpio formated area. This will
> be used to find microcode in combined initrd image. But this function is
> generic and could be used in other places.

Shouldn't this (very useful) feature get its own documentation in
Documentation/ ?

--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo [at] vger
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/


fenghua.yu at intel

Aug 18, 2012, 4:23 PM

Post #3 of 6 (72 views)
Permalink
RE: [PATCH 02/11] x86/lib/cpio.c: Find cpio data by its file name [In reply to]

> -----Original Message-----
> From: Henrique de Moraes Holschuh [mailto:hmh [at] hmh]
> Sent: Saturday, August 18, 2012 3:13 PM
> To: Yu, Fenghua
> Cc: H Peter Anvin; Ingo Molnar; Thomas Gleixner; Mallick, Asit K;
> Tigran Aivazian; Andreas Herrmann; Borislav Petkov; linux-kernel; x86
> Subject: Re: [PATCH 02/11] x86/lib/cpio.c: Find cpio data by its file
> name
>
> On Sat, 18 Aug 2012, Fenghua Yu wrote:
> > Given a file's name, find its starting point in a cpio formated area.
> This will
> > be used to find microcode in combined initrd image. But this function
> is
> > generic and could be used in other places.
>
> Shouldn't this (very useful) feature get its own documentation in
> Documentation/ ?

Yes, I can document the feature. And if it's generic and useful, this function could be put in generic kernel instead of in x86 arch.

Thanks.

-Fenghua
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo [at] vger
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/


hmh at hmh

Aug 18, 2012, 9:35 PM

Post #4 of 6 (73 views)
Permalink
Re: [PATCH 02/11] x86/lib/cpio.c: Find cpio data by its file name [In reply to]

On Sat, 18 Aug 2012, Yu, Fenghua wrote:
> > From: Henrique de Moraes Holschuh [mailto:hmh [at] hmh] On Sat, 18 Aug
> > 2012, Fenghua Yu wrote:
> > > Given a file's name, find its starting point in a cpio formated area.
> > This will
> > > be used to find microcode in combined initrd image. But this function
> > is
> > > generic and could be used in other places.
> >
> > Shouldn't this (very useful) feature get its own documentation in
> > Documentation/ ?
>
> Yes, I can document the feature. And if it's generic and useful, this
> function could be put in generic kernel instead of in x86 arch.

It is useful to override/fix all sort of critical firmware-provided tables,
for example. ACPI table overrides should use this new cpio-based scheme as
well, and I recall someone wrote something about device tree overrides in a
past thread...

--
"One disk to rule them all, One disk to find them. One disk to bring
them all and in the darkness grind them. In the Land of Redmond
where the shadows lie." -- The Silicon Valley Tarot
Henrique Holschuh
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo [at] vger
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/


hpa at zytor

Aug 18, 2012, 10:15 PM

Post #5 of 6 (73 views)
Permalink
Re: [PATCH 02/11] x86/lib/cpio.c: Find cpio data by its file name [In reply to]

On 08/18/2012 09:35 PM, Henrique de Moraes Holschuh wrote:
> On Sat, 18 Aug 2012, Yu, Fenghua wrote:
>>> From: Henrique de Moraes Holschuh [mailto:hmh [at] hmh] On Sat, 18 Aug
>>> 2012, Fenghua Yu wrote:
>>>> Given a file's name, find its starting point in a cpio formated area.
>>> This will
>>>> be used to find microcode in combined initrd image. But this function
>>> is
>>>> generic and could be used in other places.
>>>
>>> Shouldn't this (very useful) feature get its own documentation in
>>> Documentation/ ?
>>
>> Yes, I can document the feature. And if it's generic and useful, this
>> function could be put in generic kernel instead of in x86 arch.
>
> It is useful to override/fix all sort of critical firmware-provided tables,
> for example. ACPI table overrides should use this new cpio-based scheme as
> well, and I recall someone wrote something about device tree overrides in a
> past thread...
>

Indeed, we already have those two users already identified.

-hpa


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo [at] vger
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/


bp at amd64

Aug 20, 2012, 6:29 AM

Post #6 of 6 (70 views)
Permalink
Re: [PATCH 02/11] x86/lib/cpio.c: Find cpio data by its file name [In reply to]

On Sat, Aug 18, 2012 at 01:15:20AM -0700, Fenghua Yu wrote:
> From: Fenghua Yu <fenghua.yu [at] intel>
>
> 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.yu [at] intel>
> ---
> 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" <hpa [at] zytor>

stray "

> + * Fenghua Yu <fenghua.yu [at] intel>
> + */
> +#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 majordomo [at] vger
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Linux kernel RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.