From a58a6dbe3d06aace0d1419838e162aa5267a4fc0 Mon Sep 17 00:00:00 2001 From: Yabin Cui Date: Wed, 6 Apr 2016 15:52:18 -0700 Subject: [PATCH] uncrypt: split libbootloader_message_writer for reuse. init and vold also need to write bootloader message, so split this function from uncrypt into a separate library. Bug: 27176738 Change-Id: If9b0887b4f6ffab6162d9cb47a6ceb7eedd60b4d --- uncrypt/Android.mk | 12 ++- uncrypt/bootloader_message_writer.cpp | 107 ++++++++++++++++++++ uncrypt/include/bootloader_message_writer.h | 35 +++++++ uncrypt/uncrypt.cpp | 50 ++------- 4 files changed, 160 insertions(+), 44 deletions(-) create mode 100644 uncrypt/bootloader_message_writer.cpp create mode 100644 uncrypt/include/bootloader_message_writer.h diff --git a/uncrypt/Android.mk b/uncrypt/Android.mk index 6422cb2f..09cfdfca 100644 --- a/uncrypt/Android.mk +++ b/uncrypt/Android.mk @@ -14,6 +14,15 @@ LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_CLANG := true +LOCAL_SRC_FILES := bootloader_message_writer.cpp +LOCAL_MODULE := libbootloader_message_writer +LOCAL_STATIC_LIBRARIES := libbase libfs_mgr +LOCAL_C_INCLUDES := $(LOCAL_PATH)/.. +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +include $(BUILD_STATIC_LIBRARY) + include $(CLEAR_VARS) LOCAL_CLANG := true @@ -24,7 +33,8 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/.. LOCAL_MODULE := uncrypt -LOCAL_STATIC_LIBRARIES := libbase liblog libfs_mgr libcutils +LOCAL_STATIC_LIBRARIES := libbootloader_message_writer libbase \ + liblog libfs_mgr libcutils \ LOCAL_INIT_RC := uncrypt.rc diff --git a/uncrypt/bootloader_message_writer.cpp b/uncrypt/bootloader_message_writer.cpp new file mode 100644 index 00000000..3bb106aa --- /dev/null +++ b/uncrypt/bootloader_message_writer.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2016 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 +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "bootloader.h" + +static struct fstab* read_fstab(std::string* err) { + // The fstab path is always "/fstab.${ro.hardware}". + std::string fstab_path = "/fstab."; + char value[PROP_VALUE_MAX]; + if (__system_property_get("ro.hardware", value) == 0) { + *err = "failed to get ro.hardware"; + return nullptr; + } + fstab_path += value; + struct fstab* fstab = fs_mgr_read_fstab(fstab_path.c_str()); + if (fstab == nullptr) { + *err = "failed to read " + fstab_path; + } + return fstab; +} + +static std::string get_misc_blk_device(std::string* err) { + struct fstab* fstab = read_fstab(err); + if (fstab == nullptr) { + return ""; + } + fstab_rec* record = fs_mgr_get_entry_for_mount_point(fstab, "/misc"); + if (record == nullptr) { + *err = "failed to find /misc partition"; + return ""; + } + return record->blk_device; +} + +static bool write_bootloader_message(const bootloader_message& boot, std::string* err) { + std::string misc_blk_device = get_misc_blk_device(err); + if (misc_blk_device.empty()) { + return false; + } + android::base::unique_fd fd(open(misc_blk_device.c_str(), O_WRONLY | O_SYNC)); + if (fd.get() == -1) { + *err = android::base::StringPrintf("failed to open %s: %s", misc_blk_device.c_str(), + strerror(errno)); + return false; + } + if (!android::base::WriteFully(fd.get(), &boot, sizeof(boot))) { + *err = android::base::StringPrintf("failed to write %s: %s", misc_blk_device.c_str(), + strerror(errno)); + return false; + } + // TODO: O_SYNC and fsync duplicates each other? + if (fsync(fd.get()) == -1) { + *err = android::base::StringPrintf("failed to fsync %s: %s", misc_blk_device.c_str(), + strerror(errno)); + return false; + } + return true; +} + +bool clear_bootloader_message(std::string* err) { + bootloader_message boot = {}; + return write_bootloader_message(boot, err); +} + +bool write_bootloader_message(const std::vector& options, std::string* err) { + bootloader_message boot = {}; + strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); + strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); + for (const auto& s : options) { + strlcat(boot.recovery, s.c_str(), sizeof(boot.recovery)); + if (s.back() != '\n') { + strlcat(boot.recovery, "\n", sizeof(boot.recovery)); + } + } + return write_bootloader_message(boot, err); +} + +extern "C" bool write_bootloader_message(const char* options) { + std::string err; + return write_bootloader_message({options}, &err); +} diff --git a/uncrypt/include/bootloader_message_writer.h b/uncrypt/include/bootloader_message_writer.h new file mode 100644 index 00000000..e0ca3f44 --- /dev/null +++ b/uncrypt/include/bootloader_message_writer.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 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_MESSAGE_WRITER_H +#define BOOTLOADER_MESSAGE_WRITER_H + +#ifdef __cplusplus +#include +#include + +bool clear_bootloader_message(std::string* err); + +bool write_bootloader_message(const std::vector& options, std::string* err); + +#else +#include + +// C Interface. +bool write_bootloader_message(const char* options); +#endif + +#endif // BOOTLOADER_MESSAGE_WRITER_H diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp index 2ef09357..d7105a01 100644 --- a/uncrypt/uncrypt.cpp +++ b/uncrypt/uncrypt.cpp @@ -109,6 +109,7 @@ #include #include #include +#include #include #include #include @@ -117,7 +118,6 @@ #define LOG_TAG "uncrypt" #include -#include "bootloader.h" #include "unique_fd.h" #define WINDOW_SIZE 5 @@ -414,40 +414,6 @@ static int produce_block_map(const char* path, const char* map_file, const char* return 0; } -static std::string get_misc_blk_device() { - if (fstab == nullptr) { - return ""; - } - struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, "/misc"); - if (rec != nullptr) { - return rec->blk_device; - } - return ""; -} - -static int write_bootloader_message(const bootloader_message* in) { - std::string misc_blk_device = get_misc_blk_device(); - if (misc_blk_device.empty()) { - ALOGE("failed to find /misc partition."); - return -1; - } - unique_fd fd(open(misc_blk_device.c_str(), O_WRONLY | O_SYNC)); - if (!fd) { - ALOGE("failed to open %s: %s", misc_blk_device.c_str(), strerror(errno)); - return -1; - } - if (!android::base::WriteFully(fd.get(), in, sizeof(*in))) { - ALOGE("failed to write %s: %s", misc_blk_device.c_str(), strerror(errno)); - return -1; - } - // TODO: O_SYNC and fsync() duplicates each other? - if (fsync(fd.get()) == -1) { - ALOGE("failed to fsync %s: %s", misc_blk_device.c_str(), strerror(errno)); - return -1; - } - return 0; -} - static int uncrypt(const char* input_path, const char* map_file, const int socket) { ALOGI("update package is \"%s\"", input_path); @@ -510,8 +476,9 @@ static bool uncrypt_wrapper(const char* input_path, const char* map_file, const } static bool clear_bcb(const int socket) { - bootloader_message boot = {}; - if (write_bootloader_message(&boot) != 0) { + std::string err; + if (!clear_bootloader_message(&err)) { + ALOGE("failed to clear bootloader message: %s", err.c_str()); write_status_to_socket(-1, socket); return false; } @@ -538,12 +505,9 @@ static bool setup_bcb(const int socket) { ALOGI(" received command: [%s] (%zu)", content.c_str(), content.size()); // c8. setup the bcb command - bootloader_message boot = {}; - strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); - strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery)); - strlcat(boot.recovery, content.c_str(), sizeof(boot.recovery)); - if (write_bootloader_message(&boot) != 0) { - ALOGE("failed to set bootloader message"); + std::string err; + if (!write_bootloader_message({content}, &err)) { + ALOGE("failed to set bootloader message: %s", err.c_str()); write_status_to_socket(-1, socket); return false; }