Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 41cdd822 authored by Patrick Jacques's avatar Patrick Jacques
Browse files

android_os_Power: TARGET_RECOVERY_WRITE_MISC_PART support

Some devices write a padded message to the misc partitions for the
bootloader to pickup and enable recovery mode.  Enable support by
defining the 'misc' mtd partition number using:
TARGET_RECOVERY_WRITE_MISC_PART in BoardConfig.

Requires mtd misc device to be writeable by user system

Change-Id: Iffd88b07696f138d7127acda5b42ede55b468205
parent 5d4bc4e0
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -249,6 +249,10 @@ endif

LOCAL_MODULE:= libandroid_runtime

ifneq ($(TARGET_RECOVERY_WRITE_MISC_PART),)
        LOCAL_CFLAGS += -DRECOVERY_WRITE_MISC_PART='$(TARGET_RECOVERY_WRITE_MISC_PART)'
endif

include $(BUILD_SHARED_LIBRARY)

include $(call all-makefiles-under,$(LOCAL_PATH))
+89 −0
Original line number Diff line number Diff line
@@ -22,6 +22,14 @@
#include <hardware_legacy/power.h>
#include <sys/reboot.h>

#if RECOVERY_WRITE_MISC_PART
#include <fcntl.h>
#include <sys/mount.h>
#include <mtd/mtd-user.h>
#define MTD_PROC_FILENAME   "/proc/mtd"
#define BOOT_CMD_SIZE       32
#endif

namespace android
{

@@ -83,6 +91,84 @@ static void android_os_Power_shutdown(JNIEnv *env, jobject clazz)
#endif
}

#if RECOVERY_WRITE_MISC_PART
struct bootloader_message {
    char command[32];
    char status[32];
    char recovery[1024];
    char stub[2048 - 32 - 32 - 1024];
};

static char command[2048]; // block size buffer
static int mtdnum = -1;
static int mtdsize = 0;
static int mtderasesize = 0x20000 * 512;
static char mtdname[64];
static char mtddevname[32];

static int init_mtd_info() {
	if (mtdnum >= 0) {
		return 0;
	}
    int fd = open(MTD_PROC_FILENAME, O_RDONLY);
    if (fd < 0) {
        return (mtdnum = -1);
    }
    int nbytes = read(fd, command, sizeof(command) - 1);
    close(fd);
    if (nbytes < 0) {
        return (mtdnum = -2);
    }
    command[nbytes] = '\0';
	char *cursor = command;
	while (nbytes-- > 0 && *(cursor++) != '\n'); // skip one line
	while (nbytes > 0) {
		int matches = sscanf(cursor, "mtd%d: %x %x \"%63s[^\"]", &mtdnum, &mtdsize, &mtderasesize, mtdname);
		if (matches == ( RECOVERY_WRITE_MISC_PART )) {
			if (strncmp("misc", mtdname, ( RECOVERY_WRITE_MISC_PART )) == 0) {
				sprintf(mtddevname, "/dev/mtd/mtd%d", mtdnum);
				//printf("Partition for parameters: %s\n", mtddevname);
				return 0;
			}
			while (nbytes-- > 0 && *(cursor++) != '\n'); // skip a line
		}
	}
    return (mtdnum = -3);
}

int set_message(char* cmd) {
        int fd;
        int pos = 2048;
        if (init_mtd_info() != 0) {
                return -9;
        }
        fd = open(mtddevname, O_RDWR);
    if (fd < 0) {
        return fd;
    }
    struct erase_info_user erase_info;
    erase_info.start = 0;
    erase_info.length = mtderasesize;
    if (ioctl(fd, MEMERASE, &erase_info) < 0) {
                fprintf(stderr, "mtd: erase failure at 0x%08x (%s)\n", pos, strerror(errno));
    }
        if (lseek(fd, pos, SEEK_SET) != pos) {
                close(fd);
                return pos;
        }
        memset(&command, 0, sizeof(command));
        strncpy(command, cmd, strlen(cmd));
        pos = write(fd, command, sizeof(command));
        //printf("Written %d bytes\n", pos);
        if (pos < 0) {
                close(fd);
        return pos;
    }
        close(fd);
    return 0;
}
#endif  // RECOVERY_WRITE_MISC_PART

static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason)
{
    sync();
@@ -94,6 +180,9 @@ static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason)
#ifdef RECOVERY_PRE_COMMAND
	if (!strncmp(chars,"recovery",8))
		system( RECOVERY_PRE_COMMAND );
#endif
#if RECOVERY_WRITE_MISC_PART
	set_message((char*)chars);
#endif
        __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
                 LINUX_REBOOT_CMD_RESTART2, (char*) chars);