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