1 /*
2 * Copyright (C) 2017 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
18 #define LOG_TAG "libvintf"
19
20 #include "RuntimeInfo.h"
21
22 #include <android-base/logging.h>
23 #include <android-base/strings.h>
24 #include <kver/kernel_release.h>
25
26 #include "CompatibilityMatrix.h"
27 #include "parse_string.h"
28
29 namespace android {
30 namespace vintf {
31
osName() const32 const std::string &RuntimeInfo::osName() const {
33 return mOsName;
34 }
35
nodeName() const36 const std::string &RuntimeInfo::nodeName() const {
37 return mNodeName;
38 }
39
osRelease() const40 const std::string &RuntimeInfo::osRelease() const {
41 return mOsRelease;
42 }
43
osVersion() const44 const std::string &RuntimeInfo::osVersion() const {
45 return mOsVersion;
46 }
47
hardwareId() const48 const std::string &RuntimeInfo::hardwareId() const {
49 return mHardwareId;
50 }
51
kernelVersion() const52 const KernelVersion &RuntimeInfo::kernelVersion() const {
53 return mKernel.version();
54 }
55
kernelConfigs() const56 const std::map<std::string, std::string> &RuntimeInfo::kernelConfigs() const {
57 return mKernel.configs();
58 }
59
kernelSepolicyVersion() const60 size_t RuntimeInfo::kernelSepolicyVersion() const {
61 return mKernelSepolicyVersion;
62 }
63
cpuInfo() const64 const std::string &RuntimeInfo::cpuInfo() const {
65 return mCpuInfo;
66 }
67
bootVbmetaAvbVersion() const68 const Version &RuntimeInfo::bootVbmetaAvbVersion() const {
69 return mBootVbmetaAvbVersion;
70 }
71
bootAvbVersion() const72 const Version &RuntimeInfo::bootAvbVersion() const {
73 return mBootAvbVersion;
74 }
75
isMainlineKernel() const76 bool RuntimeInfo::isMainlineKernel() const {
77 return mIsMainline;
78 }
79
checkCompatibility(const CompatibilityMatrix & mat,std::string * error,CheckFlags::Type flags) const80 bool RuntimeInfo::checkCompatibility(const CompatibilityMatrix& mat, std::string* error,
81 CheckFlags::Type flags) const {
82 if (mat.mType != SchemaType::FRAMEWORK) {
83 if (error != nullptr) {
84 *error = "Should not check runtime info against " + to_string(mat.mType)
85 + " compatibility matrix.";
86 }
87 return false;
88 }
89 if (kernelSepolicyVersion() < mat.framework.mSepolicy.kernelSepolicyVersion()) {
90 if (error != nullptr) {
91 *error =
92 "kernelSepolicyVersion = " + to_string(kernelSepolicyVersion()) +
93 " but required >= " + to_string(mat.framework.mSepolicy.kernelSepolicyVersion());
94 }
95 return false;
96 }
97
98 // mat.mSepolicy.sepolicyVersion() is checked against static
99 // HalManifest.device.mSepolicyVersion in HalManifest::checkCompatibility.
100
101 if (flags.isKernelEnabled()) {
102 if (!isMainlineKernel() &&
103 mKernel.getMatchedKernelRequirements(mat.framework.mKernels, kernelLevel(), error)
104 .empty()) {
105 return false;
106 }
107 }
108
109 if (flags.isAvbEnabled()) {
110 const Version& matAvb = mat.framework.mAvbMetaVersion;
111 if (mBootAvbVersion.majorVer != matAvb.majorVer ||
112 mBootAvbVersion.minorVer < matAvb.minorVer) {
113 if (error != nullptr) {
114 std::stringstream ss;
115 ss << "AVB version " << mBootAvbVersion << " does not match framework matrix "
116 << matAvb;
117 *error = ss.str();
118 }
119 return false;
120 }
121 if (mBootVbmetaAvbVersion.majorVer != matAvb.majorVer ||
122 mBootVbmetaAvbVersion.minorVer < matAvb.minorVer) {
123 if (error != nullptr) {
124 std::stringstream ss;
125 ss << "Vbmeta version " << mBootVbmetaAvbVersion
126 << " does not match framework matrix " << matAvb;
127 *error = ss.str();
128 }
129 return false;
130 }
131 }
132
133 return true;
134 }
135
setKernelLevel(Level level)136 void RuntimeInfo::setKernelLevel(Level level) {
137 mKernel.mLevel = level;
138 }
139
kernelLevel() const140 Level RuntimeInfo::kernelLevel() const {
141 return mKernel.mLevel;
142 }
143
parseGkiKernelRelease(RuntimeInfo::FetchFlags flags,const std::string & kernelReleaseString,KernelVersion * outVersion,Level * outLevel)144 status_t RuntimeInfo::parseGkiKernelRelease(RuntimeInfo::FetchFlags flags,
145 const std::string& kernelReleaseString,
146 KernelVersion* outVersion, Level* outLevel) {
147 auto kernelRelease =
148 android::kver::KernelRelease::Parse(kernelReleaseString, true /* allow suffix */);
149 if (kernelRelease == std::nullopt) {
150 return UNKNOWN_ERROR;
151 }
152
153 if (flags & RuntimeInfo::FetchFlag::CPU_VERSION) {
154 if (kernelRelease->version() > std::numeric_limits<size_t>::max() ||
155 kernelRelease->patch_level() > std::numeric_limits<size_t>::max() ||
156 kernelRelease->sub_level() > std::numeric_limits<size_t>::max()) {
157 LOG(ERROR) << "Overflow : " << kernelRelease->string();
158 return UNKNOWN_ERROR;
159 }
160 *outVersion = {static_cast<size_t>(kernelRelease->version()),
161 static_cast<size_t>(kernelRelease->patch_level()),
162 static_cast<size_t>(kernelRelease->sub_level())};
163 }
164
165 if (flags & RuntimeInfo::FetchFlag::KERNEL_FCM) {
166 Level kernelLevel = gkiAndroidReleaseToLevel(kernelRelease->android_release());
167 if (kernelLevel == Level::UNSPECIFIED) {
168 LOG(ERROR) << "Cannot infer level corresponding to Android "
169 << kernelRelease->android_release()
170 << "; update libvintf to recognize this value.";
171 return UNKNOWN_ERROR;
172 }
173 // VintfObject may previously set mRuntimeInfo->mKernel.mLevel to the kernel level
174 // from device manifest. Check consistency.
175 if (*outLevel != Level::UNSPECIFIED && *outLevel != kernelLevel) {
176 LOG(ERROR) << "Kernel level in device manifest (" << *outLevel
177 << ") does not match kernel level in kernel release (" << kernelLevel
178 << " for Android " << kernelRelease->android_release() << ")";
179 return UNKNOWN_ERROR;
180 }
181 *outLevel = kernelLevel;
182 }
183 return OK;
184 }
185
gkiAndroidReleaseToLevel(uint64_t androidRelease)186 Level RuntimeInfo::gkiAndroidReleaseToLevel(uint64_t androidRelease) {
187 constexpr size_t ANDROID_S = 12;
188 constexpr size_t ANDROID_V = 15;
189
190 // Values prior to Android 12 is ignored because GKI kernel release format starts
191 // at Android 12.
192 if (androidRelease < ANDROID_S) return Level::UNSPECIFIED;
193
194 Level ret = Level::UNSPECIFIED;
195 if (androidRelease < ANDROID_V) {
196 ret = static_cast<Level>(androidRelease - ANDROID_S + static_cast<size_t>(Level::S));
197 } else {
198 switch (androidRelease) {
199 case 15: {
200 ret = Level::V;
201 } break;
202 // Add more levels above this line.
203 default: {
204 LOG(FATAL) << "Convert Android " << androidRelease << " to level '" << ret
205 << "' goes out of bounds. Fix by editing "
206 << "RuntimeInfo::gkiAndroidReleaseToLevel";
207 } break;
208 }
209 }
210
211 CHECK(IsValid(ret) && ret != Level::UNSPECIFIED)
212 << "Convert Android " << androidRelease << " to level '" << ret
213 << "' goes out of bounds. Fix by adding a new Level enum.";
214 return ret;
215 }
216
kernelReleaseIsMainline(std::string_view kernelRelease)217 bool RuntimeInfo::kernelReleaseIsMainline(std::string_view kernelRelease) {
218 static constexpr char kMainline[] = "-mainline-";
219 static constexpr char kMainlineSuffix[] = "-mainline";
220
221 return kernelRelease.find(kMainline) != std::string::npos ||
222 android::base::EndsWith(kernelRelease, kMainlineSuffix);
223 }
224
225 } // namespace vintf
226 } // namespace android
227