Fork me on GitHub

[转][Android][Recovery]Recovery打开adb shell

Android recovery 模式下出于安全的考虑,一般禁止adb和adb shell 登陆。如果需要在recovery 模式下进行debug,需要做一些配置修改。

烧录user版本系统,进入recovery后,输入adb shell命令,提示

error: no devices/emulators found

我们先确认recovery.img是否包含有adb (adb的源码在/system/core/adb)

ls out/target/product/bullhead/recovery/root/sbin
adbd healthd recovery ueventd watchdogd

然后检查/bootable/recovery/etc/init.rc下和adbd相关的启动配置

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
on property:ro.debuggable=1
write /sys/class/android_usb/android0/enable 1
start 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
write /sys/class/android_usb/android0/enable 1

从上面可知init.rc 中adbd 是配置的,disabled 表示开机不启动,如 ro.debuggable 被置为1,那么adb 就会开启,或是service.adb.root设置为1,则重启adbd。

看下

mvim build/core/main.mk

ifeq (true,$(strip $(enable_target_debugging)))
# Target is more debuggable and adbd is on by default
ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=1
# Enable Dalvik lock contention logging.
ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.lockprof.threshold=500
# Include the debugging/testing OTA keys in this build.
INCLUDE_TEST_OTA_KEYS := true
else # !enable_target_debugging
# Target is less debuggable and adbd is off by default
ADDITIONAL_DEFAULT_PROPERTIES += ro.debuggable=0
endif # !enable_target_debugging

关于enable_target_debugging

## user/userdebug ##

user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT))
enable_target_debugging := true
tags_to_install :=
ifneq (,$(user_variant))
# Target is secure in user builds.
ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1
ADDITIONAL_DEFAULT_PROPERTIES += security.perf_harden=1

ifeq ($(user_variant),user)
ADDITIONAL_DEFAULT_PROPERTIES += ro.adb.secure=1
endif

ifeq ($(user_variant),userdebug)
# Pick up some extra useful tools
tags_to_install += debug
else
# Disable debugging in plain user builds.
enable_target_debugging :=
endif

# Disallow mock locations by default for user builds
ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=0

else # !user_variant
# Turn on checkjni for non-user builds.
ADDITIONAL_BUILD_PROPERTIES += ro.kernel.android.checkjni=1
# Set device insecure for non-user builds.
ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=0
# Allow mock locations by default for non user builds
ADDITIONAL_DEFAULT_PROPERTIES += ro.allow.mock.location=1
endif # !user_variant

可知默认为enable_target_debugging := true,根据user_variant的值如果为user,则enable_target_debugging :=,这又和TARGET_BUILD_VARIANT有关,此变量对应于VARIANT_CHOICES=(user userdebug eng)中的一个值,由我们来选择,相关的实现在/build/envsetup.sh中。

根据上面可知,编译时如果选择userdebug或是eng,则ro.debuggable=1,如果我们要在user下也开启这些功能,就需要修改设置

enable_target_debugging := true
ro.debuggable=0

重新编译recovery.img,刷机后,进入recovery,输入adb shell命令,提示:

Exec ‘/system/bin/sh’ failed:No such fileor directory(2)

表示没有sh这个文件,无法进入shell,检查ramdisk 文件系统 system 目录out/target/product/bullhead/recovery/root/system为空。(其实这个system是用来挂载Android的/system的,关于挂载后面会讲)

但我们知道boot.img下是可以的,看system/core/rootdir/init.rc检查boot.img 启动的init.rc。查找关于/sh的代码

service console /system/bin/sh
class core
console
disabled
user shell
group shell log
seclabel u:r:shell:s0

on property:ro.debuggable=1
# Give writes to anyone for the trace folder on debug builds.
# The folder is used to store method traces.
chmod 0773 /data/misc/trace
start console

所以依葫芦画瓢,我们在Recovery的/bootable/recovery/etc/init.rc添加上面的代码。

好了,虽然这一步会在Recovery启动时启动sh,但是Recovery里面没有这个文件啊(前面说了/system是个空目录,用来挂载系统的)。所以需要编译时创建这个文件,因此在/build/core/Makefile增加创建目录的代码和把系统sh拷贝到Recovery的对应目录下

define build-recoveryimage-target
@echo ----- Making recovery image ------
$(hide) mkdir -p $(TARGET_RECOVERY_OUT)
$(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/etc $(TARGET_RECOVERY_ROOT_OUT)/sdcard $(TARGET_RECOVERY_ROOT_OUT)/tmp
...
# 添加下面代码
$(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/system/bin
$(hide) cp -r $(PRODUCT_OUT)/system/bin/sh $(TARGET_RECOVERY_ROOT_OUT)/system/bin/

这里有个问题,就是clean掉项目重新编译的时候,系统的sh还没有生成,所以这里的拷贝操作会因为找不到sh文件而出错,需要调整代码位置。

但这样还是不行,在recovery模式下,二进制文件都是静态连接方式,recovery模式中没有共享库,缺动态链接库加载器(/system/bin/linker,Android动态连接器linker与静态连接器ld)

检查sh 连接的动态库:

arm-linux-androideabi-objdump -x out/target/product/xxxx/system/bin/sh | grep NEEDED

NEEDED libc.so

知道需要改libc的编译。

所以需要修改/external/mksh/Android.mk

#LOCAL_SYSTEM_SHARED_LIBRARIES := libc
LOCAL_STATIC_LIBRARIES := libc
LOCAL_FORCE_STATIC_EXECUTABLE := true

再次编译recovery.img,刷机,进入Recovery模式后就可以使用adb shell了。

关于没有ls命令,这些命令不可用的原理和sh一样,可以自己试着去改。

Reference

https://blog.csdn.net/LoongEmbedded/article/details/67638687

坚持原创技术分享,您的支持将鼓励我继续创作!