The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/lib/earlycpio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 2b54f3c74acce40bf205dabca81a8243


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.