1 // 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/strings/string_split.h> 24 #include <base/strings/stringprintf.h> 25 #include <brillo/asynchronous_signal_handler.h> 26 #include <brillo/flag_helper.h> 27 #include <brillo/message_loops/base_message_loop.h> 28 #include <brillo/streams/file_stream.h> 29 #include <brillo/streams/stream.h> 30 31 #include "update_engine/common/boot_control.h" 32 #include "update_engine/common/error_code_utils.h" 33 #include "update_engine/common/hardware.h" 34 #include "update_engine/common/prefs.h" 35 #include "update_engine/common/subprocess.h" 36 #include "update_engine/common/terminator.h" 37 #include "update_engine/common/utils.h" 38 #include "update_engine/logging.h" 39 #include "update_engine/update_attempter_android.h" 40 41 using std::string; 42 using std::vector; 43 using update_engine::UpdateEngineStatus; 44 using update_engine::UpdateStatus; 45 46 namespace chromeos_update_engine { 47 namespace { 48 49 class SideloadDaemonState : public DaemonStateInterface, 50 public ServiceObserverInterface { 51 public: 52 explicit SideloadDaemonState(brillo::StreamPtr status_stream) 53 : status_stream_(std::move(status_stream)) { 54 // 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. 68 void SendStatusUpdate( 69 const UpdateEngineStatus& update_engine_status) override { 70 UpdateStatus status = update_engine_status.status; 71 double progress = update_engine_status.progress; 72 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; 84 status_ = status; 85 } 86 87 void SendPayloadApplicationComplete(ErrorCode error_code) override { 88 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 } 94 error_code_ = error_code; 95 brillo::MessageLoop::current()->BreakLoop(); 96 } 97 98 // Getters. 99 UpdateStatus status() { return status_; } 100 ErrorCode error_code() { return error_code_; } 101 102 private: 103 // 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 113 std::set<ServiceObserverInterface*> observers_; 114 brillo::StreamPtr status_stream_; 115 116 // The last status and error code reported. 117 UpdateStatus status_{UpdateStatus::IDLE}; 118 ErrorCode error_code_{ErrorCode::kSuccess}; 119 double progress_{-1.}; 120 }; 121 122 // Apply an update payload directly from the given payload URI. 123 bool ApplyUpdatePayload(const string& payload, 124 int64_t payload_offset, 125 int64_t payload_size, 126 const vector<string>& headers, 127 int64_t status_fd) { 128 brillo::BaseMessageLoop loop; 129 loop.SetAsCurrent(); 130 131 // 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)); 139 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(); 165 return sideload_daemon_state.status() == UpdateStatus::UPDATED_NEED_REBOOT; 166 } 167 168 } // namespace 169 } // namespace chromeos_update_engine 170 171 int 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."); 184 DEFINE_int64(status_fd, -1, "A file descriptor to notify the update status."); 185 186 chromeos_update_engine::Terminator::Init(); 187 chromeos_update_engine::SetupLogging(true /* stderr */, false /* file */); 188 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( 199 FLAGS_payload, FLAGS_offset, FLAGS_size, headers, FLAGS_status_fd)) 200 return 1; 201 202 return 0; 203 } 204