2009-06-10 23:11:53 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2009 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.
|
|
|
|
*/
|
|
|
|
|
2016-10-11 00:48:37 +02:00
|
|
|
#include "updater/install.h"
|
|
|
|
|
2009-06-24 18:36:20 +02:00
|
|
|
#include <ctype.h>
|
2009-06-10 23:11:53 +02:00
|
|
|
#include <errno.h>
|
2016-02-08 20:15:50 +01:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <ftw.h>
|
|
|
|
#include <inttypes.h>
|
2009-06-10 23:11:53 +02:00
|
|
|
#include <stdarg.h>
|
2009-06-24 18:36:20 +02:00
|
|
|
#include <stdio.h>
|
2009-06-10 23:11:53 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2016-02-08 20:15:50 +01:00
|
|
|
#include <sys/capability.h>
|
2009-06-10 23:11:53 +02:00
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
2009-09-10 23:10:48 +02:00
|
|
|
#include <sys/wait.h>
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
#include <sys/xattr.h>
|
2016-02-08 20:15:50 +01:00
|
|
|
#include <time.h>
|
|
|
|
#include <unistd.h>
|
2016-09-09 05:10:11 +02:00
|
|
|
#include <utime.h>
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-02-04 03:16:02 +01:00
|
|
|
#include <memory>
|
2016-02-08 20:15:50 +01:00
|
|
|
#include <string>
|
2016-02-04 03:16:02 +01:00
|
|
|
#include <vector>
|
|
|
|
|
2016-11-04 07:52:01 +01:00
|
|
|
#include <android-base/file.h>
|
2016-11-23 01:29:50 +01:00
|
|
|
#include <android-base/logging.h>
|
2016-10-18 03:15:20 +02:00
|
|
|
#include <android-base/parsedouble.h>
|
2016-11-04 07:52:01 +01:00
|
|
|
#include <android-base/parseint.h>
|
2016-09-24 00:30:55 +02:00
|
|
|
#include <android-base/properties.h>
|
2015-12-05 00:30:20 +01:00
|
|
|
#include <android-base/stringprintf.h>
|
2016-11-04 07:52:01 +01:00
|
|
|
#include <android-base/strings.h>
|
2018-08-27 19:50:31 +02:00
|
|
|
#include <android-base/unique_fd.h>
|
2016-12-29 00:09:20 +01:00
|
|
|
#include <applypatch/applypatch.h>
|
|
|
|
#include <bootloader_message/bootloader_message.h>
|
2016-10-06 08:17:01 +02:00
|
|
|
#include <ext4_utils/wipe.h>
|
2016-02-08 20:15:50 +01:00
|
|
|
#include <openssl/sha.h>
|
2016-04-02 03:24:39 +02:00
|
|
|
#include <selinux/label.h>
|
|
|
|
#include <selinux/selinux.h>
|
2016-09-09 05:10:11 +02:00
|
|
|
#include <ziparchive/zip_archive.h>
|
2015-09-10 02:16:55 +02:00
|
|
|
|
2009-06-10 23:11:53 +02:00
|
|
|
#include "edify/expr.h"
|
2019-05-14 19:54:43 +02:00
|
|
|
#include "edify/updater_interface.h"
|
|
|
|
#include "edify/updater_runtime_interface.h"
|
2018-05-04 07:41:23 +02:00
|
|
|
#include "otautil/dirutil.h"
|
2017-10-06 16:43:41 +02:00
|
|
|
#include "otautil/error_code.h"
|
2018-01-04 22:19:11 +01:00
|
|
|
#include "otautil/mounts.h"
|
2017-09-29 23:39:33 +02:00
|
|
|
#include "otautil/print_sha1.h"
|
2018-05-04 08:01:13 +02:00
|
|
|
#include "otautil/sysutil.h"
|
2019-05-14 19:54:43 +02:00
|
|
|
|
2019-05-22 23:48:35 +02:00
|
|
|
#ifndef __ANDROID__
|
|
|
|
#include <cutils/memory.h> // for strlcpy
|
|
|
|
#endif
|
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
static bool UpdateBlockDeviceNameForPartition(UpdaterInterface* updater, Partition* partition) {
|
|
|
|
CHECK(updater);
|
|
|
|
std::string name = updater->FindBlockDeviceName(partition->name);
|
|
|
|
if (name.empty()) {
|
|
|
|
LOG(ERROR) << "Failed to find the block device " << partition->name;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
partition->name = std::move(name);
|
|
|
|
return true;
|
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2018-02-03 01:49:15 +01:00
|
|
|
// This is the updater side handler for ui_print() in edify script. Contents will be sent over to
|
|
|
|
// the recovery side for on-screen display.
|
|
|
|
Value* UIPrintFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string buffer = android::base::Join(args, "");
|
2019-05-14 19:54:43 +02:00
|
|
|
state->updater->UiPrint(buffer);
|
2018-02-03 01:49:15 +01:00
|
|
|
return StringValue(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
// package_extract_file(package_file[, dest_file])
|
|
|
|
// Extracts a single package_file from the update package and writes it to dest_file,
|
|
|
|
// overwriting existing files if necessary. Without the dest_file argument, returns the
|
|
|
|
// contents of the package file as a binary blob.
|
|
|
|
Value* PackageExtractFileFn(const char* name, State* state,
|
|
|
|
const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() < 1 || argv.size() > 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %zu", name,
|
|
|
|
argv.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argv.size() == 2) {
|
|
|
|
// The two-argument version extracts to a file.
|
|
|
|
|
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name,
|
|
|
|
argv.size());
|
|
|
|
}
|
|
|
|
const std::string& zip_path = args[0];
|
2019-07-31 01:48:52 +02:00
|
|
|
std::string dest_path = args[1];
|
2018-02-03 01:49:15 +01:00
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
ZipArchiveHandle za = state->updater->GetPackageHandle();
|
2018-02-03 01:49:15 +01:00
|
|
|
ZipEntry entry;
|
2019-05-04 07:52:37 +02:00
|
|
|
if (FindEntry(za, zip_path, &entry) != 0) {
|
2018-02-03 01:49:15 +01:00
|
|
|
LOG(ERROR) << name << ": no " << zip_path << " in package";
|
|
|
|
return StringValue("");
|
|
|
|
}
|
|
|
|
|
2019-07-31 01:48:52 +02:00
|
|
|
// Update the destination of package_extract_file if it's a block device. During simulation the
|
|
|
|
// destination will map to a fake file.
|
|
|
|
if (std::string block_device_name = state->updater->FindBlockDeviceName(dest_path);
|
|
|
|
!block_device_name.empty()) {
|
|
|
|
dest_path = block_device_name;
|
|
|
|
}
|
|
|
|
|
2018-08-27 19:50:31 +02:00
|
|
|
android::base::unique_fd fd(TEMP_FAILURE_RETRY(
|
|
|
|
open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)));
|
2018-02-03 01:49:15 +01:00
|
|
|
if (fd == -1) {
|
|
|
|
PLOG(ERROR) << name << ": can't open " << dest_path << " for write";
|
|
|
|
return StringValue("");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool success = true;
|
|
|
|
int32_t ret = ExtractEntryToFile(za, &entry, fd);
|
|
|
|
if (ret != 0) {
|
|
|
|
LOG(ERROR) << name << ": Failed to extract entry \"" << zip_path << "\" ("
|
|
|
|
<< entry.uncompressed_length << " bytes) to \"" << dest_path
|
|
|
|
<< "\": " << ErrorCodeString(ret);
|
|
|
|
success = false;
|
|
|
|
}
|
2018-08-27 19:50:31 +02:00
|
|
|
if (fsync(fd) == -1) {
|
2018-02-03 01:49:15 +01:00
|
|
|
PLOG(ERROR) << "fsync of \"" << dest_path << "\" failed";
|
|
|
|
success = false;
|
|
|
|
}
|
2018-08-27 19:50:31 +02:00
|
|
|
|
|
|
|
if (close(fd.release()) != 0) {
|
2018-02-03 01:49:15 +01:00
|
|
|
PLOG(ERROR) << "close of \"" << dest_path << "\" failed";
|
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return StringValue(success ? "t" : "");
|
|
|
|
} else {
|
|
|
|
// The one-argument version returns the contents of the file as the result.
|
|
|
|
|
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name,
|
|
|
|
argv.size());
|
|
|
|
}
|
|
|
|
const std::string& zip_path = args[0];
|
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
ZipArchiveHandle za = state->updater->GetPackageHandle();
|
2018-02-03 01:49:15 +01:00
|
|
|
ZipEntry entry;
|
2019-05-04 07:52:37 +02:00
|
|
|
if (FindEntry(za, zip_path, &entry) != 0) {
|
2018-02-03 01:49:15 +01:00
|
|
|
return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name,
|
|
|
|
zip_path.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string buffer;
|
|
|
|
buffer.resize(entry.uncompressed_length);
|
|
|
|
|
|
|
|
int32_t ret =
|
|
|
|
ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&buffer[0]), buffer.size());
|
|
|
|
if (ret != 0) {
|
|
|
|
return ErrorAbort(state, kPackageExtractFileFailure,
|
|
|
|
"%s: Failed to extract entry \"%s\" (%zu bytes) to memory: %s", name,
|
|
|
|
zip_path.c_str(), buffer.size(), ErrorCodeString(ret));
|
|
|
|
}
|
|
|
|
|
2018-06-20 00:56:49 +02:00
|
|
|
return new Value(Value::Type::BLOB, buffer);
|
2018-02-03 01:49:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
// patch_partition_check(target_partition, source_partition)
|
|
|
|
// Checks if the target and source partitions have the desired checksums to be patched. It returns
|
|
|
|
// directly, if the target partition already has the expected checksum. Otherwise it in turn
|
|
|
|
// checks the integrity of the source partition and the backup file on /cache.
|
2018-02-03 01:49:15 +01:00
|
|
|
//
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
// For example, patch_partition_check(
|
|
|
|
// "EMMC:/dev/block/boot:12342568:8aaacf187a6929d0e9c3e9e46ea7ff495b43424d",
|
|
|
|
// "EMMC:/dev/block/boot:12363048:06b0b16299dcefc94900efed01e0763ff644ffa4")
|
|
|
|
Value* PatchPartitionCheckFn(const char* name, State* state,
|
|
|
|
const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 2) {
|
2018-02-03 01:49:15 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure,
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
"%s(): Invalid number of args (expected 2, got %zu)", name, argv.size());
|
2018-02-03 01:49:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string> args;
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
if (!ReadArgs(state, argv, &args, 0, 2)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
|
2018-02-03 01:49:15 +01:00
|
|
|
}
|
|
|
|
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
std::string err;
|
|
|
|
auto target = Partition::Parse(args[0], &err);
|
|
|
|
if (!target) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse target \"%s\": %s", name,
|
|
|
|
args[0].c_str(), err.c_str());
|
2018-02-03 01:49:15 +01:00
|
|
|
}
|
|
|
|
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
auto source = Partition::Parse(args[1], &err);
|
|
|
|
if (!source) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse source \"%s\": %s", name,
|
|
|
|
args[1].c_str(), err.c_str());
|
2018-02-03 01:49:15 +01:00
|
|
|
}
|
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
if (!UpdateBlockDeviceNameForPartition(state->updater, &source) ||
|
|
|
|
!UpdateBlockDeviceNameForPartition(state->updater, &target)) {
|
|
|
|
return StringValue("");
|
|
|
|
}
|
|
|
|
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
bool result = PatchPartitionCheck(target, source);
|
|
|
|
return StringValue(result ? "t" : "");
|
|
|
|
}
|
2018-02-03 01:49:15 +01:00
|
|
|
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
// patch_partition(target, source, patch)
|
|
|
|
// Applies the given patch to the source partition, and writes the result to the target partition.
|
|
|
|
//
|
|
|
|
// For example, patch_partition(
|
|
|
|
// "EMMC:/dev/block/boot:12342568:8aaacf187a6929d0e9c3e9e46ea7ff495b43424d",
|
|
|
|
// "EMMC:/dev/block/boot:12363048:06b0b16299dcefc94900efed01e0763ff644ffa4",
|
|
|
|
// package_extract_file("boot.img.p"))
|
|
|
|
Value* PatchPartitionFn(const char* name, State* state,
|
|
|
|
const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 3) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure,
|
|
|
|
"%s(): Invalid number of args (expected 3, got %zu)", name, argv.size());
|
2018-02-03 01:49:15 +01:00
|
|
|
}
|
|
|
|
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, argv, &args, 0, 2)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
|
|
|
|
}
|
2018-02-03 01:49:15 +01:00
|
|
|
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
std::string err;
|
|
|
|
auto target = Partition::Parse(args[0], &err);
|
|
|
|
if (!target) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse target \"%s\": %s", name,
|
|
|
|
args[0].c_str(), err.c_str());
|
2018-02-03 01:49:15 +01:00
|
|
|
}
|
|
|
|
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
auto source = Partition::Parse(args[1], &err);
|
|
|
|
if (!source) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse source \"%s\": %s", name,
|
|
|
|
args[1].c_str(), err.c_str());
|
2018-02-03 01:49:15 +01:00
|
|
|
}
|
|
|
|
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
std::vector<std::unique_ptr<Value>> values;
|
|
|
|
if (!ReadValueArgs(state, argv, &values, 2, 1) || values[0]->type != Value::Type::BLOB) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Invalid patch arg", name);
|
2018-02-03 01:49:15 +01:00
|
|
|
}
|
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
if (!UpdateBlockDeviceNameForPartition(state->updater, &source) ||
|
|
|
|
!UpdateBlockDeviceNameForPartition(state->updater, &target)) {
|
|
|
|
return StringValue("");
|
|
|
|
}
|
|
|
|
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
bool result = PatchPartition(target, source, *values[0], nullptr);
|
|
|
|
return StringValue(result ? "t" : "");
|
2018-02-03 01:49:15 +01:00
|
|
|
}
|
|
|
|
|
2010-07-01 18:18:44 +02:00
|
|
|
// mount(fs_type, partition_type, location, mount_point)
|
2016-11-04 07:25:04 +01:00
|
|
|
// mount(fs_type, partition_type, location, mount_point, mount_options)
|
2017-03-06 23:44:59 +01:00
|
|
|
|
2010-07-01 18:18:44 +02:00
|
|
|
// fs_type="ext4" partition_type="EMMC" location=device
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* MountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 4 && argv.size() != 5) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %zu", name,
|
|
|
|
argv.size());
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& fs_type = args[0];
|
|
|
|
const std::string& partition_type = args[1];
|
|
|
|
const std::string& location = args[2];
|
|
|
|
const std::string& mount_point = args[3];
|
|
|
|
std::string mount_options;
|
|
|
|
|
2017-03-06 23:44:59 +01:00
|
|
|
if (argv.size() == 5) {
|
2016-11-23 01:29:50 +01:00
|
|
|
mount_options = args[4];
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
if (fs_type.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
|
|
|
|
}
|
|
|
|
if (partition_type.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
|
|
|
|
name);
|
|
|
|
}
|
|
|
|
if (location.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
|
|
|
|
}
|
|
|
|
if (mount_point.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
|
|
|
|
name);
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
auto updater = state->updater;
|
|
|
|
if (updater->GetRuntime()->Mount(location, mount_point, fs_type, mount_options) != 0) {
|
2019-05-03 10:05:04 +02:00
|
|
|
updater->UiPrint(android::base::StringPrintf("%s: Failed to mount %s at %s: %s", name,
|
|
|
|
location.c_str(), mount_point.c_str(),
|
|
|
|
strerror(errno)));
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(mount_point);
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
|
|
|
|
2009-06-12 02:21:44 +02:00
|
|
|
// is_mounted(mount_point)
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* IsMountedFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& mount_point = args[0];
|
|
|
|
if (mount_point.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure,
|
|
|
|
"mount_point argument to unmount() can't be empty");
|
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
auto updater_runtime = state->updater->GetRuntime();
|
|
|
|
if (!updater_runtime->IsMounted(mount_point)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(mount_point);
|
2009-06-12 02:21:44 +02:00
|
|
|
}
|
|
|
|
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* UnmountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& mount_point = args[0];
|
|
|
|
if (mount_point.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure,
|
|
|
|
"mount_point argument to unmount() can't be empty");
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
auto updater = state->updater;
|
|
|
|
auto [mounted, result] = updater->GetRuntime()->Unmount(mount_point);
|
|
|
|
if (!mounted) {
|
2019-05-03 10:05:04 +02:00
|
|
|
updater->UiPrint(
|
|
|
|
android::base::StringPrintf("Failed to unmount %s: No such volume", mount_point.c_str()));
|
2016-11-23 01:29:50 +01:00
|
|
|
return nullptr;
|
2019-05-14 19:54:43 +02:00
|
|
|
} else if (result != 0) {
|
|
|
|
updater->UiPrint(android::base::StringPrintf("Failed to unmount %s: %s", mount_point.c_str(),
|
|
|
|
strerror(errno)));
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(mount_point);
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2012-02-09 20:13:23 +01:00
|
|
|
// format(fs_type, partition_type, location, fs_size, mount_point)
|
2009-06-10 23:11:53 +02:00
|
|
|
//
|
2016-11-23 01:29:50 +01:00
|
|
|
// fs_type="ext4" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location>
|
|
|
|
// fs_type="f2fs" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location>
|
2014-06-17 04:07:39 +02:00
|
|
|
// if fs_size == 0, then make fs uses the entire partition.
|
2011-01-15 03:55:05 +01:00
|
|
|
// if fs_size > 0, that is the size to use
|
2014-06-17 04:07:39 +02:00
|
|
|
// if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs")
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* FormatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 5) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %zu", name,
|
|
|
|
argv.size());
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2012-02-09 20:13:23 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& fs_type = args[0];
|
|
|
|
const std::string& partition_type = args[1];
|
|
|
|
const std::string& location = args[2];
|
|
|
|
const std::string& fs_size = args[3];
|
|
|
|
const std::string& mount_point = args[4];
|
|
|
|
|
|
|
|
if (fs_type.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
|
|
|
|
}
|
|
|
|
if (partition_type.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
|
|
|
|
name);
|
|
|
|
}
|
|
|
|
if (location.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
|
|
|
|
}
|
|
|
|
if (mount_point.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
|
|
|
|
name);
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
int64_t size;
|
|
|
|
if (!android::base::ParseInt(fs_size, &size)) {
|
2018-01-29 00:37:48 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s", name,
|
2016-11-23 01:29:50 +01:00
|
|
|
fs_size.c_str());
|
|
|
|
}
|
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
auto updater_runtime = state->updater->GetRuntime();
|
2016-11-23 01:29:50 +01:00
|
|
|
if (fs_type == "ext4") {
|
2018-12-20 18:44:06 +01:00
|
|
|
std::vector<std::string> mke2fs_args = {
|
|
|
|
"/system/bin/mke2fs", "-t", "ext4", "-b", "4096", location
|
|
|
|
};
|
2017-04-21 23:36:12 +02:00
|
|
|
if (size != 0) {
|
2018-12-20 18:44:06 +01:00
|
|
|
mke2fs_args.push_back(std::to_string(size / 4096LL));
|
2017-04-21 23:36:12 +02:00
|
|
|
}
|
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
if (auto status = updater_runtime->RunProgram(mke2fs_args, true); status != 0) {
|
2017-11-02 19:58:12 +01:00
|
|
|
LOG(ERROR) << name << ": mke2fs failed (" << status << ") on " << location;
|
|
|
|
return StringValue("");
|
2017-04-21 23:36:12 +02:00
|
|
|
}
|
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
if (auto status = updater_runtime->RunProgram(
|
|
|
|
{ "/system/bin/e2fsdroid", "-e", "-a", mount_point, location }, true);
|
2018-12-20 18:44:06 +01:00
|
|
|
status != 0) {
|
2017-04-21 23:36:12 +02:00
|
|
|
LOG(ERROR) << name << ": e2fsdroid failed (" << status << ") on " << location;
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue("");
|
2012-02-09 20:13:23 +01:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(location);
|
2018-12-20 18:44:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fs_type == "f2fs") {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (size < 0) {
|
|
|
|
LOG(ERROR) << name << ": fs_size can't be negative for f2fs: " << fs_size;
|
|
|
|
return StringValue("");
|
|
|
|
}
|
2018-12-20 18:44:06 +01:00
|
|
|
std::vector<std::string> f2fs_args = {
|
2018-12-20 23:25:15 +01:00
|
|
|
"/system/bin/make_f2fs", "-g", "android", "-w", "512", location
|
2018-12-20 18:44:06 +01:00
|
|
|
};
|
|
|
|
if (size >= 512) {
|
|
|
|
f2fs_args.push_back(std::to_string(size / 512));
|
|
|
|
}
|
2019-05-14 19:54:43 +02:00
|
|
|
if (auto status = updater_runtime->RunProgram(f2fs_args, true); status != 0) {
|
2018-12-20 23:25:15 +01:00
|
|
|
LOG(ERROR) << name << ": make_f2fs failed (" << status << ") on " << location;
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue("");
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
2017-11-29 04:48:05 +01:00
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
if (auto status = updater_runtime->RunProgram(
|
|
|
|
{ "/system/bin/sload_f2fs", "-t", mount_point, location }, true);
|
2018-12-20 23:25:15 +01:00
|
|
|
status != 0) {
|
|
|
|
LOG(ERROR) << name << ": sload_f2fs failed (" << status << ") on " << location;
|
2017-11-29 04:48:05 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(location);
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2018-12-20 18:44:06 +01:00
|
|
|
LOG(ERROR) << name << ": unsupported fs_type \"" << fs_type << "\" partition_type \""
|
|
|
|
<< partition_type << "\"";
|
2016-11-23 01:29:50 +01:00
|
|
|
return nullptr;
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
|
|
|
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* ShowProgressFn(const char* name, State* state,
|
|
|
|
const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
|
|
|
|
argv.size());
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& frac_str = args[0];
|
|
|
|
const std::string& sec_str = args[1];
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
double frac;
|
|
|
|
if (!android::base::ParseDouble(frac_str.c_str(), &frac)) {
|
2018-01-29 00:37:48 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s", name,
|
2016-11-23 01:29:50 +01:00
|
|
|
frac_str.c_str());
|
|
|
|
}
|
|
|
|
int sec;
|
|
|
|
if (!android::base::ParseInt(sec_str.c_str(), &sec)) {
|
2018-01-29 00:37:48 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s", name,
|
2016-11-23 01:29:50 +01:00
|
|
|
sec_str.c_str());
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
state->updater->WriteToCommandPipe(android::base::StringPrintf("progress %f %d", frac, sec));
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(frac_str);
|
2009-06-24 18:36:20 +02:00
|
|
|
}
|
|
|
|
|
2018-02-03 01:49:15 +01:00
|
|
|
Value* SetProgressFn(const char* name, State* state,
|
|
|
|
const std::vector<std::unique_ptr<Expr>>& argv) {
|
2017-03-06 23:44:59 +01:00
|
|
|
if (argv.size() != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& frac_str = args[0];
|
2009-06-24 18:36:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
double frac;
|
|
|
|
if (!android::base::ParseDouble(frac_str.c_str(), &frac)) {
|
2018-01-29 00:37:48 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s", name,
|
2016-11-23 01:29:50 +01:00
|
|
|
frac_str.c_str());
|
|
|
|
}
|
2009-06-24 18:36:20 +02:00
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
state->updater->WriteToCommandPipe(android::base::StringPrintf("set_progress %f", frac));
|
2009-06-24 18:36:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(frac_str);
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
|
|
|
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* GetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
|
|
|
std::string key;
|
|
|
|
if (!Evaluate(state, argv[0], &key)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2019-05-14 19:54:43 +02:00
|
|
|
|
|
|
|
auto updater_runtime = state->updater->GetRuntime();
|
|
|
|
std::string value = updater_runtime->GetProperty(key, "");
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(value);
|
2009-06-12 02:21:44 +02:00
|
|
|
}
|
|
|
|
|
2009-06-18 19:11:50 +02:00
|
|
|
// file_getprop(file, key)
|
|
|
|
//
|
|
|
|
// interprets 'file' as a getprop-style file (key=value pairs, one
|
2016-11-03 22:49:01 +01:00
|
|
|
// per line. # comment lines, blank lines, lines without '=' ignored),
|
2014-04-26 03:47:18 +02:00
|
|
|
// and returns the value for 'key' (or "" if it isn't defined).
|
2018-02-03 01:49:15 +01:00
|
|
|
Value* FileGetPropFn(const char* name, State* state,
|
|
|
|
const std::vector<std::unique_ptr<Expr>>& argv) {
|
2017-03-06 23:44:59 +01:00
|
|
|
if (argv.size() != 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
|
|
|
|
argv.size());
|
2016-11-28 20:48:43 +01:00
|
|
|
}
|
2016-11-03 22:49:01 +01:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-28 20:48:43 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& filename = args[0];
|
|
|
|
const std::string& key = args[1];
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2018-08-27 19:50:31 +02:00
|
|
|
std::string buffer;
|
2019-05-14 19:54:43 +02:00
|
|
|
auto updater_runtime = state->updater->GetRuntime();
|
|
|
|
if (!updater_runtime->ReadFileToString(filename, &buffer)) {
|
2018-08-27 19:50:31 +02:00
|
|
|
ErrorAbort(state, kFreadFailure, "%s: failed to read %s", name, filename.c_str());
|
2016-11-28 20:48:43 +01:00
|
|
|
return nullptr;
|
|
|
|
}
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
std::vector<std::string> lines = android::base::Split(buffer, "\n");
|
|
|
|
for (size_t i = 0; i < lines.size(); i++) {
|
|
|
|
std::string line = android::base::Trim(lines[i]);
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
// comment or blank line: skip to next line
|
|
|
|
if (line.empty() || line[0] == '#') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
size_t equal_pos = line.find('=');
|
|
|
|
if (equal_pos == std::string::npos) {
|
|
|
|
continue;
|
|
|
|
}
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
// trim whitespace between key and '='
|
|
|
|
std::string str = android::base::Trim(line.substr(0, equal_pos));
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
// not the key we're looking for
|
|
|
|
if (key != str) continue;
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
return StringValue(android::base::Trim(line.substr(equal_pos + 1)));
|
|
|
|
}
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
return StringValue("");
|
2009-06-18 19:11:50 +02:00
|
|
|
}
|
|
|
|
|
2009-06-12 02:21:44 +02:00
|
|
|
// apply_patch_space(bytes)
|
2018-02-03 01:49:15 +01:00
|
|
|
Value* ApplyPatchSpaceFn(const char* name, State* state,
|
|
|
|
const std::vector<std::unique_ptr<Expr>>& argv) {
|
2017-03-06 23:44:59 +01:00
|
|
|
if (argv.size() != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 args, got %zu", name,
|
|
|
|
argv.size());
|
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& bytes_str = args[0];
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
size_t bytes;
|
|
|
|
if (!android::base::ParseUint(bytes_str.c_str(), &bytes)) {
|
2018-01-29 00:37:48 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count", name,
|
|
|
|
bytes_str.c_str());
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2017-11-29 02:23:06 +01:00
|
|
|
// Skip the cache size check if the update is a retry.
|
2018-07-12 00:55:32 +02:00
|
|
|
if (state->is_retry || CheckAndFreeSpaceOnCache(bytes)) {
|
2017-11-29 02:23:06 +01:00
|
|
|
return StringValue("t");
|
|
|
|
}
|
|
|
|
return StringValue("");
|
2010-02-22 23:46:32 +01:00
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* WipeCacheFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (!argv.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name,
|
|
|
|
argv.size());
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2019-05-03 10:05:04 +02:00
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
state->updater->WriteToCommandPipe("wipe_cache");
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue("t");
|
2011-10-19 19:51:12 +02:00
|
|
|
}
|
|
|
|
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* RunProgramFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() < 1) {
|
2016-11-23 01:29:50 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
|
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
2009-09-10 23:10:48 +02:00
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
auto updater_runtime = state->updater->GetRuntime();
|
|
|
|
auto status = updater_runtime->RunProgram(args, false);
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(std::to_string(status));
|
2009-09-10 23:10:48 +02:00
|
|
|
}
|
|
|
|
|
2018-06-20 00:56:49 +02:00
|
|
|
// read_file(filename)
|
2018-07-10 00:08:50 +02:00
|
|
|
// Reads a local file 'filename' and returns its contents as a string Value.
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* ReadFileFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2018-06-20 00:56:49 +02:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
|
|
|
const std::string& filename = args[0];
|
2010-02-18 01:11:44 +01:00
|
|
|
|
2018-07-10 00:08:50 +02:00
|
|
|
std::string contents;
|
2019-05-14 19:54:43 +02:00
|
|
|
auto updater_runtime = state->updater->GetRuntime();
|
|
|
|
if (updater_runtime->ReadFileToString(filename, &contents)) {
|
2018-07-10 00:08:50 +02:00
|
|
|
return new Value(Value::Type::STRING, std::move(contents));
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2018-06-20 00:56:49 +02:00
|
|
|
|
|
|
|
// Leave it to caller to handle the failure.
|
2018-07-10 00:08:50 +02:00
|
|
|
PLOG(ERROR) << name << ": Failed to read " << filename;
|
2018-06-20 00:56:49 +02:00
|
|
|
return StringValue("");
|
2010-02-18 01:11:44 +01:00
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-04 07:52:01 +01:00
|
|
|
// write_value(value, filename)
|
|
|
|
// Writes 'value' to 'filename'.
|
|
|
|
// Example: write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq")
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* WriteValueFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
|
|
|
|
argv.size());
|
2016-11-04 07:52:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-04 07:52:01 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& filename = args[1];
|
|
|
|
if (filename.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Filename cannot be empty", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& value = args[0];
|
2019-05-14 19:54:43 +02:00
|
|
|
auto updater_runtime = state->updater->GetRuntime();
|
|
|
|
if (!updater_runtime->WriteStringToFile(value, filename)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
PLOG(ERROR) << name << ": Failed to write to \"" << filename << "\"";
|
2016-11-04 07:52:01 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
2019-05-14 19:54:43 +02:00
|
|
|
return StringValue("t");
|
2016-11-04 07:52:01 +01:00
|
|
|
}
|
|
|
|
|
2013-11-25 22:53:25 +01:00
|
|
|
// Immediately reboot the device. Recovery is not finished normally,
|
|
|
|
// so if you reboot into recovery it will re-start applying the
|
|
|
|
// current package (because nothing has cleared the copy of the
|
|
|
|
// arguments stored in the BCB).
|
|
|
|
//
|
|
|
|
// The argument is the partition name passed to the android reboot
|
|
|
|
// property. It can be "recovery" to boot from the recovery
|
|
|
|
// partition, or "" (empty string) to boot from the regular boot
|
|
|
|
// partition.
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* RebootNowFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
|
|
|
|
argv.size());
|
2016-11-18 21:01:26 +01:00
|
|
|
}
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-18 21:01:26 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& filename = args[0];
|
|
|
|
const std::string& property = args[1];
|
|
|
|
|
|
|
|
// Zero out the 'command' field of the bootloader message. Leave the rest intact.
|
|
|
|
bootloader_message boot;
|
|
|
|
std::string err;
|
|
|
|
if (!read_bootloader_message_from(&boot, filename, &err)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
|
|
|
memset(boot.command, 0, sizeof(boot.command));
|
|
|
|
if (!write_bootloader_message_to(boot, filename, &err)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err;
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2019-04-29 20:23:16 +02:00
|
|
|
Reboot(property);
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
sleep(5);
|
|
|
|
return ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name);
|
2013-11-25 22:53:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Store a string value somewhere that future invocations of recovery
|
|
|
|
// can access it. This value is called the "stage" and can be used to
|
|
|
|
// drive packages that need to do reboots in the middle of
|
|
|
|
// installation and keep track of where they are in the multi-stage
|
|
|
|
// install.
|
|
|
|
//
|
|
|
|
// The first argument is the block device for the misc partition
|
|
|
|
// ("/misc" in the fstab), which is where this value is stored. The
|
|
|
|
// second argument is the string to store; it should not exceed 31
|
|
|
|
// bytes.
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* SetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
|
|
|
|
argv.size());
|
2016-11-18 21:01:26 +01:00
|
|
|
}
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-18 21:01:26 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& filename = args[0];
|
|
|
|
const std::string& stagestr = args[1];
|
|
|
|
|
|
|
|
// Store this value in the misc partition, immediately after the
|
|
|
|
// bootloader message that the main recovery uses to save its
|
|
|
|
// arguments in case of the device restarting midway through
|
|
|
|
// package installation.
|
|
|
|
bootloader_message boot;
|
|
|
|
std::string err;
|
|
|
|
if (!read_bootloader_message_from(&boot, filename, &err)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
|
|
|
strlcpy(boot.stage, stagestr.c_str(), sizeof(boot.stage));
|
|
|
|
if (!write_bootloader_message_to(boot, filename, &err)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err;
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue(filename);
|
2013-11-25 22:53:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return the value most recently saved with SetStageFn. The argument
|
|
|
|
// is the block device for the misc partition.
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* GetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
|
2016-11-18 21:01:26 +01:00
|
|
|
}
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-18 21:01:26 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& filename = args[0];
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
bootloader_message boot;
|
|
|
|
std::string err;
|
|
|
|
if (!read_bootloader_message_from(&boot, filename, &err)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue(boot.stage);
|
2013-11-25 22:53:25 +01:00
|
|
|
}
|
|
|
|
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* WipeBlockDeviceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.size() != 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
|
|
|
|
argv.size());
|
2016-11-28 20:48:43 +01:00
|
|
|
}
|
2014-02-25 01:02:50 +01:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-28 20:48:43 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& filename = args[0];
|
|
|
|
const std::string& len_str = args[1];
|
2014-02-25 01:02:50 +01:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
size_t len;
|
|
|
|
if (!android::base::ParseUint(len_str.c_str(), &len)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2018-08-27 19:50:31 +02:00
|
|
|
|
2019-05-14 19:54:43 +02:00
|
|
|
auto updater_runtime = state->updater->GetRuntime();
|
|
|
|
int status = updater_runtime->WipeBlockDevice(filename, len);
|
|
|
|
return StringValue(status == 0 ? "t" : "");
|
2014-02-25 01:02:50 +01:00
|
|
|
}
|
|
|
|
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* EnableRebootFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (!argv.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name,
|
|
|
|
argv.size());
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2019-05-14 19:54:43 +02:00
|
|
|
state->updater->WriteToCommandPipe("enable_reboot");
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue("t");
|
2014-05-23 17:40:35 +02:00
|
|
|
}
|
|
|
|
|
2017-03-06 23:44:59 +01:00
|
|
|
Value* Tune2FsFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
|
|
|
|
if (argv.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %zu", name, argv.size());
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2014-11-21 09:12:28 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
2017-03-06 23:44:59 +01:00
|
|
|
if (!ReadArgs(state, argv, &args)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name);
|
|
|
|
}
|
2014-11-21 09:12:28 +01:00
|
|
|
|
2018-12-20 18:44:06 +01:00
|
|
|
// tune2fs expects the program name as its first arg.
|
|
|
|
args.insert(args.begin(), "tune2fs");
|
2019-05-14 19:54:43 +02:00
|
|
|
auto updater_runtime = state->updater->GetRuntime();
|
|
|
|
if (auto result = updater_runtime->Tune2Fs(args); result != 0) {
|
2016-11-23 01:29:50 +01:00
|
|
|
return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", name, result);
|
|
|
|
}
|
|
|
|
return StringValue("t");
|
2014-11-21 09:12:28 +01:00
|
|
|
}
|
|
|
|
|
2009-06-10 23:11:53 +02:00
|
|
|
void RegisterInstallFunctions() {
|
2016-11-23 01:29:50 +01:00
|
|
|
RegisterFunction("mount", MountFn);
|
|
|
|
RegisterFunction("is_mounted", IsMountedFn);
|
|
|
|
RegisterFunction("unmount", UnmountFn);
|
|
|
|
RegisterFunction("format", FormatFn);
|
|
|
|
RegisterFunction("show_progress", ShowProgressFn);
|
|
|
|
RegisterFunction("set_progress", SetProgressFn);
|
|
|
|
RegisterFunction("package_extract_file", PackageExtractFileFn);
|
|
|
|
|
|
|
|
RegisterFunction("getprop", GetPropFn);
|
|
|
|
RegisterFunction("file_getprop", FileGetPropFn);
|
|
|
|
|
|
|
|
RegisterFunction("apply_patch_space", ApplyPatchSpaceFn);
|
applypatch: Refactor applypatch().
applypatch() was initially designed for file-based OTA, operating on
individual files. It was later extended to allow patching eMMC targets
as a whole, in favor of block-based updates.
As we have deprecated file-based OTA since Oreo, part of the code in
applypatch() has become obsolete. This CL refactors the related
functions, by removing the obsolete logic and focusing on eMMC targets.
Since this CL substantially changes applypatch APIs, it adds new
functions to avoid unintentionally mixing them together. In particular,
it removes `applypatch()`, `applypatch_check()`, `applypatch_flash()`,
and adds `PatchPartition()`, `PatchPartitionCheck()`, `FlashPartition()`
and `CheckPartition()`. It also replaces the old Edify functions
`apply_patch()` and `apply_patch_check()` with `patch_partition()` and
`patch_partition_check()` respectively.
This CL requires matching changes to OTA generation script (in the same
topic).
Bug: 110106408
Test: Run recovery_unit_test and recovery_component_test on marlin.
Test: `m dist` with non-A/B target. Verify
/system/bin/install-recovery.sh on device.
Test: `m dist` with non-A/B target using BOARD_USES_FULL_RECOVERY_IMAGE.
Verify /system/bin/install-recovery.sh on device.
Test: Install an incremental OTA with the new updater and scripts.
Change-Id: Ia34a90114bb227f4216eb478c22dc98c8194cb7f
2018-06-20 09:30:48 +02:00
|
|
|
RegisterFunction("patch_partition", PatchPartitionFn);
|
|
|
|
RegisterFunction("patch_partition_check", PatchPartitionCheckFn);
|
2016-11-23 01:29:50 +01:00
|
|
|
|
|
|
|
RegisterFunction("wipe_block_device", WipeBlockDeviceFn);
|
|
|
|
|
|
|
|
RegisterFunction("read_file", ReadFileFn);
|
|
|
|
RegisterFunction("write_value", WriteValueFn);
|
|
|
|
|
|
|
|
RegisterFunction("wipe_cache", WipeCacheFn);
|
|
|
|
|
|
|
|
RegisterFunction("ui_print", UIPrintFn);
|
|
|
|
|
|
|
|
RegisterFunction("run_program", RunProgramFn);
|
|
|
|
|
|
|
|
RegisterFunction("reboot_now", RebootNowFn);
|
|
|
|
RegisterFunction("get_stage", GetStageFn);
|
|
|
|
RegisterFunction("set_stage", SetStageFn);
|
|
|
|
|
|
|
|
RegisterFunction("enable_reboot", EnableRebootFn);
|
|
|
|
RegisterFunction("tune2fs", Tune2FsFn);
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|