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
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::kSetEnablePkvmFlag:
68 case MiscWriterActions::kSetDisablePkvmFlag:
69 offset = override_offset.value_or(kPkvmFlagOffsetInVendorSpace);
70 content = (action_ == MiscWriterActions::kSetEnablePkvmFlag) ? kEnablePkvmFlag
71 : kDisablePkvmFlag;
72 break;
73 case MiscWriterActions::kSetWristOrientationFlag:
74 case MiscWriterActions::kClearWristOrientationFlag:
75 offset = override_offset.value_or(kWristOrientationFlagOffsetInVendorSpace);
76 content = (action_ == MiscWriterActions::kSetWristOrientationFlag)
77 ? std::string(kWristOrientationFlag) + chardata_
78 : std::string(strlen(kWristOrientationFlag) + sizeof(chardata_), 0);
79 break;
80 case MiscWriterActions::kWriteTimeFormat:
81 offset = override_offset.value_or(kTimeFormatValOffsetInVendorSpace);
82 content = std::string(kTimeFormat) + chardata_;
83 break;
84 case MiscWriterActions::kWriteTimeOffset:
85 offset = override_offset.value_or(kTimeOffsetValOffsetInVendorSpace);
86 content = std::string(kTimeOffset) + stringdata_;
87 content.resize(strlen(kTimeOffset) + std::to_string(kMinTimeOffset).size(), 0);
88 break;
89 case MiscWriterActions::kSetMaxRamSize:
90 case MiscWriterActions::kClearMaxRamSize:
91 offset = override_offset.value_or(kMaxRamSizeOffsetInVendorSpace);
92 content = (action_ == MiscWriterActions::kSetMaxRamSize)
93 ? std::string(kMaxRamSize).append(stringdata_).append("\n")
94 : std::string(32, 0);
95 break;
96 case MiscWriterActions::kWriteTimeRtcOffset:
97 offset = override_offset.value_or(kRTimeRtcOffsetValOffsetInVendorSpace);
98 content = std::string(kTimeRtcOffset) + stringdata_;
99 content.resize(32);
100 break;
101 case MiscWriterActions::kWriteTimeMinRtc:
102 offset = override_offset.value_or(kRTimeMinRtcValOffsetInVendorSpace);
103 content = std::string(kTimeMinRtc) + stringdata_;
104 content.resize(32);
105 break;
106 case MiscWriterActions::kSetSotaConfig:
107 goto sota_config;
108 case MiscWriterActions::kWriteDstTransition:
109 offset = override_offset.value_or(kDstTransitionOffsetInVendorSpace);
110 content = std::string(kDstTransition) + stringdata_;
111 content.resize(32);
112 break;
113 case MiscWriterActions::kWriteDstOffset:
114 offset = override_offset.value_or(kDstOffsetOffsetInVendorSpace);
115 content = std::string(kDstOffset) + stringdata_;
116 content.resize(32);
117 break;
118 case MiscWriterActions::kSetDisplayMode:
119 case MiscWriterActions::kClearDisplayMode:
120 offset = override_offset.value_or(kDisplayModeOffsetInVendorSpace);
121 content = (action_ == MiscWriterActions::kSetDisplayMode)
122 ? std::string(kDisplayModePrefix) + stringdata_
123 : std::string(32, 0);
124 content.resize(32, 0);
125 break;
126 case MiscWriterActions::kUnset:
127 LOG(ERROR) << "The misc writer action must be set";
128 return false;
129 }
130
131 if (std::string err;
132 !WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) {
133 LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err;
134 return false;
135 }
136
137 sota_config:
138 if (action_ == MiscWriterActions::kSetSotaFlag || action_ == MiscWriterActions::kSetSotaConfig) {
139 content = ::android::base::GetProperty("persist.vendor.nfc.factoryota.state", "");
140 if (content.size() != 0 && content.size() <= 40) {
141 offset = kSotaStateOffsetInVendorSpace;
142 if (std::string err;
143 !WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) {
144 LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err;
145 return false;
146 }
147 }
148 content = ::android::base::GetProperty("persist.vendor.nfc.factoryota.schedule_shipmode", "");
149 if (content.size() != 0 && content.size() <= 32) {
150 offset = kSotaScheduleShipmodeOffsetInVendorSpace;
151 if (std::string err;
152 !WriteMiscPartitionVendorSpace(content.data(), content.size(), offset, &err)) {
153 LOG(ERROR) << "Failed to write " << content << " at offset " << offset << " : " << err;
154 return false;
155 }
156 }
157 }
158
159 return true;
160 }
161
162 } // namespace pixel
163 } // namespace google
164 } // namespace hardware
165 } // namespace android
166