blob: eae9539e153b73f1a070b6fdc144f76f18b9de8a [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>
23#include <base/logging.h>
24#include <base/strings/string_split.h>
25#include <brillo/flag_helper.h>
26#include <brillo/message_loops/base_message_loop.h>
27
28#include "update_engine/common/boot_control.h"
29#include "update_engine/common/hardware.h"
30#include "update_engine/common/prefs.h"
31#include "update_engine/common/terminator.h"
32#include "update_engine/common/utils.h"
33#include "update_engine/update_attempter_android.h"
34
35using std::string;
36using std::vector;
37
38namespace chromeos_update_engine {
39namespace {
40
41void SetupLogging() {
42 string log_file;
43 logging::LoggingSettings log_settings;
44 log_settings.lock_log = logging::DONT_LOCK_LOG_FILE;
45 log_settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
46 log_settings.log_file = nullptr;
47 log_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
48
49 logging::InitLogging(log_settings);
50}
51
52class SideloadDaemonState : public DaemonStateInterface,
53 public ServiceObserverInterface {
54 public:
55 SideloadDaemonState() {
56 // Add this class as the only observer.
57 observers_.insert(this);
58 }
59 ~SideloadDaemonState() override = default;
60
61 // DaemonStateInterface overrides.
62 bool StartUpdater() override { return true; }
63 void AddObserver(ServiceObserverInterface* observer) override {}
64 void RemoveObserver(ServiceObserverInterface* observer) override {}
65 const std::set<ServiceObserverInterface*>& service_observers() override {
66 return observers_;
67 }
68
69 // ServiceObserverInterface overrides.
70 void SendStatusUpdate(int64_t last_checked_time,
71 double progress,
72 update_engine::UpdateStatus status,
73 const string& new_version,
74 int64_t new_size) override {
75 status_ = status;
76 }
77
78 void SendPayloadApplicationComplete(ErrorCode error_code) override {
79 error_code_ = error_code;
80 brillo::MessageLoop::current()->BreakLoop();
81 }
82
83 void SendChannelChangeUpdate(const string& tracking_channel) override {}
84
85 // Getters.
86 update_engine::UpdateStatus status() { return status_; }
87 ErrorCode error_code() { return error_code_; }
88
89 private:
90 std::set<ServiceObserverInterface*> observers_;
91
92 // The last status and error code reported.
93 update_engine::UpdateStatus status_{update_engine::UpdateStatus::IDLE};
94 ErrorCode error_code_{ErrorCode::kSuccess};
95};
96
97// Apply an update payload directly from the given payload URI.
98bool ApplyUpdatePayload(const string& payload,
99 int64_t payload_offset,
100 int64_t payload_size,
101 const vector<string>& headers) {
102 brillo::BaseMessageLoop loop;
103 loop.SetAsCurrent();
104
105 SideloadDaemonState sideload_daemon_state;
106
107 // During the sideload we don't access the prefs persisted on disk but instead
108 // use a temporary memory storage.
109 MemoryPrefs prefs;
110
111 std::unique_ptr<BootControlInterface> boot_control =
112 boot_control::CreateBootControl();
113 if (!boot_control) {
114 LOG(ERROR) << "Error initializing the BootControlInterface.";
115 return false;
116 }
117
118 std::unique_ptr<HardwareInterface> hardware = hardware::CreateHardware();
119 if (!hardware) {
120 LOG(ERROR) << "Error initializing the HardwareInterface.";
121 return false;
122 }
123
124 UpdateAttempterAndroid update_attempter(
125 &sideload_daemon_state, &prefs, boot_control.get(), hardware.get());
126 update_attempter.Init();
127
128 TEST_AND_RETURN_FALSE(update_attempter.ApplyPayload(
129 payload, payload_offset, payload_size, headers, nullptr));
130
131 loop.Run();
132 return sideload_daemon_state.status() ==
133 update_engine::UpdateStatus::UPDATED_NEED_REBOOT;
134}
135
136} // namespace
137} // namespace chromeos_update_engine
138
139int main(int argc, char** argv) {
140 DEFINE_string(payload,
141 "file:///data/payload.bin",
142 "The URI to the update payload to use.");
143 DEFINE_int64(
144 offset, 0, "The offset in the payload where the CrAU update starts. ");
145 DEFINE_int64(size,
146 0,
147 "The size of the CrAU part of the payload. If 0 is passed, it "
148 "will be autodetected.");
149 DEFINE_string(headers,
150 "",
151 "A list of key-value pairs, one element of the list per line.");
152
153 chromeos_update_engine::Terminator::Init();
154 chromeos_update_engine::SetupLogging();
155 brillo::FlagHelper::Init(argc, argv, "Update Engine Sideload");
156
157 LOG(INFO) << "Update Engine Sideloading starting";
158
159 // xz-embedded requires to initialize its CRC-32 table once on startup.
160 xz_crc32_init();
161
162 vector<string> headers = base::SplitString(
163 FLAGS_headers, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
164
165 if (!chromeos_update_engine::ApplyUpdatePayload(
166 FLAGS_payload, FLAGS_offset, FLAGS_size, headers))
167 return 1;
168
169 return 0;
170}