blob: 27967cda33bca6d5c8990a83196a5e06485453eb [file] [log] [blame]
Alex Deymo03a4de72016-07-20 16:08:23 -07001//
2// Copyright (C) 2016 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include <xz.h>
18
19#include <string>
20#include <vector>
21
22#include <base/command_line.h>
Alex Deymo03a4de72016-07-20 16:08:23 -070023#include <base/strings/string_split.h>
Alex Deymo40a017d2016-08-02 17:27:02 -070024#include <base/strings/stringprintf.h>
25#include <brillo/asynchronous_signal_handler.h>
Alex Deymo03a4de72016-07-20 16:08:23 -070026#include <brillo/flag_helper.h>
27#include <brillo/message_loops/base_message_loop.h>
Alex Deymo40a017d2016-08-02 17:27:02 -070028#include <brillo/streams/file_stream.h>
29#include <brillo/streams/stream.h>
Alex Deymo03a4de72016-07-20 16:08:23 -070030
31#include "update_engine/common/boot_control.h"
Alex Deymo40a017d2016-08-02 17:27:02 -070032#include "update_engine/common/error_code_utils.h"
Alex Deymo03a4de72016-07-20 16:08:23 -070033#include "update_engine/common/hardware.h"
34#include "update_engine/common/prefs.h"
Alex Deymo40a017d2016-08-02 17:27:02 -070035#include "update_engine/common/subprocess.h"
Alex Deymo03a4de72016-07-20 16:08:23 -070036#include "update_engine/common/terminator.h"
37#include "update_engine/common/utils.h"
Yifan Honge7574202020-04-06 15:08:24 -070038#include "update_engine/logging.h"
Alex Deymo03a4de72016-07-20 16:08:23 -070039#include "update_engine/update_attempter_android.h"
40
41using std::string;
42using std::vector;
Aaron Wood7f92e2b2017-08-28 14:51:21 -070043using update_engine::UpdateEngineStatus;
Amin Hassani7cc8bb02019-01-14 16:29:47 -080044using update_engine::UpdateStatus;
Alex Deymo03a4de72016-07-20 16:08:23 -070045
46namespace chromeos_update_engine {
47namespace {
48
Alex Deymo03a4de72016-07-20 16:08:23 -070049class SideloadDaemonState : public DaemonStateInterface,
50 public ServiceObserverInterface {
51 public:
Alex Deymo40a017d2016-08-02 17:27:02 -070052 explicit SideloadDaemonState(brillo::StreamPtr status_stream)
53 : status_stream_(std::move(status_stream)) {
Alex Deymo03a4de72016-07-20 16:08:23 -070054 // Add this class as the only observer.
55 observers_.insert(this);
56 }
57 ~SideloadDaemonState() override = default;
58
59 // DaemonStateInterface overrides.
60 bool StartUpdater() override { return true; }
61 void AddObserver(ServiceObserverInterface* observer) override {}
62 void RemoveObserver(ServiceObserverInterface* observer) override {}
63 const std::set<ServiceObserverInterface*>& service_observers() override {
64 return observers_;
65 }
66
67 // ServiceObserverInterface overrides.
Aaron Wood7f92e2b2017-08-28 14:51:21 -070068 void SendStatusUpdate(
69 const UpdateEngineStatus& update_engine_status) override {
70 UpdateStatus status = update_engine_status.status;
71 double progress = update_engine_status.progress;
Alex Deymo40a017d2016-08-02 17:27:02 -070072 if (status_ != status && (status == UpdateStatus::DOWNLOADING ||
73 status == UpdateStatus::FINALIZING)) {
74 // Split the progress bar in two parts for the two stages DOWNLOADING and
75 // FINALIZING.
76 ReportStatus(base::StringPrintf(
77 "ui_print Step %d/2", status == UpdateStatus::DOWNLOADING ? 1 : 2));
78 ReportStatus(base::StringPrintf("progress 0.5 0"));
79 }
80 if (status_ != status || fabs(progress - progress_) > 0.005) {
81 ReportStatus(base::StringPrintf("set_progress %.lf", progress));
82 }
83 progress_ = progress;
Alex Deymo03a4de72016-07-20 16:08:23 -070084 status_ = status;
85 }
86
87 void SendPayloadApplicationComplete(ErrorCode error_code) override {
Alex Deymo40a017d2016-08-02 17:27:02 -070088 if (error_code != ErrorCode::kSuccess) {
89 ReportStatus(
90 base::StringPrintf("ui_print Error applying update: %d (%s)",
91 error_code,
92 utils::ErrorCodeToString(error_code).c_str()));
93 }
Alex Deymo03a4de72016-07-20 16:08:23 -070094 error_code_ = error_code;
95 brillo::MessageLoop::current()->BreakLoop();
96 }
97
Alex Deymo03a4de72016-07-20 16:08:23 -070098 // Getters.
Alex Deymo40a017d2016-08-02 17:27:02 -070099 UpdateStatus status() { return status_; }
Alex Deymo03a4de72016-07-20 16:08:23 -0700100 ErrorCode error_code() { return error_code_; }
101
102 private:
Alex Deymo40a017d2016-08-02 17:27:02 -0700103 // Report a status message in the status_stream_, if any. These messages
104 // should conform to the specification defined in the Android recovery.
105 void ReportStatus(const string& message) {
106 if (!status_stream_)
107 return;
108 string status_line = message + "\n";
109 status_stream_->WriteAllBlocking(
110 status_line.data(), status_line.size(), nullptr);
111 }
112
Alex Deymo03a4de72016-07-20 16:08:23 -0700113 std::set<ServiceObserverInterface*> observers_;
Alex Deymo40a017d2016-08-02 17:27:02 -0700114 brillo::StreamPtr status_stream_;
Alex Deymo03a4de72016-07-20 16:08:23 -0700115
116 // The last status and error code reported.
Alex Deymo40a017d2016-08-02 17:27:02 -0700117 UpdateStatus status_{UpdateStatus::IDLE};
Alex Deymo03a4de72016-07-20 16:08:23 -0700118 ErrorCode error_code_{ErrorCode::kSuccess};
Alex Deymo40a017d2016-08-02 17:27:02 -0700119 double progress_{-1.};
Alex Deymo03a4de72016-07-20 16:08:23 -0700120};
121
122// Apply an update payload directly from the given payload URI.
123bool ApplyUpdatePayload(const string& payload,
124 int64_t payload_offset,
125 int64_t payload_size,
Alex Deymo40a017d2016-08-02 17:27:02 -0700126 const vector<string>& headers,
127 int64_t status_fd) {
Alex Deymo03a4de72016-07-20 16:08:23 -0700128 brillo::BaseMessageLoop loop;
129 loop.SetAsCurrent();
130
Alex Deymo40a017d2016-08-02 17:27:02 -0700131 // Setup the subprocess handler.
132 brillo::AsynchronousSignalHandler handler;
133 handler.Init();
134 Subprocess subprocess;
135 subprocess.Init(&handler);
136
137 SideloadDaemonState sideload_daemon_state(
138 brillo::FileStream::FromFileDescriptor(status_fd, true, nullptr));
Alex Deymo03a4de72016-07-20 16:08:23 -0700139
140 // During the sideload we don't access the prefs persisted on disk but instead
141 // use a temporary memory storage.
142 MemoryPrefs prefs;
143
144 std::unique_ptr<BootControlInterface> boot_control =
145 boot_control::CreateBootControl();
146 if (!boot_control) {
147 LOG(ERROR) << "Error initializing the BootControlInterface.";
148 return false;
149 }
150
151 std::unique_ptr<HardwareInterface> hardware = hardware::CreateHardware();
152 if (!hardware) {
153 LOG(ERROR) << "Error initializing the HardwareInterface.";
154 return false;
155 }
156
157 UpdateAttempterAndroid update_attempter(
158 &sideload_daemon_state, &prefs, boot_control.get(), hardware.get());
159 update_attempter.Init();
160
161 TEST_AND_RETURN_FALSE(update_attempter.ApplyPayload(
162 payload, payload_offset, payload_size, headers, nullptr));
163
164 loop.Run();
Alex Deymo40a017d2016-08-02 17:27:02 -0700165 return sideload_daemon_state.status() == UpdateStatus::UPDATED_NEED_REBOOT;
Alex Deymo03a4de72016-07-20 16:08:23 -0700166}
167
168} // namespace
169} // namespace chromeos_update_engine
170
171int main(int argc, char** argv) {
172 DEFINE_string(payload,
173 "file:///data/payload.bin",
174 "The URI to the update payload to use.");
175 DEFINE_int64(
176 offset, 0, "The offset in the payload where the CrAU update starts. ");
177 DEFINE_int64(size,
178 0,
179 "The size of the CrAU part of the payload. If 0 is passed, it "
180 "will be autodetected.");
181 DEFINE_string(headers,
182 "",
183 "A list of key-value pairs, one element of the list per line.");
Alex Deymo40a017d2016-08-02 17:27:02 -0700184 DEFINE_int64(status_fd, -1, "A file descriptor to notify the update status.");
Alex Deymo03a4de72016-07-20 16:08:23 -0700185
186 chromeos_update_engine::Terminator::Init();
Yifan Honge7574202020-04-06 15:08:24 -0700187 chromeos_update_engine::SetupLogging(true /* stderr */, false /* file */);
Alex Deymo03a4de72016-07-20 16:08:23 -0700188 brillo::FlagHelper::Init(argc, argv, "Update Engine Sideload");
189
190 LOG(INFO) << "Update Engine Sideloading starting";
191
192 // xz-embedded requires to initialize its CRC-32 table once on startup.
193 xz_crc32_init();
194
195 vector<string> headers = base::SplitString(
196 FLAGS_headers, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
197
198 if (!chromeos_update_engine::ApplyUpdatePayload(
Alex Deymo40a017d2016-08-02 17:27:02 -0700199 FLAGS_payload, FLAGS_offset, FLAGS_size, headers, FLAGS_status_fd))
Alex Deymo03a4de72016-07-20 16:08:23 -0700200 return 1;
201
202 return 0;
203}