1*acea8879SAndroid Build Coastguard Worker /*
2*acea8879SAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*acea8879SAndroid Build Coastguard Worker *
4*acea8879SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*acea8879SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*acea8879SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*acea8879SAndroid Build Coastguard Worker *
8*acea8879SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*acea8879SAndroid Build Coastguard Worker *
10*acea8879SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*acea8879SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*acea8879SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*acea8879SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*acea8879SAndroid Build Coastguard Worker * limitations under the License.
15*acea8879SAndroid Build Coastguard Worker */
16*acea8879SAndroid Build Coastguard Worker
17*acea8879SAndroid Build Coastguard Worker #include "updater/dynamic_partitions.h"
18*acea8879SAndroid Build Coastguard Worker
19*acea8879SAndroid Build Coastguard Worker #include <sys/stat.h>
20*acea8879SAndroid Build Coastguard Worker #include <sys/types.h>
21*acea8879SAndroid Build Coastguard Worker
22*acea8879SAndroid Build Coastguard Worker #include <memory>
23*acea8879SAndroid Build Coastguard Worker #include <string>
24*acea8879SAndroid Build Coastguard Worker #include <vector>
25*acea8879SAndroid Build Coastguard Worker
26*acea8879SAndroid Build Coastguard Worker #include <android-base/file.h>
27*acea8879SAndroid Build Coastguard Worker #include <android-base/logging.h>
28*acea8879SAndroid Build Coastguard Worker #include <android-base/strings.h>
29*acea8879SAndroid Build Coastguard Worker
30*acea8879SAndroid Build Coastguard Worker #include "edify/expr.h"
31*acea8879SAndroid Build Coastguard Worker #include "edify/updater_runtime_interface.h"
32*acea8879SAndroid Build Coastguard Worker #include "otautil/error_code.h"
33*acea8879SAndroid Build Coastguard Worker #include "otautil/paths.h"
34*acea8879SAndroid Build Coastguard Worker #include "private/utils.h"
35*acea8879SAndroid Build Coastguard Worker
ReadStringArgs(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv,const std::vector<std::string> & arg_names)36*acea8879SAndroid Build Coastguard Worker static std::vector<std::string> ReadStringArgs(const char* name, State* state,
37*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv,
38*acea8879SAndroid Build Coastguard Worker const std::vector<std::string>& arg_names) {
39*acea8879SAndroid Build Coastguard Worker if (argv.size() != arg_names.size()) {
40*acea8879SAndroid Build Coastguard Worker ErrorAbort(state, kArgsParsingFailure, "%s expects %zu arguments, got %zu", name,
41*acea8879SAndroid Build Coastguard Worker arg_names.size(), argv.size());
42*acea8879SAndroid Build Coastguard Worker return {};
43*acea8879SAndroid Build Coastguard Worker }
44*acea8879SAndroid Build Coastguard Worker
45*acea8879SAndroid Build Coastguard Worker std::vector<std::unique_ptr<Value>> args;
46*acea8879SAndroid Build Coastguard Worker if (!ReadValueArgs(state, argv, &args)) {
47*acea8879SAndroid Build Coastguard Worker return {};
48*acea8879SAndroid Build Coastguard Worker }
49*acea8879SAndroid Build Coastguard Worker
50*acea8879SAndroid Build Coastguard Worker CHECK_EQ(args.size(), arg_names.size());
51*acea8879SAndroid Build Coastguard Worker
52*acea8879SAndroid Build Coastguard Worker for (size_t i = 0; i < arg_names.size(); ++i) {
53*acea8879SAndroid Build Coastguard Worker if (args[i]->type != Value::Type::STRING) {
54*acea8879SAndroid Build Coastguard Worker ErrorAbort(state, kArgsParsingFailure, "%s argument to %s must be string",
55*acea8879SAndroid Build Coastguard Worker arg_names[i].c_str(), name);
56*acea8879SAndroid Build Coastguard Worker return {};
57*acea8879SAndroid Build Coastguard Worker }
58*acea8879SAndroid Build Coastguard Worker }
59*acea8879SAndroid Build Coastguard Worker
60*acea8879SAndroid Build Coastguard Worker std::vector<std::string> ret;
61*acea8879SAndroid Build Coastguard Worker std::transform(args.begin(), args.end(), std::back_inserter(ret),
62*acea8879SAndroid Build Coastguard Worker [](const auto& arg) { return arg->data; });
63*acea8879SAndroid Build Coastguard Worker return ret;
64*acea8879SAndroid Build Coastguard Worker }
65*acea8879SAndroid Build Coastguard Worker
UnmapPartitionFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)66*acea8879SAndroid Build Coastguard Worker Value* UnmapPartitionFn(const char* name, State* state,
67*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
68*acea8879SAndroid Build Coastguard Worker auto args = ReadStringArgs(name, state, argv, { "name" });
69*acea8879SAndroid Build Coastguard Worker if (args.empty()) return StringValue("");
70*acea8879SAndroid Build Coastguard Worker
71*acea8879SAndroid Build Coastguard Worker auto updater_runtime = state->updater->GetRuntime();
72*acea8879SAndroid Build Coastguard Worker return updater_runtime->UnmapPartitionOnDeviceMapper(args[0]) ? StringValue("t")
73*acea8879SAndroid Build Coastguard Worker : StringValue("");
74*acea8879SAndroid Build Coastguard Worker }
75*acea8879SAndroid Build Coastguard Worker
MapPartitionFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)76*acea8879SAndroid Build Coastguard Worker Value* MapPartitionFn(const char* name, State* state,
77*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
78*acea8879SAndroid Build Coastguard Worker auto args = ReadStringArgs(name, state, argv, { "name" });
79*acea8879SAndroid Build Coastguard Worker if (args.empty()) return StringValue("");
80*acea8879SAndroid Build Coastguard Worker
81*acea8879SAndroid Build Coastguard Worker std::string path;
82*acea8879SAndroid Build Coastguard Worker auto updater_runtime = state->updater->GetRuntime();
83*acea8879SAndroid Build Coastguard Worker bool result = updater_runtime->MapPartitionOnDeviceMapper(args[0], &path);
84*acea8879SAndroid Build Coastguard Worker return result ? StringValue(path) : StringValue("");
85*acea8879SAndroid Build Coastguard Worker }
86*acea8879SAndroid Build Coastguard Worker
87*acea8879SAndroid Build Coastguard Worker static constexpr char kMetadataUpdatedMarker[] = "/dynamic_partition_metadata.UPDATED";
88*acea8879SAndroid Build Coastguard Worker
UpdateDynamicPartitionsFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)89*acea8879SAndroid Build Coastguard Worker Value* UpdateDynamicPartitionsFn(const char* name, State* state,
90*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
91*acea8879SAndroid Build Coastguard Worker if (argv.size() != 1) {
92*acea8879SAndroid Build Coastguard Worker ErrorAbort(state, kArgsParsingFailure, "%s expects 1 arguments, got %zu", name, argv.size());
93*acea8879SAndroid Build Coastguard Worker return StringValue("");
94*acea8879SAndroid Build Coastguard Worker }
95*acea8879SAndroid Build Coastguard Worker std::vector<std::unique_ptr<Value>> args;
96*acea8879SAndroid Build Coastguard Worker if (!ReadValueArgs(state, argv, &args)) {
97*acea8879SAndroid Build Coastguard Worker return nullptr;
98*acea8879SAndroid Build Coastguard Worker }
99*acea8879SAndroid Build Coastguard Worker const std::unique_ptr<Value>& op_list_value = args[0];
100*acea8879SAndroid Build Coastguard Worker if (op_list_value->type != Value::Type::BLOB) {
101*acea8879SAndroid Build Coastguard Worker ErrorAbort(state, kArgsParsingFailure, "op_list argument to %s must be blob", name);
102*acea8879SAndroid Build Coastguard Worker return StringValue("");
103*acea8879SAndroid Build Coastguard Worker }
104*acea8879SAndroid Build Coastguard Worker
105*acea8879SAndroid Build Coastguard Worker std::string updated_marker = Paths::Get().stash_directory_base() + kMetadataUpdatedMarker;
106*acea8879SAndroid Build Coastguard Worker if (state->is_retry) {
107*acea8879SAndroid Build Coastguard Worker struct stat sb;
108*acea8879SAndroid Build Coastguard Worker int result = stat(updated_marker.c_str(), &sb);
109*acea8879SAndroid Build Coastguard Worker if (result == 0) {
110*acea8879SAndroid Build Coastguard Worker LOG(INFO) << "Skipping already updated dynamic partition metadata based on marker";
111*acea8879SAndroid Build Coastguard Worker return StringValue("t");
112*acea8879SAndroid Build Coastguard Worker }
113*acea8879SAndroid Build Coastguard Worker } else {
114*acea8879SAndroid Build Coastguard Worker // Delete the obsolete marker if any.
115*acea8879SAndroid Build Coastguard Worker std::string err;
116*acea8879SAndroid Build Coastguard Worker if (!android::base::RemoveFileIfExists(updated_marker, &err)) {
117*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to remove dynamic partition metadata updated marker " << updated_marker
118*acea8879SAndroid Build Coastguard Worker << ": " << err;
119*acea8879SAndroid Build Coastguard Worker return StringValue("");
120*acea8879SAndroid Build Coastguard Worker }
121*acea8879SAndroid Build Coastguard Worker }
122*acea8879SAndroid Build Coastguard Worker
123*acea8879SAndroid Build Coastguard Worker auto updater_runtime = state->updater->GetRuntime();
124*acea8879SAndroid Build Coastguard Worker if (!updater_runtime->UpdateDynamicPartitions(op_list_value->data)) {
125*acea8879SAndroid Build Coastguard Worker return StringValue("");
126*acea8879SAndroid Build Coastguard Worker }
127*acea8879SAndroid Build Coastguard Worker
128*acea8879SAndroid Build Coastguard Worker if (!SetUpdatedMarker(updated_marker)) {
129*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to set metadata updated marker.";
130*acea8879SAndroid Build Coastguard Worker return StringValue("");
131*acea8879SAndroid Build Coastguard Worker }
132*acea8879SAndroid Build Coastguard Worker
133*acea8879SAndroid Build Coastguard Worker return StringValue("t");
134*acea8879SAndroid Build Coastguard Worker }
135*acea8879SAndroid Build Coastguard Worker
RegisterDynamicPartitionsFunctions()136*acea8879SAndroid Build Coastguard Worker void RegisterDynamicPartitionsFunctions() {
137*acea8879SAndroid Build Coastguard Worker RegisterFunction("unmap_partition", UnmapPartitionFn);
138*acea8879SAndroid Build Coastguard Worker RegisterFunction("map_partition", MapPartitionFn);
139*acea8879SAndroid Build Coastguard Worker RegisterFunction("update_dynamic_partitions", UpdateDynamicPartitionsFn);
140*acea8879SAndroid Build Coastguard Worker }
141