diff options
author | Steve Kondik <shade@chemlab.org> | 2013-10-19 19:49:20 -0700 |
---|---|---|
committer | Tom Marshall <tdm@cyngn.com> | 2015-11-20 15:46:34 -0800 |
commit | f30dd3d81206fcfcce0404436fa55c997d03924e (patch) | |
tree | 1b9721c8724d6c7c09f523a1c58c155419e712e3 | |
parent | 7e9b637c45449d2d4607c9f5ba681deb39c5b230 (diff) | |
download | bootable_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.mk | 95 | ||||
-rw-r--r-- | etc/init.rc | 11 | ||||
-rw-r--r-- | etc/mkshrc | 70 | ||||
-rw-r--r-- | recovery.cpp | 71 | ||||
-rw-r--r-- | recovery_cmds.h | 77 |
5 files changed, 316 insertions, 8 deletions
@@ -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 |