xref: /aosp_15_r20/system/update_engine/aosp/sideload_main.cc (revision 5a9231315b4521097b8dc3750bc806fcafe0c72f)
1*5a923131SAndroid Build Coastguard Worker //
2*5a923131SAndroid Build Coastguard Worker // Copyright (C) 2016 The Android Open Source Project
3*5a923131SAndroid Build Coastguard Worker //
4*5a923131SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*5a923131SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*5a923131SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*5a923131SAndroid Build Coastguard Worker //
8*5a923131SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
9*5a923131SAndroid Build Coastguard Worker //
10*5a923131SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*5a923131SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*5a923131SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5a923131SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*5a923131SAndroid Build Coastguard Worker // limitations under the License.
15*5a923131SAndroid Build Coastguard Worker //
16*5a923131SAndroid Build Coastguard Worker 
17*5a923131SAndroid Build Coastguard Worker #include <xz.h>
18*5a923131SAndroid Build Coastguard Worker 
19*5a923131SAndroid Build Coastguard Worker #include <string>
20*5a923131SAndroid Build Coastguard Worker #include <vector>
21*5a923131SAndroid Build Coastguard Worker 
22*5a923131SAndroid Build Coastguard Worker #include <base/command_line.h>
23*5a923131SAndroid Build Coastguard Worker #include <base/strings/string_split.h>
24*5a923131SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
25*5a923131SAndroid Build Coastguard Worker #include <brillo/asynchronous_signal_handler.h>
26*5a923131SAndroid Build Coastguard Worker #include <brillo/flag_helper.h>
27*5a923131SAndroid Build Coastguard Worker #include <brillo/message_loops/base_message_loop.h>
28*5a923131SAndroid Build Coastguard Worker #include <brillo/streams/file_stream.h>
29*5a923131SAndroid Build Coastguard Worker #include <brillo/streams/stream.h>
30*5a923131SAndroid Build Coastguard Worker 
31*5a923131SAndroid Build Coastguard Worker #include "update_engine/aosp/update_attempter_android.h"
32*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/boot_control.h"
33*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/error_code_utils.h"
34*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/hardware.h"
35*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/logging.h"
36*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/prefs.h"
37*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/subprocess.h"
38*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/terminator.h"
39*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/utils.h"
40*5a923131SAndroid Build Coastguard Worker 
41*5a923131SAndroid Build Coastguard Worker using std::string;
42*5a923131SAndroid Build Coastguard Worker using std::vector;
43*5a923131SAndroid Build Coastguard Worker using update_engine::UpdateEngineStatus;
44*5a923131SAndroid Build Coastguard Worker using update_engine::UpdateStatus;
45*5a923131SAndroid Build Coastguard Worker 
46*5a923131SAndroid Build Coastguard Worker namespace chromeos_update_engine {
47*5a923131SAndroid Build Coastguard Worker namespace {
48*5a923131SAndroid Build Coastguard Worker 
49*5a923131SAndroid Build Coastguard Worker class SideloadDaemonState : public DaemonStateInterface,
50*5a923131SAndroid Build Coastguard Worker                             public ServiceObserverInterface {
51*5a923131SAndroid Build Coastguard Worker  public:
SideloadDaemonState(brillo::StreamPtr status_stream)52*5a923131SAndroid Build Coastguard Worker   explicit SideloadDaemonState(brillo::StreamPtr status_stream)
53*5a923131SAndroid Build Coastguard Worker       : status_stream_(std::move(status_stream)) {
54*5a923131SAndroid Build Coastguard Worker     // Add this class as the only observer.
55*5a923131SAndroid Build Coastguard Worker     observers_.insert(this);
56*5a923131SAndroid Build Coastguard Worker   }
57*5a923131SAndroid Build Coastguard Worker   ~SideloadDaemonState() override = default;
58*5a923131SAndroid Build Coastguard Worker 
59*5a923131SAndroid Build Coastguard Worker   // DaemonStateInterface overrides.
StartUpdater()60*5a923131SAndroid Build Coastguard Worker   bool StartUpdater() override { return true; }
AddObserver(ServiceObserverInterface * observer)61*5a923131SAndroid Build Coastguard Worker   void AddObserver(ServiceObserverInterface* observer) override {}
RemoveObserver(ServiceObserverInterface * observer)62*5a923131SAndroid Build Coastguard Worker   void RemoveObserver(ServiceObserverInterface* observer) override {}
service_observers()63*5a923131SAndroid Build Coastguard Worker   const std::set<ServiceObserverInterface*>& service_observers() override {
64*5a923131SAndroid Build Coastguard Worker     return observers_;
65*5a923131SAndroid Build Coastguard Worker   }
66*5a923131SAndroid Build Coastguard Worker 
67*5a923131SAndroid Build Coastguard Worker   // ServiceObserverInterface overrides.
SendStatusUpdate(const UpdateEngineStatus & update_engine_status)68*5a923131SAndroid Build Coastguard Worker   void SendStatusUpdate(
69*5a923131SAndroid Build Coastguard Worker       const UpdateEngineStatus& update_engine_status) override {
70*5a923131SAndroid Build Coastguard Worker     UpdateStatus status = update_engine_status.status;
71*5a923131SAndroid Build Coastguard Worker     double progress = update_engine_status.progress;
72*5a923131SAndroid Build Coastguard Worker     if (status_ != status && (status == UpdateStatus::DOWNLOADING ||
73*5a923131SAndroid Build Coastguard Worker                               status == UpdateStatus::FINALIZING)) {
74*5a923131SAndroid Build Coastguard Worker       // Split the progress bar in two parts for the two stages DOWNLOADING and
75*5a923131SAndroid Build Coastguard Worker       // FINALIZING.
76*5a923131SAndroid Build Coastguard Worker       ReportStatus(android::base::StringPrintf(
77*5a923131SAndroid Build Coastguard Worker           "ui_print Step %d/2", status == UpdateStatus::DOWNLOADING ? 1 : 2));
78*5a923131SAndroid Build Coastguard Worker       ReportStatus(android::base::StringPrintf("progress 0.5 0"));
79*5a923131SAndroid Build Coastguard Worker     }
80*5a923131SAndroid Build Coastguard Worker     if (status_ != status || fabs(progress - progress_) > 0.005) {
81*5a923131SAndroid Build Coastguard Worker       ReportStatus(android::base::StringPrintf("set_progress %.lf", progress));
82*5a923131SAndroid Build Coastguard Worker     }
83*5a923131SAndroid Build Coastguard Worker     progress_ = progress;
84*5a923131SAndroid Build Coastguard Worker     status_ = status;
85*5a923131SAndroid Build Coastguard Worker   }
86*5a923131SAndroid Build Coastguard Worker 
SendPayloadApplicationComplete(ErrorCode error_code)87*5a923131SAndroid Build Coastguard Worker   void SendPayloadApplicationComplete(ErrorCode error_code) override {
88*5a923131SAndroid Build Coastguard Worker     if (error_code != ErrorCode::kSuccess) {
89*5a923131SAndroid Build Coastguard Worker       ReportStatus(android::base::StringPrintf(
90*5a923131SAndroid Build Coastguard Worker           "ui_print Error applying update: %d (%s)",
91*5a923131SAndroid Build Coastguard Worker           error_code,
92*5a923131SAndroid Build Coastguard Worker           utils::ErrorCodeToString(error_code).c_str()));
93*5a923131SAndroid Build Coastguard Worker     }
94*5a923131SAndroid Build Coastguard Worker     error_code_ = error_code;
95*5a923131SAndroid Build Coastguard Worker     brillo::MessageLoop::current()->BreakLoop();
96*5a923131SAndroid Build Coastguard Worker   }
97*5a923131SAndroid Build Coastguard Worker 
98*5a923131SAndroid Build Coastguard Worker   // Getters.
status()99*5a923131SAndroid Build Coastguard Worker   UpdateStatus status() { return status_; }
error_code()100*5a923131SAndroid Build Coastguard Worker   ErrorCode error_code() { return error_code_; }
101*5a923131SAndroid Build Coastguard Worker 
102*5a923131SAndroid Build Coastguard Worker  private:
103*5a923131SAndroid Build Coastguard Worker   // Report a status message in the status_stream_, if any. These messages
104*5a923131SAndroid Build Coastguard Worker   // should conform to the specification defined in the Android recovery.
ReportStatus(const string & message)105*5a923131SAndroid Build Coastguard Worker   void ReportStatus(const string& message) {
106*5a923131SAndroid Build Coastguard Worker     if (!status_stream_)
107*5a923131SAndroid Build Coastguard Worker       return;
108*5a923131SAndroid Build Coastguard Worker     string status_line = message + "\n";
109*5a923131SAndroid Build Coastguard Worker     status_stream_->WriteAllBlocking(
110*5a923131SAndroid Build Coastguard Worker         status_line.data(), status_line.size(), nullptr);
111*5a923131SAndroid Build Coastguard Worker   }
112*5a923131SAndroid Build Coastguard Worker 
113*5a923131SAndroid Build Coastguard Worker   std::set<ServiceObserverInterface*> observers_;
114*5a923131SAndroid Build Coastguard Worker   brillo::StreamPtr status_stream_;
115*5a923131SAndroid Build Coastguard Worker 
116*5a923131SAndroid Build Coastguard Worker   // The last status and error code reported.
117*5a923131SAndroid Build Coastguard Worker   UpdateStatus status_{UpdateStatus::IDLE};
118*5a923131SAndroid Build Coastguard Worker   ErrorCode error_code_{ErrorCode::kSuccess};
119*5a923131SAndroid Build Coastguard Worker   double progress_{-1.};
120*5a923131SAndroid Build Coastguard Worker };
121*5a923131SAndroid Build Coastguard Worker 
122*5a923131SAndroid Build Coastguard Worker // Apply an update payload directly from the given payload URI.
ApplyUpdatePayload(const string & payload,int64_t payload_offset,int64_t payload_size,const vector<string> & headers,int64_t status_fd)123*5a923131SAndroid Build Coastguard Worker bool ApplyUpdatePayload(const string& payload,
124*5a923131SAndroid Build Coastguard Worker                         int64_t payload_offset,
125*5a923131SAndroid Build Coastguard Worker                         int64_t payload_size,
126*5a923131SAndroid Build Coastguard Worker                         const vector<string>& headers,
127*5a923131SAndroid Build Coastguard Worker                         int64_t status_fd) {
128*5a923131SAndroid Build Coastguard Worker   brillo::BaseMessageLoop loop;
129*5a923131SAndroid Build Coastguard Worker   loop.SetAsCurrent();
130*5a923131SAndroid Build Coastguard Worker 
131*5a923131SAndroid Build Coastguard Worker   // Setup the subprocess handler.
132*5a923131SAndroid Build Coastguard Worker   brillo::AsynchronousSignalHandler handler;
133*5a923131SAndroid Build Coastguard Worker   handler.Init();
134*5a923131SAndroid Build Coastguard Worker   Subprocess subprocess;
135*5a923131SAndroid Build Coastguard Worker   subprocess.Init(&handler);
136*5a923131SAndroid Build Coastguard Worker 
137*5a923131SAndroid Build Coastguard Worker   SideloadDaemonState sideload_daemon_state(
138*5a923131SAndroid Build Coastguard Worker       brillo::FileStream::FromFileDescriptor(status_fd, true, nullptr));
139*5a923131SAndroid Build Coastguard Worker 
140*5a923131SAndroid Build Coastguard Worker   // During the sideload we don't access the prefs persisted on disk but instead
141*5a923131SAndroid Build Coastguard Worker   // use a temporary memory storage.
142*5a923131SAndroid Build Coastguard Worker   MemoryPrefs prefs;
143*5a923131SAndroid Build Coastguard Worker 
144*5a923131SAndroid Build Coastguard Worker   std::unique_ptr<BootControlInterface> boot_control =
145*5a923131SAndroid Build Coastguard Worker       boot_control::CreateBootControl();
146*5a923131SAndroid Build Coastguard Worker   if (!boot_control) {
147*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "Error initializing the BootControlInterface.";
148*5a923131SAndroid Build Coastguard Worker     return false;
149*5a923131SAndroid Build Coastguard Worker   }
150*5a923131SAndroid Build Coastguard Worker 
151*5a923131SAndroid Build Coastguard Worker   std::unique_ptr<HardwareInterface> hardware = hardware::CreateHardware();
152*5a923131SAndroid Build Coastguard Worker   if (!hardware) {
153*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "Error initializing the HardwareInterface.";
154*5a923131SAndroid Build Coastguard Worker     return false;
155*5a923131SAndroid Build Coastguard Worker   }
156*5a923131SAndroid Build Coastguard Worker 
157*5a923131SAndroid Build Coastguard Worker   UpdateAttempterAndroid update_attempter(&sideload_daemon_state,
158*5a923131SAndroid Build Coastguard Worker                                           &prefs,
159*5a923131SAndroid Build Coastguard Worker                                           boot_control.get(),
160*5a923131SAndroid Build Coastguard Worker                                           hardware.get(),
161*5a923131SAndroid Build Coastguard Worker                                           nullptr);
162*5a923131SAndroid Build Coastguard Worker   update_attempter.Init();
163*5a923131SAndroid Build Coastguard Worker 
164*5a923131SAndroid Build Coastguard Worker   TEST_AND_RETURN_FALSE(update_attempter.ApplyPayload(
165*5a923131SAndroid Build Coastguard Worker       payload, payload_offset, payload_size, headers, nullptr));
166*5a923131SAndroid Build Coastguard Worker 
167*5a923131SAndroid Build Coastguard Worker   loop.Run();
168*5a923131SAndroid Build Coastguard Worker   return sideload_daemon_state.status() == UpdateStatus::UPDATED_NEED_REBOOT;
169*5a923131SAndroid Build Coastguard Worker }
170*5a923131SAndroid Build Coastguard Worker 
171*5a923131SAndroid Build Coastguard Worker }  // namespace
172*5a923131SAndroid Build Coastguard Worker }  // namespace chromeos_update_engine
173*5a923131SAndroid Build Coastguard Worker 
main(int argc,char ** argv)174*5a923131SAndroid Build Coastguard Worker int main(int argc, char** argv) {
175*5a923131SAndroid Build Coastguard Worker   DEFINE_string(payload,
176*5a923131SAndroid Build Coastguard Worker                 "file:///data/payload.bin",
177*5a923131SAndroid Build Coastguard Worker                 "The URI to the update payload to use.");
178*5a923131SAndroid Build Coastguard Worker   DEFINE_int64(
179*5a923131SAndroid Build Coastguard Worker       offset, 0, "The offset in the payload where the CrAU update starts. ");
180*5a923131SAndroid Build Coastguard Worker   DEFINE_int64(size,
181*5a923131SAndroid Build Coastguard Worker                0,
182*5a923131SAndroid Build Coastguard Worker                "The size of the CrAU part of the payload. If 0 is passed, it "
183*5a923131SAndroid Build Coastguard Worker                "will be autodetected.");
184*5a923131SAndroid Build Coastguard Worker   DEFINE_string(headers,
185*5a923131SAndroid Build Coastguard Worker                 "",
186*5a923131SAndroid Build Coastguard Worker                 "A list of key-value pairs, one element of the list per line.");
187*5a923131SAndroid Build Coastguard Worker   DEFINE_int64(status_fd, -1, "A file descriptor to notify the update status.");
188*5a923131SAndroid Build Coastguard Worker 
189*5a923131SAndroid Build Coastguard Worker   chromeos_update_engine::Terminator::Init();
190*5a923131SAndroid Build Coastguard Worker   chromeos_update_engine::SetupLogging(true /* stderr */, false /* file */);
191*5a923131SAndroid Build Coastguard Worker   brillo::FlagHelper::Init(argc, argv, "Update Engine Sideload");
192*5a923131SAndroid Build Coastguard Worker 
193*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "Update Engine Sideloading starting";
194*5a923131SAndroid Build Coastguard Worker 
195*5a923131SAndroid Build Coastguard Worker   // xz-embedded requires to initialize its CRC-32 table once on startup.
196*5a923131SAndroid Build Coastguard Worker   xz_crc32_init();
197*5a923131SAndroid Build Coastguard Worker 
198*5a923131SAndroid Build Coastguard Worker   vector<string> headers = base::SplitString(
199*5a923131SAndroid Build Coastguard Worker       FLAGS_headers, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
200*5a923131SAndroid Build Coastguard Worker 
201*5a923131SAndroid Build Coastguard Worker   if (!chromeos_update_engine::ApplyUpdatePayload(
202*5a923131SAndroid Build Coastguard Worker           FLAGS_payload, FLAGS_offset, FLAGS_size, headers, FLAGS_status_fd))
203*5a923131SAndroid Build Coastguard Worker     return 1;
204*5a923131SAndroid Build Coastguard Worker 
205*5a923131SAndroid Build Coastguard Worker   return 0;
206*5a923131SAndroid Build Coastguard Worker }
207