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 <kver/kernel_release.h>
24
25 #include "CompatibilityMatrix.h"
26 #include "parse_string.h"
27
28 namespace android {
29 namespace vintf {
30
osName() const31 const std::string &RuntimeInfo::osName() const {
32 return mOsName;
33 }
34
nodeName() const35 const std::string &RuntimeInfo::nodeName() const {
36 return mNodeName;
37 }
38
osRelease() const39 const std::string &RuntimeInfo::osRelease() const {
40 return mOsRelease;
41 }
42
osVersion() const43 const std::string &RuntimeInfo::osVersion() const {
44 return mOsVersion;
45 }
46
hardwareId() const47 const std::string &RuntimeInfo::hardwareId() const {
48 return mHardwareId;
49 }
50
kernelVersion() const51 const KernelVersion &RuntimeInfo::kernelVersion() const {
52 return mKernel.version();
53 }
54
kernelConfigs() const55 const std::map<std::string, std::string> &RuntimeInfo::kernelConfigs() const {
56 return mKernel.configs();
57 }
58
kernelSepolicyVersion() const59 size_t RuntimeInfo::kernelSepolicyVersion() const {
60 return mKernelSepolicyVersion;
61 }
62
cpuInfo() const63 const std::string &RuntimeInfo::cpuInfo() const {
64 return mCpuInfo;
65 }
66
bootVbmetaAvbVersion() const67 const Version &RuntimeInfo::bootVbmetaAvbVersion() const {
68 return mBootVbmetaAvbVersion;
69 }
70
bootAvbVersion() const71 const Version &RuntimeInfo::bootAvbVersion() const {
72 return mBootAvbVersion;
73 }
74
isMainlineKernel() const75 bool RuntimeInfo::isMainlineKernel() const {
76 return mIsMainline;
77 }
78
checkCompatibility(const CompatibilityMatrix & mat,std::string * error,CheckFlags::Type flags) const79 bool RuntimeInfo::checkCompatibility(const CompatibilityMatrix& mat, std::string* error,
80 CheckFlags::Type flags) const {
81 if (mat.mType != SchemaType::FRAMEWORK) {
82 if (error != nullptr) {
83 *error = "Should not check runtime info against " + to_string(mat.mType)
84 + " compatibility matrix.";
85 }
86 return false;
87 }
88 if (kernelSepolicyVersion() < mat.framework.mSepolicy.kernelSepolicyVersion()) {
89 if (error != nullptr) {
90 *error =
91 "kernelSepolicyVersion = " + to_string(kernelSepolicyVersion()) +
92 " but required >= " + to_string(mat.framework.mSepolicy.kernelSepolicyVersion());
93 }
94 return false;
95 }
96
97 // mat.mSepolicy.sepolicyVersion() is checked against static
98 // HalManifest.device.mSepolicyVersion in HalManifest::checkCompatibility.
99
100 if (flags.isKernelEnabled()) {
101 if (!isMainlineKernel() &&
102 mKernel.getMatchedKernelRequirements(mat.framework.mKernels, kernelLevel(), error)
103 .empty()) {
104 return false;
105 }
106 }
107
108 if (flags.isAvbEnabled()) {
109 const Version& matAvb = mat.framework.mAvbMetaVersion;
110 if (mBootAvbVersion.majorVer != matAvb.majorVer ||
111 mBootAvbVersion.minorVer < matAvb.minorVer) {
112 if (error != nullptr) {
113 std::stringstream ss;
114 ss << "AVB version " << mBootAvbVersion << " does not match framework matrix "
115 << matAvb;
116 *error = ss.str();
117 }
118 return false;
119 }
120 if (mBootVbmetaAvbVersion.majorVer != matAvb.majorVer ||
121 mBootVbmetaAvbVersion.minorVer < matAvb.minorVer) {
122 if (error != nullptr) {
123 std::stringstream ss;
124 ss << "Vbmeta version " << mBootVbmetaAvbVersion
125 << " does not match framework matrix " << matAvb;
126 *error = ss.str();
127 }
128 return false;
129 }
130 }
131
132 return true;
133 }
134
setKernelLevel(Level level)135 void RuntimeInfo::setKernelLevel(Level level) {
136 mKernel.mLevel = level;
137 }
138
kernelLevel() const139 Level RuntimeInfo::kernelLevel() const {
140 return mKernel.mLevel;
141 }
142
parseGkiKernelRelease(RuntimeInfo::FetchFlags flags,const std::string & kernelReleaseString,KernelVersion * outVersion,Level * outLevel)143 status_t RuntimeInfo::parseGkiKernelRelease(RuntimeInfo::FetchFlags flags,
144 const std::string& kernelReleaseString,
145 KernelVersion* outVersion, Level* outLevel) {
146 auto kernelRelease =
147 android::kver::KernelRelease::Parse(kernelReleaseString, true /* allow suffix */);
148 if (kernelRelease == std::nullopt) {
149 return UNKNOWN_ERROR;
150 }
151
152 if (flags & RuntimeInfo::FetchFlag::CPU_VERSION) {
153 if (kernelRelease->version() > std::numeric_limits<size_t>::max() ||
154 kernelRelease->patch_level() > std::numeric_limits<size_t>::max() ||
155 kernelRelease->sub_level() > std::numeric_limits<size_t>::max()) {
156 LOG(ERROR) << "Overflow : " << kernelRelease->string();
157 return UNKNOWN_ERROR;
158 }
159 *outVersion = {static_cast<size_t>(kernelRelease->version()),
160 static_cast<size_t>(kernelRelease->patch_level()),
161 static_cast<size_t>(kernelRelease->sub_level())};
162 }
163
164 if (flags & RuntimeInfo::FetchFlag::KERNEL_FCM) {
165 Level kernelLevel = gkiAndroidReleaseToLevel(kernelRelease->android_release());
166 if (kernelLevel == Level::UNSPECIFIED) {
167 LOG(ERROR) << "Cannot infer level corresponding to Android "
168 << kernelRelease->android_release()
169 << "; update libvintf to recognize this value.";
170 return UNKNOWN_ERROR;
171 }
172 // VintfObject may previously set mRuntimeInfo->mKernel.mLevel to the kernel level
173 // from device manifest. Check consistency.
174 if (*outLevel != Level::UNSPECIFIED && *outLevel != kernelLevel) {
175 LOG(ERROR) << "Kernel level in device manifest (" << *outLevel
176 << ") does not match kernel level in kernel release (" << kernelLevel
177 << " for Android " << kernelRelease->android_release() << ")";
178 return UNKNOWN_ERROR;
179 }
180 *outLevel = kernelLevel;
181 }
182 return OK;
183 }
184
gkiAndroidReleaseToLevel(uint64_t androidRelease)185 Level RuntimeInfo::gkiAndroidReleaseToLevel(uint64_t androidRelease) {
186 constexpr size_t ANDROID_S = 12;
187
188 // Values prior to Android 12 is ignored because GKI kernel release format starts
189 // at Android 12.
190 if (androidRelease < ANDROID_S) return Level::UNSPECIFIED;
191
192 Level ret = static_cast<Level>(androidRelease - ANDROID_S + static_cast<size_t>(Level::S));
193 CHECK(ret < Level::LAST_PLUS_ONE)
194 << "Convert Android " << androidRelease << " to level '" << ret
195 << "' goes out of bounds. Fix by adding a new Level enum.";
196 return ret;
197 }
198
199 } // namespace vintf
200 } // namespace android
201