aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <shade@chemlab.org>2013-10-19 19:49:20 -0700
committerTom Marshall <tdm@cyngn.com>2015-11-20 15:46:34 -0800
commitf30dd3d81206fcfcce0404436fa55c997d03924e (patch)
tree1b9721c8724d6c7c09f523a1c58c155419e712e3
parent7e9b637c45449d2d4607c9f5ba681deb39c5b230 (diff)
downloadbootable_recovery-f30dd3d81206fcfcce0404436fa55c997d03924e.zip
bootable_recovery-f30dd3d81206fcfcce0404436fa55c997d03924e.tar.gz
bootable_recovery-f30dd3d81206fcfcce0404436fa55c997d03924e.tar.bz2
sr: Get a proper shell environment in recovery
* Secure ADB support * Toybox applets * mksh * Various other tools Change-Id: I80b0e2aa5eb7142eaa9f157709f4e029077d8dfa
-rw-r--r--Android.mk95
-rw-r--r--etc/init.rc11
-rw-r--r--etc/mkshrc70
-rw-r--r--recovery.cpp71
-rw-r--r--recovery_cmds.h77
5 files changed, 316 insertions, 8 deletions
diff --git a/Android.mk b/Android.mk
index 3db2656..ede6a96 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,4 +1,5 @@
# Copyright (C) 2007 The Android Open Source Project
+# Copyright (C) 2015 The CyanogenMod Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -44,13 +45,17 @@ LOCAL_SRC_FILES := \
verifier.cpp \
wear_ui.cpp \
+# External tools
+LOCAL_SRC_FILES += \
+ ../../system/core/toolbox/newfs_msdos.c \
+ ../../system/core/toolbox/start.c \
+ ../../system/core/toolbox/stop.c
+
LOCAL_MODULE := recovery
LOCAL_FORCE_STATIC_EXECUTABLE := true
-ifeq ($(HOST_OS),linux)
LOCAL_REQUIRED_MODULES := mkfs.f2fs
-endif
RECOVERY_API_VERSION := 3
RECOVERY_FSTAB_VERSION := 2
@@ -65,12 +70,19 @@ LOCAL_C_INCLUDES += \
LOCAL_STATIC_LIBRARIES := \
libext4_utils_static \
+ libmake_ext4fs_static \
+ libminizip_static \
libsparse_static \
+ libfsck_msdos \
+ libminipigz \
+ libreboot_static \
libminzip \
libz \
libmtdutils \
libmincrypt \
libminadbd \
+ libtoybox_driver \
+ libmksh_static \
libfusesideload \
libminui \
libpng \
@@ -79,10 +91,11 @@ LOCAL_STATIC_LIBRARIES := \
libcutils \
liblog \
libselinux \
+ libc++_static \
libm \
libc \
- libc++_static \
- libz
+ libext2_blkid \
+ libext2_uuid
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
@@ -96,8 +109,82 @@ else
LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB)
endif
+LOCAL_C_INCLUDES += system/extras/ext4_utils
+LOCAL_C_INCLUDES += external/boringssl/include
+
+# Symlinks
+RECOVERY_SYMLINKS := $(addprefix $(TARGET_RECOVERY_ROOT_OUT)/sbin/,$(RECOVERY_LINKS))
+
+ifeq ($(ONE_SHOT_MAKEFILE),)
+LOCAL_ADDITIONAL_DEPENDENCIES += \
+ mount.exfat_static \
+ recovery_e2fsck \
+ recovery_mke2fs \
+ recovery_tune2fs \
+ recovery_mkshrc
+
+endif
+
+TOYBOX_INSTLIST := $(HOST_OUT_EXECUTABLES)/toybox-instlist
+LOCAL_ADDITIONAL_DEPENDENCIES += toybox_recovery_links
+
+# Set up the static symlinks
+RECOVERY_TOOLS := \
+ gunzip gzip make_ext4fs minizip reboot setup_adbd sh start stop toybox
+LOCAL_POST_INSTALL_CMD := \
+ $(hide) $(foreach t,$(RECOVERY_TOOLS),ln -sf recovery $(TARGET_RECOVERY_ROOT_OUT)/sbin/$(t);)
+
include $(BUILD_EXECUTABLE)
+# Run toybox-instlist and generate the rest of the symlinks
+toybox_recovery_links: $(TOYBOX_INSTLIST)
+toybox_recovery_links: TOY_LIST=$(shell $(TOYBOX_INSTLIST))
+toybox_recovery_links: TOYBOX_BINARY := $(TARGET_RECOVERY_ROOT_OUT)/sbin/toybox
+toybox_recovery_links:
+ @echo -e ${CL_CYN}"Generate Toybox links:"${CL_RST} $(TOY_LIST)
+ $(hide) $(foreach t,$(TOY_LIST),ln -sf toybox $(TARGET_RECOVERY_ROOT_OUT)/sbin/$(t);)
+
+# mkshrc
+include $(CLEAR_VARS)
+LOCAL_MODULE := recovery_mkshrc
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/etc
+LOCAL_SRC_FILES := etc/mkshrc
+LOCAL_MODULE_STEM := mkshrc
+include $(BUILD_PREBUILT)
+
+# make_ext4fs
+include $(CLEAR_VARS)
+LOCAL_MODULE := libmake_ext4fs_static
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -Dmain=make_ext4fs_main
+LOCAL_SRC_FILES := \
+ ../../system/extras/ext4_utils/make_ext4fs_main.c \
+ ../../system/extras/ext4_utils/canned_fs_config.c
+include $(BUILD_STATIC_LIBRARY)
+
+# Minizip static library
+include $(CLEAR_VARS)
+LOCAL_MODULE := libminizip_static
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -Dmain=minizip_main -D__ANDROID__ -DIOAPI_NO_64
+LOCAL_C_INCLUDES := external/zlib
+LOCAL_SRC_FILES := \
+ ../../external/zlib/src/contrib/minizip/ioapi.c \
+ ../../external/zlib/src/contrib/minizip/minizip.c \
+ ../../external/zlib/src/contrib/minizip/zip.c
+include $(BUILD_STATIC_LIBRARY)
+
+# Reboot static library
+include $(CLEAR_VARS)
+LOCAL_MODULE := libreboot_static
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -Dmain=reboot_main
+LOCAL_SRC_FILES := ../../system/core/reboot/reboot.c
+include $(BUILD_STATIC_LIBRARY)
+
+
# All the APIs for testing
include $(CLEAR_VARS)
LOCAL_CLANG := true
diff --git a/etc/init.rc b/etc/init.rc
index dc18659..ea7c054 100644
--- a/etc/init.rc
+++ b/etc/init.rc
@@ -84,17 +84,20 @@ service healthd /sbin/healthd -r
service recovery /sbin/recovery
seclabel u:r:recovery:s0
+service setup_adbd /sbin/setup_adbd
+ oneshot
+ seclabel u:r:recovery:s0
+ disabled
+
service adbd /sbin/adbd --root_seclabel=u:r:su:s0 --device_banner=recovery
disabled
socket adbd stream 660 system system
seclabel u:r:adbd:s0
-# Always start adbd on userdebug and eng builds
+# setup_adbd will start adb once it has checked the keys
on property:ro.debuggable=1
- write /sys/class/android_usb/android0/enable 1
- start adbd
+ start setup_adbd
-# Restart adbd so it can run as root
on property:service.adb.root=1
write /sys/class/android_usb/android0/enable 0
restart adbd
diff --git a/etc/mkshrc b/etc/mkshrc
new file mode 100644
index 0000000..b2923c6
--- /dev/null
+++ b/etc/mkshrc
@@ -0,0 +1,70 @@
+# Copyright (c) 2010, 2012, 2013, 2014
+# Thorsten Glaser <tg@mirbsd.org>
+# This file is provided under the same terms as mksh.
+#-
+# Minimal /system/etc/mkshrc for Android
+#
+# Support: https://launchpad.net/mksh
+
+: ${HOME:=/}
+: ${HOSTNAME:=$(getprop ro.product.device)}
+: ${HOSTNAME:=android}
+: ${MKSH:=/sbin/sh}
+: ${SHELL:=$MKSH}
+: ${TERM:=linux}
+: ${TMPDIR:=/tmp}
+: ${USER:=$(id -un)}
+export HOME HOSTNAME MKSH SHELL TERM TMPDIR USER
+
+if (( USER_ID )); then PS1='$'; else PS1='#'; fi
+PS4='[$EPOCHREALTIME] '; PS1='${|
+ local e=$?
+
+ (( e )) && REPLY+="$e|"
+
+ return $e
+}$USER@$HOSTNAME:${PWD:-?} '"$PS1 "
+
+function hd {
+ local -Uui16 -Z11 pos=0
+ local -Uui16 -Z5 hv=2147483647
+ local dasc line i
+
+ cat "$@" | { set +U; if read -arN -1 line; then
+ typeset -i1 'line[*]'
+ i=0
+ while (( i < ${#line[*]} )); do
+ hv=${line[i++]}
+ if (( (pos & 15) == 0 )); then
+ (( pos )) && print -r -- "$dasc|"
+ print -n "${pos#16#} "
+ dasc=' |'
+ fi
+ print -n "${hv#16#} "
+ if (( (hv < 32) || (hv > 126) )); then
+ dasc+=.
+ else
+ dasc+=${line[i-1]#1#}
+ fi
+ (( (pos++ & 15) == 7 )) && print -n -- '- '
+ done
+ while (( pos & 15 )); do
+ print -n ' '
+ (( (pos++ & 15) == 7 )) && print -n -- '- '
+ done
+ (( hv == 2147483647 )) || print -r -- "$dasc|"
+ fi; }
+}
+
+function setenv {
+ eval export "\"$1\""'="$2"'
+}
+
+for p in ~/bin; do
+ [[ -d $p/. ]] || continue
+ [[ :$PATH: = *:$p:* ]] || PATH=$p:$PATH
+done
+
+unset p
+
+: place customisations above this line
diff --git a/recovery.cpp b/recovery.cpp
index da962ba..5288dab 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -52,6 +52,10 @@
#include "fuse_sideload.h"
#include "fuse_sdcard_provider.h"
+extern "C" {
+#include "recovery_cmds.h"
+}
+
struct selabel_handle *sehandle;
static const struct option OPTIONS[] = {
@@ -987,6 +991,40 @@ load_locale_from_cache() {
}
}
+static const char *key_src = "/data/misc/adb/adb_keys";
+static const char *key_dest = "/adb_keys";
+
+
+static void
+setup_adbd() {
+ struct stat f;
+ // Mount /data and copy adb_keys to root if it exists
+ ensure_path_mounted("/data");
+ if (stat(key_src, &f) == 0) {
+ FILE *file_src = fopen(key_src, "r");
+ if (file_src == NULL) {
+ LOGE("Can't open %s\n", key_src);
+ } else {
+ FILE *file_dest = fopen(key_dest, "w");
+ if (file_dest == NULL) {
+ LOGE("Can't open %s\n", key_dest);
+ } else {
+ char buf[4096];
+ while (fgets(buf, sizeof(buf), file_src)) fputs(buf, file_dest);
+ check_and_fclose(file_dest, key_dest);
+
+ // Enable secure adbd
+ property_set("ro.adb.secure", "1");
+ }
+ check_and_fclose(file_src, key_src);
+ }
+ }
+ ensure_path_unmounted("/data");
+
+ // Trigger (re)start of adb daemon
+ property_set("service.adb.root", "1");
+}
+
static RecoveryUI* gCurrentUI = NULL;
void
@@ -1005,6 +1043,8 @@ ui_print(const char* format, ...) {
}
}
+extern "C" int toybox_driver(int argc, char **argv);
+
int
main(int argc, char **argv) {
// If this binary is started with the single argument "--adbd",
@@ -1019,6 +1059,37 @@ main(int argc, char **argv) {
return 0;
}
+ // Handle alternative invocations
+ char* command = argv[0];
+ char* stripped = strrchr(argv[0], '/');
+ if (stripped)
+ command = stripped + 1;
+
+ if (strcmp(command, "recovery") != 0) {
+ struct recovery_cmd cmd = get_command(command);
+ if (cmd.name)
+ return cmd.main_func(argc, argv);
+
+ if (!strcmp(command, "setup_adbd")) {
+ load_volume_table();
+ setup_adbd();
+ return 0;
+ }
+ if (strstr(argv[0], "start")) {
+ property_set("ctl.start", argv[1]);
+ return 0;
+ }
+ if (strstr(argv[0], "stop")) {
+ property_set("ctl.stop", argv[1]);
+ return 0;
+ }
+ return toybox_driver(argc, argv);
+ }
+
+ // Clear umask for packages that copy files out to /tmp and then over
+ // to /system without properly setting all permissions (eg. gapps).
+ umask(0);
+
time_t start = time(NULL);
// redirect_stdio should be called only in non-sideload mode. Otherwise
diff --git a/recovery_cmds.h b/recovery_cmds.h
new file mode 100644
index 0000000..a420ae1
--- /dev/null
+++ b/recovery_cmds.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _RECOVERY_CMDS_H
+#define _RECOVERY_CMDS_H
+
+#include <stdio.h>
+#include <string.h>
+
+int minizip_main(int argc, char **argv);
+int make_ext4fs_main(int argc, char **argv);
+int reboot_main(int argc, char **argv);
+int poweroff_main(int argc, char **argv);
+int fsck_msdos_main(int argc, char **argv);
+int newfs_msdos_main(int argc, char **argv);
+int pigz_main(int argc, char **argv);
+int start_main(int argc, char **argv);
+int stop_main(int argc, char **argv);
+int mksh_main(int argc, char **argv);
+#ifdef USE_F2FS
+int make_f2fs_main(int argc, char **argv);
+int fsck_f2fs_main(int argc, char **argv);
+int fibmap_main(int argc, char **argv);
+#endif
+
+int toybox_driver(int argc, char **argv);
+
+struct recovery_cmd {
+ const char *name;
+ int (*main_func)(int argc, char **argv);
+};
+
+static const struct recovery_cmd recovery_cmds[] = {
+ { "minizip", minizip_main },
+ { "make_ext4fs", make_ext4fs_main },
+ { "reboot", reboot_main },
+ { "poweroff", reboot_main },
+ { "fsck_msdos", fsck_msdos_main },
+ { "newfs_msdos", newfs_msdos_main },
+ { "pigz", pigz_main },
+ { "gzip", pigz_main },
+ { "gunzip", pigz_main },
+ { "start", start_main },
+ { "stop", stop_main },
+ { "sh", mksh_main },
+#ifdef USE_F2FS
+ { "mkfs.f2fs", make_f2fs_main },
+ { "fsck.f2fs", fsck_f2fs_main },
+ { "fibmap.f2fs", fibmap_main },
+#endif
+ { NULL, NULL },
+};
+
+struct recovery_cmd get_command(char* command) {
+ int i;
+
+ for (i = 0; recovery_cmds[i].name; i++) {
+ if (strcmp(command, recovery_cmds[i].name) == 0)
+ break;
+ }
+
+ return recovery_cmds[i];
+}
+#endif