aboutsummaryrefslogtreecommitdiff
path: root/recovery
diff options
context:
space:
mode:
authorEthan Chen <intervigil@gmail.com>2016-05-24 18:44:57 -0700
committerZhao Wei Liew <zhaoweiliew@gmail.com>2016-05-29 18:36:38 +0800
commita2119cee4941b0cd5d8300483274c679038c813b (patch)
tree281a820ce452ec61e27a460047e3bef090affa46 /recovery
parent4920076b6beefc1de0339cf14491d9225cd56e3d (diff)
msm8916: Commonize msm8939 and msm8916
Change-Id: Iddc1a5e7793fe8110cba1f2314b53e3bb164c34d
Diffstat (limited to 'recovery')
-rw-r--r--recovery/Android.mk8
-rw-r--r--recovery/recovery_updater.c183
2 files changed, 191 insertions, 0 deletions
diff --git a/recovery/Android.mk b/recovery/Android.mk
new file mode 100644
index 0000000..86fb070
--- /dev/null
+++ b/recovery/Android.mk
@@ -0,0 +1,8 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_C_INCLUDES := bootable/recovery
+LOCAL_SRC_FILES := recovery_updater.c
+LOCAL_MODULE := librecovery_updater_cm
+LOCAL_MODULE_TAGS := eng
+include $(BUILD_STATIC_LIBRARY)
diff --git a/recovery/recovery_updater.c b/recovery/recovery_updater.c
new file mode 100644
index 0000000..c0036f9
--- /dev/null
+++ b/recovery/recovery_updater.c
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ * 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 <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "edify/expr.h"
+
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+#define ALPHABET_LEN 256
+#define KB 1024
+
+#define TZ_PART_PATH "/dev/block/platform/7824900.sdhci/by-name/tz"
+#define TZ_VER_STR "QC_IMAGE_VERSION_STRING="
+#define TZ_VER_STR_LEN 24
+#define TZ_VER_BUF_LEN 255
+#define TZ_SZ 500 * KB /* MMAP 500K of TZ, TZ partition is 500K */
+
+/* Boyer-Moore string search implementation from Wikipedia */
+
+/* Return longest suffix length of suffix ending at str[p] */
+static int max_suffix_len(const char *str, size_t str_len, size_t p) {
+ uint32_t i;
+
+ for (i = 0; (str[p - i] == str[str_len - 1 - i]) && (i < p); ) {
+ i++;
+ }
+
+ return i;
+}
+
+/* Generate table of distance between last character of pat and rightmost
+ * occurrence of character c in pat
+ */
+static void bm_make_delta1(int *delta1, const char *pat, size_t pat_len) {
+ uint32_t i;
+ for (i = 0; i < ALPHABET_LEN; i++) {
+ delta1[i] = pat_len;
+ }
+ for (i = 0; i < pat_len - 1; i++) {
+ uint8_t idx = (uint8_t) pat[i];
+ delta1[idx] = pat_len - 1 - i;
+ }
+}
+
+/* Generate table of next possible full match from mismatch at pat[p] */
+static void bm_make_delta2(int *delta2, const char *pat, size_t pat_len) {
+ int p;
+ uint32_t last_prefix = pat_len - 1;
+
+ for (p = pat_len - 1; p >= 0; p--) {
+ /* Compare whether pat[p-pat_len] is suffix of pat */
+ if (strncmp(pat + p, pat, pat_len - p) == 0) {
+ last_prefix = p + 1;
+ }
+ delta2[p] = last_prefix + (pat_len - 1 - p);
+ }
+
+ for (p = 0; p < (int) pat_len - 1; p++) {
+ /* Get longest suffix of pattern ending on character pat[p] */
+ int suf_len = max_suffix_len(pat, pat_len, p);
+ if (pat[p - suf_len] != pat[pat_len - 1 - suf_len]) {
+ delta2[pat_len - 1 - suf_len] = pat_len - 1 - p + suf_len;
+ }
+ }
+}
+
+static char * bm_search(const char *str, size_t str_len, const char *pat,
+ size_t pat_len) {
+ int delta1[ALPHABET_LEN];
+ int delta2[pat_len];
+ int i;
+
+ bm_make_delta1(delta1, pat, pat_len);
+ bm_make_delta2(delta2, pat, pat_len);
+
+ if (pat_len == 0) {
+ return (char *) str;
+ }
+
+ i = pat_len - 1;
+ while (i < (int) str_len) {
+ int j = pat_len - 1;
+ while (j >= 0 && (str[i] == pat[j])) {
+ i--;
+ j--;
+ }
+ if (j < 0) {
+ return (char *) (str + i + 1);
+ }
+ i += MAX(delta1[(uint8_t) str[i]], delta2[j]);
+ }
+
+ return NULL;
+}
+
+static int get_tz_version(char *ver_str, size_t len) {
+ int ret = 0;
+ int fd;
+ char *tz_data = NULL;
+ char *offset = NULL;
+
+ fd = open(TZ_PART_PATH, O_RDONLY);
+ if (fd < 0) {
+ ret = errno;
+ goto err_ret;
+ }
+
+ tz_data = (char *) mmap(NULL, TZ_SZ, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (tz_data == (char *)-1) {
+ ret = errno;
+ goto err_fd_close;
+ }
+
+ /* Do Boyer-Moore search across TZ data */
+ offset = bm_search(tz_data, TZ_SZ, TZ_VER_STR, TZ_VER_STR_LEN);
+ if (offset != NULL) {
+ strncpy(ver_str, offset + TZ_VER_STR_LEN, len);
+ } else {
+ ret = -ENOENT;
+ }
+
+ munmap(tz_data, TZ_SZ);
+err_fd_close:
+ close(fd);
+err_ret:
+ return ret;
+}
+
+/* verify_trustzone("TZ_VERSION", "TZ_VERSION", ...) */
+Value * VerifyTrustZoneFn(const char *name, State *state, int argc, Expr *argv[]) {
+ char current_tz_version[TZ_VER_BUF_LEN];
+ char *tz_version;
+ int i, ret;
+
+ ret = get_tz_version(current_tz_version, TZ_VER_BUF_LEN);
+ if (ret) {
+ return ErrorAbort(state, "%s() failed to read current TZ version: %d",
+ name, ret);
+ }
+
+ for (i = 1; i <= argc; i++) {
+ ret = ReadArgs(state, argv, i, &tz_version);
+ if (ret < 0) {
+ return ErrorAbort(state, "%s() error parsing arguments: %d",
+ name, ret);
+ }
+
+ uiPrintf(state, "Comparing TZ version %s to %s",
+ tz_version, current_tz_version);
+ if (strncmp(tz_version, current_tz_version, strlen(tz_version)) == 0) {
+ return StringValue(strdup("1"));
+ }
+ }
+
+ return StringValue(strdup("0"));
+}
+
+void Register_librecovery_updater_cm() {
+ RegisterFunction("cm.verify_trustzone", VerifyTrustZoneFn);
+}