Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

100
usr/Kconfig Normal file
View file

@ -0,0 +1,100 @@
#
# Configuration for initramfs
#
config INITRAMFS_SOURCE
string "Initramfs source file(s)"
default ""
help
This can be either a single cpio archive with a .cpio suffix or a
space-separated list of directories and files for building the
initramfs image. A cpio archive should contain a filesystem archive
to be used as an initramfs image. Directories should contain a
filesystem layout to be included in the initramfs image. Files
should contain entries according to the format described by the
"usr/gen_init_cpio" program in the kernel tree.
When multiple directories and files are specified then the
initramfs image will be the aggregate of all of them.
See <file:Documentation/early-userspace/README> for more details.
If you are not sure, leave it blank.
config INITRAMFS_ROOT_UID
int "User ID to map to 0 (user root)"
depends on INITRAMFS_SOURCE!=""
default "0"
help
This setting is only meaningful if the INITRAMFS_SOURCE is
contains a directory. Setting this user ID (UID) to something
other than "0" will cause all files owned by that UID to be
owned by user root in the initial ramdisk image.
If you are not sure, leave it set to "0".
config INITRAMFS_ROOT_GID
int "Group ID to map to 0 (group root)"
depends on INITRAMFS_SOURCE!=""
default "0"
help
This setting is only meaningful if the INITRAMFS_SOURCE is
contains a directory. Setting this group ID (GID) to something
other than "0" will cause all files owned by that GID to be
owned by group root in the initial ramdisk image.
If you are not sure, leave it set to "0".
config RD_GZIP
bool "Support initial ramdisks compressed using gzip" if EXPERT
default y
depends on BLK_DEV_INITRD
select DECOMPRESS_GZIP
help
Support loading of a gzip encoded initial ramdisk or cpio buffer.
If unsure, say Y.
config RD_BZIP2
bool "Support initial ramdisks compressed using bzip2" if EXPERT
default !EXPERT
depends on BLK_DEV_INITRD
select DECOMPRESS_BZIP2
help
Support loading of a bzip2 encoded initial ramdisk or cpio buffer
If unsure, say N.
config RD_LZMA
bool "Support initial ramdisks compressed using LZMA" if EXPERT
default !EXPERT
depends on BLK_DEV_INITRD
select DECOMPRESS_LZMA
help
Support loading of a LZMA encoded initial ramdisk or cpio buffer
If unsure, say N.
config RD_XZ
bool "Support initial ramdisks compressed using XZ" if EXPERT
default !EXPERT
depends on BLK_DEV_INITRD
select DECOMPRESS_XZ
help
Support loading of a XZ encoded initial ramdisk or cpio buffer.
If unsure, say N.
config RD_LZO
bool "Support initial ramdisks compressed using LZO" if EXPERT
default !EXPERT
depends on BLK_DEV_INITRD
select DECOMPRESS_LZO
help
Support loading of a LZO encoded initial ramdisk or cpio buffer
If unsure, say N.
config RD_LZ4
bool "Support initial ramdisks compressed using LZ4" if EXPERT
default !EXPERT
depends on BLK_DEV_INITRD
select DECOMPRESS_LZ4
help
Support loading of a LZ4 encoded initial ramdisk or cpio buffer
If unsure, say N.

74
usr/Makefile Normal file
View file

@ -0,0 +1,74 @@
#
# kbuild file for usr/ - including initramfs image
#
klibcdirs:;
PHONY += klibcdirs
# Bzip2
suffix_$(CONFIG_RD_BZIP2) = .bz2
# Lzma
suffix_$(CONFIG_RD_LZMA) = .lzma
# XZ
suffix_$(CONFIG_RD_XZ) = .xz
# Lzo
suffix_$(CONFIG_RD_LZO) = .lzo
# Lz4
suffix_$(CONFIG_RD_LZ4) = .lz4
# Gzip
suffix_$(CONFIG_RD_GZIP) = .gz
AFLAGS_initramfs_data.o += -DINITRAMFS_IMAGE="usr/initramfs_data.cpio$(suffix_y)"
# Generate builtin.o based on initramfs_data.o
obj-$(CONFIG_BLK_DEV_INITRD) := initramfs_data.o
# initramfs_data.o contains the compressed initramfs_data.cpio image.
# The image is included using .incbin, a dependency which is not
# tracked automatically.
$(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio$(suffix_y) FORCE
#####
# Generate the initramfs cpio archive
hostprogs-y := gen_init_cpio
initramfs := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh
ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
$(shell echo $(CONFIG_INITRAMFS_SOURCE)),-d)
ramfs-args := \
$(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \
$(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID))
# .initramfs_data.cpio.d is used to identify all files included
# in initramfs and to detect if any files are added/removed.
# Removed files are identified by directory timestamp being updated
# The dependency list is generated by gen_initramfs.sh -l
ifneq ($(wildcard $(obj)/.initramfs_data.cpio.d),)
include $(obj)/.initramfs_data.cpio.d
endif
quiet_cmd_initfs = GEN $@
cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
targets := initramfs_data.cpio.gz initramfs_data.cpio.bz2 \
initramfs_data.cpio.lzma initramfs_data.cpio.xz \
initramfs_data.cpio.lzo initramfs_data.cpio.lz4 \
initramfs_data.cpio
# do not try to update files included in initramfs
$(deps_initramfs): ;
$(deps_initramfs): klibcdirs
# We rebuild initramfs_data.cpio if:
# 1) Any included file is newer then initramfs_data.cpio
# 2) There are changes in which files are included (added or deleted)
# 3) If gen_init_cpio are newer than initramfs_data.cpio
# 4) arguments to gen_initramfs.sh changes
$(obj)/initramfs_data.cpio$(suffix_y): $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs
$(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.d
$(call if_changed,initfs)

623
usr/gen_init_cpio.c Normal file
View file

@ -0,0 +1,623 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include <limits.h>
/*
* Original work by Jeff Garzik
*
* External file lists, symlink, pipe and fifo support by Thayne Harbaugh
* Hard link support by Luciano Rocha
*/
#define xstr(s) #s
#define str(s) xstr(s)
static unsigned int offset;
static unsigned int ino = 721;
static time_t default_mtime;
struct file_handler {
const char *type;
int (*handler)(const char *line);
};
static void push_string(const char *name)
{
unsigned int name_len = strlen(name) + 1;
fputs(name, stdout);
putchar(0);
offset += name_len;
}
static void push_pad (void)
{
while (offset & 3) {
putchar(0);
offset++;
}
}
static void push_rest(const char *name)
{
unsigned int name_len = strlen(name) + 1;
unsigned int tmp_ofs;
fputs(name, stdout);
putchar(0);
offset += name_len;
tmp_ofs = name_len + 110;
while (tmp_ofs & 3) {
putchar(0);
offset++;
tmp_ofs++;
}
}
static void push_hdr(const char *s)
{
fputs(s, stdout);
offset += 110;
}
static void cpio_trailer(void)
{
char s[256];
const char name[] = "TRAILER!!!";
sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"
"%08X%08X%08X%08X%08X%08X%08X",
"070701", /* magic */
0, /* ino */
0, /* mode */
(long) 0, /* uid */
(long) 0, /* gid */
1, /* nlink */
(long) 0, /* mtime */
0, /* filesize */
0, /* major */
0, /* minor */
0, /* rmajor */
0, /* rminor */
(unsigned)strlen(name)+1, /* namesize */
0); /* chksum */
push_hdr(s);
push_rest(name);
while (offset % 512) {
putchar(0);
offset++;
}
}
static int cpio_mkslink(const char *name, const char *target,
unsigned int mode, uid_t uid, gid_t gid)
{
char s[256];
if (name[0] == '/')
name++;
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
"%08X%08X%08X%08X%08X%08X%08X",
"070701", /* magic */
ino++, /* ino */
S_IFLNK | mode, /* mode */
(long) uid, /* uid */
(long) gid, /* gid */
1, /* nlink */
(long) default_mtime, /* mtime */
(unsigned)strlen(target)+1, /* filesize */
3, /* major */
1, /* minor */
0, /* rmajor */
0, /* rminor */
(unsigned)strlen(name) + 1,/* namesize */
0); /* chksum */
push_hdr(s);
push_string(name);
push_pad();
push_string(target);
push_pad();
return 0;
}
static int cpio_mkslink_line(const char *line)
{
char name[PATH_MAX + 1];
char target[PATH_MAX + 1];
unsigned int mode;
int uid;
int gid;
int rc = -1;
if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, target, &mode, &uid, &gid)) {
fprintf(stderr, "Unrecognized dir format '%s'", line);
goto fail;
}
rc = cpio_mkslink(name, target, mode, uid, gid);
fail:
return rc;
}
static int cpio_mkgeneric(const char *name, unsigned int mode,
uid_t uid, gid_t gid)
{
char s[256];
if (name[0] == '/')
name++;
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
"%08X%08X%08X%08X%08X%08X%08X",
"070701", /* magic */
ino++, /* ino */
mode, /* mode */
(long) uid, /* uid */
(long) gid, /* gid */
2, /* nlink */
(long) default_mtime, /* mtime */
0, /* filesize */
3, /* major */
1, /* minor */
0, /* rmajor */
0, /* rminor */
(unsigned)strlen(name) + 1,/* namesize */
0); /* chksum */
push_hdr(s);
push_rest(name);
return 0;
}
enum generic_types {
GT_DIR,
GT_PIPE,
GT_SOCK
};
struct generic_type {
const char *type;
mode_t mode;
};
static struct generic_type generic_type_table[] = {
[GT_DIR] = {
.type = "dir",
.mode = S_IFDIR
},
[GT_PIPE] = {
.type = "pipe",
.mode = S_IFIFO
},
[GT_SOCK] = {
.type = "sock",
.mode = S_IFSOCK
}
};
static int cpio_mkgeneric_line(const char *line, enum generic_types gt)
{
char name[PATH_MAX + 1];
unsigned int mode;
int uid;
int gid;
int rc = -1;
if (4 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d", name, &mode, &uid, &gid)) {
fprintf(stderr, "Unrecognized %s format '%s'",
line, generic_type_table[gt].type);
goto fail;
}
mode |= generic_type_table[gt].mode;
rc = cpio_mkgeneric(name, mode, uid, gid);
fail:
return rc;
}
static int cpio_mkdir_line(const char *line)
{
return cpio_mkgeneric_line(line, GT_DIR);
}
static int cpio_mkpipe_line(const char *line)
{
return cpio_mkgeneric_line(line, GT_PIPE);
}
static int cpio_mksock_line(const char *line)
{
return cpio_mkgeneric_line(line, GT_SOCK);
}
static int cpio_mknod(const char *name, unsigned int mode,
uid_t uid, gid_t gid, char dev_type,
unsigned int maj, unsigned int min)
{
char s[256];
if (dev_type == 'b')
mode |= S_IFBLK;
else
mode |= S_IFCHR;
if (name[0] == '/')
name++;
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
"%08X%08X%08X%08X%08X%08X%08X",
"070701", /* magic */
ino++, /* ino */
mode, /* mode */
(long) uid, /* uid */
(long) gid, /* gid */
1, /* nlink */
(long) default_mtime, /* mtime */
0, /* filesize */
3, /* major */
1, /* minor */
maj, /* rmajor */
min, /* rminor */
(unsigned)strlen(name) + 1,/* namesize */
0); /* chksum */
push_hdr(s);
push_rest(name);
return 0;
}
static int cpio_mknod_line(const char *line)
{
char name[PATH_MAX + 1];
unsigned int mode;
int uid;
int gid;
char dev_type;
unsigned int maj;
unsigned int min;
int rc = -1;
if (7 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d %c %u %u",
name, &mode, &uid, &gid, &dev_type, &maj, &min)) {
fprintf(stderr, "Unrecognized nod format '%s'", line);
goto fail;
}
rc = cpio_mknod(name, mode, uid, gid, dev_type, maj, min);
fail:
return rc;
}
static int cpio_mkfile(const char *name, const char *location,
unsigned int mode, uid_t uid, gid_t gid,
unsigned int nlinks)
{
char s[256];
char *filebuf = NULL;
struct stat buf;
long size;
int file = -1;
int retval;
int rc = -1;
int namesize;
unsigned int i;
mode |= S_IFREG;
file = open (location, O_RDONLY);
if (file < 0) {
fprintf (stderr, "File %s could not be opened for reading\n", location);
goto error;
}
retval = fstat(file, &buf);
if (retval) {
fprintf(stderr, "File %s could not be stat()'ed\n", location);
goto error;
}
filebuf = malloc(buf.st_size);
if (!filebuf) {
fprintf (stderr, "out of memory\n");
goto error;
}
retval = read (file, filebuf, buf.st_size);
if (retval < 0) {
fprintf (stderr, "Can not read %s file\n", location);
goto error;
}
size = 0;
for (i = 1; i <= nlinks; i++) {
/* data goes on last link */
if (i == nlinks) size = buf.st_size;
if (name[0] == '/')
name++;
namesize = strlen(name) + 1;
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
"%08lX%08X%08X%08X%08X%08X%08X",
"070701", /* magic */
ino, /* ino */
mode, /* mode */
(long) uid, /* uid */
(long) gid, /* gid */
nlinks, /* nlink */
(long) buf.st_mtime, /* mtime */
size, /* filesize */
3, /* major */
1, /* minor */
0, /* rmajor */
0, /* rminor */
namesize, /* namesize */
0); /* chksum */
push_hdr(s);
push_string(name);
push_pad();
if (size) {
if (fwrite(filebuf, size, 1, stdout) != 1) {
fprintf(stderr, "writing filebuf failed\n");
goto error;
}
offset += size;
push_pad();
}
name += namesize;
}
ino++;
rc = 0;
error:
if (filebuf) free(filebuf);
if (file >= 0) close(file);
return rc;
}
static char *cpio_replace_env(char *new_location)
{
char expanded[PATH_MAX + 1];
char *start, *end, *var;
while ((start = strstr(new_location, "${")) &&
(end = strchr(start + 2, '}'))) {
*start = *end = 0;
var = getenv(start + 2);
snprintf(expanded, sizeof expanded, "%s%s%s",
new_location, var ? var : "", end + 1);
strcpy(new_location, expanded);
}
return new_location;
}
static int cpio_mkfile_line(const char *line)
{
char name[PATH_MAX + 1];
char *dname = NULL; /* malloc'ed buffer for hard links */
char location[PATH_MAX + 1];
unsigned int mode;
int uid;
int gid;
int nlinks = 1;
int end = 0, dname_len = 0;
int rc = -1;
if (5 > sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX)
"s %o %d %d %n",
name, location, &mode, &uid, &gid, &end)) {
fprintf(stderr, "Unrecognized file format '%s'", line);
goto fail;
}
if (end && isgraph(line[end])) {
int len;
int nend;
dname = malloc(strlen(line));
if (!dname) {
fprintf (stderr, "out of memory (%d)\n", dname_len);
goto fail;
}
dname_len = strlen(name) + 1;
memcpy(dname, name, dname_len);
do {
nend = 0;
if (sscanf(line + end, "%" str(PATH_MAX) "s %n",
name, &nend) < 1)
break;
len = strlen(name) + 1;
memcpy(dname + dname_len, name, len);
dname_len += len;
nlinks++;
end += nend;
} while (isgraph(line[end]));
} else {
dname = name;
}
rc = cpio_mkfile(dname, cpio_replace_env(location),
mode, uid, gid, nlinks);
fail:
if (dname_len) free(dname);
return rc;
}
static void usage(const char *prog)
{
fprintf(stderr, "Usage:\n"
"\t%s [-t <timestamp>] <cpio_list>\n"
"\n"
"<cpio_list> is a file containing newline separated entries that\n"
"describe the files to be included in the initramfs archive:\n"
"\n"
"# a comment\n"
"file <name> <location> <mode> <uid> <gid> [<hard links>]\n"
"dir <name> <mode> <uid> <gid>\n"
"nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>\n"
"slink <name> <target> <mode> <uid> <gid>\n"
"pipe <name> <mode> <uid> <gid>\n"
"sock <name> <mode> <uid> <gid>\n"
"\n"
"<name> name of the file/dir/nod/etc in the archive\n"
"<location> location of the file in the current filesystem\n"
" expands shell variables quoted with ${}\n"
"<target> link target\n"
"<mode> mode/permissions of the file\n"
"<uid> user id (0=root)\n"
"<gid> group id (0=root)\n"
"<dev_type> device type (b=block, c=character)\n"
"<maj> major number of nod\n"
"<min> minor number of nod\n"
"<hard links> space separated list of other links to file\n"
"\n"
"example:\n"
"# A simple initramfs\n"
"dir /dev 0755 0 0\n"
"nod /dev/console 0600 0 0 c 5 1\n"
"dir /root 0700 0 0\n"
"dir /sbin 0755 0 0\n"
"file /sbin/kinit /usr/src/klibc/kinit/kinit 0755 0 0\n"
"\n"
"<timestamp> is time in seconds since Epoch that will be used\n"
"as mtime for symlinks, special files and directories. The default\n"
"is to use the current time for these entries.\n",
prog);
}
struct file_handler file_handler_table[] = {
{
.type = "file",
.handler = cpio_mkfile_line,
}, {
.type = "nod",
.handler = cpio_mknod_line,
}, {
.type = "dir",
.handler = cpio_mkdir_line,
}, {
.type = "slink",
.handler = cpio_mkslink_line,
}, {
.type = "pipe",
.handler = cpio_mkpipe_line,
}, {
.type = "sock",
.handler = cpio_mksock_line,
}, {
.type = NULL,
.handler = NULL,
}
};
#define LINE_SIZE (2 * PATH_MAX + 50)
int main (int argc, char *argv[])
{
FILE *cpio_list;
char line[LINE_SIZE];
char *args, *type;
int ec = 0;
int line_nr = 0;
const char *filename;
default_mtime = time(NULL);
while (1) {
int opt = getopt(argc, argv, "t:h");
char *invalid;
if (opt == -1)
break;
switch (opt) {
case 't':
default_mtime = strtol(optarg, &invalid, 10);
if (!*optarg || *invalid) {
fprintf(stderr, "Invalid timestamp: %s\n",
optarg);
usage(argv[0]);
exit(1);
}
break;
case 'h':
case '?':
usage(argv[0]);
exit(opt == 'h' ? 0 : 1);
}
}
if (argc - optind != 1) {
usage(argv[0]);
exit(1);
}
filename = argv[optind];
if (!strcmp(filename, "-"))
cpio_list = stdin;
else if (!(cpio_list = fopen(filename, "r"))) {
fprintf(stderr, "ERROR: unable to open '%s': %s\n\n",
filename, strerror(errno));
usage(argv[0]);
exit(1);
}
while (fgets(line, LINE_SIZE, cpio_list)) {
int type_idx;
size_t slen = strlen(line);
line_nr++;
if ('#' == *line) {
/* comment - skip to next line */
continue;
}
if (! (type = strtok(line, " \t"))) {
fprintf(stderr,
"ERROR: incorrect format, could not locate file type line %d: '%s'\n",
line_nr, line);
ec = -1;
break;
}
if ('\n' == *type) {
/* a blank line */
continue;
}
if (slen == strlen(type)) {
/* must be an empty line */
continue;
}
if (! (args = strtok(NULL, "\n"))) {
fprintf(stderr,
"ERROR: incorrect format, newline required line %d: '%s'\n",
line_nr, line);
ec = -1;
}
for (type_idx = 0; file_handler_table[type_idx].type; type_idx++) {
int rc;
if (! strcmp(line, file_handler_table[type_idx].type)) {
if ((rc = file_handler_table[type_idx].handler(args))) {
ec = rc;
fprintf(stderr, " line %d\n", line_nr);
}
break;
}
}
if (NULL == file_handler_table[type_idx].type) {
fprintf(stderr, "unknown file type line %d: '%s'\n",
line_nr, line);
}
}
if (ec == 0)
cpio_trailer();
exit(ec);
}

38
usr/initramfs_data.S Normal file
View file

@ -0,0 +1,38 @@
/*
initramfs_data includes the compressed binary that is the
filesystem used for early user space.
Note: Older versions of "as" (prior to binutils 2.11.90.0.23
released on 2001-07-14) dit not support .incbin.
If you are forced to use older binutils than that then the
following trick can be applied to create the resulting binary:
ld -m elf_i386 --format binary --oformat elf32-i386 -r \
-T initramfs_data.scr initramfs_data.cpio.gz -o initramfs_data.o
ld -m elf_i386 -r -o built-in.o initramfs_data.o
For including the .init.ramfs sections, see include/asm-generic/vmlinux.lds.
The above example is for i386 - the parameters vary from architectures.
Eventually look up LDFLAGS_BLOB in an older version of the
arch/$(ARCH)/Makefile to see the flags used before .incbin was introduced.
Using .incbin has the advantage over ld that the correct flags are set
in the ELF header, as required by certain architectures.
*/
#include <linux/stringify.h>
#include <asm-generic/vmlinux.lds.h>
.section .init.ramfs,"a"
__irf_start:
.incbin __stringify(INITRAMFS_IMAGE)
__irf_end:
.section .init.ramfs.info,"a"
.globl VMLINUX_SYMBOL(__initramfs_size)
VMLINUX_SYMBOL(__initramfs_size):
#ifdef CONFIG_64BIT
.quad __irf_end - __irf_start
#else
.long __irf_end - __irf_start
#endif