Add --wipe-and-use-fbe option to fastboot for FBE userdata marker.

With this option, userdata is wiped and recreated with the
"convert_fbe" file in the root, which triggers conversion to FBE.

Bug: 25898323
Change-Id: I9347b7057b6278e7e6437504896b22c82dd01d89
This commit is contained in:
Paul Crowley 2015-11-27 09:29:37 +00:00
parent 68e26811f0
commit 8f7f56e25b
3 changed files with 112 additions and 15 deletions

View File

@ -81,6 +81,8 @@ static unsigned ramdisk_offset = 0x01000000;
static unsigned second_offset = 0x00f00000;
static unsigned tags_offset = 0x00000100;
static const std::string convert_fbe_marker_filename("convert_fbe");
enum fb_buffer_type {
FB_BUFFER,
FB_BUFFER_SPARSE,
@ -322,11 +324,17 @@ static void usage() {
" provided, this will default to the value\n"
" given by --slot. If slots are not\n"
" supported, this does nothing.\n"
#if !defined(_WIN32)
" --wipe-and-use-fbe On devices which support it,\n"
" erase userdata and cache, and\n"
" enable file-based encryption\n"
#endif
" --unbuffered Do not buffer input or output.\n"
" --version Display version.\n"
" -h, --help show this message.\n"
);
}
static void* load_bootable_image(const char* kernel, const char* ramdisk,
const char* secondstage, int64_t* sz,
const char* cmdline) {
@ -446,8 +454,60 @@ static FILE* win32_tmpfile() {
#define tmpfile win32_tmpfile
static std::string make_temporary_directory() {
fprintf(stderr, "make_temporary_directory not supported under Windows, sorry!");
return "";
}
#else
static std::string make_temporary_directory() {
const char *tmpdir = getenv("TMPDIR");
if (tmpdir == nullptr) {
tmpdir = P_tmpdir;
}
std::string result = std::string(tmpdir) + "/fastboot_userdata_XXXXXX";
if (mkdtemp(&result[0]) == NULL) {
fprintf(stderr, "Unable to create temporary directory: %s\n",
strerror(errno));
return "";
}
return result;
}
#endif
static std::string create_fbemarker_tmpdir() {
std::string dir = make_temporary_directory();
if (dir.empty()) {
fprintf(stderr, "Unable to create local temp directory for FBE marker\n");
return "";
}
std::string marker_file = dir + "/" + convert_fbe_marker_filename;
int fd = open(marker_file.c_str(), O_CREAT | O_WRONLY | O_CLOEXEC, 0666);
if (fd == -1) {
fprintf(stderr, "Unable to create FBE marker file %s locally: %d, %s\n",
marker_file.c_str(), errno, strerror(errno));
return "";
}
close(fd);
return dir;
}
static void delete_fbemarker_tmpdir(const std::string& dir) {
std::string marker_file = dir + "/" + convert_fbe_marker_filename;
if (unlink(marker_file.c_str()) == -1) {
fprintf(stderr, "Unable to delete FBE marker file %s locally: %d, %s\n",
marker_file.c_str(), errno, strerror(errno));
return;
}
if (rmdir(dir.c_str()) == -1) {
fprintf(stderr, "Unable to delete FBE marker directory %s locally: %d, %s\n",
dir.c_str(), errno, strerror(errno));
return;
}
}
static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) {
FILE* fp = tmpfile();
if (fp == nullptr) {
@ -994,7 +1054,8 @@ static int64_t parse_num(const char *arg)
static void fb_perform_format(Transport* transport,
const char* partition, int skip_if_not_supported,
const char* type_override, const char* size_override) {
const char* type_override, const char* size_override,
const std::string& initial_dir) {
std::string partition_type, partition_size;
struct fastboot_buffer buf;
@ -1058,7 +1119,7 @@ static void fb_perform_format(Transport* transport,
}
fd = fileno(tmpfile());
if (fs_generator_generate(gen, fd, size)) {
if (fs_generator_generate(gen, fd, size, initial_dir)) {
fprintf(stderr, "Cannot generate image: %s\n", strerror(errno));
close(fd);
return;
@ -1087,6 +1148,7 @@ int main(int argc, char **argv)
bool wants_reboot_bootloader = false;
bool wants_set_active = false;
bool erase_first = true;
bool set_fbe_marker = false;
void *data;
int64_t sz;
int longindex;
@ -1109,6 +1171,9 @@ int main(int argc, char **argv)
{"slot", required_argument, 0, 0},
{"set_active", optional_argument, 0, 'a'},
{"set-active", optional_argument, 0, 'a'},
#if !defined(_WIN32)
{"wipe-and-use-fbe", no_argument, 0, 0},
#endif
{0, 0, 0, 0}
};
@ -1190,6 +1255,15 @@ int main(int argc, char **argv)
return 0;
} else if (strcmp("slot", longopts[longindex].name) == 0) {
slot_override = std::string(optarg);
#if !defined(_WIN32)
} else if (strcmp("wipe-and-use-fbe", longopts[longindex].name) == 0) {
wants_wipe = true;
set_fbe_marker = true;
#endif
} else {
fprintf(stderr, "Internal error in options processing for %s\n",
longopts[longindex].name);
return 1;
}
break;
default:
@ -1283,7 +1357,8 @@ int main(int argc, char **argv)
if (erase_first && needs_erase(transport, partition.c_str())) {
fb_queue_erase(partition.c_str());
}
fb_perform_format(transport, partition.c_str(), 0, type_override, size_override);
fb_perform_format(transport, partition.c_str(), 0,
type_override, size_override, "");
};
do_for_partitions(transport, argv[1], slot_override.c_str(), format, true);
skip(2);
@ -1413,13 +1488,23 @@ int main(int argc, char **argv)
if (wants_wipe) {
fprintf(stderr, "wiping userdata...\n");
fb_queue_erase("userdata");
fb_perform_format(transport, "userdata", 1, nullptr, nullptr);
if (set_fbe_marker) {
fprintf(stderr, "setting FBE marker...\n");
std::string initial_userdata_dir = create_fbemarker_tmpdir();
if (initial_userdata_dir.empty()) {
return 1;
}
fb_perform_format(transport, "userdata", 1, nullptr, nullptr, initial_userdata_dir);
delete_fbemarker_tmpdir(initial_userdata_dir);
} else {
fb_perform_format(transport, "userdata", 1, nullptr, nullptr, "");
}
std::string cache_type;
if (fb_getvar(transport, "partition-type:cache", &cache_type) && !cache_type.empty()) {
fprintf(stderr, "wiping cache...\n");
fb_queue_erase("cache");
fb_perform_format(transport, "cache", 1, nullptr, nullptr);
fb_perform_format(transport, "cache", 1, nullptr, nullptr, "");
}
}
if (wants_set_active) {

View File

@ -1,7 +1,8 @@
#include "fs.h"
#include "fastboot.h"
#include "make_ext4fs.h"
#include "make_f2fs.h"
#include "fs.h"
#include <errno.h>
#include <stdio.h>
@ -13,24 +14,32 @@
#include <sparse/sparse.h>
static int generate_ext4_image(int fd, long long partSize)
static int generate_ext4_image(int fd, long long partSize, const std::string& initial_dir)
{
make_ext4fs_sparse_fd(fd, partSize, NULL, NULL);
if (initial_dir.empty()) {
make_ext4fs_sparse_fd(fd, partSize, NULL, NULL);
} else {
make_ext4fs_sparse_fd_directory(fd, partSize, NULL, NULL, initial_dir.c_str());
}
return 0;
}
#ifdef USE_F2FS
static int generate_f2fs_image(int fd, long long partSize)
static int generate_f2fs_image(int fd, long long partSize, const std::string& initial_dir)
{
if (!initial_dir.empty()) {
fprintf(stderr, "Unable to set initial directory on F2FS filesystem\n");
return -1;
}
return make_f2fs_sparse_fd(fd, partSize, NULL, NULL);
}
#endif
static const struct fs_generator {
const char* fs_type; //must match what fastboot reports for partition type
int (*generate)(int fd, long long partSize); //returns 0 or error value
//returns 0 or error value
int (*generate)(int fd, long long partSize, const std::string& initial_dir);
} generators[] = {
{ "ext4", generate_ext4_image},
@ -48,7 +57,8 @@ const struct fs_generator* fs_get_generator(const std::string& fs_type) {
return nullptr;
}
int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize)
int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize,
const std::string& initial_dir)
{
return gen->generate(tmpFileNo, partSize);
return gen->generate(tmpFileNo, partSize, initial_dir);
}

View File

@ -1,11 +1,13 @@
#ifndef _FS_H_
#define _FS_H_
#include <string>
#include <stdint.h>
struct fs_generator;
const struct fs_generator* fs_get_generator(const std::string& fs_type);
int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize);
int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize,
const std::string& initial_dir);
#endif