Loading fastboot/Android.mk +6 −2 Original line number Original line Diff line number Diff line Loading @@ -83,6 +83,7 @@ LOCAL_MODULE_HOST_OS := darwin linux windows LOCAL_CFLAGS := $(fastboot_cflags) LOCAL_CFLAGS := $(fastboot_cflags) LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin) LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin) LOCAL_CXX_STL := $(fastboot_stl) LOCAL_CXX_STL := $(fastboot_stl) LOCAL_HEADER_LIBRARIES := bootimg_headers LOCAL_LDLIBS_darwin := $(fastboot_ldflags_darwin) LOCAL_LDLIBS_darwin := $(fastboot_ldflags_darwin) LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows) LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows) LOCAL_REQUIRED_MODULES := mke2fs make_f2fs LOCAL_REQUIRED_MODULES := mke2fs make_f2fs Loading @@ -93,8 +94,6 @@ LOCAL_SRC_FILES := main.cpp LOCAL_SHARED_LIBRARIES := $(fastboot_shared_libs) LOCAL_SHARED_LIBRARIES := $(fastboot_shared_libs) LOCAL_SHARED_LIBRARIES_windows := AdbWinApi LOCAL_SHARED_LIBRARIES_windows := AdbWinApi LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs) LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs) LOCAL_STATIC_LIBRARIES_darwin := libselinux LOCAL_STATIC_LIBRARIES_linux := libselinux include $(BUILD_HOST_EXECUTABLE) include $(BUILD_HOST_EXECUTABLE) # # Loading @@ -120,8 +119,10 @@ my_dist_files := include $(CLEAR_VARS) include $(CLEAR_VARS) LOCAL_MODULE := fastboot_test LOCAL_MODULE := fastboot_test LOCAL_MODULE_HOST_OS := darwin linux windows LOCAL_MODULE_HOST_OS := darwin linux windows LOCAL_MODULE_HOST_CROSS_ARCH := x86 # Avoid trying to build for win64. LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \ fastboot_test.cpp \ socket_mock.cpp \ socket_mock.cpp \ socket_test.cpp \ socket_test.cpp \ tcp_test.cpp \ tcp_test.cpp \ Loading @@ -130,7 +131,10 @@ LOCAL_SRC_FILES := \ LOCAL_CFLAGS := $(fastboot_cflags) LOCAL_CFLAGS := $(fastboot_cflags) LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin) LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin) LOCAL_CXX_STL := $(fastboot_stl) LOCAL_CXX_STL := $(fastboot_stl) LOCAL_HEADER_LIBRARIES := bootimg_headers LOCAL_LDLIBS_darwin := $(fastboot_ldflags_darwin) LOCAL_LDLIBS_darwin := $(fastboot_ldflags_darwin) LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows) LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows) LOCAL_SHARED_LIBRARIES := $(fastboot_shared_libs) LOCAL_SHARED_LIBRARIES_windows := AdbWinApi LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs) LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs) include $(BUILD_HOST_NATIVE_TEST) include $(BUILD_HOST_NATIVE_TEST) fastboot/fastboot.cpp +36 −94 Original line number Original line Diff line number Diff line Loading @@ -77,7 +77,6 @@ char cur_product[FB_RESPONSE_SZ + 1]; static const char* serial = nullptr; static const char* serial = nullptr; static unsigned short vendor_id = 0; static bool g_long_listing = false; static bool g_long_listing = false; // Don't resparse files in too-big chunks. // Don't resparse files in too-big chunks. // libsparse will support INT_MAX, but this results in large allocations, so // libsparse will support INT_MAX, but this results in large allocations, so Loading Loading @@ -190,11 +189,6 @@ static void* load_file(const std::string& path, int64_t* sz) { } } static int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) { static int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) { // Require a matching vendor id if the user specified one with -i. if (vendor_id != 0 && info->dev_vendor != vendor_id) { return -1; } if (info->ifc_class != 0xff || info->ifc_subclass != 0x42 || info->ifc_protocol != 0x03) { if (info->ifc_class != 0xff || info->ifc_subclass != 0x42 || info->ifc_protocol != 0x03) { return -1; return -1; } } Loading Loading @@ -381,8 +375,6 @@ static int show_help() { " -w Wipe userdata.\n" " -w Wipe userdata.\n" " -s SERIAL Specify a USB device.\n" " -s SERIAL Specify a USB device.\n" " -s tcp|udp:HOST[:PORT] Specify a network device.\n" " -s tcp|udp:HOST[:PORT] Specify a network device.\n" // TODO: remove -i? " -i VENDOR_ID Filter devices by USB vendor id.\n" " -S SIZE[K|M|G] Use sparse files above this limit (0 to disable).\n" " -S SIZE[K|M|G] Use sparse files above this limit (0 to disable).\n" " --slot SLOT Use SLOT; 'all' for both slots, 'other' for\n" " --slot SLOT Use SLOT; 'all' for both slots, 'other' for\n" " non-current slot (default: current active slot).\n" " non-current slot (default: current active slot).\n" Loading Loading @@ -881,46 +873,18 @@ static void flash_buf(const std::string& partition, struct fastboot_buffer *buf) } } } } static std::string get_current_slot(Transport* transport) static std::string get_current_slot(Transport* transport) { { std::string current_slot; std::string current_slot; if (fb_getvar(transport, "current-slot", ¤t_slot)) { if (!fb_getvar(transport, "current-slot", ¤t_slot)) return ""; if (current_slot == "_a") return "a"; // Legacy support if (current_slot == "_b") return "b"; // Legacy support return current_slot; return current_slot; } } return ""; } // Legacy support static std::vector<std::string> get_suffixes_obsolete(Transport* transport) { std::vector<std::string> suffixes; std::string suffix_list; if (!fb_getvar(transport, "slot-suffixes", &suffix_list)) { return suffixes; } suffixes = android::base::Split(suffix_list, ","); // Unfortunately some devices will return an error message in the // guise of a valid value. If we only see only one suffix, it's probably // not real. if (suffixes.size() == 1) { suffixes.clear(); } return suffixes; } // Legacy support static bool supports_AB_obsolete(Transport* transport) { return !get_suffixes_obsolete(transport).empty(); } static int get_slot_count(Transport* transport) { static int get_slot_count(Transport* transport) { std::string var; std::string var; int count; int count = 0; if (!fb_getvar(transport, "slot-count", &var)) { if (!fb_getvar(transport, "slot-count", &var) || !android::base::ParseInt(var, &count)) { if (supports_AB_obsolete(transport)) return 2; // Legacy support return 0; } } if (!android::base::ParseInt(var, &count)) return 0; return count; return count; } } Loading Loading @@ -950,8 +914,6 @@ static std::string get_other_slot(Transport* transport) { static std::string verify_slot(Transport* transport, const std::string& slot_name, bool allow_all) { static std::string verify_slot(Transport* transport, const std::string& slot_name, bool allow_all) { std::string slot = slot_name; std::string slot = slot_name; if (slot == "_a") slot = "a"; // Legacy support if (slot == "_b") slot = "b"; // Legacy support if (slot == "all") { if (slot == "all") { if (allow_all) { if (allow_all) { return "all"; return "all"; Loading Loading @@ -1063,20 +1025,14 @@ static void do_update_signature(ZipArchiveHandle zip, const char* filename) { // Sets slot_override as the active slot. If slot_override is blank, // Sets slot_override as the active slot. If slot_override is blank, // set current slot as active instead. This clears slot-unbootable. // set current slot as active instead. This clears slot-unbootable. static void set_active(Transport* transport, const std::string& slot_override) { static void set_active(Transport* transport, const std::string& slot_override) { std::string separator = ""; if (!supports_AB(transport)) return; if (!supports_AB(transport)) { if (supports_AB_obsolete(transport)) { separator = "_"; // Legacy support } else { return; } } if (slot_override != "") { if (slot_override != "") { fb_set_active(separator + slot_override); fb_set_active(slot_override); } else { } else { std::string current_slot = get_current_slot(transport); std::string current_slot = get_current_slot(transport); if (current_slot != "") { if (current_slot != "") { fb_set_active(separator + current_slot); fb_set_active(current_slot); } } } } } } Loading Loading @@ -1459,7 +1415,7 @@ int FastBoot::Main(int argc, char* argv[]) { serial = getenv("ANDROID_SERIAL"); serial = getenv("ANDROID_SERIAL"); int c; int c; while ((c = getopt_long(argc, argv, "a::hi:ls:S:vw", longopts, &longindex)) != -1) { while ((c = getopt_long(argc, argv, "a::hls:S:vw", longopts, &longindex)) != -1) { if (c == 0) { if (c == 0) { std::string name{longopts[longindex].name}; std::string name{longopts[longindex].name}; if (name == "base") { if (name == "base") { Loading @@ -1475,24 +1431,9 @@ int FastBoot::Main(int argc, char* argv[]) { } else if (name == "kernel-offset") { } else if (name == "kernel-offset") { g_boot_img_hdr.kernel_addr = strtoul(optarg, 0, 16); g_boot_img_hdr.kernel_addr = strtoul(optarg, 0, 16); } else if (name == "os-patch-level") { } else if (name == "os-patch-level") { unsigned year, month, day; ParseOsPatchLevel(&g_boot_img_hdr, optarg); if (sscanf(optarg, "%u-%u-%u", &year, &month, &day) != 3) { syntax_error("OS patch level should be YYYY-MM-DD: %s", optarg); } if (year < 2000 || year >= 2128) syntax_error("year out of range: %d", year); if (month < 1 || month > 12) syntax_error("month out of range: %d", month); g_boot_img_hdr.SetOsPatchLevel(year, month); } else if (name == "os-version") { } else if (name == "os-version") { unsigned major = 0, minor = 0, patch = 0; ParseOsVersion(&g_boot_img_hdr, optarg); std::vector<std::string> versions = android::base::Split(optarg, "."); if (versions.size() < 1 || versions.size() > 3 || (versions.size() >= 1 && !android::base::ParseUint(versions[0], &major)) || (versions.size() >= 2 && !android::base::ParseUint(versions[1], &minor)) || (versions.size() == 3 && !android::base::ParseUint(versions[2], &patch)) || (major > 0x7f || minor > 0x7f || patch > 0x7f)) { syntax_error("bad OS version: %s", optarg); } g_boot_img_hdr.SetOsVersion(major, minor, patch); } else if (name == "page-size") { } else if (name == "page-size") { g_boot_img_hdr.page_size = strtoul(optarg, nullptr, 0); g_boot_img_hdr.page_size = strtoul(optarg, nullptr, 0); if (g_boot_img_hdr.page_size == 0) die("invalid page size"); if (g_boot_img_hdr.page_size == 0) die("invalid page size"); Loading Loading @@ -1529,16 +1470,6 @@ int FastBoot::Main(int argc, char* argv[]) { break; break; case 'h': case 'h': return show_help(); return show_help(); case 'i': { char *endptr = nullptr; unsigned long val = strtoul(optarg, &endptr, 0); if (!endptr || *endptr != '\0' || (val & ~0xffff)) { die("invalid vendor id '%s'", optarg); } vendor_id = (unsigned short)val; break; } case 'l': case 'l': g_long_listing = true; g_long_listing = true; break; break; Loading Loading @@ -1584,9 +1515,6 @@ int FastBoot::Main(int argc, char* argv[]) { const double start = now(); const double start = now(); if (!supports_AB(transport) && supports_AB_obsolete(transport)) { fprintf(stderr, "Warning: Device A/B support is outdated. Bootloader update required.\n"); } if (slot_override != "") slot_override = verify_slot(transport, slot_override); if (slot_override != "") slot_override = verify_slot(transport, slot_override); if (next_active != "") next_active = verify_slot(transport, next_active, false); if (next_active != "") next_active = verify_slot(transport, next_active, false); Loading Loading @@ -1730,15 +1658,6 @@ int FastBoot::Main(int argc, char* argv[]) { wants_reboot = true; wants_reboot = true; } else if (command == "set_active") { } else if (command == "set_active") { std::string slot = verify_slot(transport, next_arg(&args), false); std::string slot = verify_slot(transport, next_arg(&args), false); // Legacy support: verify_slot() removes leading underscores, we need to put them back // in for old bootloaders. Legacy bootloaders do not have the slot-count variable but // do have slot-suffixes. std::string var; if (!fb_getvar(transport, "slot-count", &var) && fb_getvar(transport, "slot-suffixes", &var)) { slot = "_" + slot; } fb_set_active(slot); fb_set_active(slot); } else if (command == "stage") { } else if (command == "stage") { std::string filename = next_arg(&args); std::string filename = next_arg(&args); Loading Loading @@ -1801,3 +1720,26 @@ int FastBoot::Main(int argc, char* argv[]) { fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start)); fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start)); return status; return status; } } void FastBoot::ParseOsPatchLevel(boot_img_hdr_v1* hdr, const char* arg) { unsigned year, month, day; if (sscanf(arg, "%u-%u-%u", &year, &month, &day) != 3) { syntax_error("OS patch level should be YYYY-MM-DD: %s", arg); } if (year < 2000 || year >= 2128) syntax_error("year out of range: %d", year); if (month < 1 || month > 12) syntax_error("month out of range: %d", month); hdr->SetOsPatchLevel(year, month); } void FastBoot::ParseOsVersion(boot_img_hdr_v1* hdr, const char* arg) { unsigned major = 0, minor = 0, patch = 0; std::vector<std::string> versions = android::base::Split(arg, "."); if (versions.size() < 1 || versions.size() > 3 || (versions.size() >= 1 && !android::base::ParseUint(versions[0], &major)) || (versions.size() >= 2 && !android::base::ParseUint(versions[1], &minor)) || (versions.size() == 3 && !android::base::ParseUint(versions[2], &patch)) || (major > 0x7f || minor > 0x7f || patch > 0x7f)) { syntax_error("bad OS version: %s", arg); } hdr->SetOsVersion(major, minor, patch); } fastboot/fastboot.h +6 −4 Original line number Original line Diff line number Diff line Loading @@ -26,14 +26,15 @@ * SUCH DAMAGE. * SUCH DAMAGE. */ */ #ifndef _FASTBOOT_H_ #pragma once #define _FASTBOOT_H_ #include <inttypes.h> #include <inttypes.h> #include <stdlib.h> #include <stdlib.h> #include <string> #include <string> #include <bootimg.h> class Transport; class Transport; struct sparse_file; struct sparse_file; Loading Loading @@ -99,6 +100,7 @@ extern char cur_product[FB_RESPONSE_SZ + 1]; class FastBoot { class FastBoot { public: public: int Main(int argc, char* argv[]); int Main(int argc, char* argv[]); }; #endif void ParseOsPatchLevel(boot_img_hdr_v1*, const char*); void ParseOsVersion(boot_img_hdr_v1*, const char*); }; fastboot/fastboot_test.cpp 0 → 100644 +61 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 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 "fastboot.h" #include <gtest/gtest.h> TEST(FastBoot, ParseOsPatchLevel) { FastBoot fb; boot_img_hdr_v1 hdr; hdr = {}; fb.ParseOsPatchLevel(&hdr, "2018-01-05"); ASSERT_EQ(2018U, 2000U + ((hdr.os_version >> 4) & 0x7f)); ASSERT_EQ(1U, ((hdr.os_version >> 0) & 0xf)); EXPECT_DEATH(fb.ParseOsPatchLevel(&hdr, "2018"), "should be YYYY-MM-DD"); EXPECT_DEATH(fb.ParseOsPatchLevel(&hdr, "2018-01"), "should be YYYY-MM-DD"); EXPECT_DEATH(fb.ParseOsPatchLevel(&hdr, "2128-01-05"), "year out of range"); EXPECT_DEATH(fb.ParseOsPatchLevel(&hdr, "2018-13-05"), "month out of range"); } TEST(FastBoot, ParseOsVersion) { FastBoot fb; boot_img_hdr_v1 hdr; hdr = {}; fb.ParseOsVersion(&hdr, "1.2.3"); ASSERT_EQ(1U, ((hdr.os_version >> 25) & 0x7f)); ASSERT_EQ(2U, ((hdr.os_version >> 18) & 0x7f)); ASSERT_EQ(3U, ((hdr.os_version >> 11) & 0x7f)); fb.ParseOsVersion(&hdr, "1.2"); ASSERT_EQ(1U, ((hdr.os_version >> 25) & 0x7f)); ASSERT_EQ(2U, ((hdr.os_version >> 18) & 0x7f)); ASSERT_EQ(0U, ((hdr.os_version >> 11) & 0x7f)); fb.ParseOsVersion(&hdr, "1"); ASSERT_EQ(1U, ((hdr.os_version >> 25) & 0x7f)); ASSERT_EQ(0U, ((hdr.os_version >> 18) & 0x7f)); ASSERT_EQ(0U, ((hdr.os_version >> 11) & 0x7f)); EXPECT_DEATH(fb.ParseOsVersion(&hdr, ""), "bad OS version"); EXPECT_DEATH(fb.ParseOsVersion(&hdr, "1.2.3.4"), "bad OS version"); EXPECT_DEATH(fb.ParseOsVersion(&hdr, "128.2.3"), "bad OS version"); EXPECT_DEATH(fb.ParseOsVersion(&hdr, "1.128.3"), "bad OS version"); EXPECT_DEATH(fb.ParseOsVersion(&hdr, "1.2.128"), "bad OS version"); } fastboot/fs.h +1 −4 Original line number Original line Diff line number Diff line #ifndef _FS_H_ #pragma once #define _FS_H_ #include <string> #include <string> #include <stdint.h> #include <stdint.h> Loading @@ -9,5 +8,3 @@ struct fs_generator; const struct fs_generator* fs_get_generator(const std::string& fs_type); const struct fs_generator* fs_get_generator(const std::string& fs_type); int fs_generator_generate(const struct fs_generator* gen, const char* fileName, long long partSize, int fs_generator_generate(const struct fs_generator* gen, const char* fileName, long long partSize, const std::string& initial_dir, unsigned eraseBlkSize = 0, unsigned logicalBlkSize = 0); const std::string& initial_dir, unsigned eraseBlkSize = 0, unsigned logicalBlkSize = 0); #endif Loading
fastboot/Android.mk +6 −2 Original line number Original line Diff line number Diff line Loading @@ -83,6 +83,7 @@ LOCAL_MODULE_HOST_OS := darwin linux windows LOCAL_CFLAGS := $(fastboot_cflags) LOCAL_CFLAGS := $(fastboot_cflags) LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin) LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin) LOCAL_CXX_STL := $(fastboot_stl) LOCAL_CXX_STL := $(fastboot_stl) LOCAL_HEADER_LIBRARIES := bootimg_headers LOCAL_LDLIBS_darwin := $(fastboot_ldflags_darwin) LOCAL_LDLIBS_darwin := $(fastboot_ldflags_darwin) LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows) LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows) LOCAL_REQUIRED_MODULES := mke2fs make_f2fs LOCAL_REQUIRED_MODULES := mke2fs make_f2fs Loading @@ -93,8 +94,6 @@ LOCAL_SRC_FILES := main.cpp LOCAL_SHARED_LIBRARIES := $(fastboot_shared_libs) LOCAL_SHARED_LIBRARIES := $(fastboot_shared_libs) LOCAL_SHARED_LIBRARIES_windows := AdbWinApi LOCAL_SHARED_LIBRARIES_windows := AdbWinApi LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs) LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs) LOCAL_STATIC_LIBRARIES_darwin := libselinux LOCAL_STATIC_LIBRARIES_linux := libselinux include $(BUILD_HOST_EXECUTABLE) include $(BUILD_HOST_EXECUTABLE) # # Loading @@ -120,8 +119,10 @@ my_dist_files := include $(CLEAR_VARS) include $(CLEAR_VARS) LOCAL_MODULE := fastboot_test LOCAL_MODULE := fastboot_test LOCAL_MODULE_HOST_OS := darwin linux windows LOCAL_MODULE_HOST_OS := darwin linux windows LOCAL_MODULE_HOST_CROSS_ARCH := x86 # Avoid trying to build for win64. LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \ fastboot_test.cpp \ socket_mock.cpp \ socket_mock.cpp \ socket_test.cpp \ socket_test.cpp \ tcp_test.cpp \ tcp_test.cpp \ Loading @@ -130,7 +131,10 @@ LOCAL_SRC_FILES := \ LOCAL_CFLAGS := $(fastboot_cflags) LOCAL_CFLAGS := $(fastboot_cflags) LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin) LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin) LOCAL_CXX_STL := $(fastboot_stl) LOCAL_CXX_STL := $(fastboot_stl) LOCAL_HEADER_LIBRARIES := bootimg_headers LOCAL_LDLIBS_darwin := $(fastboot_ldflags_darwin) LOCAL_LDLIBS_darwin := $(fastboot_ldflags_darwin) LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows) LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows) LOCAL_SHARED_LIBRARIES := $(fastboot_shared_libs) LOCAL_SHARED_LIBRARIES_windows := AdbWinApi LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs) LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs) include $(BUILD_HOST_NATIVE_TEST) include $(BUILD_HOST_NATIVE_TEST)
fastboot/fastboot.cpp +36 −94 Original line number Original line Diff line number Diff line Loading @@ -77,7 +77,6 @@ char cur_product[FB_RESPONSE_SZ + 1]; static const char* serial = nullptr; static const char* serial = nullptr; static unsigned short vendor_id = 0; static bool g_long_listing = false; static bool g_long_listing = false; // Don't resparse files in too-big chunks. // Don't resparse files in too-big chunks. // libsparse will support INT_MAX, but this results in large allocations, so // libsparse will support INT_MAX, but this results in large allocations, so Loading Loading @@ -190,11 +189,6 @@ static void* load_file(const std::string& path, int64_t* sz) { } } static int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) { static int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) { // Require a matching vendor id if the user specified one with -i. if (vendor_id != 0 && info->dev_vendor != vendor_id) { return -1; } if (info->ifc_class != 0xff || info->ifc_subclass != 0x42 || info->ifc_protocol != 0x03) { if (info->ifc_class != 0xff || info->ifc_subclass != 0x42 || info->ifc_protocol != 0x03) { return -1; return -1; } } Loading Loading @@ -381,8 +375,6 @@ static int show_help() { " -w Wipe userdata.\n" " -w Wipe userdata.\n" " -s SERIAL Specify a USB device.\n" " -s SERIAL Specify a USB device.\n" " -s tcp|udp:HOST[:PORT] Specify a network device.\n" " -s tcp|udp:HOST[:PORT] Specify a network device.\n" // TODO: remove -i? " -i VENDOR_ID Filter devices by USB vendor id.\n" " -S SIZE[K|M|G] Use sparse files above this limit (0 to disable).\n" " -S SIZE[K|M|G] Use sparse files above this limit (0 to disable).\n" " --slot SLOT Use SLOT; 'all' for both slots, 'other' for\n" " --slot SLOT Use SLOT; 'all' for both slots, 'other' for\n" " non-current slot (default: current active slot).\n" " non-current slot (default: current active slot).\n" Loading Loading @@ -881,46 +873,18 @@ static void flash_buf(const std::string& partition, struct fastboot_buffer *buf) } } } } static std::string get_current_slot(Transport* transport) static std::string get_current_slot(Transport* transport) { { std::string current_slot; std::string current_slot; if (fb_getvar(transport, "current-slot", ¤t_slot)) { if (!fb_getvar(transport, "current-slot", ¤t_slot)) return ""; if (current_slot == "_a") return "a"; // Legacy support if (current_slot == "_b") return "b"; // Legacy support return current_slot; return current_slot; } } return ""; } // Legacy support static std::vector<std::string> get_suffixes_obsolete(Transport* transport) { std::vector<std::string> suffixes; std::string suffix_list; if (!fb_getvar(transport, "slot-suffixes", &suffix_list)) { return suffixes; } suffixes = android::base::Split(suffix_list, ","); // Unfortunately some devices will return an error message in the // guise of a valid value. If we only see only one suffix, it's probably // not real. if (suffixes.size() == 1) { suffixes.clear(); } return suffixes; } // Legacy support static bool supports_AB_obsolete(Transport* transport) { return !get_suffixes_obsolete(transport).empty(); } static int get_slot_count(Transport* transport) { static int get_slot_count(Transport* transport) { std::string var; std::string var; int count; int count = 0; if (!fb_getvar(transport, "slot-count", &var)) { if (!fb_getvar(transport, "slot-count", &var) || !android::base::ParseInt(var, &count)) { if (supports_AB_obsolete(transport)) return 2; // Legacy support return 0; } } if (!android::base::ParseInt(var, &count)) return 0; return count; return count; } } Loading Loading @@ -950,8 +914,6 @@ static std::string get_other_slot(Transport* transport) { static std::string verify_slot(Transport* transport, const std::string& slot_name, bool allow_all) { static std::string verify_slot(Transport* transport, const std::string& slot_name, bool allow_all) { std::string slot = slot_name; std::string slot = slot_name; if (slot == "_a") slot = "a"; // Legacy support if (slot == "_b") slot = "b"; // Legacy support if (slot == "all") { if (slot == "all") { if (allow_all) { if (allow_all) { return "all"; return "all"; Loading Loading @@ -1063,20 +1025,14 @@ static void do_update_signature(ZipArchiveHandle zip, const char* filename) { // Sets slot_override as the active slot. If slot_override is blank, // Sets slot_override as the active slot. If slot_override is blank, // set current slot as active instead. This clears slot-unbootable. // set current slot as active instead. This clears slot-unbootable. static void set_active(Transport* transport, const std::string& slot_override) { static void set_active(Transport* transport, const std::string& slot_override) { std::string separator = ""; if (!supports_AB(transport)) return; if (!supports_AB(transport)) { if (supports_AB_obsolete(transport)) { separator = "_"; // Legacy support } else { return; } } if (slot_override != "") { if (slot_override != "") { fb_set_active(separator + slot_override); fb_set_active(slot_override); } else { } else { std::string current_slot = get_current_slot(transport); std::string current_slot = get_current_slot(transport); if (current_slot != "") { if (current_slot != "") { fb_set_active(separator + current_slot); fb_set_active(current_slot); } } } } } } Loading Loading @@ -1459,7 +1415,7 @@ int FastBoot::Main(int argc, char* argv[]) { serial = getenv("ANDROID_SERIAL"); serial = getenv("ANDROID_SERIAL"); int c; int c; while ((c = getopt_long(argc, argv, "a::hi:ls:S:vw", longopts, &longindex)) != -1) { while ((c = getopt_long(argc, argv, "a::hls:S:vw", longopts, &longindex)) != -1) { if (c == 0) { if (c == 0) { std::string name{longopts[longindex].name}; std::string name{longopts[longindex].name}; if (name == "base") { if (name == "base") { Loading @@ -1475,24 +1431,9 @@ int FastBoot::Main(int argc, char* argv[]) { } else if (name == "kernel-offset") { } else if (name == "kernel-offset") { g_boot_img_hdr.kernel_addr = strtoul(optarg, 0, 16); g_boot_img_hdr.kernel_addr = strtoul(optarg, 0, 16); } else if (name == "os-patch-level") { } else if (name == "os-patch-level") { unsigned year, month, day; ParseOsPatchLevel(&g_boot_img_hdr, optarg); if (sscanf(optarg, "%u-%u-%u", &year, &month, &day) != 3) { syntax_error("OS patch level should be YYYY-MM-DD: %s", optarg); } if (year < 2000 || year >= 2128) syntax_error("year out of range: %d", year); if (month < 1 || month > 12) syntax_error("month out of range: %d", month); g_boot_img_hdr.SetOsPatchLevel(year, month); } else if (name == "os-version") { } else if (name == "os-version") { unsigned major = 0, minor = 0, patch = 0; ParseOsVersion(&g_boot_img_hdr, optarg); std::vector<std::string> versions = android::base::Split(optarg, "."); if (versions.size() < 1 || versions.size() > 3 || (versions.size() >= 1 && !android::base::ParseUint(versions[0], &major)) || (versions.size() >= 2 && !android::base::ParseUint(versions[1], &minor)) || (versions.size() == 3 && !android::base::ParseUint(versions[2], &patch)) || (major > 0x7f || minor > 0x7f || patch > 0x7f)) { syntax_error("bad OS version: %s", optarg); } g_boot_img_hdr.SetOsVersion(major, minor, patch); } else if (name == "page-size") { } else if (name == "page-size") { g_boot_img_hdr.page_size = strtoul(optarg, nullptr, 0); g_boot_img_hdr.page_size = strtoul(optarg, nullptr, 0); if (g_boot_img_hdr.page_size == 0) die("invalid page size"); if (g_boot_img_hdr.page_size == 0) die("invalid page size"); Loading Loading @@ -1529,16 +1470,6 @@ int FastBoot::Main(int argc, char* argv[]) { break; break; case 'h': case 'h': return show_help(); return show_help(); case 'i': { char *endptr = nullptr; unsigned long val = strtoul(optarg, &endptr, 0); if (!endptr || *endptr != '\0' || (val & ~0xffff)) { die("invalid vendor id '%s'", optarg); } vendor_id = (unsigned short)val; break; } case 'l': case 'l': g_long_listing = true; g_long_listing = true; break; break; Loading Loading @@ -1584,9 +1515,6 @@ int FastBoot::Main(int argc, char* argv[]) { const double start = now(); const double start = now(); if (!supports_AB(transport) && supports_AB_obsolete(transport)) { fprintf(stderr, "Warning: Device A/B support is outdated. Bootloader update required.\n"); } if (slot_override != "") slot_override = verify_slot(transport, slot_override); if (slot_override != "") slot_override = verify_slot(transport, slot_override); if (next_active != "") next_active = verify_slot(transport, next_active, false); if (next_active != "") next_active = verify_slot(transport, next_active, false); Loading Loading @@ -1730,15 +1658,6 @@ int FastBoot::Main(int argc, char* argv[]) { wants_reboot = true; wants_reboot = true; } else if (command == "set_active") { } else if (command == "set_active") { std::string slot = verify_slot(transport, next_arg(&args), false); std::string slot = verify_slot(transport, next_arg(&args), false); // Legacy support: verify_slot() removes leading underscores, we need to put them back // in for old bootloaders. Legacy bootloaders do not have the slot-count variable but // do have slot-suffixes. std::string var; if (!fb_getvar(transport, "slot-count", &var) && fb_getvar(transport, "slot-suffixes", &var)) { slot = "_" + slot; } fb_set_active(slot); fb_set_active(slot); } else if (command == "stage") { } else if (command == "stage") { std::string filename = next_arg(&args); std::string filename = next_arg(&args); Loading Loading @@ -1801,3 +1720,26 @@ int FastBoot::Main(int argc, char* argv[]) { fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start)); fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start)); return status; return status; } } void FastBoot::ParseOsPatchLevel(boot_img_hdr_v1* hdr, const char* arg) { unsigned year, month, day; if (sscanf(arg, "%u-%u-%u", &year, &month, &day) != 3) { syntax_error("OS patch level should be YYYY-MM-DD: %s", arg); } if (year < 2000 || year >= 2128) syntax_error("year out of range: %d", year); if (month < 1 || month > 12) syntax_error("month out of range: %d", month); hdr->SetOsPatchLevel(year, month); } void FastBoot::ParseOsVersion(boot_img_hdr_v1* hdr, const char* arg) { unsigned major = 0, minor = 0, patch = 0; std::vector<std::string> versions = android::base::Split(arg, "."); if (versions.size() < 1 || versions.size() > 3 || (versions.size() >= 1 && !android::base::ParseUint(versions[0], &major)) || (versions.size() >= 2 && !android::base::ParseUint(versions[1], &minor)) || (versions.size() == 3 && !android::base::ParseUint(versions[2], &patch)) || (major > 0x7f || minor > 0x7f || patch > 0x7f)) { syntax_error("bad OS version: %s", arg); } hdr->SetOsVersion(major, minor, patch); }
fastboot/fastboot.h +6 −4 Original line number Original line Diff line number Diff line Loading @@ -26,14 +26,15 @@ * SUCH DAMAGE. * SUCH DAMAGE. */ */ #ifndef _FASTBOOT_H_ #pragma once #define _FASTBOOT_H_ #include <inttypes.h> #include <inttypes.h> #include <stdlib.h> #include <stdlib.h> #include <string> #include <string> #include <bootimg.h> class Transport; class Transport; struct sparse_file; struct sparse_file; Loading Loading @@ -99,6 +100,7 @@ extern char cur_product[FB_RESPONSE_SZ + 1]; class FastBoot { class FastBoot { public: public: int Main(int argc, char* argv[]); int Main(int argc, char* argv[]); }; #endif void ParseOsPatchLevel(boot_img_hdr_v1*, const char*); void ParseOsVersion(boot_img_hdr_v1*, const char*); };
fastboot/fastboot_test.cpp 0 → 100644 +61 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 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 "fastboot.h" #include <gtest/gtest.h> TEST(FastBoot, ParseOsPatchLevel) { FastBoot fb; boot_img_hdr_v1 hdr; hdr = {}; fb.ParseOsPatchLevel(&hdr, "2018-01-05"); ASSERT_EQ(2018U, 2000U + ((hdr.os_version >> 4) & 0x7f)); ASSERT_EQ(1U, ((hdr.os_version >> 0) & 0xf)); EXPECT_DEATH(fb.ParseOsPatchLevel(&hdr, "2018"), "should be YYYY-MM-DD"); EXPECT_DEATH(fb.ParseOsPatchLevel(&hdr, "2018-01"), "should be YYYY-MM-DD"); EXPECT_DEATH(fb.ParseOsPatchLevel(&hdr, "2128-01-05"), "year out of range"); EXPECT_DEATH(fb.ParseOsPatchLevel(&hdr, "2018-13-05"), "month out of range"); } TEST(FastBoot, ParseOsVersion) { FastBoot fb; boot_img_hdr_v1 hdr; hdr = {}; fb.ParseOsVersion(&hdr, "1.2.3"); ASSERT_EQ(1U, ((hdr.os_version >> 25) & 0x7f)); ASSERT_EQ(2U, ((hdr.os_version >> 18) & 0x7f)); ASSERT_EQ(3U, ((hdr.os_version >> 11) & 0x7f)); fb.ParseOsVersion(&hdr, "1.2"); ASSERT_EQ(1U, ((hdr.os_version >> 25) & 0x7f)); ASSERT_EQ(2U, ((hdr.os_version >> 18) & 0x7f)); ASSERT_EQ(0U, ((hdr.os_version >> 11) & 0x7f)); fb.ParseOsVersion(&hdr, "1"); ASSERT_EQ(1U, ((hdr.os_version >> 25) & 0x7f)); ASSERT_EQ(0U, ((hdr.os_version >> 18) & 0x7f)); ASSERT_EQ(0U, ((hdr.os_version >> 11) & 0x7f)); EXPECT_DEATH(fb.ParseOsVersion(&hdr, ""), "bad OS version"); EXPECT_DEATH(fb.ParseOsVersion(&hdr, "1.2.3.4"), "bad OS version"); EXPECT_DEATH(fb.ParseOsVersion(&hdr, "128.2.3"), "bad OS version"); EXPECT_DEATH(fb.ParseOsVersion(&hdr, "1.128.3"), "bad OS version"); EXPECT_DEATH(fb.ParseOsVersion(&hdr, "1.2.128"), "bad OS version"); }
fastboot/fs.h +1 −4 Original line number Original line Diff line number Diff line #ifndef _FS_H_ #pragma once #define _FS_H_ #include <string> #include <string> #include <stdint.h> #include <stdint.h> Loading @@ -9,5 +8,3 @@ struct fs_generator; const struct fs_generator* fs_get_generator(const std::string& fs_type); const struct fs_generator* fs_get_generator(const std::string& fs_type); int fs_generator_generate(const struct fs_generator* gen, const char* fileName, long long partSize, int fs_generator_generate(const struct fs_generator* gen, const char* fileName, long long partSize, const std::string& initial_dir, unsigned eraseBlkSize = 0, unsigned logicalBlkSize = 0); const std::string& initial_dir, unsigned eraseBlkSize = 0, unsigned logicalBlkSize = 0); #endif