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 
31 const std::string &RuntimeInfo::osName() const {
32     return mOsName;
33 }
34 
35 const std::string &RuntimeInfo::nodeName() const {
36     return mNodeName;
37 }
38 
39 const std::string &RuntimeInfo::osRelease() const {
40     return mOsRelease;
41 }
42 
43 const std::string &RuntimeInfo::osVersion() const {
44     return mOsVersion;
45 }
46 
47 const std::string &RuntimeInfo::hardwareId() const {
48     return mHardwareId;
49 }
50 
51 const KernelVersion &RuntimeInfo::kernelVersion() const {
52     return mKernel.version();
53 }
54 
55 const std::map<std::string, std::string> &RuntimeInfo::kernelConfigs() const {
56     return mKernel.configs();
57 }
58 
59 size_t RuntimeInfo::kernelSepolicyVersion() const {
60     return mKernelSepolicyVersion;
61 }
62 
63 const std::string &RuntimeInfo::cpuInfo() const {
64     return mCpuInfo;
65 }
66 
67 const Version &RuntimeInfo::bootVbmetaAvbVersion() const {
68     return mBootVbmetaAvbVersion;
69 }
70 
71 const Version &RuntimeInfo::bootAvbVersion() const {
72     return mBootAvbVersion;
73 }
74 
75 bool RuntimeInfo::isMainlineKernel() const {
76     return mIsMainline;
77 }
78 
79 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 
135 void RuntimeInfo::setKernelLevel(Level level) {
136     mKernel.mLevel = level;
137 }
138 
139 Level RuntimeInfo::kernelLevel() const {
140     return mKernel.mLevel;
141 }
142 
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 
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