blob: f130ea222cb900865817bd8797022a4129d61832 [file] [log] [blame]
Doug Zongker512536a2010-02-17 16:11:44 -08001/*
2 * Copyright (C) 2009 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
Tao Bao36c35112016-10-25 14:17:26 -070017#include "applypatch_modes.h"
18
Tao Baod34e6bc2018-07-13 13:11:09 -070019#include <getopt.h>
Doug Zongker512536a2010-02-17 16:11:44 -080020#include <stdio.h>
Doug Zongkerc4351c72010-02-22 14:46:32 -080021#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
Doug Zongker512536a2010-02-17 16:11:44 -080024
Yabin Cuid483c202016-02-03 17:08:52 -080025#include <memory>
Tianjie Xuaced5d92016-10-12 10:55:04 -070026#include <string>
Yabin Cuid483c202016-02-03 17:08:52 -080027#include <vector>
28
Tao Baod34e6bc2018-07-13 13:11:09 -070029#include <android-base/file.h>
Tao Bao859bfc52018-04-25 23:00:27 -070030#include <android-base/logging.h>
Tao Bao36c35112016-10-25 14:17:26 -070031#include <android-base/parseint.h>
32#include <android-base/strings.h>
Tao Baofada91c2016-10-27 18:16:06 -070033#include <openssl/sha.h>
34
Tao Baod80a9982016-03-03 11:43:47 -080035#include "applypatch/applypatch.h"
Doug Zongkerc4351c72010-02-22 14:46:32 -080036#include "edify/expr.h"
Doug Zongkerc4351c72010-02-22 14:46:32 -080037
Tao Baod34e6bc2018-07-13 13:11:09 -070038static int CheckMode(const std::string& target) {
39 return applypatch_check(target, {});
Doug Zongkerc4351c72010-02-22 14:46:32 -080040}
41
Tao Baod34e6bc2018-07-13 13:11:09 -070042static int FlashMode(const std::string& target_emmc, const std::string& source_file) {
43 std::vector<std::string> pieces = android::base::Split(target_emmc, ":");
44 if (pieces.size() != 4 || pieces[0] != "EMMC") {
45 return 2;
Tao Bao511d7592018-06-19 15:56:49 -070046 }
Tao Baod34e6bc2018-07-13 13:11:09 -070047 size_t target_size;
48 if (!android::base::ParseUint(pieces[2], &target_size) || target_size == 0) {
49 LOG(ERROR) << "Failed to parse \"" << pieces[2] << "\" as byte count";
50 return 1;
51 }
52 return applypatch_flash(source_file.c_str(), target_emmc.c_str(), pieces[3].c_str(), target_size);
53}
Doug Zongkerc4351c72010-02-22 14:46:32 -080054
Tao Baod34e6bc2018-07-13 13:11:09 -070055static int PatchMode(const std::string& target_emmc, const std::string& source_emmc,
56 const std::string& patch_file, const std::string& bonus_file) {
57 std::vector<std::string> target_pieces = android::base::Split(target_emmc, ":");
58 if (target_pieces.size() != 4 || target_pieces[0] != "EMMC") {
Tao Bao511d7592018-06-19 15:56:49 -070059 return 2;
60 }
Tao Bao36c35112016-10-25 14:17:26 -070061
Tao Bao511d7592018-06-19 15:56:49 -070062 size_t target_size;
Tao Baod34e6bc2018-07-13 13:11:09 -070063 if (!android::base::ParseUint(target_pieces[2], &target_size) || target_size == 0) {
64 LOG(ERROR) << "Failed to parse \"" << target_pieces[2] << "\" as byte count";
Tao Bao511d7592018-06-19 15:56:49 -070065 return 1;
66 }
67
Tao Baod34e6bc2018-07-13 13:11:09 -070068 std::vector<std::string> source_pieces = android::base::Split(source_emmc, ":");
69 if (source_pieces.size() != 4 || source_pieces[0] != "EMMC") {
Tao Bao859bfc52018-04-25 23:00:27 -070070 return 2;
71 }
Doug Zongkerc4351c72010-02-22 14:46:32 -080072
Tao Baod34e6bc2018-07-13 13:11:09 -070073 size_t source_size;
74 if (!android::base::ParseUint(source_pieces[2], &source_size) || source_size == 0) {
75 LOG(ERROR) << "Failed to parse \"" << source_pieces[2] << "\" as byte count";
76 return 1;
Tao Bao859bfc52018-04-25 23:00:27 -070077 }
Doug Zongkerc4351c72010-02-22 14:46:32 -080078
Tao Baod34e6bc2018-07-13 13:11:09 -070079 std::string contents;
80 if (!android::base::ReadFileToString(patch_file, &contents)) {
81 PLOG(ERROR) << "Failed to read patch file \"" << patch_file << "\"";
82 return 1;
Tao Bao859bfc52018-04-25 23:00:27 -070083 }
Tao Baod34e6bc2018-07-13 13:11:09 -070084 std::vector<std::unique_ptr<Value>> patches;
85 patches.push_back(std::make_unique<Value>(Value::Type::BLOB, std::move(contents)));
86 std::vector<std::string> sha1s{ source_pieces[3] };
87
88 std::unique_ptr<Value> bonus;
89 if (!bonus_file.empty()) {
90 std::string bonus_contents;
91 if (!android::base::ReadFileToString(bonus_file, &bonus_contents)) {
92 PLOG(ERROR) << "Failed to read bonus file \"" << bonus_file << "\"";
93 return 1;
94 }
95 bonus = std::make_unique<Value>(Value::Type::BLOB, std::move(bonus_contents));
96 }
97
98 return applypatch(source_emmc.c_str(), target_emmc.c_str(), target_pieces[3].c_str(), target_size,
99 sha1s, patches, bonus.get());
100}
101
102static void Usage() {
103 printf(
104 "Usage: \n"
105 "check mode\n"
106 " applypatch --check EMMC:<target-file>:<target-size>:<target-sha1>\n\n"
107 "flash mode\n"
108 " applypatch --flash <source-file>\n"
109 " --target EMMC:<target-file>:<target-size>:<target-sha1>\n\n"
110 "patch mode\n"
111 " applypatch [--bonus <bonus-file>]\n"
112 " --patch <patch-file>\n"
113 " --target EMMC:<target-file>:<target-size>:<target-sha1>\n"
114 " --source EMMC:<source-file>:<source-size>:<source-sha1>\n\n"
115 "show license\n"
116 " applypatch --license\n"
117 "\n\n");
118}
119
120int applypatch_modes(int argc, char* argv[]) {
121 static constexpr struct option OPTIONS[]{
122 // clang-format off
123 { "bonus", required_argument, nullptr, 0 },
124 { "check", required_argument, nullptr, 0 },
125 { "flash", required_argument, nullptr, 0 },
126 { "license", no_argument, nullptr, 0 },
127 { "patch", required_argument, nullptr, 0 },
128 { "source", required_argument, nullptr, 0 },
129 { "target", required_argument, nullptr, 0 },
130 { nullptr, 0, nullptr, 0 },
131 // clang-format on
132 };
133
134 std::string check_target;
135 std::string source;
136 std::string target;
137 std::string patch;
138 std::string bonus;
139
140 bool check_mode = false;
141 bool flash_mode = false;
142 bool patch_mode = false;
143
144 optind = 1;
145
146 int arg;
147 int option_index;
148 while ((arg = getopt_long(argc, argv, "", OPTIONS, &option_index)) != -1) {
149 switch (arg) {
150 case 0: {
151 std::string option = OPTIONS[option_index].name;
152 if (option == "bonus") {
153 bonus = optarg;
154 } else if (option == "check") {
155 check_target = optarg;
156 check_mode = true;
157 } else if (option == "flash") {
158 source = optarg;
159 flash_mode = true;
160 } else if (option == "license") {
161 return ShowLicenses();
162 } else if (option == "patch") {
163 patch = optarg;
164 patch_mode = true;
165 } else if (option == "source") {
166 source = optarg;
167 } else if (option == "target") {
168 target = optarg;
169 }
170 break;
171 }
172 case '?':
173 default:
174 LOG(ERROR) << "Invalid argument";
175 Usage();
176 return 2;
177 }
178 }
179
180 if (check_mode) {
181 return CheckMode(check_target);
182 }
183 if (flash_mode) {
184 if (!bonus.empty()) {
185 LOG(ERROR) << "bonus file not supported in flash mode";
186 return 1;
187 }
188 return FlashMode(target, source);
189 }
190 if (patch_mode) {
191 return PatchMode(target, source, patch, bonus);
192 }
193
194 Usage();
195 return 2;
Doug Zongker512536a2010-02-17 16:11:44 -0800196}