summaryrefslogtreecommitdiffstats
path: root/recovery
diff options
context:
space:
mode:
authorMichael Ward <mikeward@google.com>2011-06-30 19:05:19 -0700
committerMichael Ward <mikeward@google.com>2011-07-06 16:27:14 -0700
commite03df7326702365d88caf5cc4de72259e7f22f0f (patch)
tree77f6740d8fb1275c1949eb5b0f809ef59e145d95 /recovery
parent8bd4bb233333fcafe76ed3c19b73440128b9832f (diff)
downloaddevice_samsung_tuna-e03df7326702365d88caf5cc4de72259e7f22f0f.zip
device_samsung_tuna-e03df7326702365d88caf5cc4de72259e7f22f0f.tar.gz
device_samsung_tuna-e03df7326702365d88caf5cc4de72259e7f22f0f.tar.bz2
Support bootloader and radio OTAs for Prime.
For bootloader figure out the correct xloader location in bootloader.img and write to /xloader. The sbl is always in the same place, and can be written to /sbl. For radio the radio.img just needs to be written to /radio. Change-Id: I7b3b82b5c093331287ada24ba8ebce31a79f74bf
Diffstat (limited to 'recovery')
-rw-r--r--recovery/Android.mk13
-rw-r--r--recovery/bootloader.c157
-rw-r--r--recovery/bootloader.h25
-rw-r--r--recovery/recovery_updater.c62
4 files changed, 257 insertions, 0 deletions
diff --git a/recovery/Android.mk b/recovery/Android.mk
index 375424c..585db84 100644
--- a/recovery/Android.mk
+++ b/recovery/Android.mk
@@ -12,4 +12,17 @@ LOCAL_MODULE := librecovery_ui_tuna
include $(BUILD_STATIC_LIBRARY)
+include $(CLEAR_VARS)
+
+# Edify extension functions for doing bootloader updates on Tuna devices.
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES += bootable/recovery
+LOCAL_SRC_FILES := recovery_updater.c bootloader.c
+
+# should match TARGET_RECOVERY_UPDATER_LIBS set in BoardConfig.mk
+LOCAL_MODULE := librecovery_updater_tuna
+
+include $(BUILD_STATIC_LIBRARY)
+
endif
diff --git a/recovery/bootloader.c b/recovery/bootloader.c
new file mode 100644
index 0000000..e178b7b
--- /dev/null
+++ b/recovery/bootloader.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2011 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 <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "bootloader.h"
+
+#define PARTITION_TABLE_SIZE 4096 // 4KB
+
+#define BOOT_PART_LEN 0x20000 // 128KB
+
+#define SMALL_BUFFER_SIZE 0x20
+
+static const char* FAMILY_LOCATION = "/sys/board_properties/soc/family";
+static const char* TYPE_LOCATION = "/sys/board_properties/soc/type";
+
+unsigned int read_whole_file(const char* fname, char* buffer,
+ int buffer_size) {
+ memset(buffer, 0, buffer_size);
+
+ FILE* f = fopen(fname, "rb");
+ if (f == NULL) {
+ fprintf(stderr, "Cannot open %s!\n", fname);
+ return 0;
+ }
+
+ int read_byte_count = fread(buffer, 1, buffer_size, f);
+ fclose(f);
+ if (read_byte_count >= buffer_size) {
+ fprintf(stderr, "The data in %s is too large for the buffer", fname);
+ return 0;
+ }
+
+ return 1;
+}
+
+// Four different device/chip type xloaders are supported by a bootloader.img:
+// 4460 EMU, 4460 HS, 4430 EMU, 4430 HS.
+// The layout of the bootloader.img is:
+//
+// Partition table (4KB)
+// 4460 EMU xloader (128KB)
+// 4460 HS xloader (128KB)
+// 4430 EMU xloader (128KB)
+// 4430 HS xloader(128KB)
+// sbl (the rest)
+unsigned int get_xloader_offset() {
+ unsigned int offset = 0;
+ char* file_data = malloc(SMALL_BUFFER_SIZE);
+ if (file_data == NULL) {
+ return -1;
+ }
+
+ if (!read_whole_file(FAMILY_LOCATION, file_data, SMALL_BUFFER_SIZE)) {
+ fprintf(stderr, "Cannot read the family\n");
+ free(file_data);
+ return -1;
+ }
+
+ if (strncmp(file_data, "OMAP4430", 8) == 0) {
+ offset += (BOOT_PART_LEN * 2);
+ } else if (strncmp(file_data, "OMAP4460", 8) != 0) {
+ fprintf(stderr, "Unknown family: %s\n", file_data);
+ free(file_data);
+ return -1;
+ }
+
+ if (!read_whole_file(TYPE_LOCATION, file_data, SMALL_BUFFER_SIZE)) {
+ fprintf(stderr, "Cannot read the type\n");
+ free(file_data);
+ return -1;
+ }
+
+ if (strncmp(file_data, "HS", 2) == 0) {
+ offset += BOOT_PART_LEN;
+ } else if (strncmp(file_data, "EMU", 3) != 0) {
+ fprintf(stderr, "Unknown type: %s\n", file_data);
+ free(file_data);
+ return -1;
+ }
+
+ return offset;
+}
+
+int update_bootloader(const char* image_data,
+ size_t image_size,
+ const char* xloader_loc,
+ const char* sbl_loc) {
+ unsigned int xloader_offset=0;
+ unsigned int sbl_offset=0;
+
+ int type_family_offset = get_xloader_offset();
+ if (type_family_offset < 0) {
+ return -1;
+ }
+
+ // The offsets into the relevant parts of the bootloader image
+ xloader_offset = PARTITION_TABLE_SIZE + type_family_offset;
+ sbl_offset = PARTITION_TABLE_SIZE + (BOOT_PART_LEN * 4);
+
+ if (image_size < sbl_offset) {
+ fprintf(stderr, "image size %d is too small\n", image_size);
+ return -1;
+ }
+
+ int written = 0;
+ int close_status = 0;
+
+ FILE* xloader = fopen(xloader_loc, "r+b");
+ if (xloader == NULL) {
+ fprintf(stderr, "Could not open %s\n", xloader_loc);
+ return -1;
+ }
+
+ // index into the correct xloader offset
+ written = fwrite(image_data+xloader_offset, 1, BOOT_PART_LEN, xloader);
+ close_status = fclose(xloader);
+ if (written != BOOT_PART_LEN || close_status != 0) {
+ fprintf(stderr, "Failed writing to /xloader\n");
+ return -1;
+ }
+
+ unsigned int sbl_size = image_size - sbl_offset;
+ FILE* sbl = fopen(sbl_loc, "r+b");
+ if (sbl == NULL) {
+ fprintf(stderr, "Could not open %s\n", sbl_loc);
+ return -1;
+ }
+
+ written = fwrite(image_data+sbl_offset, 1, sbl_size, sbl);
+ close_status = fclose(sbl);
+ if (written != sbl_size || close_status != 0) {
+ fprintf(stderr, "Failed writing to /sbl\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/recovery/bootloader.h b/recovery/bootloader.h
new file mode 100644
index 0000000..f7f7f26
--- /dev/null
+++ b/recovery/bootloader.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 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 __BOOTLOADER_H__
+#define __BOOTLOADER_H__
+
+int update_bootloader(const char* image_data,
+ size_t image_size,
+ const char* xloader_loc,
+ const char* sbl_loc);
+
+#endif
diff --git a/recovery/recovery_updater.c b/recovery/recovery_updater.c
new file mode 100644
index 0000000..02963f5
--- /dev/null
+++ b/recovery/recovery_updater.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 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 <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "edify/expr.h"
+#include "bootloader.h"
+
+Value* WriteBootloaderFn(const char* name, State* state, int argc, Expr* argv[])
+{
+ int result = -1;
+ Value* img;
+ Value* xloader_loc;
+ Value* sbl_loc;
+
+ if (argc != 3) {
+ return ErrorAbort(state, "%s() expects 3 args, got %d", name, argc);
+ }
+
+ if (ReadValueArgs(state, argv, 3, &img, &xloader_loc, &sbl_loc) < 0) {
+ return NULL;
+ }
+
+ if(img->type != VAL_BLOB ||
+ xloader_loc->type != VAL_STRING ||
+ sbl_loc->type != VAL_STRING) {
+ FreeValue(img);
+ FreeValue(xloader_loc);
+ FreeValue(sbl_loc);
+ return ErrorAbort(state, "%s(): argument types are incorrect", name);
+ }
+
+ result = update_bootloader(img->data, img->size,
+ xloader_loc->data, sbl_loc->data);
+ FreeValue(img);
+ FreeValue(xloader_loc);
+ FreeValue(sbl_loc);
+ return StringValue(strdup(result == 0 ? "t" : ""));
+}
+
+void Register_librecovery_updater_tuna() {
+ fprintf(stderr, "installing samsung updater extensions\n");
+
+ RegisterFunction("samsung.write_bootloader", WriteBootloaderFn);
+}