VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
880a13c40be81 (Thomas Gleixner 2019-05-29 07:17:57 -0700   1) // SPDX-License-Identifier: GPL-2.0-only
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200   2) /* ----------------------------------------------------------------------- *
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200   3)  *
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200   4)  *   Copyright 2012 Intel Corporation; author H. Peter Anvin
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200   5)  *
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200   6)  * ----------------------------------------------------------------------- */
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200   7) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200   8) /*
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200   9)  * earlycpio.c
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  10)  *
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  11)  * Find a specific cpio member; must precede any compressed content.
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  12)  * This is used to locate data items in the initramfs used by the
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  13)  * kernel itself during early boot (before the main initramfs is
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  14)  * decompressed.)  It is the responsibility of the initramfs creator
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  15)  * to ensure that these items are uncompressed at the head of the
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  16)  * blob.  Depending on the boot loader or package tool that may be a
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  17)  * separate file or part of the same file.
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  18)  */
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  19) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  20) #include <linux/earlycpio.h>
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  21) #include <linux/kernel.h>
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  22) #include <linux/string.h>
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  23) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  24) enum cpio_fields {
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  25) 	C_MAGIC,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  26) 	C_INO,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  27) 	C_MODE,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  28) 	C_UID,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  29) 	C_GID,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  30) 	C_NLINK,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  31) 	C_MTIME,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  32) 	C_FILESIZE,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  33) 	C_MAJ,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  34) 	C_MIN,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  35) 	C_RMAJ,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  36) 	C_RMIN,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  37) 	C_NAMESIZE,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  38) 	C_CHKSUM,
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  39) 	C_NFIELDS
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  40) };
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  41) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  42) /**
c95c2d328cd05 (Randy Dunlap    2021-04-16 15:46:26 -0700  43)  * find_cpio_data - Search for files in an uncompressed cpio
598bae70c2a8e (Tang Chen       2013-08-14 17:37:07 +0800  44)  * @path:       The directory to search for, including a slash at the end
4e20ace06f705 (Randy Dunlap    2020-10-15 20:11:01 -0700  45)  * @data:       Pointer to the cpio archive or a header inside
598bae70c2a8e (Tang Chen       2013-08-14 17:37:07 +0800  46)  * @len:        Remaining length of the cpio based on data pointer
598bae70c2a8e (Tang Chen       2013-08-14 17:37:07 +0800  47)  * @nextoff:    When a matching file is found, this is the offset from the
598bae70c2a8e (Tang Chen       2013-08-14 17:37:07 +0800  48)  *              beginning of the cpio to the beginning of the next file, not the
598bae70c2a8e (Tang Chen       2013-08-14 17:37:07 +0800  49)  *              matching file itself. It can be used to iterate through the cpio
598bae70c2a8e (Tang Chen       2013-08-14 17:37:07 +0800  50)  *              to find all files inside of a directory path.
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  51)  *
c95c2d328cd05 (Randy Dunlap    2021-04-16 15:46:26 -0700  52)  * Return:      &struct cpio_data containing the address, length and
598bae70c2a8e (Tang Chen       2013-08-14 17:37:07 +0800  53)  *              filename (with the directory path cut off) of the found file.
598bae70c2a8e (Tang Chen       2013-08-14 17:37:07 +0800  54)  *              If you search for a filename and not for files in a directory,
598bae70c2a8e (Tang Chen       2013-08-14 17:37:07 +0800  55)  *              pass the absolute path of the filename in the cpio and make sure
598bae70c2a8e (Tang Chen       2013-08-14 17:37:07 +0800  56)  *              the match returned an empty filename string.
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  57)  */
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  58) 
0db0628d90125 (Paul Gortmaker  2013-06-19 14:53:51 -0400  59) struct cpio_data find_cpio_data(const char *path, void *data,
598bae70c2a8e (Tang Chen       2013-08-14 17:37:07 +0800  60) 				size_t len,  long *nextoff)
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  61) {
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  62) 	const size_t cpio_header_len = 8*C_NFIELDS - 2;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  63) 	struct cpio_data cd = { NULL, 0, "" };
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  64) 	const char *p, *dptr, *nptr;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  65) 	unsigned int ch[C_NFIELDS], *chp, v;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  66) 	unsigned char c, x;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  67) 	size_t mypathsize = strlen(path);
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  68) 	int i, j;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  69) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  70) 	p = data;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  71) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  72) 	while (len > cpio_header_len) {
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  73) 		if (!*p) {
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  74) 			/* All cpio headers need to be 4-byte aligned */
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  75) 			p += 4;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  76) 			len -= 4;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  77) 			continue;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  78) 		}
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  79) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  80) 		j = 6;		/* The magic field is only 6 characters */
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  81) 		chp = ch;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  82) 		for (i = C_NFIELDS; i; i--) {
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  83) 			v = 0;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  84) 			while (j--) {
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  85) 				v <<= 4;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  86) 				c = *p++;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  87) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  88) 				x = c - '0';
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  89) 				if (x < 10) {
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  90) 					v += x;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  91) 					continue;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  92) 				}
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  93) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  94) 				x = (c | 0x20) - 'a';
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  95) 				if (x < 6) {
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  96) 					v += x + 10;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  97) 					continue;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  98) 				}
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200  99) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 100) 				goto quit; /* Invalid hexadecimal */
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 101) 			}
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 102) 			*chp++ = v;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 103) 			j = 8;	/* All other fields are 8 characters */
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 104) 		}
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 105) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 106) 		if ((ch[C_MAGIC] - 0x070701) > 1)
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 107) 			goto quit; /* Invalid magic */
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 108) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 109) 		len -= cpio_header_len;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 110) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 111) 		dptr = PTR_ALIGN(p + ch[C_NAMESIZE], 4);
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 112) 		nptr = PTR_ALIGN(dptr + ch[C_FILESIZE], 4);
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 113) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 114) 		if (nptr > p + len || dptr < p || nptr < dptr)
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 115) 			goto quit; /* Buffer overrun */
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 116) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 117) 		if ((ch[C_MODE] & 0170000) == 0100000 &&
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 118) 		    ch[C_NAMESIZE] >= mypathsize &&
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 119) 		    !memcmp(p, path, mypathsize)) {
7557933e6b99d (Borislav Petkov 2016-06-06 17:10:44 +0200 120) 
7557933e6b99d (Borislav Petkov 2016-06-06 17:10:44 +0200 121) 			if (nextoff)
7557933e6b99d (Borislav Petkov 2016-06-06 17:10:44 +0200 122) 				*nextoff = (long)nptr - (long)data;
7557933e6b99d (Borislav Petkov 2016-06-06 17:10:44 +0200 123) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 124) 			if (ch[C_NAMESIZE] - mypathsize >= MAX_CPIO_FILE_NAME) {
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 125) 				pr_warn(
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 126) 				"File %s exceeding MAX_CPIO_FILE_NAME [%d]\n",
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 127) 				p, MAX_CPIO_FILE_NAME);
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 128) 			}
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 129) 			strlcpy(cd.name, p + mypathsize, MAX_CPIO_FILE_NAME);
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 130) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 131) 			cd.data = (void *)dptr;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 132) 			cd.size = ch[C_FILESIZE];
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 133) 			return cd; /* Found it! */
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 134) 		}
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 135) 		len -= (nptr - p);
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 136) 		p = nptr;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 137) 	}
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 138) 
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 139) quit:
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 140) 	return cd;
e6459606b04e6 (H. Peter Anvin  2012-10-01 00:23:52 +0200 141) }