• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 <getopt.h>
18 #include <stdint.h>
19 #include <stdlib.h>
20 
21 #include <iostream>
22 #include <vector>
23 #include <map>
24 #include <memory>
25 #include <optional>
26 #include <string>
27 #include <string_view>
28 
29 #include <android-base/logging.h>
30 #include <android-base/parseint.h>
31 
32 #include "misc_writer/misc_writer.h"
33 
34 using namespace std::string_literals;
35 using android::hardware::google::pixel::MiscWriter;
36 using android::hardware::google::pixel::MiscWriterActions;
37 
Usage(std::string_view name)38 static int Usage(std::string_view name) {
39   std::cerr << name << " usage:\n";
40   std::cerr << name << " [--override-vendor-space-offset <offset>] --<misc_writer_action>\n";
41   std::cerr << "Supported misc_writer_action is one of: \n";
42   std::cerr << "  --set-dark-theme     Write the dark theme flag\n";
43   std::cerr << "  --clear-dark-theme   Clear the dark theme flag\n";
44   std::cerr << "  --set-sota           Write the silent OTA flag\n";
45   std::cerr << "  --clear-sota         Clear the silent OTA flag\n";
46   std::cerr << "  --set-sota-config    Set the silent OTA configs\n";
47   std::cerr << "  --set-enable-pkvm    Write the enable pKVM flag\n";
48   std::cerr << "  --set-disable-pkvm   Write the disable pKVM flag\n";
49   std::cerr << "  --set-wrist-orientation <0-3> Write the wrist orientation flag\n";
50   std::cerr << "  --clear-wrist-orientation     Clear the wrist orientation flag\n";
51   std::cerr << "  --set-timeformat              Write the time format value (1=24hr, 0=12hr)\n";
52   std::cerr << "  --set-timeoffset              Write the time offset value (tz_time - utc_time)\n";
53   std::cerr << "  --set-max-ram-size <2048-65536> Write the sw limit max ram size in MB\n";
54   std::cerr << "  --set-max-ram-size <-1>         Clear the sw limit max ram size\n";
55   std::cerr << "  --set-timertcoffset           Write the time offset value (utc_time - rtc_time)\n";
56   std::cerr << "  --set-minrtc                  Write the minimum expected rtc value for tilb\n";
57   std::cerr << "  --set-dsttransition           Write the next dst transition in the current timezone\n";
58   std::cerr << "  --set-dstoffset               Write the time offset during the next dst transition\n";
59   std::cerr << "  --set-display-mode <mode>     Write the display mode at boot\n";
60   std::cerr << "  --clear-display-mode          Clear the display mode at boot\n";
61   std::cerr << "  --set-trending-issue-pattern <string within 2000 byte> Write a regex string";
62   std::cerr << "  --wipe-flood-status           Clear flood status";
63   std::cerr << "  --set-disable-faceauth-eval   Write disable-faceauth-eval flag\n";
64   std::cerr << "  --clear-disable-faceauth-eval Clear disable-faceauth-eval flag\n";
65   std::cerr << "  --set-sota-boot      Set sota boot flag\n";
66   std::cerr << "Writes the given hex string to the specified offset in vendor space in /misc "
67                "partition.\nDefault offset is used for each action unless "
68                "--override-vendor-space-offset is specified.\n";
69   return EXIT_FAILURE;
70 }
71 
72 // misc_writer is a vendor tool that writes data to the vendor space in /misc.
main(int argc,char ** argv)73 int main(int argc, char** argv) {
74   constexpr struct option OPTIONS[] = {
75     { "set-dark-theme", no_argument, nullptr, 0 },
76     { "clear-dark-theme", no_argument, nullptr, 0 },
77     { "set-sota", no_argument, nullptr, 0 },
78     { "clear-sota", no_argument, nullptr, 0 },
79     { "set-wrist-orientation", required_argument, nullptr, 0 },
80     { "clear-wrist-orientation", no_argument, nullptr, 0 },
81     { "override-vendor-space-offset", required_argument, nullptr, 0 },
82     { "set-enable-pkvm", no_argument, nullptr, 0 },
83     { "set-disable-pkvm", no_argument, nullptr, 0 },
84     { "set-timeformat", required_argument, nullptr, 0},
85     { "set-timeoffset", required_argument, nullptr, 0},
86     { "set-max-ram-size", required_argument, nullptr, 0},
87     { "set-timertcoffset", required_argument, nullptr, 0},
88     { "set-minrtc", required_argument, nullptr, 0},
89     { "set-sota-config", no_argument, nullptr, 0 },
90     { "set-dsttransition", required_argument, nullptr, 0},
91     { "set-dstoffset", required_argument, nullptr, 0 },
92     { "set-display-mode", required_argument, nullptr, 0 },
93     { "clear-display-mode", no_argument, nullptr, 0 },
94     { "set-disable-faceauth-eval", no_argument, nullptr, 0 },
95     { "clear-disable-faceauth-eval", no_argument, nullptr, 0 },
96     { "set-trending-issue-pattern", required_argument, nullptr, 0 },
97     { "wipe-flood-status", no_argument, nullptr, 0 },
98     { "set-sota-boot", no_argument, nullptr, 0 },
99     { nullptr, 0, nullptr, 0 },
100   };
101 
102   std::map<std::string, MiscWriterActions> action_map{
103     { "set-dark-theme", MiscWriterActions::kSetDarkThemeFlag },
104     { "clear-dark-theme", MiscWriterActions::kClearDarkThemeFlag },
105     { "set-sota", MiscWriterActions::kSetSotaFlag },
106     { "clear-sota", MiscWriterActions::kClearSotaFlag },
107     { "set-enable-pkvm", MiscWriterActions::kSetEnablePkvmFlag },
108     { "set-disable-pkvm", MiscWriterActions::kSetDisablePkvmFlag },
109     { "clear-wrist-orientation", MiscWriterActions::kClearWristOrientationFlag },
110     { "set-sota-config", MiscWriterActions::kSetSotaConfig },
111     { "clear-display-mode", MiscWriterActions::kClearDisplayMode },
112     { "set-disable-faceauth-eval", MiscWriterActions::kSetDisableFaceauthEval },
113     { "clear-disable-faceauth-eval", MiscWriterActions::kClearDisableFaceauthEval },
114     { "set-sota-boot", MiscWriterActions::kSetSotaBootFlag },
115   };
116 
117   std::unique_ptr<MiscWriter> misc_writer;
118   std::optional<size_t> override_offset;
119 
120   int arg;
121   int option_index = 0;
122   while ((arg = getopt_long(argc, argv, "", OPTIONS, &option_index)) != -1) {
123     if (arg != 0) {
124       LOG(ERROR) << "Invalid command argument";
125       return Usage(argv[0]);
126     }
127     auto option_name = OPTIONS[option_index].name;
128     if (option_name == "override-vendor-space-offset"s) {
129       LOG(WARNING) << "Overriding the vendor space offset in misc partition to " << optarg;
130       size_t offset;
131       if (!android::base::ParseUint(optarg, &offset)) {
132         LOG(ERROR) << "Failed to parse the offset: " << optarg;
133         return Usage(argv[0]);
134       }
135       override_offset = offset;
136     } else if (option_name == "set-wrist-orientation"s) {
137       int orientation;
138       if (!android::base::ParseInt(optarg, &orientation)) {
139         LOG(ERROR) << "Failed to parse the orientation: " << optarg;
140         return Usage(argv[0]);
141       }
142       if (orientation < 0 || orientation > 3) {
143         LOG(ERROR) << "Orientation out of range: " << optarg;
144         return Usage(argv[0]);
145       }
146       if (misc_writer) {
147         LOG(ERROR) << "Misc writer action has already been set";
148         return Usage(argv[0]);
149       }
150       misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kSetWristOrientationFlag,
151                                                      '0' + orientation);
152     } else if (option_name == "set-timeformat"s) {
153       int timeformat;
154       if (!android::base::ParseInt(optarg, &timeformat)) {
155         LOG(ERROR) << "Failed to parse the timeformat: " << optarg;
156         return Usage(argv[0]);
157       }
158       if (timeformat < 0 || timeformat > 1) {
159         LOG(ERROR) << "Time format out of range: " << optarg;
160         return Usage(argv[0]);
161       }
162       if (misc_writer) {
163         LOG(ERROR) << "Misc writer action has already been set";
164         return Usage(argv[0]);
165       }
166       misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kWriteTimeFormat,
167                                                      '0' + timeformat);
168     } else if (option_name == "set-timeoffset"s) {
169       int timeoffset;
170       if (!android::base::ParseInt(optarg, &timeoffset)) {
171         LOG(ERROR) << "Failed to parse the timeoffset: " << optarg;
172         return Usage(argv[0]);
173       }
174       if (timeoffset < MiscWriter::kMinTimeOffset || timeoffset > MiscWriter::kMaxTimeOffset) {
175         LOG(ERROR) << "Time offset out of range: " << optarg;
176         return Usage(argv[0]);
177       }
178       if (misc_writer) {
179         LOG(ERROR) << "Misc writer action has already been set";
180         return Usage(argv[0]);
181       }
182       misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kWriteTimeOffset,
183                                                      std::to_string(timeoffset));
184     } else if (option_name == "set-max-ram-size"s) {
185       int max_ram_size;
186       if (!android::base::ParseInt(optarg, &max_ram_size)) {
187         LOG(ERROR) << "Failed to parse the max_ram_size: " << optarg;
188         return Usage(argv[0]);
189       }
190       if (max_ram_size != MiscWriter::kRamSizeDefault &&
191           (max_ram_size < MiscWriter::kRamSizeMin || max_ram_size > MiscWriter::kRamSizeMax)) {
192         LOG(ERROR) << "max_ram_size out of range: " << optarg;
193         return Usage(argv[0]);
194       }
195       if (misc_writer) {
196         LOG(ERROR) << "Misc writer action has already been set";
197         return Usage(argv[0]);
198       }
199 
200       if (max_ram_size == MiscWriter::kRamSizeDefault) {
201         misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kClearMaxRamSize);
202       } else {
203         misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kSetMaxRamSize,
204                                                    std::to_string(max_ram_size));
205       }
206     } else if (option_name == "set-timertcoffset"s) {
207       long long int timertcoffset = strtoll(optarg, NULL, 10);
208       if (0 == timertcoffset) {
209         LOG(ERROR) << "Failed to parse the timertcoffset:" << optarg;
210         return Usage(argv[0]);
211       }
212       if (misc_writer) {
213         LOG(ERROR) << "Misc writer action has already been set";
214         return Usage(argv[0]);
215       }
216       misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kWriteTimeRtcOffset,
217                                                      std::to_string(timertcoffset));
218     } else if (option_name == "set-minrtc"s) {
219       long long int minrtc = strtoll(optarg, NULL, 10);
220       if (0 == minrtc) {
221         LOG(ERROR) << "Failed to parse the minrtc:" << optarg;
222         return Usage(argv[0]);
223       }
224       if (misc_writer) {
225         LOG(ERROR) << "Misc writer action has already been set";
226         return Usage(argv[0]);
227       }
228       misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kWriteTimeMinRtc,
229                                                      std::to_string(minrtc));
230     } else if (option_name == "set-display-mode"s) {
231       std::string mode(optarg);
232       if (mode.size() > MiscWriter::kDisplayModeMaxSize) {
233         LOG(ERROR) << "Display mode too long:" << optarg;
234         return Usage(argv[0]);
235       }
236       if (misc_writer) {
237         LOG(ERROR) << "Misc writer action has already been set";
238         return Usage(argv[0]);
239       }
240       misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kSetDisplayMode, mode);
241     } else if (auto iter = action_map.find(option_name); iter != action_map.end()) {
242       if (misc_writer) {
243         LOG(ERROR) << "Misc writer action has already been set";
244         return Usage(argv[0]);
245       }
246       misc_writer = std::make_unique<MiscWriter>(iter->second);
247     } else if (option_name == "set-dsttransition"s) {
248       long long int dst_transition = strtoll(optarg, NULL, 10);
249       if (misc_writer) {
250         LOG(ERROR) << "Misc writer action has already been set";
251         return Usage(argv[0]);
252       }
253       misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kWriteDstTransition,
254                                                      std::to_string(dst_transition));
255     } else if (option_name == "set-dstoffset"s) {
256       int dst_offset;
257       if (!android::base::ParseInt(optarg, &dst_offset)) {
258         LOG(ERROR) << "Failed to parse the dst offset: " << optarg;
259         return Usage(argv[0]);
260       }
261       if (misc_writer) {
262         LOG(ERROR) << "Misc writer action has already been set";
263         return Usage(argv[0]);
264       }
265       misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kWriteDstOffset,
266                                                      std::to_string(dst_offset));
267     } else if (option_name == "set-trending-issue-pattern"s) {
268       std::vector<char> merged;
269       for (int j = 2 ; j < argc ; j++) {
270         for (int i = 0 ; argv[j][i] != '\0'; ++i) {
271             merged.push_back(argv[j][i]);
272         }
273         merged.push_back('\0');
274       }
275       std::string msg;
276       msg.assign(merged.begin(), merged.end());
277       misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kWriteEagleEyePatterns, msg);
278     } else if (option_name == "wipe-flood-status"s) {
279       misc_writer = std::make_unique<MiscWriter>(MiscWriterActions::kWipeFloodStatus, "\0\0");
280     } else {
281       LOG(FATAL) << "Unreachable path, option_name: " << option_name;
282     }
283   }
284 
285   if (!misc_writer) {
286     LOG(ERROR) << "An action must be specified for misc writer";
287     return Usage(argv[0]);
288   }
289 
290   if (!misc_writer->PerformAction(override_offset)) {
291     return EXIT_FAILURE;
292   }
293 
294   return EXIT_SUCCESS;
295 }
296