1# Lint as: python2, python3 2# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import logging 7import os 8 9from autotest_lib.client.bin import test, utils 10from autotest_lib.client.common_lib import error 11 12DEFAULT_MIN_GB = 16 13# Allowable amount of bits eMMC vendor can use in firmware to support bad block 14# replacement and metadata. 15EMMC_VENDOR_ALLOWED_GB = 0.25 16# Amount of data available for user data in device, the rest is left for 17# over provisioning. 18# Typically a SATA device will use 7% over provisioning [the difference 19# between GB and GiB], but some eMMC device can use 9%. 20# With Flash becoming more error prone as lithography shrinks, the trend 21# is to increase over provisioning. 22DEFAULT_USER_DENSITY = 0.9 23 24 25class hardware_DiskSize(test.test): 26 """ 27 Check that disk size is around 16GB at least. 28 """ 29 30 version = 1 31 32 def _is_emmc(self): 33 path = os.path.join("/sys/class/block/", self._device, 34 "device", "type") 35 if not os.path.exists(path): 36 return False 37 return utils.read_one_line(path) == 'MMC' 38 39 40 @classmethod 41 def _gib_to_gb(cls, gib): 42 return float(gib) * (1 << 30) / (10 ** 9) 43 44 def _compute_min_gb(self): 45 """Computes minimum size allowed primary storage device. 46 47 TODO(tbroch): Add computation of raw bytes in eMMC using 'Chip Specific 48 Data' (CSD & EXT_CSD) defined by JEDEC JESD84-A44.pdf if possible. 49 50 CSD :: /sys/class/block/<device>/device/csd 51 EXT_CSD :: debugfs 52 53 Algorithm should look something like this: 54 CSD[C_SIZE] = 0xfff == eMMC > 2GB 55 EXT_CSD[SEC_COUNT] = # of 512byte sectors 56 57 Now for existing eMMC I've examined I do see the C_SIZE == 0xfff. 58 Unfortunately the SEC_COUNT appears to have excluded the sectors 59 reserved for metadata & repair. Perhaps thats by design in which case 60 there is no mechanism to determine the actual raw sectors. 61 62 For now I use 0.25GB as an acceptable fudge. 63 64 Returns: 65 integer, in GB of minimum storage size. 66 """ 67 68 min_gb = DEFAULT_MIN_GB 69 if self._is_emmc(): 70 min_gb -= EMMC_VENDOR_ALLOWED_GB 71 min_gb *= DEFAULT_USER_DENSITY 72 return self._gib_to_gb(min_gb) 73 74 75 def run_once(self): 76 root_dev = utils.get_root_device() 77 self._device = os.path.basename(root_dev) 78 disk_size = utils.get_disk_size(root_dev) 79 if not disk_size: 80 raise error.TestError('Unable to determine main disk size') 81 82 # Capacity of a hard disk is quoted with SI prefixes, incrementing by 83 # powers of 1000, instead of powers of 1024. 84 gb = float(disk_size) / (10 ** 9) 85 86 self.write_perf_keyval({"gb_main_disk_size": gb}) 87 min_gb = self._compute_min_gb() 88 logging.info("DiskSize: %.3f GB MinDiskSize: %.3f GB", gb, min_gb) 89 if (gb < min_gb): 90 raise error.TestError("DiskSize %.3f GB below minimum (%.3f GB)" \ 91 % (gb, min_gb)) 92