diff options
-rw-r--r-- | Android.mk | 2 | ||||
-rw-r--r-- | legacy_properties.h | 104 | ||||
-rw-r--r-- | legacy_property_service.c | 211 | ||||
-rw-r--r-- | legacy_property_service.h | 25 | ||||
-rw-r--r-- | twinstall.cpp | 32 |
5 files changed, 372 insertions, 2 deletions
diff --git a/Android.mk b/Android.mk index 013e4e1b5..46098cccf 100644 --- a/Android.mk +++ b/Android.mk @@ -322,7 +322,7 @@ ifeq ($(TARGET_BOARD_PLATFORM),rk30xx) LOCAL_CFLAGS += -DRK3066 endif LOCAL_C_INCLUDES := bootable/recovery/libmincrypt/includes -LOCAL_SRC_FILES = adb_install.cpp bootloader.cpp verifier.cpp mtdutils/mtdutils.c +LOCAL_SRC_FILES = adb_install.cpp bootloader.cpp verifier.cpp mtdutils/mtdutils.c legacy_property_service.c LOCAL_SHARED_LIBRARIES += libc liblog libcutils libmtdutils LOCAL_STATIC_LIBRARIES += libmincrypttwrp diff --git a/legacy_properties.h b/legacy_properties.h new file mode 100644 index 000000000..9eb6bc751 --- /dev/null +++ b/legacy_properties.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _INCLUDE_LEGACY_PROPERTIES_H +#define _INCLUDE_LEGACY_PROPERTIES_H + +#include <sys/system_properties.h> + +typedef struct prop_area prop_area; +typedef struct prop_msg prop_msg; + +#define PROP_AREA_MAGIC 0x504f5250 +#define PROP_AREA_VERSION 0x45434f76 + +#define PROP_SERVICE_NAME "property_service" + +/* #define PROP_MAX_ENTRIES 247 */ +/* 247 -> 32620 bytes (<32768) */ + +#define TOC_NAME_LEN(toc) ((toc) >> 24) +#define TOC_TO_INFO(area, toc) ((prop_info*) (((char*) area) + ((toc) & 0xFFFFFF))) + +struct prop_area { + unsigned volatile count; + unsigned volatile serial; + unsigned magic; + unsigned version; + unsigned reserved[4]; + unsigned toc[1]; +}; + +#define SERIAL_VALUE_LEN(serial) ((serial) >> 24) +#define SERIAL_DIRTY(serial) ((serial) & 1) + +struct prop_info { + char name[PROP_NAME_MAX]; + unsigned volatile serial; + char value[PROP_VALUE_MAX]; +}; + +struct prop_msg +{ + unsigned cmd; + char name[PROP_NAME_MAX]; + char value[PROP_VALUE_MAX]; +}; + +#define PROP_MSG_SETPROP 1 + +/* +** Rules: +** +** - there is only one writer, but many readers +** - prop_area.count will never decrease in value +** - once allocated, a prop_info's name will not change +** - once allocated, a prop_info's offset will not change +** - reading a value requires the following steps +** 1. serial = pi->serial +** 2. if SERIAL_DIRTY(serial), wait*, then goto 1 +** 3. memcpy(local, pi->value, SERIAL_VALUE_LEN(serial) + 1) +** 4. if pi->serial != serial, goto 2 +** +** - writing a value requires the following steps +** 1. pi->serial = pi->serial | 1 +** 2. memcpy(pi->value, local_value, value_len) +** 3. pi->serial = (value_len << 24) | ((pi->serial + 1) & 0xffffff) +** +** Improvements: +** - maintain the toc sorted by pi->name to allow lookup +** by binary search +** +*/ + +#define PROP_PATH_RAMDISK_DEFAULT "/default.prop" +#define PROP_PATH_SYSTEM_BUILD "/system/build.prop" +#define PROP_PATH_SYSTEM_DEFAULT "/system/default.prop" +#define PROP_PATH_LOCAL_OVERRIDE "/data/local.prop" + +#endif diff --git a/legacy_property_service.c b/legacy_property_service.c new file mode 100644 index 000000000..0dc95ad48 --- /dev/null +++ b/legacy_property_service.c @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2007 The Android Open Source 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. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <stdarg.h> +#include <dirent.h> +#include <limits.h> +#include <errno.h> + +#include <cutils/properties.h> + +#include "legacy_properties.h" + +#include <sys/mman.h> +#include <sys/atomics.h> +#include "legacy_property_service.h" + + +static int persistent_properties_loaded = 0; +static int property_area_inited = 0; + +static int property_set_fd = -1; + + +typedef struct { + void *data; + size_t size; + int fd; +} workspace; + +static int init_workspace(workspace *w, size_t size) +{ + void *data; + int fd; + + /* dev is a tmpfs that we can use to carve a shared workspace + * out of, so let's do that... + */ + fd = open("/dev/__legacy_properties__", O_RDWR | O_CREAT, 0600); + if (fd < 0) + return -1; + + if (ftruncate(fd, size) < 0) + goto out; + + data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if(data == MAP_FAILED) + goto out; + + close(fd); + + fd = open("/dev/__legacy_properties__", O_RDONLY); + if (fd < 0) + return -1; + + unlink("/dev/__legacy_properties__"); + + w->data = data; + w->size = size; + w->fd = fd; + return 0; + +out: + close(fd); + return -1; +} + +/* (8 header words + 247 toc words) = 1020 bytes */ +/* 1024 bytes header and toc + 247 prop_infos @ 128 bytes = 32640 bytes */ + +#define PA_COUNT_MAX 247 +#define PA_INFO_START 1024 +#define PA_SIZE 32768 + +static workspace pa_workspace; +static prop_info *pa_info_array; + +prop_area *__legacy_property_area__; + +static int init_property_area(void) +{ + prop_area *pa; + + if(pa_info_array) + return -1; + + if(init_workspace(&pa_workspace, PA_SIZE)) + return -1; + + fcntl(pa_workspace.fd, F_SETFD, FD_CLOEXEC); + + pa_info_array = (void*) (((char*) pa_workspace.data) + PA_INFO_START); + + pa = pa_workspace.data; + memset(pa, 0, PA_SIZE); + pa->magic = PROP_AREA_MAGIC; + pa->version = PROP_AREA_VERSION; + + /* plug into the lib property services */ + __legacy_property_area__ = pa; + property_area_inited = 1; + return 0; +} + +static void update_prop_info(prop_info *pi, const char *value, unsigned len) +{ + pi->serial = pi->serial | 1; + memcpy(pi->value, value, len + 1); + pi->serial = (len << 24) | ((pi->serial + 1) & 0xffffff); + __futex_wake(&pi->serial, INT32_MAX); +} + +static const prop_info *__legacy_property_find(const char *name) +{ + prop_area *pa = __legacy_property_area__; + unsigned count = pa->count; + unsigned *toc = pa->toc; + unsigned len = strlen(name); + prop_info *pi; + + while(count--) { + unsigned entry = *toc++; + if(TOC_NAME_LEN(entry) != len) continue; + + pi = TOC_TO_INFO(pa, entry); + if(memcmp(name, pi->name, len)) continue; + + return pi; + } + + return 0; +} + +static int legacy_property_set(const char *name, const char *value) +{ + prop_area *pa; + prop_info *pi; + + int namelen = strlen(name); + int valuelen = strlen(value); + + if(namelen >= PROP_NAME_MAX) return -1; + if(valuelen >= PROP_VALUE_MAX) return -1; + if(namelen < 1) return -1; + + pi = (prop_info*) __legacy_property_find(name); + + + if(pi != 0) { + /* ro.* properties may NEVER be modified once set */ + if(!strncmp(name, "ro.", 3)) return -1; + + pa = __legacy_property_area__; + update_prop_info(pi, value, valuelen); + pa->serial++; + __futex_wake(&pa->serial, INT32_MAX); + } else { + pa = __legacy_property_area__; + if(pa->count == PA_COUNT_MAX) return -1; + + pi = pa_info_array + pa->count; + pi->serial = (valuelen << 24); + memcpy(pi->name, name, namelen + 1); + memcpy(pi->value, value, valuelen + 1); + + pa->toc[pa->count] = + (namelen << 24) | (((unsigned) pi) - ((unsigned) pa)); + + pa->count++; + pa->serial++; + __futex_wake(&pa->serial, INT32_MAX); + } + + return 0; +} + +void legacy_get_property_workspace(int *fd, int *sz) +{ + *fd = pa_workspace.fd; + *sz = pa_workspace.size; +} + +static void copy_property_to_legacy(const char *key, const char *value, void *cookie) +{ + legacy_property_set(key, value); +} + +void legacy_properties_init() +{ + init_property_area(); + property_list(copy_property_to_legacy, 0); +} + diff --git a/legacy_property_service.h b/legacy_property_service.h new file mode 100644 index 000000000..172055fa2 --- /dev/null +++ b/legacy_property_service.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2007 The Android Open Source 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 _LEGACY_PROPERTY_H +#define _LEGACY_PROPERTY_H + +#include <stdbool.h> + +void legacy_get_property_workspace(int *fd, int *sz); +void legacy_properties_init(); + +#endif /* _LEGACY_PROPERTY_H */ diff --git a/twinstall.cpp b/twinstall.cpp index af12ce36f..b3b9b774b 100644 --- a/twinstall.cpp +++ b/twinstall.cpp @@ -48,6 +48,34 @@ #include "twrp-functions.hpp" extern "C" { #include "gui/gui.h" + #include "legacy_property_service.h" +} + +static const char* properties_path = "/dev/__properties__"; +static const char* properties_path_renamed = "/dev/__properties_kk__"; + +static void switch_to_legacy_properties() +{ + char tmp[32]; + int propfd, propsz; + legacy_properties_init(); + legacy_get_property_workspace(&propfd, &propsz); + sprintf(tmp, "%d,%d", dup(propfd), propsz); + setenv("ANDROID_PROPERTY_WORKSPACE", tmp, 1); + + if (TWFunc::Path_Exists(properties_path)) { + // hide real properties so that the updater uses the envvar to find the legacy format properties + if (rename(properties_path, properties_path_renamed) != 0) + LOGERR("Renaming properties failed: %s (assertions in old installers may fail)\n", strerror(errno)); + } +} + +static void switch_to_new_properties() +{ + if (TWFunc::Path_Exists(properties_path_renamed)) { + if (rename(properties_path_renamed, properties_path) != 0) + LOGERR("Restoring properties failed: %s\n", strerror(errno)); + } } static int Run_Update_Binary(const char *path, ZipArchive *Zip, int* wipe_cache) { @@ -127,8 +155,9 @@ static int Run_Update_Binary(const char *path, ZipArchive *Zip, int* wipe_cache) pid_t pid = fork(); if (pid == 0) { + switch_to_legacy_properties(); close(pipe_fd[0]); - execv(Temp_Binary.c_str(), (char* const*)args); + execve(Temp_Binary.c_str(), (char* const*)args, environ); printf("E:Can't execute '%s'\n", Temp_Binary.c_str()); _exit(-1); } @@ -175,6 +204,7 @@ static int Run_Update_Binary(const char *path, ZipArchive *Zip, int* wipe_cache) fclose(child_data); waitpid(pid, &status, 0); + switch_to_new_properties(); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { LOGERR("Error executing updater binary in zip '%s'\n", path); return INSTALL_ERROR; |