• 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 "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