blob: 35ed11bd068a5188928e8f3755d6e04c66564659 [file] [log] [blame]
Alex Deymo578b7872016-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>
23#include <base/logging.h>
24#include <base/strings/string_split.h>
Alex Deymo5462f452016-08-02 17:27:02 -070025#include <base/strings/stringprintf.h>
26#include <brillo/asynchronous_signal_handler.h>
Alex Deymo578b7872016-07-20 16:08:23 -070027#include <brillo/flag_helper.h>
Alex Deymo5462f452016-08-02 17:27:02 -070028#include <brillo/make_unique_ptr.h>
Alex Deymo578b7872016-07-20 16:08:23 -070029#include <brillo/message_loops/base_message_loop.h>
Alex Deymo5462f452016-08-02 17:27:02 -070030#include <brillo/streams/file_stream.h>
31#include <brillo/streams/stream.h>
Alex Deymo578b7872016-07-20 16:08:23 -070032
33#include "update_engine/common/boot_control.h"
Alex Deymo5462f452016-08-02 17:27:02 -070034#include "update_engine/common/error_code_utils.h"
Alex Deymo578b7872016-07-20 16:08:23 -070035#include "update_engine/common/hardware.h"
36#include "update_engine/common/prefs.h"
Alex Deymo5462f452016-08-02 17:27:02 -070037#include "update_engine/common/subprocess.h"
Alex Deymo578b7872016-07-20 16:08:23 -070038#include "update_engine/common/terminator.h"
39#include "update_engine/common/utils.h"
40#include "update_engine/update_attempter_android.h"
41
42using std::string;
43using std::vector;
Alex Deymo5462f452016-08-02 17:27:02 -070044using update_engine::UpdateStatus;
Alex Deymo578b7872016-07-20 16:08:23 -070045
Alex Deymo9629bbc2016-08-10 17:02:49 -070046namespace {
47// The root directory used for temporary files in update_engine_sideload.
48const char kSideloadRootTempDir[] = "/tmp/update_engine_sideload";
49} // namespace
50
Alex Deymo578b7872016-07-20 16:08:23 -070051namespace chromeos_update_engine {
52namespace {
53
54void SetupLogging() {
55 string log_file;
56 logging::LoggingSettings log_settings;
57 log_settings.lock_log = logging::DONT_LOCK_LOG_FILE;
58 log_settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
59 log_settings.log_file = nullptr;
60 log_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
61
62 logging::InitLogging(log_settings);
63}
64
65class SideloadDaemonState : public DaemonStateInterface,
66 public ServiceObserverInterface {
67 public:
Alex Deymo5462f452016-08-02 17:27:02 -070068 explicit SideloadDaemonState(brillo::StreamPtr status_stream)
69 : status_stream_(std::move(status_stream)) {
Alex Deymo578b7872016-07-20 16:08:23 -070070 // Add this class as the only observer.
71 observers_.insert(this);
72 }
73 ~SideloadDaemonState() override = default;
74
75 // DaemonStateInterface overrides.
76 bool StartUpdater() override { return true; }
77 void AddObserver(ServiceObserverInterface* observer) override {}
78 void RemoveObserver(ServiceObserverInterface* observer) override {}
79 const std::set<ServiceObserverInterface*>& service_observers() override {
80 return observers_;
81 }
82
83 // ServiceObserverInterface overrides.
84 void SendStatusUpdate(int64_t last_checked_time,
85 double progress,
Alex Deymo5462f452016-08-02 17:27:02 -070086 UpdateStatus status,
Alex Deymo578b7872016-07-20 16:08:23 -070087 const string& new_version,
88 int64_t new_size) override {
Alex Deymo5462f452016-08-02 17:27:02 -070089 if (status_ != status && (status == UpdateStatus::DOWNLOADING ||
90 status == UpdateStatus::FINALIZING)) {
91 // Split the progress bar in two parts for the two stages DOWNLOADING and
92 // FINALIZING.
93 ReportStatus(base::StringPrintf(
94 "ui_print Step %d/2", status == UpdateStatus::DOWNLOADING ? 1 : 2));
95 ReportStatus(base::StringPrintf("progress 0.5 0"));
96 }
97 if (status_ != status || fabs(progress - progress_) > 0.005) {
98 ReportStatus(base::StringPrintf("set_progress %.lf", progress));
99 }
100 progress_ = progress;
Alex Deymo578b7872016-07-20 16:08:23 -0700101 status_ = status;
102 }
103
104 void SendPayloadApplicationComplete(ErrorCode error_code) override {
Alex Deymo5462f452016-08-02 17:27:02 -0700105 if (error_code != ErrorCode::kSuccess) {
106 ReportStatus(
107 base::StringPrintf("ui_print Error applying update: %d (%s)",
108 error_code,
109 utils::ErrorCodeToString(error_code).c_str()));
110 }
Alex Deymo578b7872016-07-20 16:08:23 -0700111 error_code_ = error_code;
112 brillo::MessageLoop::current()->BreakLoop();
113 }
114
115 void SendChannelChangeUpdate(const string& tracking_channel) override {}
116
117 // Getters.
Alex Deymo5462f452016-08-02 17:27:02 -0700118 UpdateStatus status() { return status_; }
Alex Deymo578b7872016-07-20 16:08:23 -0700119 ErrorCode error_code() { return error_code_; }
120
121 private:
Alex Deymo5462f452016-08-02 17:27:02 -0700122 // Report a status message in the status_stream_, if any. These messages
123 // should conform to the specification defined in the Android recovery.
124 void ReportStatus(const string& message) {
125 if (!status_stream_)
126 return;
127 string status_line = message + "\n";
128 status_stream_->WriteAllBlocking(
129 status_line.data(), status_line.size(), nullptr);
130 }
131
Alex Deymo578b7872016-07-20 16:08:23 -0700132 std::set<ServiceObserverInterface*> observers_;
Alex Deymo5462f452016-08-02 17:27:02 -0700133 brillo::StreamPtr status_stream_;
Alex Deymo578b7872016-07-20 16:08:23 -0700134
135 // The last status and error code reported.
Alex Deymo5462f452016-08-02 17:27:02 -0700136 UpdateStatus status_{UpdateStatus::IDLE};
Alex Deymo578b7872016-07-20 16:08:23 -0700137 ErrorCode error_code_{ErrorCode::kSuccess};
Alex Deymo5462f452016-08-02 17:27:02 -0700138 double progress_{-1.};
Alex Deymo578b7872016-07-20 16:08:23 -0700139};
140
141// Apply an update payload directly from the given payload URI.
142bool ApplyUpdatePayload(const string& payload,
143 int64_t payload_offset,
144 int64_t payload_size,
Alex Deymo5462f452016-08-02 17:27:02 -0700145 const vector<string>& headers,
146 int64_t status_fd) {
Alex Deymoa386d052016-08-01 13:09:36 -0700147 base::MessageLoopForIO base_loop;
148 brillo::BaseMessageLoop loop(&base_loop);
Alex Deymo578b7872016-07-20 16:08:23 -0700149 loop.SetAsCurrent();
150
Alex Deymo5462f452016-08-02 17:27:02 -0700151 // Setup the subprocess handler.
152 brillo::AsynchronousSignalHandler handler;
153 handler.Init();
154 Subprocess subprocess;
155 subprocess.Init(&handler);
156
157 SideloadDaemonState sideload_daemon_state(
158 brillo::FileStream::FromFileDescriptor(status_fd, true, nullptr));
Alex Deymo578b7872016-07-20 16:08:23 -0700159
160 // During the sideload we don't access the prefs persisted on disk but instead
161 // use a temporary memory storage.
162 MemoryPrefs prefs;
163
164 std::unique_ptr<BootControlInterface> boot_control =
165 boot_control::CreateBootControl();
166 if (!boot_control) {
167 LOG(ERROR) << "Error initializing the BootControlInterface.";
168 return false;
169 }
170
171 std::unique_ptr<HardwareInterface> hardware = hardware::CreateHardware();
172 if (!hardware) {
173 LOG(ERROR) << "Error initializing the HardwareInterface.";
174 return false;
175 }
176
177 UpdateAttempterAndroid update_attempter(
178 &sideload_daemon_state, &prefs, boot_control.get(), hardware.get());
179 update_attempter.Init();
180
181 TEST_AND_RETURN_FALSE(update_attempter.ApplyPayload(
182 payload, payload_offset, payload_size, headers, nullptr));
183
184 loop.Run();
Alex Deymo5462f452016-08-02 17:27:02 -0700185 return sideload_daemon_state.status() == UpdateStatus::UPDATED_NEED_REBOOT;
Alex Deymo578b7872016-07-20 16:08:23 -0700186}
187
188} // namespace
189} // namespace chromeos_update_engine
190
191int main(int argc, char** argv) {
192 DEFINE_string(payload,
193 "file:///data/payload.bin",
194 "The URI to the update payload to use.");
195 DEFINE_int64(
196 offset, 0, "The offset in the payload where the CrAU update starts. ");
197 DEFINE_int64(size,
198 0,
199 "The size of the CrAU part of the payload. If 0 is passed, it "
200 "will be autodetected.");
201 DEFINE_string(headers,
202 "",
203 "A list of key-value pairs, one element of the list per line.");
Alex Deymo5462f452016-08-02 17:27:02 -0700204 DEFINE_int64(status_fd, -1, "A file descriptor to notify the update status.");
Alex Deymo578b7872016-07-20 16:08:23 -0700205
206 chromeos_update_engine::Terminator::Init();
207 chromeos_update_engine::SetupLogging();
208 brillo::FlagHelper::Init(argc, argv, "Update Engine Sideload");
209
210 LOG(INFO) << "Update Engine Sideloading starting";
211
212 // xz-embedded requires to initialize its CRC-32 table once on startup.
213 xz_crc32_init();
214
Alex Deymo9629bbc2016-08-10 17:02:49 -0700215 // When called from recovery, /data is not accessible, so we need to use
216 // /tmp for temporary files.
217 chromeos_update_engine::utils::SetRootTempDir(kSideloadRootTempDir);
218
Alex Deymo578b7872016-07-20 16:08:23 -0700219 vector<string> headers = base::SplitString(
220 FLAGS_headers, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
221
222 if (!chromeos_update_engine::ApplyUpdatePayload(
Alex Deymo5462f452016-08-02 17:27:02 -0700223 FLAGS_payload, FLAGS_offset, FLAGS_size, headers, FLAGS_status_fd))
Alex Deymo578b7872016-07-20 16:08:23 -0700224 return 1;
225
226 return 0;
227}