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