aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/acpi/initrd_table_override.txt94
-rw-r--r--arch/x86/kernel/acpi/boot.c6
-rw-r--r--arch/x86/kernel/setup.c4
-rw-r--r--drivers/acpi/Kconfig9
-rw-r--r--drivers/acpi/osl.c202
-rw-r--r--include/linux/acpi.h16
-rw-r--r--include/linux/earlycpio.h17
-rw-r--r--lib/Makefile3
-rw-r--r--lib/earlycpio.c145
9 files changed, 484 insertions, 12 deletions
diff --git a/Documentation/acpi/initrd_table_override.txt b/Documentation/acpi/initrd_table_override.txt
new file mode 100644
index 000000000000..35c3f5415476
--- /dev/null
+++ b/Documentation/acpi/initrd_table_override.txt
@@ -0,0 +1,94 @@
1Overriding ACPI tables via initrd
2=================================
3
41) Introduction (What is this about)
52) What is this for
63) How does it work
74) References (Where to retrieve userspace tools)
8
91) What is this about
10---------------------
11
12If the ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible to
13override nearly any ACPI table provided by the BIOS with an instrumented,
14modified one.
15
16For a full list of ACPI tables that can be overridden, take a look at
17the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in drivers/acpi/osl.c
18All ACPI tables iasl (Intel's ACPI compiler and disassembler) knows should
19be overridable, except:
20 - ACPI_SIG_RSDP (has a signature of 6 bytes)
21 - ACPI_SIG_FACS (does not have an ordinary ACPI table header)
22Both could get implemented as well.
23
24
252) What is this for
26-------------------
27
28Please keep in mind that this is a debug option.
29ACPI tables should not get overridden for productive use.
30If BIOS ACPI tables are overridden the kernel will get tainted with the
31TAINT_OVERRIDDEN_ACPI_TABLE flag.
32Complain to your platform/BIOS vendor if you find a bug which is so sever
33that a workaround is not accepted in the Linux kernel.
34
35Still, it can and should be enabled in any kernel, because:
36 - There is no functional change with not instrumented initrds
37 - It provides a powerful feature to easily debug and test ACPI BIOS table
38 compatibility with the Linux kernel.
39
40
413) How does it work
42-------------------
43
44# Extract the machine's ACPI tables:
45cd /tmp
46acpidump >acpidump
47acpixtract -a acpidump
48# Disassemble, modify and recompile them:
49iasl -d *.dat
50# For example add this statement into a _PRT (PCI Routing Table) function
51# of the DSDT:
52Store("HELLO WORLD", debug)
53iasl -sa dsdt.dsl
54# Add the raw ACPI tables to an uncompressed cpio archive.
55# They must be put into a /kernel/firmware/acpi directory inside the
56# cpio archive.
57# The uncompressed cpio archive must be the first.
58# Other, typically compressed cpio archives, must be
59# concatenated on top of the uncompressed one.
60mkdir -p kernel/firmware/acpi
61cp dsdt.aml kernel/firmware/acpi
62# A maximum of: #define ACPI_OVERRIDE_TABLES 10
63# tables are currently allowed (see osl.c):
64iasl -sa facp.dsl
65iasl -sa ssdt1.dsl
66cp facp.aml kernel/firmware/acpi
67cp ssdt1.aml kernel/firmware/acpi
68# Create the uncompressed cpio archive and concatenate the original initrd
69# on top:
70find kernel | cpio -H newc --create > /boot/instrumented_initrd
71cat /boot/initrd >>/boot/instrumented_initrd
72# reboot with increased acpi debug level, e.g. boot params:
73acpi.debug_level=0x2 acpi.debug_layer=0xFFFFFFFF
74# and check your syslog:
75[ 1.268089] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0._PRT]
76[ 1.272091] [ACPI Debug] String [0x0B] "HELLO WORLD"
77
78iasl is able to disassemble and recompile quite a lot different,
79also static ACPI tables.
80
81
824) Where to retrieve userspace tools
83------------------------------------
84
85iasl and acpixtract are part of Intel's ACPICA project:
86http://acpica.org/
87and should be packaged by distributions (for example in the acpica package
88on SUSE).
89
90acpidump can be found in Len Browns pmtools:
91ftp://kernel.org/pub/linux/kernel/people/lenb/acpi/utils/pmtools/acpidump
92This tool is also part of the acpica package on SUSE.
93Alternatively, used ACPI tables can be retrieved via sysfs in latest kernels:
94/sys/firmware/acpi/tables
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index e48cafcf92ae..bacf4b0d91f4 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1706,3 +1706,9 @@ int __acpi_release_global_lock(unsigned int *lock)
1706 } while (unlikely (val != old)); 1706 } while (unlikely (val != old));
1707 return old & 0x1; 1707 return old & 0x1;
1708} 1708}
1709
1710void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size)
1711{
1712 e820_add_region(addr, size, E820_ACPI);
1713 update_e820();
1714}
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index c228322ca180..23ddd558fbd5 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -952,6 +952,10 @@ void __init setup_arch(char **cmdline_p)
952 952
953 reserve_initrd(); 953 reserve_initrd();
954 954
955#if defined(CONFIG_ACPI) && defined(CONFIG_BLK_DEV_INITRD)
956 acpi_initrd_override((void *)initrd_start, initrd_end - initrd_start);
957#endif
958
955 reserve_crashkernel(); 959 reserve_crashkernel();
956 960
957 vsmp_init(); 961 vsmp_init();
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 0300bf612946..38c5078da11d 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -267,6 +267,15 @@ config ACPI_CUSTOM_DSDT
267 bool 267 bool
268 default ACPI_CUSTOM_DSDT_FILE != "" 268 default ACPI_CUSTOM_DSDT_FILE != ""
269 269
270config ACPI_INITRD_TABLE_OVERRIDE
271 bool "ACPI tables can be passed via uncompressed cpio in initrd"
272 default n
273 help
274 This option provides functionality to override arbitrary ACPI tables
275 via initrd. No functional change if no ACPI tables are passed via
276 initrd, therefore it's safe to say Y.
277 See Documentation/acpi/initrd_table_override.txt for details
278
270config ACPI_BLACKLIST_YEAR 279config ACPI_BLACKLIST_YEAR
271 int "Disable ACPI for systems before Jan 1st this year" if X86_32 280 int "Disable ACPI for systems before Jan 1st this year" if X86_32
272 default 0 281 default 0
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 6dc4a2b1e956..3ff267861541 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -534,6 +534,137 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
534 return AE_OK; 534 return AE_OK;
535} 535}
536 536
537#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
538#include <linux/earlycpio.h>
539#include <linux/memblock.h>
540
541static u64 acpi_tables_addr;
542static int all_tables_size;
543
544/* Copied from acpica/tbutils.c:acpi_tb_checksum() */
545u8 __init acpi_table_checksum(u8 *buffer, u32 length)
546{
547 u8 sum = 0;
548 u8 *end = buffer + length;
549
550 while (buffer < end)
551 sum = (u8) (sum + *(buffer++));
552 return sum;
553}
554
555/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
556static const char * const table_sigs[] = {
557 ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
558 ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
559 ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
560 ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
561 ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
562 ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
563 ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
564 ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
565 ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };
566
567/* Non-fatal errors: Affected tables/files are ignored */
568#define INVALID_TABLE(x, path, name) \
569 { pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); continue; }
570
571#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
572
573/* Must not increase 10 or needs code modification below */
574#define ACPI_OVERRIDE_TABLES 10
575
576void __init acpi_initrd_override(void *data, size_t size)
577{
578 int sig, no, table_nr = 0, total_offset = 0;
579 long offset = 0;
580 struct acpi_table_header *table;
581 char cpio_path[32] = "kernel/firmware/acpi/";
582 struct cpio_data file;
583 struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES];
584 char *p;
585
586 if (data == NULL || size == 0)
587 return;
588
589 for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) {
590 file = find_cpio_data(cpio_path, data, size, &offset);
591 if (!file.data)
592 break;
593
594 data += offset;
595 size -= offset;
596
597 if (file.size < sizeof(struct acpi_table_header))
598 INVALID_TABLE("Table smaller than ACPI header",
599 cpio_path, file.name);
600
601 table = file.data;
602
603 for (sig = 0; table_sigs[sig]; sig++)
604 if (!memcmp(table->signature, table_sigs[sig], 4))
605 break;
606
607 if (!table_sigs[sig])
608 INVALID_TABLE("Unknown signature",
609 cpio_path, file.name);
610 if (file.size != table->length)
611 INVALID_TABLE("File length does not match table length",
612 cpio_path, file.name);
613 if (acpi_table_checksum(file.data, table->length))
614 INVALID_TABLE("Bad table checksum",
615 cpio_path, file.name);
616
617 pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n",
618 table->signature, cpio_path, file.name, table->length);
619
620 all_tables_size += table->length;
621 early_initrd_files[table_nr].data = file.data;
622 early_initrd_files[table_nr].size = file.size;
623 table_nr++;
624 }
625 if (table_nr == 0)
626 return;
627
628 acpi_tables_addr =
629 memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
630 all_tables_size, PAGE_SIZE);
631 if (!acpi_tables_addr) {
632 WARN_ON(1);
633 return;
634 }
635 /*
636 * Only calling e820_add_reserve does not work and the
637 * tables are invalid (memory got used) later.
638 * memblock_reserve works as expected and the tables won't get modified.
639 * But it's not enough on X86 because ioremap will
640 * complain later (used by acpi_os_map_memory) that the pages
641 * that should get mapped are not marked "reserved".
642 * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area)
643 * works fine.
644 */
645 memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size);
646 arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
647
648 p = early_ioremap(acpi_tables_addr, all_tables_size);
649
650 for (no = 0; no < table_nr; no++) {
651 memcpy(p + total_offset, early_initrd_files[no].data,
652 early_initrd_files[no].size);
653 total_offset += early_initrd_files[no].size;
654 }
655 early_iounmap(p, all_tables_size);
656}
657#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
658
659static void acpi_table_taint(struct acpi_table_header *table)
660{
661 pr_warn(PREFIX
662 "Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
663 table->signature, table->oem_table_id);
664 add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
665}
666
667
537acpi_status 668acpi_status
538acpi_os_table_override(struct acpi_table_header * existing_table, 669acpi_os_table_override(struct acpi_table_header * existing_table,
539 struct acpi_table_header ** new_table) 670 struct acpi_table_header ** new_table)
@@ -547,24 +678,73 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
547 if (strncmp(existing_table->signature, "DSDT", 4) == 0) 678 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
548 *new_table = (struct acpi_table_header *)AmlCode; 679 *new_table = (struct acpi_table_header *)AmlCode;
549#endif 680#endif
550 if (*new_table != NULL) { 681 if (*new_table != NULL)
551 printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], " 682 acpi_table_taint(existing_table);
552 "this is unsafe: tainting kernel\n",
553 existing_table->signature,
554 existing_table->oem_table_id);
555 add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
556 }
557 return AE_OK; 683 return AE_OK;
558} 684}
559 685
560acpi_status 686acpi_status
561acpi_os_physical_table_override(struct acpi_table_header *existing_table, 687acpi_os_physical_table_override(struct acpi_table_header *existing_table,
562 acpi_physical_address * new_address, 688 acpi_physical_address *address,
563 u32 *new_table_length) 689 u32 *table_length)
564{ 690{
565 return AE_SUPPORT; 691#ifndef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
566} 692 *table_length = 0;
693 *address = 0;
694 return AE_OK;
695#else
696 int table_offset = 0;
697 struct acpi_table_header *table;
698
699 *table_length = 0;
700 *address = 0;
701
702 if (!acpi_tables_addr)
703 return AE_OK;
704
705 do {
706 if (table_offset + ACPI_HEADER_SIZE > all_tables_size) {
707 WARN_ON(1);
708 return AE_OK;
709 }
567 710
711 table = acpi_os_map_memory(acpi_tables_addr + table_offset,
712 ACPI_HEADER_SIZE);
713
714 if (table_offset + table->length > all_tables_size) {
715 acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
716 WARN_ON(1);
717 return AE_OK;
718 }
719
720 table_offset += table->length;
721
722 if (memcmp(existing_table->signature, table->signature, 4)) {
723 acpi_os_unmap_memory(table,
724 ACPI_HEADER_SIZE);
725 continue;
726 }
727
728 /* Only override tables with matching oem id */
729 if (memcmp(table->oem_table_id, existing_table->oem_table_id,
730 ACPI_OEM_TABLE_ID_SIZE)) {
731 acpi_os_unmap_memory(table,
732 ACPI_HEADER_SIZE);
733 continue;
734 }
735
736 table_offset -= table->length;
737 *table_length = table->length;
738 acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
739 *address = acpi_tables_addr + table_offset;
740 break;
741 } while (table_offset + ACPI_HEADER_SIZE < all_tables_size);
742
743 if (*address != 0)
744 acpi_table_taint(existing_table);
745 return AE_OK;
746#endif
747}
568 748
569static irqreturn_t acpi_irq(int irq, void *dev_id) 749static irqreturn_t acpi_irq(int irq, void *dev_id)
570{ 750{
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index c33fa3ce9b7c..3994d7790b23 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -78,6 +78,14 @@ typedef int (*acpi_table_handler) (struct acpi_table_header *table);
78 78
79typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end); 79typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
80 80
81#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
82void acpi_initrd_override(void *data, size_t size);
83#else
84static inline void acpi_initrd_override(void *data, size_t size)
85{
86}
87#endif
88
81char * __acpi_map_table (unsigned long phys_addr, unsigned long size); 89char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
82void __acpi_unmap_table(char *map, unsigned long size); 90void __acpi_unmap_table(char *map, unsigned long size);
83int early_acpi_boot_init(void); 91int early_acpi_boot_init(void);
@@ -479,6 +487,14 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
479 487
480acpi_status acpi_os_prepare_sleep(u8 sleep_state, 488acpi_status acpi_os_prepare_sleep(u8 sleep_state,
481 u32 pm1a_control, u32 pm1b_control); 489 u32 pm1a_control, u32 pm1b_control);
490#ifdef CONFIG_X86
491void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
492#else
493static inline void arch_reserve_mem_area(acpi_physical_address addr,
494 size_t size)
495{
496}
497#endif /* CONFIG_X86 */
482#else 498#else
483#define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0) 499#define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)
484#endif 500#endif
diff --git a/include/linux/earlycpio.h b/include/linux/earlycpio.h
new file mode 100644
index 000000000000..111f46d83d00
--- /dev/null
+++ b/include/linux/earlycpio.h
@@ -0,0 +1,17 @@
1#ifndef _LINUX_EARLYCPIO_H
2#define _LINUX_EARLYCPIO_H
3
4#include <linux/types.h>
5
6#define MAX_CPIO_FILE_NAME 18
7
8struct cpio_data {
9 void *data;
10 size_t size;
11 char name[MAX_CPIO_FILE_NAME];
12};
13
14struct cpio_data find_cpio_data(const char *path, void *data, size_t len,
15 long *offset);
16
17#endif /* _LINUX_EARLYCPIO_H */
diff --git a/lib/Makefile b/lib/Makefile
index e3723c7527da..e2152fa7ff4d 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -12,7 +12,8 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
12 idr.o int_sqrt.o extable.o \ 12 idr.o int_sqrt.o extable.o \
13 sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \ 13 sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
14 proportions.o flex_proportions.o prio_heap.o ratelimit.o show_mem.o \ 14 proportions.o flex_proportions.o prio_heap.o ratelimit.o show_mem.o \
15 is_single_threaded.o plist.o decompress.o kobject_uevent.o 15 is_single_threaded.o plist.o decompress.o kobject_uevent.o \
16 earlycpio.o
16 17
17lib-$(CONFIG_MMU) += ioremap.o 18lib-$(CONFIG_MMU) += ioremap.o
18lib-$(CONFIG_SMP) += cpumask.o 19lib-$(CONFIG_SMP) += cpumask.o
diff --git a/lib/earlycpio.c b/lib/earlycpio.c
new file mode 100644
index 000000000000..8078ef49cb79
--- /dev/null
+++ b/lib/earlycpio.c
@@ -0,0 +1,145 @@
1/* ----------------------------------------------------------------------- *
2 *
3 * Copyright 2012 Intel Corporation; author H. Peter Anvin
4 *
5 * This file is part of the Linux kernel, and is made available
6 * under the terms of the GNU General Public License version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * ----------------------------------------------------------------------- */
15
16/*
17 * earlycpio.c
18 *
19 * Find a specific cpio member; must precede any compressed content.
20 * This is used to locate data items in the initramfs used by the
21 * kernel itself during early boot (before the main initramfs is
22 * decompressed.) It is the responsibility of the initramfs creator
23 * to ensure that these items are uncompressed at the head of the
24 * blob. Depending on the boot loader or package tool that may be a
25 * separate file or part of the same file.
26 */
27
28#include <linux/earlycpio.h>
29#include <linux/kernel.h>
30#include <linux/string.h>
31
32enum cpio_fields {
33 C_MAGIC,
34 C_INO,
35 C_MODE,
36 C_UID,
37 C_GID,
38 C_NLINK,
39 C_MTIME,
40 C_FILESIZE,
41 C_MAJ,
42 C_MIN,
43 C_RMAJ,
44 C_RMIN,
45 C_NAMESIZE,
46 C_CHKSUM,
47 C_NFIELDS
48};
49
50/**
51 * cpio_data find_cpio_data - Search for files in an uncompressed cpio
52 * @path: The directory to search for, including a slash at the end
53 * @data: Pointer to the the cpio archive or a header inside
54 * @len: Remaining length of the cpio based on data pointer
55 * @offset: When a matching file is found, this is the offset to the
56 * beginning of the cpio. It can be used to iterate through
57 * the cpio to find all files inside of a directory path
58 *
59 * @return: struct cpio_data containing the address, length and
60 * filename (with the directory path cut off) of the found file.
61 * If you search for a filename and not for files in a directory,
62 * pass the absolute path of the filename in the cpio and make sure
63 * the match returned an empty filename string.
64 */
65
66struct cpio_data __cpuinit find_cpio_data(const char *path, void *data,
67 size_t len, long *offset)
68{
69 const size_t cpio_header_len = 8*C_NFIELDS - 2;
70 struct cpio_data cd = { NULL, 0, "" };
71 const char *p, *dptr, *nptr;
72 unsigned int ch[C_NFIELDS], *chp, v;
73 unsigned char c, x;
74 size_t mypathsize = strlen(path);
75 int i, j;
76
77 p = data;
78
79 while (len > cpio_header_len) {
80 if (!*p) {
81 /* All cpio headers need to be 4-byte aligned */
82 p += 4;
83 len -= 4;
84 continue;
85 }
86
87 j = 6; /* The magic field is only 6 characters */
88 chp = ch;
89 for (i = C_NFIELDS; i; i--) {
90 v = 0;
91 while (j--) {
92 v <<= 4;
93 c = *p++;
94
95 x = c - '0';
96 if (x < 10) {
97 v += x;
98 continue;
99 }
100
101 x = (c | 0x20) - 'a';
102 if (x < 6) {
103 v += x + 10;
104 continue;
105 }
106
107 goto quit; /* Invalid hexadecimal */
108 }
109 *chp++ = v;
110 j = 8; /* All other fields are 8 characters */
111 }
112
113 if ((ch[C_MAGIC] - 0x070701) > 1)
114 goto quit; /* Invalid magic */
115
116 len -= cpio_header_len;
117
118 dptr = PTR_ALIGN(p + ch[C_NAMESIZE], 4);
119 nptr = PTR_ALIGN(dptr + ch[C_FILESIZE], 4);
120
121 if (nptr > p + len || dptr < p || nptr < dptr)
122 goto quit; /* Buffer overrun */
123
124 if ((ch[C_MODE] & 0170000) == 0100000 &&
125 ch[C_NAMESIZE] >= mypathsize &&
126 !memcmp(p, path, mypathsize)) {
127 *offset = (long)nptr - (long)data;
128 if (ch[C_NAMESIZE] - mypathsize >= MAX_CPIO_FILE_NAME) {
129 pr_warn(
130 "File %s exceeding MAX_CPIO_FILE_NAME [%d]\n",
131 p, MAX_CPIO_FILE_NAME);
132 }
133 strlcpy(cd.name, p + mypathsize, MAX_CPIO_FILE_NAME);
134
135 cd.data = (void *)dptr;
136 cd.size = ch[C_FILESIZE];
137 return cd; /* Found it! */
138 }
139 len -= (nptr - p);
140 p = nptr;
141 }
142
143quit:
144 return cd;
145}