1*acea8879SAndroid Build Coastguard Worker /*
2*acea8879SAndroid Build Coastguard Worker * Copyright (C) 2009 The Android Open Source Project
3*acea8879SAndroid Build Coastguard Worker *
4*acea8879SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*acea8879SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*acea8879SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*acea8879SAndroid Build Coastguard Worker *
8*acea8879SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*acea8879SAndroid Build Coastguard Worker *
10*acea8879SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*acea8879SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*acea8879SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*acea8879SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*acea8879SAndroid Build Coastguard Worker * limitations under the License.
15*acea8879SAndroid Build Coastguard Worker */
16*acea8879SAndroid Build Coastguard Worker
17*acea8879SAndroid Build Coastguard Worker #include "applypatch_modes.h"
18*acea8879SAndroid Build Coastguard Worker
19*acea8879SAndroid Build Coastguard Worker #include <getopt.h>
20*acea8879SAndroid Build Coastguard Worker #include <stdio.h>
21*acea8879SAndroid Build Coastguard Worker #include <stdlib.h>
22*acea8879SAndroid Build Coastguard Worker #include <string.h>
23*acea8879SAndroid Build Coastguard Worker #include <unistd.h>
24*acea8879SAndroid Build Coastguard Worker
25*acea8879SAndroid Build Coastguard Worker #include <memory>
26*acea8879SAndroid Build Coastguard Worker #include <string>
27*acea8879SAndroid Build Coastguard Worker #include <vector>
28*acea8879SAndroid Build Coastguard Worker
29*acea8879SAndroid Build Coastguard Worker #include <android-base/file.h>
30*acea8879SAndroid Build Coastguard Worker #include <android-base/logging.h>
31*acea8879SAndroid Build Coastguard Worker #include <android-base/parseint.h>
32*acea8879SAndroid Build Coastguard Worker #include <android-base/strings.h>
33*acea8879SAndroid Build Coastguard Worker #include <openssl/sha.h>
34*acea8879SAndroid Build Coastguard Worker
35*acea8879SAndroid Build Coastguard Worker #include "applypatch/applypatch.h"
36*acea8879SAndroid Build Coastguard Worker #include "edify/expr.h"
37*acea8879SAndroid Build Coastguard Worker
CheckMode(const std::string & target_emmc)38*acea8879SAndroid Build Coastguard Worker static int CheckMode(const std::string& target_emmc) {
39*acea8879SAndroid Build Coastguard Worker std::string err;
40*acea8879SAndroid Build Coastguard Worker auto target = Partition::Parse(target_emmc, &err);
41*acea8879SAndroid Build Coastguard Worker if (!target) {
42*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to parse target \"" << target_emmc << "\": " << err;
43*acea8879SAndroid Build Coastguard Worker return 2;
44*acea8879SAndroid Build Coastguard Worker }
45*acea8879SAndroid Build Coastguard Worker return CheckPartition(target) ? 0 : 1;
46*acea8879SAndroid Build Coastguard Worker }
47*acea8879SAndroid Build Coastguard Worker
FlashMode(const std::string & target_emmc,const std::string & source_file)48*acea8879SAndroid Build Coastguard Worker static int FlashMode(const std::string& target_emmc, const std::string& source_file) {
49*acea8879SAndroid Build Coastguard Worker std::string err;
50*acea8879SAndroid Build Coastguard Worker auto target = Partition::Parse(target_emmc, &err);
51*acea8879SAndroid Build Coastguard Worker if (!target) {
52*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to parse target \"" << target_emmc << "\": " << err;
53*acea8879SAndroid Build Coastguard Worker return 2;
54*acea8879SAndroid Build Coastguard Worker }
55*acea8879SAndroid Build Coastguard Worker return FlashPartition(target, source_file) ? 0 : 1;
56*acea8879SAndroid Build Coastguard Worker }
57*acea8879SAndroid Build Coastguard Worker
PatchMode(const std::string & target_emmc,const std::string & source_emmc,const std::string & patch_file,const std::string & bonus_file)58*acea8879SAndroid Build Coastguard Worker static int PatchMode(const std::string& target_emmc, const std::string& source_emmc,
59*acea8879SAndroid Build Coastguard Worker const std::string& patch_file, const std::string& bonus_file) {
60*acea8879SAndroid Build Coastguard Worker std::string err;
61*acea8879SAndroid Build Coastguard Worker auto target = Partition::Parse(target_emmc, &err);
62*acea8879SAndroid Build Coastguard Worker if (!target) {
63*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to parse target \"" << target_emmc << "\": " << err;
64*acea8879SAndroid Build Coastguard Worker return 2;
65*acea8879SAndroid Build Coastguard Worker }
66*acea8879SAndroid Build Coastguard Worker
67*acea8879SAndroid Build Coastguard Worker auto source = Partition::Parse(source_emmc, &err);
68*acea8879SAndroid Build Coastguard Worker if (!source) {
69*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to parse source \"" << source_emmc << "\": " << err;
70*acea8879SAndroid Build Coastguard Worker return 2;
71*acea8879SAndroid Build Coastguard Worker }
72*acea8879SAndroid Build Coastguard Worker
73*acea8879SAndroid Build Coastguard Worker std::string patch_contents;
74*acea8879SAndroid Build Coastguard Worker if (!android::base::ReadFileToString(patch_file, &patch_contents)) {
75*acea8879SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to read patch file \"" << patch_file << "\"";
76*acea8879SAndroid Build Coastguard Worker return 1;
77*acea8879SAndroid Build Coastguard Worker }
78*acea8879SAndroid Build Coastguard Worker
79*acea8879SAndroid Build Coastguard Worker Value patch(Value::Type::BLOB, std::move(patch_contents));
80*acea8879SAndroid Build Coastguard Worker std::unique_ptr<Value> bonus;
81*acea8879SAndroid Build Coastguard Worker if (!bonus_file.empty()) {
82*acea8879SAndroid Build Coastguard Worker std::string bonus_contents;
83*acea8879SAndroid Build Coastguard Worker if (!android::base::ReadFileToString(bonus_file, &bonus_contents)) {
84*acea8879SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to read bonus file \"" << bonus_file << "\"";
85*acea8879SAndroid Build Coastguard Worker return 1;
86*acea8879SAndroid Build Coastguard Worker }
87*acea8879SAndroid Build Coastguard Worker bonus = std::make_unique<Value>(Value::Type::BLOB, std::move(bonus_contents));
88*acea8879SAndroid Build Coastguard Worker }
89*acea8879SAndroid Build Coastguard Worker
90*acea8879SAndroid Build Coastguard Worker return PatchPartition(target, source, patch, bonus.get(), false) ? 0 : 1;
91*acea8879SAndroid Build Coastguard Worker }
92*acea8879SAndroid Build Coastguard Worker
Usage()93*acea8879SAndroid Build Coastguard Worker static void Usage() {
94*acea8879SAndroid Build Coastguard Worker printf(
95*acea8879SAndroid Build Coastguard Worker "Usage: \n"
96*acea8879SAndroid Build Coastguard Worker "check mode\n"
97*acea8879SAndroid Build Coastguard Worker " applypatch --check EMMC:<target-file>:<target-size>:<target-sha1>\n\n"
98*acea8879SAndroid Build Coastguard Worker "flash mode\n"
99*acea8879SAndroid Build Coastguard Worker " applypatch --flash <source-file>\n"
100*acea8879SAndroid Build Coastguard Worker " --target EMMC:<target-file>:<target-size>:<target-sha1>\n\n"
101*acea8879SAndroid Build Coastguard Worker "patch mode\n"
102*acea8879SAndroid Build Coastguard Worker " applypatch [--bonus <bonus-file>]\n"
103*acea8879SAndroid Build Coastguard Worker " --patch <patch-file>\n"
104*acea8879SAndroid Build Coastguard Worker " --target EMMC:<target-file>:<target-size>:<target-sha1>\n"
105*acea8879SAndroid Build Coastguard Worker " --source EMMC:<source-file>:<source-size>:<source-sha1>\n\n"
106*acea8879SAndroid Build Coastguard Worker "show license\n"
107*acea8879SAndroid Build Coastguard Worker " applypatch --license\n"
108*acea8879SAndroid Build Coastguard Worker "\n\n");
109*acea8879SAndroid Build Coastguard Worker }
110*acea8879SAndroid Build Coastguard Worker
applypatch_modes(int argc,char * argv[])111*acea8879SAndroid Build Coastguard Worker int applypatch_modes(int argc, char* argv[]) {
112*acea8879SAndroid Build Coastguard Worker static constexpr struct option OPTIONS[]{
113*acea8879SAndroid Build Coastguard Worker // clang-format off
114*acea8879SAndroid Build Coastguard Worker { "bonus", required_argument, nullptr, 0 },
115*acea8879SAndroid Build Coastguard Worker { "check", required_argument, nullptr, 0 },
116*acea8879SAndroid Build Coastguard Worker { "flash", required_argument, nullptr, 0 },
117*acea8879SAndroid Build Coastguard Worker { "license", no_argument, nullptr, 0 },
118*acea8879SAndroid Build Coastguard Worker { "patch", required_argument, nullptr, 0 },
119*acea8879SAndroid Build Coastguard Worker { "source", required_argument, nullptr, 0 },
120*acea8879SAndroid Build Coastguard Worker { "target", required_argument, nullptr, 0 },
121*acea8879SAndroid Build Coastguard Worker { nullptr, 0, nullptr, 0 },
122*acea8879SAndroid Build Coastguard Worker // clang-format on
123*acea8879SAndroid Build Coastguard Worker };
124*acea8879SAndroid Build Coastguard Worker
125*acea8879SAndroid Build Coastguard Worker std::string check_target;
126*acea8879SAndroid Build Coastguard Worker std::string source;
127*acea8879SAndroid Build Coastguard Worker std::string target;
128*acea8879SAndroid Build Coastguard Worker std::string patch;
129*acea8879SAndroid Build Coastguard Worker std::string bonus;
130*acea8879SAndroid Build Coastguard Worker
131*acea8879SAndroid Build Coastguard Worker bool check_mode = false;
132*acea8879SAndroid Build Coastguard Worker bool flash_mode = false;
133*acea8879SAndroid Build Coastguard Worker bool patch_mode = false;
134*acea8879SAndroid Build Coastguard Worker
135*acea8879SAndroid Build Coastguard Worker optind = 1;
136*acea8879SAndroid Build Coastguard Worker
137*acea8879SAndroid Build Coastguard Worker int arg;
138*acea8879SAndroid Build Coastguard Worker int option_index;
139*acea8879SAndroid Build Coastguard Worker while ((arg = getopt_long(argc, argv, "", OPTIONS, &option_index)) != -1) {
140*acea8879SAndroid Build Coastguard Worker switch (arg) {
141*acea8879SAndroid Build Coastguard Worker case 0: {
142*acea8879SAndroid Build Coastguard Worker std::string option = OPTIONS[option_index].name;
143*acea8879SAndroid Build Coastguard Worker if (option == "bonus") {
144*acea8879SAndroid Build Coastguard Worker bonus = optarg;
145*acea8879SAndroid Build Coastguard Worker } else if (option == "check") {
146*acea8879SAndroid Build Coastguard Worker check_target = optarg;
147*acea8879SAndroid Build Coastguard Worker check_mode = true;
148*acea8879SAndroid Build Coastguard Worker } else if (option == "flash") {
149*acea8879SAndroid Build Coastguard Worker source = optarg;
150*acea8879SAndroid Build Coastguard Worker flash_mode = true;
151*acea8879SAndroid Build Coastguard Worker } else if (option == "license") {
152*acea8879SAndroid Build Coastguard Worker return ShowLicenses();
153*acea8879SAndroid Build Coastguard Worker } else if (option == "patch") {
154*acea8879SAndroid Build Coastguard Worker patch = optarg;
155*acea8879SAndroid Build Coastguard Worker patch_mode = true;
156*acea8879SAndroid Build Coastguard Worker } else if (option == "source") {
157*acea8879SAndroid Build Coastguard Worker source = optarg;
158*acea8879SAndroid Build Coastguard Worker } else if (option == "target") {
159*acea8879SAndroid Build Coastguard Worker target = optarg;
160*acea8879SAndroid Build Coastguard Worker }
161*acea8879SAndroid Build Coastguard Worker break;
162*acea8879SAndroid Build Coastguard Worker }
163*acea8879SAndroid Build Coastguard Worker case '?':
164*acea8879SAndroid Build Coastguard Worker default:
165*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << "Invalid argument";
166*acea8879SAndroid Build Coastguard Worker Usage();
167*acea8879SAndroid Build Coastguard Worker return 2;
168*acea8879SAndroid Build Coastguard Worker }
169*acea8879SAndroid Build Coastguard Worker }
170*acea8879SAndroid Build Coastguard Worker
171*acea8879SAndroid Build Coastguard Worker if (check_mode) {
172*acea8879SAndroid Build Coastguard Worker return CheckMode(check_target);
173*acea8879SAndroid Build Coastguard Worker }
174*acea8879SAndroid Build Coastguard Worker if (flash_mode) {
175*acea8879SAndroid Build Coastguard Worker if (!bonus.empty()) {
176*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << "bonus file not supported in flash mode";
177*acea8879SAndroid Build Coastguard Worker return 1;
178*acea8879SAndroid Build Coastguard Worker }
179*acea8879SAndroid Build Coastguard Worker return FlashMode(target, source);
180*acea8879SAndroid Build Coastguard Worker }
181*acea8879SAndroid Build Coastguard Worker if (patch_mode) {
182*acea8879SAndroid Build Coastguard Worker return PatchMode(target, source, patch, bonus);
183*acea8879SAndroid Build Coastguard Worker }
184*acea8879SAndroid Build Coastguard Worker
185*acea8879SAndroid Build Coastguard Worker Usage();
186*acea8879SAndroid Build Coastguard Worker return 2;
187*acea8879SAndroid Build Coastguard Worker }
188