Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c84b9fe authored by David Anderson's avatar David Anderson
Browse files

fastboot: add a wipe-super command.

Usage: fastboot wipe-super [super_empty.img]

This command will read the given super_empty.img (using the default one
in ANDROID_PRODUCT_OUT if not specified), and flash by generating a
temporary super.img with no partition data. This command will even work
on retrofit devices.

This command is intended to be used either during device bringup or with
scripts that will manually flash individual dynamic partitions, in place
of using "fastboot flashall".

Bug: 136282057
Test: fastboot wipe-super on retrofit and non-retrofit device
Change-Id: Icab368a63ff36fcce9ac9304eb3966dd38bd78c4
parent 99087dec
Loading
Loading
Loading
Loading
+80 −0
Original line number Original line Diff line number Diff line
@@ -389,6 +389,8 @@ static int show_help() {
            " set_active SLOT            Set the active slot.\n"
            " set_active SLOT            Set the active slot.\n"
            " oem [COMMAND...]           Execute OEM-specific command.\n"
            " oem [COMMAND...]           Execute OEM-specific command.\n"
            " gsi wipe|disable           Wipe or disable a GSI installation (fastbootd only).\n"
            " gsi wipe|disable           Wipe or disable a GSI installation (fastbootd only).\n"
            " wipe-super [SUPER_EMPTY]   Wipe the super partition. This will reset it to\n"
            "                            contain an empty set of default dynamic partitions.\n"
            "\n"
            "\n"
            "boot image:\n"
            "boot image:\n"
            " boot KERNEL [RAMDISK [SECOND]]\n"
            " boot KERNEL [RAMDISK [SECOND]]\n"
@@ -1582,6 +1584,76 @@ static bool should_flash_in_userspace(const std::string& partition_name) {
    return false;
    return false;
}
}


static bool wipe_super(const android::fs_mgr::LpMetadata& metadata, const std::string& slot,
                       std::string* message) {
    auto super_device = GetMetadataSuperBlockDevice(metadata);
    auto block_size = metadata.geometry.logical_block_size;
    auto super_bdev_name = android::fs_mgr::GetBlockDevicePartitionName(*super_device);

    if (super_bdev_name != "super") {
        // retrofit devices do not allow flashing to the retrofit partitions,
        // so enable it if we can.
        fb->RawCommand("oem allow-flash-super");
    }

    // Note: do not use die() in here, since we want TemporaryDir's destructor
    // to be called.
    TemporaryDir temp_dir;

    bool ok;
    if (metadata.block_devices.size() > 1) {
        ok = WriteSplitImageFiles(temp_dir.path, metadata, block_size, {}, true);
    } else {
        auto image_path = temp_dir.path + "/"s + super_bdev_name + ".img";
        ok = WriteToImageFile(image_path, metadata, block_size, {}, true);
    }
    if (!ok) {
        *message = "Could not generate a flashable super image file";
        return false;
    }

    for (const auto& block_device : metadata.block_devices) {
        auto partition = android::fs_mgr::GetBlockDevicePartitionName(block_device);
        bool force_slot = !!(block_device.flags & LP_BLOCK_DEVICE_SLOT_SUFFIXED);

        std::string image_name;
        if (metadata.block_devices.size() > 1) {
            image_name = "super_" + partition + ".img";
        } else {
            image_name = partition + ".img";
        }

        auto image_path = temp_dir.path + "/"s + image_name;
        auto flash = [&](const std::string& partition_name) {
            do_flash(partition_name.c_str(), image_path.c_str());
        };
        do_for_partitions(partition, slot, flash, force_slot);

        unlink(image_path.c_str());
    }
    return true;
}

static void do_wipe_super(const std::string& image, const std::string& slot_override) {
    if (access(image.c_str(), R_OK) != 0) {
        die("Could not read image: %s", image.c_str());
    }
    auto metadata = android::fs_mgr::ReadFromImageFile(image);
    if (!metadata) {
        die("Could not parse image: %s", image.c_str());
    }

    auto slot = slot_override;
    if (slot.empty()) {
        slot = get_current_slot();
    }

    std::string message;
    if (!wipe_super(*metadata.get(), slot, &message)) {
        die(message);
    }
}

int FastBootTool::Main(int argc, char* argv[]) {
int FastBootTool::Main(int argc, char* argv[]) {
    bool wants_wipe = false;
    bool wants_wipe = false;
    bool wants_reboot = false;
    bool wants_reboot = false;
@@ -1958,6 +2030,14 @@ int FastBootTool::Main(int argc, char* argv[]) {
            } else {
            } else {
                syntax_error("expected 'wipe' or 'disable'");
                syntax_error("expected 'wipe' or 'disable'");
            }
            }
        } else if (command == "wipe-super") {
            std::string image;
            if (args.empty()) {
                image = find_item_given_name("super_empty.img");
            } else {
                image = next_arg(&args);
            }
            do_wipe_super(image, slot_override);
        } else {
        } else {
            syntax_error("unknown command %s", command.c_str());
            syntax_error("unknown command %s", command.c_str());
        }
        }
+4 −0
Original line number Original line Diff line number Diff line
@@ -53,6 +53,10 @@ void die(const char* fmt, ...) {
    exit(EXIT_FAILURE);
    exit(EXIT_FAILURE);
}
}


void die(const std::string& str) {
    die("%s", str.c_str());
}

void set_verbose() {
void set_verbose() {
    g_verbose = true;
    g_verbose = true;
}
}
+3 −0
Original line number Original line Diff line number Diff line
@@ -15,4 +15,7 @@ void set_verbose();
// use the same attribute for compile-time format string checking.
// use the same attribute for compile-time format string checking.
void die(const char* fmt, ...) __attribute__((__noreturn__))
void die(const char* fmt, ...) __attribute__((__noreturn__))
__attribute__((__format__(__printf__, 1, 2)));
__attribute__((__format__(__printf__, 1, 2)));

void verbose(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
void verbose(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2)));

void die(const std::string& str) __attribute__((__noreturn__));