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 <string.h>
20 
21 #include <android-base/file.h>
22 #include <android-base/logging.h>
23 #include <android-base/stringprintf.h>
24 #include <bootloader_message/bootloader_message.h>
25 
26 namespace android {
27 namespace hardware {
28 namespace google {
29 namespace pixel {
30 
OffsetAndSizeInVendorSpace(size_t offset,size_t size)31 bool MiscWriter::OffsetAndSizeInVendorSpace(size_t offset, size_t size) {
32   auto total_size = WIPE_PACKAGE_OFFSET_IN_MISC - VENDOR_SPACE_OFFSET_IN_MISC;
33   return size <= total_size && offset <= total_size - size;
34 }
35 
WriteMiscPartitionVendorSpace(const void * data,size_t size,size_t offset,std::string * err)36 bool MiscWriter::WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset,
37                                                std::string* err) {
38   if (!OffsetAndSizeInVendorSpace(offset, size)) {
39     *err = android::base::StringPrintf("Out of bound write (offset %zu size %zu)", offset, size);
40     return false;
41   }
42   auto misc_blk_device = get_misc_blk_device(err);
43   if (misc_blk_device.empty()) {
44     return false;
45   }
46   return write_misc_partition(data, size, misc_blk_device, VENDOR_SPACE_OFFSET_IN_MISC + offset,
47                               err);
48 }
49 
PerformAction(std::optional<size_t> override_offset)50 bool MiscWriter::PerformAction(std::optional<size_t> override_offset) {
51   size_t offset = 0;
52   std::string content;
53   switch (action_) {
54     case MiscWriterActions::kSetDarkThemeFlag:
55     case MiscWriterActions::kClearDarkThemeFlag:
56       offset = override_offset.value_or(kThemeFlagOffsetInVendorSpace);
57       content = (action_ == MiscWriterActions::kSetDarkThemeFlag)
58                     ? kDarkThemeFlag
59                     : std::string(strlen(kDarkThemeFlag), 0);
60       break;
61     case MiscWriterActions::kSetSotaFlag:
62     case MiscWriterActions::kClearSotaFlag:
63       offset = override_offset.value_or(kSotaFlagOffsetInVendorSpace);
64       content = (action_ == MiscWriterActions::kSetSotaFlag) ? kSotaFlag
65                                                              : std::string(strlen(kSotaFlag), 0);
66       break;
67     case MiscWriterActions::kUnset:
68       LOG(ERROR) << "The misc writer action must be set";
69       return false;
70   }
71 
72   if (std::string err;
73       !WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) {
74     LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err;
75     return false;
76   }
77   return true;
78 }
79 
80 }  // namespace pixel
81 }  // namespace google
82 }  // namespace hardware
83 }  // namespace android
84