diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index e7f1a0721..a4a0b5250 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -1303,6 +1303,36 @@ static int64_t parse_num(const char *arg) return num; } +static std::string fb_fix_numeric_var(std::string var) { + // Some bootloaders (angler, for example), send spurious leading whitespace. + var = android::base::Trim(var); + // Some bootloaders (hammerhead, for example) use implicit hex. + // This code used to use strtol with base 16. + if (!android::base::StartsWith(var, "0x")) var = "0x" + var; + return var; +} + +static unsigned fb_get_flash_block_size(Transport* transport, std::string name) { + std::string sizeString; + if (!fb_getvar(transport, name.c_str(), &sizeString)) { + /* This device does not report flash block sizes, so return 0 */ + return 0; + } + sizeString = fb_fix_numeric_var(sizeString); + + unsigned size; + if (!android::base::ParseUint(sizeString, &size)) { + fprintf(stderr, "Couldn't parse %s '%s'.\n", name.c_str(), sizeString.c_str()); + return 0; + } + if (size < 4096 || (size & (size - 1)) != 0) { + fprintf(stderr, "Invalid %s %u: must be a power of 2 and at least 4096.\n", + name.c_str(), size); + return 0; + } + return size; +} + static void fb_perform_format(Transport* transport, const char* partition, int skip_if_not_supported, const char* type_override, const char* size_override, @@ -1345,11 +1375,7 @@ static void fb_perform_format(Transport* transport, } partition_size = size_override; } - // Some bootloaders (angler, for example), send spurious leading whitespace. - partition_size = android::base::Trim(partition_size); - // Some bootloaders (hammerhead, for example) use implicit hex. - // This code used to use strtol with base 16. - if (!android::base::StartsWith(partition_size, "0x")) partition_size = "0x" + partition_size; + partition_size = fb_fix_numeric_var(partition_size); gen = fs_get_generator(partition_type); if (!gen) { @@ -1370,7 +1396,12 @@ static void fb_perform_format(Transport* transport, } fd = fileno(tmpfile()); - if (fs_generator_generate(gen, fd, size, initial_dir)) { + + unsigned eraseBlkSize, logicalBlkSize; + eraseBlkSize = fb_get_flash_block_size(transport, "erase-block-size"); + logicalBlkSize = fb_get_flash_block_size(transport, "logical-block-size"); + + if (fs_generator_generate(gen, fd, size, initial_dir, eraseBlkSize, logicalBlkSize)) { fprintf(stderr, "Cannot generate image: %s\n", strerror(errno)); close(fd); return; diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp index 9b73165c1..5d9ccfe09 100644 --- a/fastboot/fs.cpp +++ b/fastboot/fs.cpp @@ -14,18 +14,21 @@ #include #include -static int generate_ext4_image(int fd, long long partSize, const std::string& initial_dir) +static int generate_ext4_image(int fd, long long partSize, const std::string& initial_dir, + unsigned eraseBlkSize, unsigned logicalBlkSize) { if (initial_dir.empty()) { - make_ext4fs_sparse_fd(fd, partSize, NULL, NULL); + make_ext4fs_sparse_fd_align(fd, partSize, NULL, NULL, eraseBlkSize, logicalBlkSize); } else { - make_ext4fs_sparse_fd_directory(fd, partSize, NULL, NULL, initial_dir.c_str()); + make_ext4fs_sparse_fd_directory_align(fd, partSize, NULL, NULL, initial_dir.c_str(), + eraseBlkSize, logicalBlkSize); } return 0; } #ifdef USE_F2FS -static int generate_f2fs_image(int fd, long long partSize, const std::string& initial_dir) +static int generate_f2fs_image(int fd, long long partSize, const std::string& initial_dir, + unsigned /* unused */, unsigned /* unused */) { if (!initial_dir.empty()) { fprintf(stderr, "Unable to set initial directory on F2FS filesystem\n"); @@ -39,7 +42,8 @@ static const struct fs_generator { const char* fs_type; //must match what fastboot reports for partition type //returns 0 or error value - int (*generate)(int fd, long long partSize, const std::string& initial_dir); + int (*generate)(int fd, long long partSize, const std::string& initial_dir, + unsigned eraseBlkSize, unsigned logicalBlkSize); } generators[] = { { "ext4", generate_ext4_image}, @@ -58,7 +62,7 @@ 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, - const std::string& initial_dir) + const std::string& initial_dir, unsigned eraseBlkSize, unsigned logicalBlkSize) { - return gen->generate(tmpFileNo, partSize, initial_dir); + return gen->generate(tmpFileNo, partSize, initial_dir, eraseBlkSize, logicalBlkSize); } diff --git a/fastboot/fs.h b/fastboot/fs.h index 0a68507b0..0a5f5a4d7 100644 --- a/fastboot/fs.h +++ b/fastboot/fs.h @@ -8,6 +8,6 @@ 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, - const std::string& initial_dir); + const std::string& initial_dir, unsigned eraseBlkSize = 0, unsigned logicalBlkSize = 0); #endif