14fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian/* 24fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian * Copyright (C) 2016 The Android Open Source Project 34fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian * 44fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian * Licensed under the Apache License, Version 2.0 (the "License"); 54fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian * you may not use this file except in compliance with the License. 64fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian * You may obtain a copy of the License at 74fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian * 84fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian * http://www.apache.org/licenses/LICENSE-2.0 94fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian * 104fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian * Unless required by applicable law or agreed to in writing, software 114fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian * distributed under the License is distributed on an "AS IS" BASIS, 124fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian * See the License for the specific language governing permissions and 144fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian * limitations under the License. 154fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian */ 164fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 174fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian#define LOG_TAG "storaged" 184fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 19726339c7e8bd7c1e07031cfda3936debca975831Jin Qian#include <stdio.h> 204fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian#include <string.h> 218847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian#include <sys/statvfs.h> 224fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 234fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian#include <android-base/file.h> 244fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian#include <android-base/parseint.h> 25726339c7e8bd7c1e07031cfda3936debca975831Jin Qian#include <android-base/logging.h> 26b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian#include <android-base/strings.h> 274fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian#include <log/log_event_list.h> 284fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 294fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian#include "storaged.h" 304fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 314fc338e60bf1d85212f1540d109beb1b248c4830Jin Qianusing namespace std; 324fc338e60bf1d85212f1540d109beb1b248c4830Jin Qianusing namespace android::base; 334fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 348847c62579282cd67a80d7354ccf26064aaed4e5Jin Qianconst string emmc_info_t::emmc_sysfs = "/sys/bus/mmc/devices/mmc0:0001/"; 358847c62579282cd67a80d7354ccf26064aaed4e5Jin Qianconst string emmc_info_t::emmc_debugfs = "/d/mmc0/mmc0:0001/ext_csd"; 368847c62579282cd67a80d7354ccf26064aaed4e5Jin Qianconst char* emmc_info_t::emmc_ver_str[9] = { 378847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0", "5.1" 388847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian}; 398847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian 408847c62579282cd67a80d7354ccf26064aaed4e5Jin Qianconst string ufs_info_t::health_file = "/sys/devices/soc/624000.ufshc/health"; 418847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian 428847c62579282cd67a80d7354ccf26064aaed4e5Jin Qianstatic bool FileExists(const std::string& filename) 438847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian{ 448847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian struct stat buffer; 458847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian return stat(filename.c_str(), &buffer) == 0; 468847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian} 478847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian 488847c62579282cd67a80d7354ccf26064aaed4e5Jin Qianstorage_info_t* storage_info_t::get_storage_info() 498847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian{ 508847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian if (FileExists(emmc_info_t::emmc_sysfs) || 518847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian FileExists(emmc_info_t::emmc_debugfs)) { 528847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian return new emmc_info_t; 538847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian } 548847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian if (FileExists(ufs_info_t::health_file)) { 558847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian return new ufs_info_t; 568847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian } 578847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian return new storage_info_t; 588847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian} 598847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian 608847c62579282cd67a80d7354ccf26064aaed4e5Jin Qianvoid storage_info_t::refresh() 614fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian{ 628847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian struct statvfs buf; 638847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian if (statvfs(userdata_path.c_str(), &buf) != 0) { 648847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian PLOG_TO(SYSTEM, WARNING) << "Failed to get userdata info"; 658847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian return; 668847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian } 67b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian 688847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian userdata_total_kb = buf.f_bsize * buf.f_blocks >> 10; 698847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian userdata_free_kb = buf.f_bfree * buf.f_blocks >> 10; 70726339c7e8bd7c1e07031cfda3936debca975831Jin Qian} 714fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 72726339c7e8bd7c1e07031cfda3936debca975831Jin Qianvoid storage_info_t::publish() 73726339c7e8bd7c1e07031cfda3936debca975831Jin Qian{ 744fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian android_log_event_list(EVENTLOGTAG_EMMCINFO) 754fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian << version << eol << lifetime_a << lifetime_b 764fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian << LOG_ID_EVENTS; 774fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian} 784fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 798847c62579282cd67a80d7354ccf26064aaed4e5Jin Qianvoid emmc_info_t::report() 80726339c7e8bd7c1e07031cfda3936debca975831Jin Qian{ 81726339c7e8bd7c1e07031cfda3936debca975831Jin Qian if (!report_sysfs() && !report_debugfs()) 828847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian return; 83726339c7e8bd7c1e07031cfda3936debca975831Jin Qian 84726339c7e8bd7c1e07031cfda3936debca975831Jin Qian publish(); 85726339c7e8bd7c1e07031cfda3936debca975831Jin Qian} 86726339c7e8bd7c1e07031cfda3936debca975831Jin Qian 87726339c7e8bd7c1e07031cfda3936debca975831Jin Qianbool emmc_info_t::report_sysfs() 884fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian{ 894fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian string buffer; 90726339c7e8bd7c1e07031cfda3936debca975831Jin Qian uint16_t rev = 0; 91726339c7e8bd7c1e07031cfda3936debca975831Jin Qian 92726339c7e8bd7c1e07031cfda3936debca975831Jin Qian if (!ReadFileToString(emmc_sysfs + "rev", &buffer)) { 934fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian return false; 944fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian } 954fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 96726339c7e8bd7c1e07031cfda3936debca975831Jin Qian if (sscanf(buffer.c_str(), "0x%hx", &rev) < 1 || 97726339c7e8bd7c1e07031cfda3936debca975831Jin Qian rev < 7 || rev > ARRAY_SIZE(emmc_ver_str)) { 984fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian return false; 994fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian } 1004fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 1014fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian version = "emmc "; 102726339c7e8bd7c1e07031cfda3936debca975831Jin Qian version += emmc_ver_str[rev]; 1034fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 104726339c7e8bd7c1e07031cfda3936debca975831Jin Qian if (!ReadFileToString(emmc_sysfs + "pre_eol_info", &buffer)) { 1054fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian return false; 1064fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian } 1074fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 108726339c7e8bd7c1e07031cfda3936debca975831Jin Qian if (sscanf(buffer.c_str(), "%hx", &eol) < 1 || eol == 0) { 109726339c7e8bd7c1e07031cfda3936debca975831Jin Qian return false; 110726339c7e8bd7c1e07031cfda3936debca975831Jin Qian } 111726339c7e8bd7c1e07031cfda3936debca975831Jin Qian 112726339c7e8bd7c1e07031cfda3936debca975831Jin Qian if (!ReadFileToString(emmc_sysfs + "life_time", &buffer)) { 113726339c7e8bd7c1e07031cfda3936debca975831Jin Qian return false; 114726339c7e8bd7c1e07031cfda3936debca975831Jin Qian } 115726339c7e8bd7c1e07031cfda3936debca975831Jin Qian 116726339c7e8bd7c1e07031cfda3936debca975831Jin Qian if (sscanf(buffer.c_str(), "0x%hx 0x%hx", &lifetime_a, &lifetime_b) < 2 || 117726339c7e8bd7c1e07031cfda3936debca975831Jin Qian (lifetime_a == 0 && lifetime_b == 0)) { 118726339c7e8bd7c1e07031cfda3936debca975831Jin Qian return false; 119726339c7e8bd7c1e07031cfda3936debca975831Jin Qian } 120726339c7e8bd7c1e07031cfda3936debca975831Jin Qian 121726339c7e8bd7c1e07031cfda3936debca975831Jin Qian return true; 1224fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian} 1234fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 124726339c7e8bd7c1e07031cfda3936debca975831Jin Qianconst size_t EXT_CSD_FILE_MIN_SIZE = 1024; 125726339c7e8bd7c1e07031cfda3936debca975831Jin Qian/* 2 characters in string for each byte */ 126726339c7e8bd7c1e07031cfda3936debca975831Jin Qianconst size_t EXT_CSD_REV_IDX = 192 * 2; 127726339c7e8bd7c1e07031cfda3936debca975831Jin Qianconst size_t EXT_PRE_EOL_INFO_IDX = 267 * 2; 128726339c7e8bd7c1e07031cfda3936debca975831Jin Qianconst size_t EXT_DEVICE_LIFE_TIME_EST_A_IDX = 268 * 2; 129726339c7e8bd7c1e07031cfda3936debca975831Jin Qianconst size_t EXT_DEVICE_LIFE_TIME_EST_B_IDX = 269 * 2; 130726339c7e8bd7c1e07031cfda3936debca975831Jin Qian 131726339c7e8bd7c1e07031cfda3936debca975831Jin Qianbool emmc_info_t::report_debugfs() 1324fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian{ 1334fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian string buffer; 134726339c7e8bd7c1e07031cfda3936debca975831Jin Qian uint16_t rev = 0; 135726339c7e8bd7c1e07031cfda3936debca975831Jin Qian 136726339c7e8bd7c1e07031cfda3936debca975831Jin Qian if (!ReadFileToString(emmc_debugfs, &buffer) || 1374fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) { 1384fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian return false; 1394fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian } 1404fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 141726339c7e8bd7c1e07031cfda3936debca975831Jin Qian string str = buffer.substr(EXT_CSD_REV_IDX, 2); 142726339c7e8bd7c1e07031cfda3936debca975831Jin Qian if (!ParseUint(str, &rev) || 143726339c7e8bd7c1e07031cfda3936debca975831Jin Qian rev < 7 || rev > ARRAY_SIZE(emmc_ver_str)) { 144726339c7e8bd7c1e07031cfda3936debca975831Jin Qian return false; 145726339c7e8bd7c1e07031cfda3936debca975831Jin Qian } 146726339c7e8bd7c1e07031cfda3936debca975831Jin Qian 147726339c7e8bd7c1e07031cfda3936debca975831Jin Qian version = "emmc "; 148726339c7e8bd7c1e07031cfda3936debca975831Jin Qian version += emmc_ver_str[rev]; 149726339c7e8bd7c1e07031cfda3936debca975831Jin Qian 150726339c7e8bd7c1e07031cfda3936debca975831Jin Qian str = buffer.substr(EXT_PRE_EOL_INFO_IDX, 2); 1514fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian if (!ParseUint(str, &eol)) { 1524fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian return false; 1534fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian } 1544fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 155726339c7e8bd7c1e07031cfda3936debca975831Jin Qian str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_A_IDX, 2); 1564fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian if (!ParseUint(str, &lifetime_a)) { 1574fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian return false; 1584fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian } 1594fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 160726339c7e8bd7c1e07031cfda3936debca975831Jin Qian str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_B_IDX, 2); 1614fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian if (!ParseUint(str, &lifetime_b)) { 1624fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian return false; 1634fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian } 1644fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian 1654fc338e60bf1d85212f1540d109beb1b248c4830Jin Qian return true; 166b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian} 167b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian 1688847c62579282cd67a80d7354ccf26064aaed4e5Jin Qianvoid ufs_info_t::report() 169b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian{ 170b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian string buffer; 171b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian if (!ReadFileToString(health_file, &buffer)) { 1728847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian return; 173b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian } 174b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian 175b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian vector<string> lines = Split(buffer, "\n"); 176b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian if (lines.empty()) { 1778847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian return; 178b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian } 179b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian 180b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian char rev[8]; 181b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian if (sscanf(lines[0].c_str(), "ufs version: 0x%7s\n", rev) < 1) { 1828847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian return; 183b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian } 184b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian 185b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian version = "ufs " + string(rev); 186b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian 187b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian for (size_t i = 1; i < lines.size(); i++) { 188b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian char token[32]; 189b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian uint16_t val; 190b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian int ret; 191b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian if ((ret = sscanf(lines[i].c_str(), 192b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian "Health Descriptor[Byte offset 0x%*d]: %31s = 0x%hx", 193b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian token, &val)) < 2) { 194b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian continue; 195b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian } 196b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian 197b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian if (string(token) == "bPreEOLInfo") { 198b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian eol = val; 199b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian } else if (string(token) == "bDeviceLifeTimeEstA") { 200b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian lifetime_a = val; 201b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian } else if (string(token) == "bDeviceLifeTimeEstB") { 202b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian lifetime_b = val; 203b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian } 204b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian } 205b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian 206b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian if (eol == 0 || (lifetime_a == 0 && lifetime_b == 0)) { 2078847c62579282cd67a80d7354ccf26064aaed4e5Jin Qian return; 208b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian } 209b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian 210b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian publish(); 211b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian} 212b90f1ae1e5d9886dc32b2f653ab2899a0416bd71Jin Qian 213