xref: /aosp_15_r20/bootable/deprecated-ota/updater/dynamic_partitions.cpp (revision acea8879c968027b49a027136800575dd9783ddf)
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