Commit 18dd0bf22b6f0c1bd5e4e813a42245ed86ec57b6

Authored by Linus Torvalds

Merge branch 'x86-acpi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 ACPI update from Peter Anvin:
 "This is a patchset which didn't make the last merge window.  It adds a
  debugging capability to feed ACPI tables via the initramfs.

  On a grander scope, it formalizes using the initramfs protocol for
  feeding arbitrary blobs which need to be accessed early to the kernel:
  they are fed first in the initramfs blob (lots of bootloaders can
  concatenate this at boot time, others can use a single file) in an
  uncompressed cpio archive using filenames starting with "kernel/".

  The ACPI maintainers requested that this patchset be fed via the x86
  tree rather than the ACPI tree as the footprint in the general x86
  code is much bigger than in the ACPI code proper."

* 'x86-acpi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  X86 ACPI: Use #ifdef not #if for CONFIG_X86 check
  ACPI: Fix build when disabled
  ACPI: Document ACPI table overriding via initrd
  ACPI: Create acpi_table_taint() function to avoid code duplication
  ACPI: Implement physical address table override
  ACPI: Store valid ACPI tables passed via early initrd in reserved memblock areas
  x86, acpi: Introduce x86 arch specific arch_reserve_mem_area() for e820 handling
  lib: Add early cpio decoder

Showing 9 changed files Side-by-side Diff

Documentation/acpi/initrd_table_override.txt
  1 +Overriding ACPI tables via initrd
  2 +=================================
  3 +
  4 +1) Introduction (What is this about)
  5 +2) What is this for
  6 +3) How does it work
  7 +4) References (Where to retrieve userspace tools)
  8 +
  9 +1) What is this about
  10 +---------------------
  11 +
  12 +If the ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible to
  13 +override nearly any ACPI table provided by the BIOS with an instrumented,
  14 +modified one.
  15 +
  16 +For a full list of ACPI tables that can be overridden, take a look at
  17 +the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in drivers/acpi/osl.c
  18 +All ACPI tables iasl (Intel's ACPI compiler and disassembler) knows should
  19 +be overridable, except:
  20 + - ACPI_SIG_RSDP (has a signature of 6 bytes)
  21 + - ACPI_SIG_FACS (does not have an ordinary ACPI table header)
  22 +Both could get implemented as well.
  23 +
  24 +
  25 +2) What is this for
  26 +-------------------
  27 +
  28 +Please keep in mind that this is a debug option.
  29 +ACPI tables should not get overridden for productive use.
  30 +If BIOS ACPI tables are overridden the kernel will get tainted with the
  31 +TAINT_OVERRIDDEN_ACPI_TABLE flag.
  32 +Complain to your platform/BIOS vendor if you find a bug which is so sever
  33 +that a workaround is not accepted in the Linux kernel.
  34 +
  35 +Still, 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 +
  41 +3) How does it work
  42 +-------------------
  43 +
  44 +# Extract the machine's ACPI tables:
  45 +cd /tmp
  46 +acpidump >acpidump
  47 +acpixtract -a acpidump
  48 +# Disassemble, modify and recompile them:
  49 +iasl -d *.dat
  50 +# For example add this statement into a _PRT (PCI Routing Table) function
  51 +# of the DSDT:
  52 +Store("HELLO WORLD", debug)
  53 +iasl -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.
  60 +mkdir -p kernel/firmware/acpi
  61 +cp dsdt.aml kernel/firmware/acpi
  62 +# A maximum of: #define ACPI_OVERRIDE_TABLES 10
  63 +# tables are currently allowed (see osl.c):
  64 +iasl -sa facp.dsl
  65 +iasl -sa ssdt1.dsl
  66 +cp facp.aml kernel/firmware/acpi
  67 +cp ssdt1.aml kernel/firmware/acpi
  68 +# Create the uncompressed cpio archive and concatenate the original initrd
  69 +# on top:
  70 +find kernel | cpio -H newc --create > /boot/instrumented_initrd
  71 +cat /boot/initrd >>/boot/instrumented_initrd
  72 +# reboot with increased acpi debug level, e.g. boot params:
  73 +acpi.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 +
  78 +iasl is able to disassemble and recompile quite a lot different,
  79 +also static ACPI tables.
  80 +
  81 +
  82 +4) Where to retrieve userspace tools
  83 +------------------------------------
  84 +
  85 +iasl and acpixtract are part of Intel's ACPICA project:
  86 +http://acpica.org/
  87 +and should be packaged by distributions (for example in the acpica package
  88 +on SUSE).
  89 +
  90 +acpidump can be found in Len Browns pmtools:
  91 +ftp://kernel.org/pub/linux/kernel/people/lenb/acpi/utils/pmtools/acpidump
  92 +This tool is also part of the acpica package on SUSE.
  93 +Alternatively, used ACPI tables can be retrieved via sysfs in latest kernels:
  94 +/sys/firmware/acpi/tables
arch/x86/kernel/acpi/boot.c
... ... @@ -1706,4 +1706,10 @@
1706 1706 } while (unlikely (val != old));
1707 1707 return old & 0x1;
1708 1708 }
  1709 +
  1710 +void __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 +}
arch/x86/kernel/setup.c
... ... @@ -952,6 +952,10 @@
952 952  
953 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 959 reserve_crashkernel();
956 960  
957 961 vsmp_init();
drivers/acpi/Kconfig
... ... @@ -267,6 +267,15 @@
267 267 bool
268 268 default ACPI_CUSTOM_DSDT_FILE != ""
269 269  
  270 +config 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 +
270 279 config ACPI_BLACKLIST_YEAR
271 280 int "Disable ACPI for systems before Jan 1st this year" if X86_32
272 281 default 0
... ... @@ -534,6 +534,137 @@
534 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 +
  541 +static u64 acpi_tables_addr;
  542 +static int all_tables_size;
  543 +
  544 +/* Copied from acpica/tbutils.c:acpi_tb_checksum() */
  545 +u8 __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: */
  556 +static 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 +
  576 +void __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 +
  659 +static 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 +
537 668 acpi_status
538 669 acpi_os_table_override(struct acpi_table_header * existing_table,
539 670 struct acpi_table_header ** new_table)
540 671  
541 672  
542 673  
... ... @@ -547,24 +678,73 @@
547 678 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
548 679 *new_table = (struct acpi_table_header *)AmlCode;
549 680 #endif
550   - if (*new_table != NULL) {
551   - printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
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   - }
  681 + if (*new_table != NULL)
  682 + acpi_table_taint(existing_table);
557 683 return AE_OK;
558 684 }
559 685  
560 686 acpi_status
561 687 acpi_os_physical_table_override(struct acpi_table_header *existing_table,
562   - acpi_physical_address * new_address,
563   - u32 *new_table_length)
  688 + acpi_physical_address *address,
  689 + u32 *table_length)
564 690 {
565   - return AE_SUPPORT;
566   -}
  691 +#ifndef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
  692 + *table_length = 0;
  693 + *address = 0;
  694 + return AE_OK;
  695 +#else
  696 + int table_offset = 0;
  697 + struct acpi_table_header *table;
567 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 + }
  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  
569 749 static irqreturn_t acpi_irq(int irq, void *dev_id)
570 750 {
include/linux/acpi.h
... ... @@ -78,6 +78,14 @@
78 78  
79 79 typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
80 80  
  81 +#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
  82 +void acpi_initrd_override(void *data, size_t size);
  83 +#else
  84 +static inline void acpi_initrd_override(void *data, size_t size)
  85 +{
  86 +}
  87 +#endif
  88 +
81 89 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
82 90 void __acpi_unmap_table(char *map, unsigned long size);
83 91 int early_acpi_boot_init(void);
... ... @@ -479,6 +487,14 @@
479 487  
480 488 acpi_status acpi_os_prepare_sleep(u8 sleep_state,
481 489 u32 pm1a_control, u32 pm1b_control);
  490 +#ifdef CONFIG_X86
  491 +void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
  492 +#else
  493 +static inline void arch_reserve_mem_area(acpi_physical_address addr,
  494 + size_t size)
  495 +{
  496 +}
  497 +#endif /* CONFIG_X86 */
482 498 #else
483 499 #define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)
484 500 #endif
include/linux/earlycpio.h
  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 +
  8 +struct cpio_data {
  9 + void *data;
  10 + size_t size;
  11 + char name[MAX_CPIO_FILE_NAME];
  12 +};
  13 +
  14 +struct cpio_data find_cpio_data(const char *path, void *data, size_t len,
  15 + long *offset);
  16 +
  17 +#endif /* _LINUX_EARLYCPIO_H */
... ... @@ -12,7 +12,8 @@
12 12 idr.o int_sqrt.o extable.o \
13 13 sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
14 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  
17 18 lib-$(CONFIG_MMU) += ioremap.o
18 19 lib-$(CONFIG_SMP) += cpumask.o
  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 +
  32 +enum 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 +
  66 +struct 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 +
  143 +quit:
  144 + return cd;
  145 +}