1#!/usr/bin/env python
2#
3# Copyright (C) 2018 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17"""VTS tests to verify ACPIO partition overlay application."""
18
19import logging
20import os
21import shutil
22import struct
23import subprocess
24import tempfile
25import zlib
26
27from vts.runners.host import asserts
28from vts.runners.host import base_test
29from vts.runners.host import const
30from vts.runners.host import test_runner
31from vts.utils.python.android import api
32from vts.utils.python.file import target_file_utils
33from vts.utils.python.os import path_utils
34from hashlib import sha1
35
36BLOCK_DEV_PATH = "/dev/block"  # path to block devices
37PROPERTY_SLOT_SUFFIX = "ro.boot.slot_suffix"  # indicates current slot suffix for A/B devices
38SSDT_PATH = "/sys/firmware/acpi/tables"
39acpio_idx_string = ""
40
41class VtsFirmwareAcpioVerification(base_test.BaseTestClass):
42    """Validates ACPI overlay application.
43
44    Attributes:
45        temp_dir: The temporary directory on host.
46        device_path: The temporary directory on device.
47    """
48
49    def setUpClass(self):
50        """Initializes the DUT and creates temporary directories."""
51        self.dut = self.android_devices[0]
52        self.shell = self.dut.shell
53        self.adb = self.dut.adb
54        self.temp_dir = tempfile.mkdtemp()
55        logging.debug("Create %s", self.temp_dir)
56
57    def setUp(self):
58        """Checks if the the preconditions to run the test are met."""
59        global acpio_idx_string
60        asserts.skipIf("x86" not in self.dut.cpu_abi, "Skipping test for NON-x86 ABI")
61        acpio_idx_string = self.adb.shell(
62            "cat /proc/cmdline | "
63            "grep -o \"androidboot.acpio_idx=[^ ]*\" |"
64            "cut -d \"=\" -f 2 ")
65        acpio_idx_string = acpio_idx_string.replace('\n','')
66        asserts.assertTrue(acpio_idx_string, "Skipping test for x86 NON-ACPI ABI")
67
68    def getSha1(self, filename):
69        """Check the file hash."""
70        sha1Obj = sha1()
71        with open(filename, 'rb') as f:
72            sha1Obj.update(f.read())
73        return sha1Obj.hexdigest()
74
75    def testAcpioPartition(self):
76        """Validates ACPIO partition using mkdtboimg.py."""
77        temp_SSDT_dump = "SSDT.dump"
78        temp_SSDT_dump_hashes = []
79        current_SSDT = "SSDT"
80        current_SSDT_hashes = []
81
82        slot_suffix = str(self.dut.getProp(PROPERTY_SLOT_SUFFIX))
83        current_acpio_partition = "acpio" + slot_suffix
84        acpio_path = target_file_utils.FindFiles(
85            self.shell, BLOCK_DEV_PATH, current_acpio_partition, "-type l")
86        if not acpio_path:
87            asserts.fail("Unable to find path to acpio image on device.")
88        logging.debug("ACPIO path %s", acpio_path)
89        host_acpio_image = os.path.join(self.temp_dir, "acpio")
90        self.adb.pull("%s %s" % (acpio_path[0], host_acpio_image))
91        mkdtimg_bin_path = os.path.join("host", "bin", "mkdtboimg.py")
92        unpacked_acpio_file = os.path.join(self.temp_dir, temp_SSDT_dump)
93        acpio_dump_cmd = [
94            "%s" % mkdtimg_bin_path, "dump",
95            "%s" % host_acpio_image, "-b",
96            "%s" % unpacked_acpio_file
97        ]
98        try:
99            subprocess.check_call(acpio_dump_cmd)
100        except Exception as e:
101            logging.exception(e)
102            asserts.fail("Invalid ACPIO Image")
103        asserts.assertTrue(acpio_idx_string, "Kernel command line missing androidboot.acpio_idx")
104        acpio_idx_list = acpio_idx_string.split(",")
105        for idx in acpio_idx_list:
106            temp_SSDT_dump_file = "SSDT.dump." + idx.rstrip()
107            temp_SSDT_dump_file_hash=self.getSha1(os.path.join(self.temp_dir, temp_SSDT_dump_file))
108            temp_SSDT_dump_hashes.append(temp_SSDT_dump_file_hash)
109
110        SSDT_path = target_file_utils.FindFiles(self.shell, SSDT_PATH, "SSDT*")
111        for current_SSDT_file in SSDT_path:
112            host_SSDT_file = os.path.join(self.temp_dir, current_SSDT)
113            self.adb.pull("%s %s" % (current_SSDT_file, host_SSDT_file))
114            SSDT_file_hash=self.getSha1(host_SSDT_file)
115            current_SSDT_hashes.append(SSDT_file_hash)
116        asserts.assertTrue(current_SSDT_hashes, "No get current SSDT hash.")
117        asserts.assertTrue(set(temp_SSDT_dump_hashes) & set(current_SSDT_hashes), "Hash is not the same.")
118
119if __name__ == "__main__":
120    test_runner.main()
121