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 "misc_writer/misc_writer.h"
18
19 #include <android-base/file.h>
20 #include <android-base/logging.h>
21 #include <android-base/properties.h>
22 #include <android-base/stringprintf.h>
23 #include <bootloader_message/bootloader_message.h>
24 #include <string.h>
25 #include <charconv>
26
27 namespace android {
28 namespace hardware {
29 namespace google {
30 namespace pixel {
31
OffsetAndSizeInVendorSpace(size_t offset,size_t size)32 bool MiscWriter::OffsetAndSizeInVendorSpace(size_t offset, size_t size) {
33 auto total_size = WIPE_PACKAGE_OFFSET_IN_MISC - VENDOR_SPACE_OFFSET_IN_MISC;
34 return size <= total_size && offset <= total_size - size;
35 }
36
WriteMiscPartitionVendorSpace(const void * data,size_t size,size_t offset,std::string * err)37 bool MiscWriter::WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset,
38 std::string* err) {
39 if (!OffsetAndSizeInVendorSpace(offset, size)) {
40 *err = android::base::StringPrintf("Out of bound write (offset %zu size %zu)", offset, size);
41 return false;
42 }
43 auto misc_blk_device = get_misc_blk_device(err);
44 if (misc_blk_device.empty()) {
45 return false;
46 }
47 return write_misc_partition(data, size, misc_blk_device, VENDOR_SPACE_OFFSET_IN_MISC + offset,
48 err);
49 }
50
PerformAction(std::optional<size_t> override_offset)51 bool MiscWriter::PerformAction(std::optional<size_t> override_offset) {
52 size_t offset = 0;
53 std::string content;
54 switch (action_) {
55 case MiscWriterActions::kSetDarkThemeFlag:
56 case MiscWriterActions::kClearDarkThemeFlag:
57 offset = override_offset.value_or(kThemeFlagOffsetInVendorSpace);
58 content = (action_ == MiscWriterActions::kSetDarkThemeFlag)
59 ? kDarkThemeFlag
60 : std::string(strlen(kDarkThemeFlag), 0);
61 break;
62 case MiscWriterActions::kSetSotaFlag:
63 case MiscWriterActions::kClearSotaFlag:
64 offset = override_offset.value_or(kSotaFlagOffsetInVendorSpace);
65 content = (action_ == MiscWriterActions::kSetSotaFlag) ? kSotaFlag
66 : std::string(strlen(kSotaFlag), 0);
67 break;
68 case MiscWriterActions::kSetEnablePkvmFlag:
69 case MiscWriterActions::kSetDisablePkvmFlag:
70 offset = override_offset.value_or(kPkvmFlagOffsetInVendorSpace);
71 content = (action_ == MiscWriterActions::kSetEnablePkvmFlag) ? kEnablePkvmFlag
72 : kDisablePkvmFlag;
73 break;
74 case MiscWriterActions::kSetWristOrientationFlag:
75 case MiscWriterActions::kClearWristOrientationFlag:
76 offset = override_offset.value_or(kWristOrientationFlagOffsetInVendorSpace);
77 content = (action_ == MiscWriterActions::kSetWristOrientationFlag)
78 ? std::string(kWristOrientationFlag) + chardata_
79 : std::string(strlen(kWristOrientationFlag) + sizeof(chardata_), 0);
80 break;
81 case MiscWriterActions::kWriteTimeFormat:
82 offset = override_offset.value_or(kTimeFormatValOffsetInVendorSpace);
83 content = std::string(kTimeFormat) + chardata_;
84 break;
85 case MiscWriterActions::kWriteTimeOffset:
86 offset = override_offset.value_or(kTimeOffsetValOffsetInVendorSpace);
87 content = std::string(kTimeOffset) + stringdata_;
88 content.resize(strlen(kTimeOffset) + std::to_string(kMinTimeOffset).size(), 0);
89 break;
90 case MiscWriterActions::kSetMaxRamSize:
91 case MiscWriterActions::kClearMaxRamSize:
92 offset = override_offset.value_or(kMaxRamSizeOffsetInVendorSpace);
93 content = (action_ == MiscWriterActions::kSetMaxRamSize)
94 ? std::string(kMaxRamSize).append(stringdata_).append("\n")
95 : std::string(32, 0);
96 break;
97 case MiscWriterActions::kWriteTimeRtcOffset:
98 offset = override_offset.value_or(kRTimeRtcOffsetValOffsetInVendorSpace);
99 content = std::string(kTimeRtcOffset) + stringdata_;
100 content.resize(32);
101 break;
102 case MiscWriterActions::kWriteTimeMinRtc:
103 offset = override_offset.value_or(kRTimeMinRtcValOffsetInVendorSpace);
104 content = std::string(kTimeMinRtc) + stringdata_;
105 content.resize(32);
106 break;
107 case MiscWriterActions::kSetSotaConfig:
108 return UpdateSotaConfig(override_offset);
109 case MiscWriterActions::kWriteDstTransition:
110 offset = override_offset.value_or(kDstTransitionOffsetInVendorSpace);
111 content = std::string(kDstTransition) + stringdata_;
112 content.resize(32);
113 break;
114 case MiscWriterActions::kWriteDstOffset:
115 offset = override_offset.value_or(kDstOffsetOffsetInVendorSpace);
116 content = std::string(kDstOffset) + stringdata_;
117 content.resize(32);
118 break;
119 case MiscWriterActions::kSetDisplayMode:
120 case MiscWriterActions::kClearDisplayMode:
121 offset = override_offset.value_or(kDisplayModeOffsetInVendorSpace);
122 content = (action_ == MiscWriterActions::kSetDisplayMode)
123 ? std::string(kDisplayModePrefix) + stringdata_
124 : std::string(32, 0);
125 content.resize(32, 0);
126 break;
127 case MiscWriterActions::kWriteEagleEyePatterns:
128 offset = override_offset.value_or(kEagleEyeOffset);
129 content = stringdata_;
130 content.resize(sizeof(bootloader_message_vendor_t::eagleEye), 0);
131 break;
132 case MiscWriterActions::kWipeFloodStatus:
133 offset = override_offset.value_or(kFloodOffset);
134 content = std::string(2, 0);
135 break;
136 case MiscWriterActions::kSetDisableFaceauthEval:
137 case MiscWriterActions::kClearDisableFaceauthEval:
138 offset = override_offset.value_or(kFaceauthEvalValOffsetInVendorSpace);
139 content = (action_ == MiscWriterActions::kSetDisableFaceauthEval)
140 ? kDisableFaceauthEvalFlag
141 : std::string(32, 0);
142 content.resize(32, 0);
143 break;
144 case MiscWriterActions::kSetSotaBootFlag:
145 offset = override_offset.value_or(kSotaBootOffsetInVendorSpace);
146 content = kSotaBoot;
147 break;
148 case MiscWriterActions::kUnset:
149 LOG(ERROR) << "The misc writer action must be set";
150 return false;
151 }
152
153 if (std::string err;
154 !WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) {
155 LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err;
156 return false;
157 }
158
159 #if ENABLE_SOTA_BOOT
160 if (action_ == MiscWriterActions::kSetSotaFlag) {
161 offset = override_offset.value_or(kSotaBootOffsetInVendorSpace);
162 content = kSotaBoot;
163 if (std::string err;
164 !WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) {
165 LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err;
166 return false;
167 }
168 }
169 #endif //ENABLE_SOTA_BOOT
170 return true;
171 }
172
UpdateSotaConfig(std::optional<size_t> override_offset)173 bool MiscWriter::UpdateSotaConfig(std::optional<size_t> override_offset) {
174 size_t offset = 0;
175 std::string content;
176 std::string err;
177
178 // Update sota state
179 offset = override_offset.value_or(kSotaStateOffsetInVendorSpace);
180 content = ::android::base::GetProperty("persist.vendor.nfc.factoryota.state", "");
181 if (content.size() != 0) {
182 content.resize(sizeof(bootloader_message_vendor_t::sota_client_state));
183 if (!WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) {
184 LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err;
185 return false;
186 }
187 }
188
189 // Update sota schedule_shipmode
190 offset = override_offset.value_or(kSotaScheduleShipmodeOffsetInVendorSpace);
191 content = ::android::base::GetProperty("persist.vendor.nfc.factoryota.schedule_shipmode", "");
192 if (content.size() != 0) {
193 content.resize(sizeof(bootloader_message_vendor_t::sota_schedule_shipmode));
194 if (!WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) {
195 LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err;
196 return false;
197 }
198 }
199
200 // Update sota csku signature
201 offset = override_offset.value_or(offsetof(bootloader_message_vendor_t, sota_csku_signature));
202 std::string signature;
203 signature += ::android::base::GetProperty("persist.vendor.factoryota.signature1", "");
204 signature += ::android::base::GetProperty("persist.vendor.factoryota.signature2", "");
205 signature += ::android::base::GetProperty("persist.vendor.factoryota.signature3", "");
206 if (signature.size() != 0) {
207 LOG(INFO) << "persist.vendor.factoryota.signature=" << signature;
208 if (signature.length() != 2 * sizeof(bootloader_message_vendor_t::sota_csku_signature)) {
209 LOG(ERROR) << "signature.length() should be "
210 << 2 * sizeof(bootloader_message_vendor_t::sota_csku_signature) << " not "
211 << signature.length();
212 return false;
213 }
214 content.resize(sizeof(bootloader_message_vendor_t::sota_csku_signature));
215 // Traslate hex string to bytes
216 for (size_t i = 0; i < 2 * content.size(); i += 2)
217 if (std::from_chars(&signature[i], &signature[i + 2], content[i / 2], 16).ec != std::errc{}) {
218 LOG(ERROR) << "Failed to convert " << signature << " to bytes";
219 return false;
220 }
221 if (!WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) {
222 LOG(ERROR) << "Failed to write signature at offset " << offset << " : " << err;
223 return false;
224 }
225
226 // Update sota csku
227 offset = override_offset.value_or(offsetof(bootloader_message_vendor_t, sota_csku));
228 content = ::android::base::GetProperty("persist.vendor.factoryota.csku", "");
229 content.resize(sizeof(bootloader_message_vendor_t::sota_csku));
230 LOG(INFO) << "persist.vendor.factoryota.csku=" << content;
231 if (!WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) {
232 LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err;
233 return false;
234 }
235 }
236
237 return true;
238 }
239
240 } // namespace pixel
241 } // namespace google
242 } // namespace hardware
243 } // namespace android
244