Loading bootloader_message/bootloader_message.cpp +3 −34 Original line number Diff line number Diff line Loading @@ -45,7 +45,7 @@ void SetMiscBlockDeviceForTest(std::string_view misc_device) { g_misc_device_for_test = misc_device; } static std::string get_misc_blk_device(std::string* err) { std::string get_misc_blk_device(std::string* err) { if (g_misc_device_for_test.has_value() && !g_misc_device_for_test->empty()) { return *g_misc_device_for_test; } Loading Loading @@ -111,7 +111,7 @@ static bool read_misc_partition(void* p, size_t size, const std::string& misc_bl return true; } static bool write_misc_partition(const void* p, size_t size, const std::string& misc_blk_device, bool write_misc_partition(const void* p, size_t size, const std::string& misc_blk_device, size_t offset, std::string* err) { android::base::unique_fd fd(open(misc_blk_device.c_str(), O_WRONLY)); if (fd == -1) { Loading Loading @@ -261,37 +261,6 @@ bool write_wipe_package(const std::string& package_data, std::string* err) { WIPE_PACKAGE_OFFSET_IN_MISC, err); } static bool OffsetAndSizeInVendorSpace(size_t offset, size_t size) { auto total_size = WIPE_PACKAGE_OFFSET_IN_MISC - VENDOR_SPACE_OFFSET_IN_MISC; return size <= total_size && offset <= total_size - size; } bool ReadMiscPartitionVendorSpace(void* data, size_t size, size_t offset, std::string* err) { if (!OffsetAndSizeInVendorSpace(offset, size)) { *err = android::base::StringPrintf("Out of bound read (offset %zu size %zu)", offset, size); return false; } auto misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return read_misc_partition(data, size, misc_blk_device, VENDOR_SPACE_OFFSET_IN_MISC + offset, err); } bool WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset, std::string* err) { if (!OffsetAndSizeInVendorSpace(offset, size)) { *err = android::base::StringPrintf("Out of bound write (offset %zu size %zu)", offset, size); return false; } auto misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return write_misc_partition(data, size, misc_blk_device, VENDOR_SPACE_OFFSET_IN_MISC + offset, err); } static bool ValidateSystemSpaceRegion(size_t offset, size_t size, std::string* err) { if (size <= SYSTEM_SPACE_SIZE_IN_MISC && offset <= (SYSTEM_SPACE_SIZE_IN_MISC - size)) { return true; Loading bootloader_message/include/bootloader_message/bootloader_message.h +7 −8 Original line number Diff line number Diff line Loading @@ -212,11 +212,18 @@ struct misc_system_space_layout { #include <string> #include <vector> // Gets the block device name of /misc partition. std::string get_misc_blk_device(std::string* err); // Return the block device name for the bootloader message partition and waits // for the device for up to 10 seconds. In case of error returns the empty // string. std::string get_bootloader_message_blk_device(std::string* err); // Writes |size| bytes of data from buffer |p| to |misc_blk_device| at |offset|. If the write fails, // sets the error message in |err|. bool write_misc_partition(const void* p, size_t size, const std::string& misc_blk_device, size_t offset, std::string* err); // Read bootloader message into boot. Error message will be set in err. bool read_bootloader_message(bootloader_message* boot, std::string* err); Loading Loading @@ -261,14 +268,6 @@ bool read_wipe_package(std::string* package_data, size_t size, std::string* err) // Write the wipe package into BCB (to offset WIPE_PACKAGE_OFFSET_IN_MISC). bool write_wipe_package(const std::string& package_data, std::string* err); // Reads data from the vendor space in /misc partition, with the given offset and size. Note that // offset is in relative to the start of vendor space. bool ReadMiscPartitionVendorSpace(void* data, size_t size, size_t offset, std::string* err); // Writes the given data to the vendor space in /misc partition, at the given offset. Note that // offset is in relative to the start of the vendor space. bool WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset, std::string* err); // Read or write the Virtual A/B message from system space in /misc. bool ReadMiscVirtualAbMessage(misc_virtual_ab_message* message, std::string* err); bool WriteMiscVirtualAbMessage(const misc_virtual_ab_message& message, std::string* err); Loading misc_writer/Android.bp +75 −5 Original line number Diff line number Diff line Loading @@ -14,14 +14,30 @@ // limitations under the License. // cc_binary { name: "misc_writer", cc_defaults { name: "misc_writer_defaults", vendor: true, cpp_std: "experimental", srcs: [ "misc_writer.cpp", cflags: [ "-Wall", "-Werror", ], shared_libs: [ "libbase", ], static_libs: [ "libbootloader_message_vendor", "libfstab", ], } // TODO(xunchang) Remove duplicates after we convert the device specific librecovery_ui to recovery // module. Then libmisc_writer can build as a vendor module available in recovery. cc_library_static { name: "libmisc_writer", cpp_std: "experimental", cflags: [ Loading @@ -34,7 +50,61 @@ cc_binary { ], static_libs: [ "libbootloader_message_vendor", "libbootloader_message", "libfstab", ], srcs: [ "misc_writer.cpp", ], export_include_dirs: [ "include", ], } cc_library_static { name: "libmisc_writer_vendor", defaults: [ "misc_writer_defaults", ], srcs: [ "misc_writer.cpp", ], export_include_dirs: [ "include", ], } cc_binary { name: "misc_writer", defaults: [ "misc_writer_defaults", ], srcs: [ "misc_writer_main.cpp", ], static_libs: [ "libmisc_writer_vendor", ] } cc_test { name: "misc_writer_test", defaults: [ "misc_writer_defaults", ], srcs: [ "misc_writer_test.cpp", ], test_suites: ["device-tests"], static_libs: [ "libmisc_writer_vendor", ] } misc_writer/include/misc_writer/misc_writer.h 0 → 100644 +66 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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. */ #pragma once #include <stddef.h> #include <stdint.h> #include <optional> #include <string> namespace android { namespace hardware { namespace google { namespace pixel { enum class MiscWriterActions : int32_t { kSetDarkThemeFlag = 0, kClearDarkThemeFlag, kSetSotaFlag, kClearSotaFlag, kUnset = -1, }; class MiscWriter { public: static constexpr uint32_t kThemeFlagOffsetInVendorSpace = 0; static constexpr char kDarkThemeFlag[] = "theme-dark"; static constexpr uint32_t kSotaFlagOffsetInVendorSpace = 32; static constexpr char kSotaFlag[] = "enable-sota"; // Returns true of |size| bytes data starting from |offset| is fully inside the vendor space. static bool OffsetAndSizeInVendorSpace(size_t offset, size_t size); // Writes the given data to the vendor space in /misc partition, at the given offset. Note that // offset is in relative to the start of the vendor space. static bool WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset, std::string* err); explicit MiscWriter(const MiscWriterActions& action) : action_(action) {} // Performs the stored MiscWriterActions. If |override_offset| is set, writes to the input offset // in the vendor space of /misc instead of the default offset. bool PerformAction(std::optional<size_t> override_offset = std::nullopt); private: MiscWriterActions action_{ MiscWriterActions::kUnset }; }; } // namespace pixel } // namespace google } // namespace hardware } // namespace android misc_writer/misc_writer.cpp +52 −75 Original line number Diff line number Diff line Loading @@ -14,93 +14,70 @@ * limitations under the License. */ #include <errno.h> #include <getopt.h> #include <stdint.h> #include <stdlib.h> #include <unistd.h> #include "misc_writer/misc_writer.h" #include <iostream> #include <string> #include <string_view> #include <vector> #include <string.h> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/parseint.h> #include <android-base/stringprintf.h> #include <bootloader_message/bootloader_message.h> using namespace std::string_literals; namespace android { namespace hardware { namespace google { namespace pixel { static std::vector<uint8_t> ParseHexString(std::string_view hex_string) { auto length = hex_string.size(); if (length % 2 != 0 || length == 0) { return {}; bool MiscWriter::OffsetAndSizeInVendorSpace(size_t offset, size_t size) { auto total_size = WIPE_PACKAGE_OFFSET_IN_MISC - VENDOR_SPACE_OFFSET_IN_MISC; return size <= total_size && offset <= total_size - size; } std::vector<uint8_t> result(length / 2); for (size_t i = 0; i < length / 2; i++) { auto sub = "0x" + std::string(hex_string.substr(i * 2, 2)); if (!android::base::ParseUint(sub, &result[i])) { return {}; bool MiscWriter::WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset, std::string* err) { if (!OffsetAndSizeInVendorSpace(offset, size)) { *err = android::base::StringPrintf("Out of bound write (offset %zu size %zu)", offset, size); return false; } auto misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return result; return write_misc_partition(data, size, misc_blk_device, VENDOR_SPACE_OFFSET_IN_MISC + offset, err); } static int Usage(std::string_view name) { std::cerr << name << " usage:\n"; std::cerr << name << " [--vendor-space-offset <offset>] --hex-string 0xABCDEF\n"; std::cerr << "Writes the given hex string to the specified offset in vendor space in /misc " "partition. Offset defaults to 0 if unspecified.\n"; return EXIT_FAILURE; } // misc_writer is a vendor tool that writes data to the vendor space in /misc. int main(int argc, char** argv) { constexpr struct option OPTIONS[] = { { "vendor-space-offset", required_argument, nullptr, 0 }, { "hex-string", required_argument, nullptr, 0 }, { nullptr, 0, nullptr, 0 }, }; // Offset defaults to 0 if unspecified. bool MiscWriter::PerformAction(std::optional<size_t> override_offset) { size_t offset = 0; std::string_view hex_string; int arg; int option_index; while ((arg = getopt_long(argc, argv, "", OPTIONS, &option_index)) != -1) { if (arg != 0) { LOG(ERROR) << "Invalid command argument"; return Usage(argv[0]); } auto option_name = OPTIONS[option_index].name; if (option_name == "vendor-space-offset"s) { if (!android::base::ParseUint(optarg, &offset)) { LOG(ERROR) << "Failed to parse the offset: " << optarg; return Usage(argv[0]); } } else if (option_name == "hex-string"s) { hex_string = optarg; } std::string content; switch (action_) { case MiscWriterActions::kSetDarkThemeFlag: case MiscWriterActions::kClearDarkThemeFlag: offset = override_offset.value_or(kThemeFlagOffsetInVendorSpace); content = (action_ == MiscWriterActions::kSetDarkThemeFlag) ? kDarkThemeFlag : std::string(strlen(kDarkThemeFlag), 0); break; case MiscWriterActions::kSetSotaFlag: case MiscWriterActions::kClearSotaFlag: offset = override_offset.value_or(kSotaFlagOffsetInVendorSpace); content = (action_ == MiscWriterActions::kSetSotaFlag) ? kSotaFlag : std::string(strlen(kSotaFlag), 0); break; case MiscWriterActions::kUnset: LOG(ERROR) << "The misc writer action must be set"; return false; } if (hex_string.starts_with("0x") || hex_string.starts_with("0X")) { hex_string = hex_string.substr(2); if (std::string err; !WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) { LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err; return false; } if (hex_string.empty()) { LOG(ERROR) << "Invalid input hex string: " << hex_string; return Usage(argv[0]); return true; } auto data = ParseHexString(hex_string); if (data.empty()) { LOG(ERROR) << "Failed to parse the input hex string: " << hex_string; return EXIT_FAILURE; } if (std::string err; !WriteMiscPartitionVendorSpace(data.data(), data.size(), offset, &err)) { LOG(ERROR) << "Failed to write to misc partition: " << err; return EXIT_FAILURE; } return EXIT_SUCCESS; } } // namespace pixel } // namespace google } // namespace hardware } // namespace android Loading
bootloader_message/bootloader_message.cpp +3 −34 Original line number Diff line number Diff line Loading @@ -45,7 +45,7 @@ void SetMiscBlockDeviceForTest(std::string_view misc_device) { g_misc_device_for_test = misc_device; } static std::string get_misc_blk_device(std::string* err) { std::string get_misc_blk_device(std::string* err) { if (g_misc_device_for_test.has_value() && !g_misc_device_for_test->empty()) { return *g_misc_device_for_test; } Loading Loading @@ -111,7 +111,7 @@ static bool read_misc_partition(void* p, size_t size, const std::string& misc_bl return true; } static bool write_misc_partition(const void* p, size_t size, const std::string& misc_blk_device, bool write_misc_partition(const void* p, size_t size, const std::string& misc_blk_device, size_t offset, std::string* err) { android::base::unique_fd fd(open(misc_blk_device.c_str(), O_WRONLY)); if (fd == -1) { Loading Loading @@ -261,37 +261,6 @@ bool write_wipe_package(const std::string& package_data, std::string* err) { WIPE_PACKAGE_OFFSET_IN_MISC, err); } static bool OffsetAndSizeInVendorSpace(size_t offset, size_t size) { auto total_size = WIPE_PACKAGE_OFFSET_IN_MISC - VENDOR_SPACE_OFFSET_IN_MISC; return size <= total_size && offset <= total_size - size; } bool ReadMiscPartitionVendorSpace(void* data, size_t size, size_t offset, std::string* err) { if (!OffsetAndSizeInVendorSpace(offset, size)) { *err = android::base::StringPrintf("Out of bound read (offset %zu size %zu)", offset, size); return false; } auto misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return read_misc_partition(data, size, misc_blk_device, VENDOR_SPACE_OFFSET_IN_MISC + offset, err); } bool WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset, std::string* err) { if (!OffsetAndSizeInVendorSpace(offset, size)) { *err = android::base::StringPrintf("Out of bound write (offset %zu size %zu)", offset, size); return false; } auto misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return write_misc_partition(data, size, misc_blk_device, VENDOR_SPACE_OFFSET_IN_MISC + offset, err); } static bool ValidateSystemSpaceRegion(size_t offset, size_t size, std::string* err) { if (size <= SYSTEM_SPACE_SIZE_IN_MISC && offset <= (SYSTEM_SPACE_SIZE_IN_MISC - size)) { return true; Loading
bootloader_message/include/bootloader_message/bootloader_message.h +7 −8 Original line number Diff line number Diff line Loading @@ -212,11 +212,18 @@ struct misc_system_space_layout { #include <string> #include <vector> // Gets the block device name of /misc partition. std::string get_misc_blk_device(std::string* err); // Return the block device name for the bootloader message partition and waits // for the device for up to 10 seconds. In case of error returns the empty // string. std::string get_bootloader_message_blk_device(std::string* err); // Writes |size| bytes of data from buffer |p| to |misc_blk_device| at |offset|. If the write fails, // sets the error message in |err|. bool write_misc_partition(const void* p, size_t size, const std::string& misc_blk_device, size_t offset, std::string* err); // Read bootloader message into boot. Error message will be set in err. bool read_bootloader_message(bootloader_message* boot, std::string* err); Loading Loading @@ -261,14 +268,6 @@ bool read_wipe_package(std::string* package_data, size_t size, std::string* err) // Write the wipe package into BCB (to offset WIPE_PACKAGE_OFFSET_IN_MISC). bool write_wipe_package(const std::string& package_data, std::string* err); // Reads data from the vendor space in /misc partition, with the given offset and size. Note that // offset is in relative to the start of vendor space. bool ReadMiscPartitionVendorSpace(void* data, size_t size, size_t offset, std::string* err); // Writes the given data to the vendor space in /misc partition, at the given offset. Note that // offset is in relative to the start of the vendor space. bool WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset, std::string* err); // Read or write the Virtual A/B message from system space in /misc. bool ReadMiscVirtualAbMessage(misc_virtual_ab_message* message, std::string* err); bool WriteMiscVirtualAbMessage(const misc_virtual_ab_message& message, std::string* err); Loading
misc_writer/Android.bp +75 −5 Original line number Diff line number Diff line Loading @@ -14,14 +14,30 @@ // limitations under the License. // cc_binary { name: "misc_writer", cc_defaults { name: "misc_writer_defaults", vendor: true, cpp_std: "experimental", srcs: [ "misc_writer.cpp", cflags: [ "-Wall", "-Werror", ], shared_libs: [ "libbase", ], static_libs: [ "libbootloader_message_vendor", "libfstab", ], } // TODO(xunchang) Remove duplicates after we convert the device specific librecovery_ui to recovery // module. Then libmisc_writer can build as a vendor module available in recovery. cc_library_static { name: "libmisc_writer", cpp_std: "experimental", cflags: [ Loading @@ -34,7 +50,61 @@ cc_binary { ], static_libs: [ "libbootloader_message_vendor", "libbootloader_message", "libfstab", ], srcs: [ "misc_writer.cpp", ], export_include_dirs: [ "include", ], } cc_library_static { name: "libmisc_writer_vendor", defaults: [ "misc_writer_defaults", ], srcs: [ "misc_writer.cpp", ], export_include_dirs: [ "include", ], } cc_binary { name: "misc_writer", defaults: [ "misc_writer_defaults", ], srcs: [ "misc_writer_main.cpp", ], static_libs: [ "libmisc_writer_vendor", ] } cc_test { name: "misc_writer_test", defaults: [ "misc_writer_defaults", ], srcs: [ "misc_writer_test.cpp", ], test_suites: ["device-tests"], static_libs: [ "libmisc_writer_vendor", ] }
misc_writer/include/misc_writer/misc_writer.h 0 → 100644 +66 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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. */ #pragma once #include <stddef.h> #include <stdint.h> #include <optional> #include <string> namespace android { namespace hardware { namespace google { namespace pixel { enum class MiscWriterActions : int32_t { kSetDarkThemeFlag = 0, kClearDarkThemeFlag, kSetSotaFlag, kClearSotaFlag, kUnset = -1, }; class MiscWriter { public: static constexpr uint32_t kThemeFlagOffsetInVendorSpace = 0; static constexpr char kDarkThemeFlag[] = "theme-dark"; static constexpr uint32_t kSotaFlagOffsetInVendorSpace = 32; static constexpr char kSotaFlag[] = "enable-sota"; // Returns true of |size| bytes data starting from |offset| is fully inside the vendor space. static bool OffsetAndSizeInVendorSpace(size_t offset, size_t size); // Writes the given data to the vendor space in /misc partition, at the given offset. Note that // offset is in relative to the start of the vendor space. static bool WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset, std::string* err); explicit MiscWriter(const MiscWriterActions& action) : action_(action) {} // Performs the stored MiscWriterActions. If |override_offset| is set, writes to the input offset // in the vendor space of /misc instead of the default offset. bool PerformAction(std::optional<size_t> override_offset = std::nullopt); private: MiscWriterActions action_{ MiscWriterActions::kUnset }; }; } // namespace pixel } // namespace google } // namespace hardware } // namespace android
misc_writer/misc_writer.cpp +52 −75 Original line number Diff line number Diff line Loading @@ -14,93 +14,70 @@ * limitations under the License. */ #include <errno.h> #include <getopt.h> #include <stdint.h> #include <stdlib.h> #include <unistd.h> #include "misc_writer/misc_writer.h" #include <iostream> #include <string> #include <string_view> #include <vector> #include <string.h> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/parseint.h> #include <android-base/stringprintf.h> #include <bootloader_message/bootloader_message.h> using namespace std::string_literals; namespace android { namespace hardware { namespace google { namespace pixel { static std::vector<uint8_t> ParseHexString(std::string_view hex_string) { auto length = hex_string.size(); if (length % 2 != 0 || length == 0) { return {}; bool MiscWriter::OffsetAndSizeInVendorSpace(size_t offset, size_t size) { auto total_size = WIPE_PACKAGE_OFFSET_IN_MISC - VENDOR_SPACE_OFFSET_IN_MISC; return size <= total_size && offset <= total_size - size; } std::vector<uint8_t> result(length / 2); for (size_t i = 0; i < length / 2; i++) { auto sub = "0x" + std::string(hex_string.substr(i * 2, 2)); if (!android::base::ParseUint(sub, &result[i])) { return {}; bool MiscWriter::WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset, std::string* err) { if (!OffsetAndSizeInVendorSpace(offset, size)) { *err = android::base::StringPrintf("Out of bound write (offset %zu size %zu)", offset, size); return false; } auto misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return result; return write_misc_partition(data, size, misc_blk_device, VENDOR_SPACE_OFFSET_IN_MISC + offset, err); } static int Usage(std::string_view name) { std::cerr << name << " usage:\n"; std::cerr << name << " [--vendor-space-offset <offset>] --hex-string 0xABCDEF\n"; std::cerr << "Writes the given hex string to the specified offset in vendor space in /misc " "partition. Offset defaults to 0 if unspecified.\n"; return EXIT_FAILURE; } // misc_writer is a vendor tool that writes data to the vendor space in /misc. int main(int argc, char** argv) { constexpr struct option OPTIONS[] = { { "vendor-space-offset", required_argument, nullptr, 0 }, { "hex-string", required_argument, nullptr, 0 }, { nullptr, 0, nullptr, 0 }, }; // Offset defaults to 0 if unspecified. bool MiscWriter::PerformAction(std::optional<size_t> override_offset) { size_t offset = 0; std::string_view hex_string; int arg; int option_index; while ((arg = getopt_long(argc, argv, "", OPTIONS, &option_index)) != -1) { if (arg != 0) { LOG(ERROR) << "Invalid command argument"; return Usage(argv[0]); } auto option_name = OPTIONS[option_index].name; if (option_name == "vendor-space-offset"s) { if (!android::base::ParseUint(optarg, &offset)) { LOG(ERROR) << "Failed to parse the offset: " << optarg; return Usage(argv[0]); } } else if (option_name == "hex-string"s) { hex_string = optarg; } std::string content; switch (action_) { case MiscWriterActions::kSetDarkThemeFlag: case MiscWriterActions::kClearDarkThemeFlag: offset = override_offset.value_or(kThemeFlagOffsetInVendorSpace); content = (action_ == MiscWriterActions::kSetDarkThemeFlag) ? kDarkThemeFlag : std::string(strlen(kDarkThemeFlag), 0); break; case MiscWriterActions::kSetSotaFlag: case MiscWriterActions::kClearSotaFlag: offset = override_offset.value_or(kSotaFlagOffsetInVendorSpace); content = (action_ == MiscWriterActions::kSetSotaFlag) ? kSotaFlag : std::string(strlen(kSotaFlag), 0); break; case MiscWriterActions::kUnset: LOG(ERROR) << "The misc writer action must be set"; return false; } if (hex_string.starts_with("0x") || hex_string.starts_with("0X")) { hex_string = hex_string.substr(2); if (std::string err; !WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) { LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err; return false; } if (hex_string.empty()) { LOG(ERROR) << "Invalid input hex string: " << hex_string; return Usage(argv[0]); return true; } auto data = ParseHexString(hex_string); if (data.empty()) { LOG(ERROR) << "Failed to parse the input hex string: " << hex_string; return EXIT_FAILURE; } if (std::string err; !WriteMiscPartitionVendorSpace(data.data(), data.size(), offset, &err)) { LOG(ERROR) << "Failed to write to misc partition: " << err; return EXIT_FAILURE; } return EXIT_SUCCESS; } } // namespace pixel } // namespace google } // namespace hardware } // namespace android