Files
chipsec-chipsec/source/tool/tests/software/test_util.py
T
2016-04-16 12:55:19 -07:00

235 lines
9.0 KiB
Python

import os
import struct
import tempfile
import unittest
from tests.software import mock_helper
import chipsec_util
from chipsec import logger
from chipsec import chipset
from chipsec.helper import oshelper
class TestChipsecUtil(unittest.TestCase):
"""Test the commands exposed by chipsec_utils.
Each test may define its virtual helper and then call the _chipsec_util
method with the command line arguments.
"""
def setUp(self):
"""Setup the environment for the utils tests.
We mock the helper registry to only contain our emulated helper.
"""
fileno, self.log_file = tempfile.mkstemp()
os.close(fileno)
self.old_registry = oshelper.Helper.registry
oshelper.Helper.registry = []
oshelper._helper = None
chipset._chipset = None
def tearDown(self):
os.remove(self.log_file)
oshelper._helper = None
chipset._chipset = None
chipsec_util._cs = None
oshelper.Helper.registry = self.old_registry
def _chipsec_util(self, arg, helper_class=mock_helper.TestHelper):
"""Run the chipsec_util command with the arguments.
Each test may setup a virtual helper to emulate the expected behaviour
from the hardware. If no helper is provided, TestHelper will be used.
It verifies that no error is being reported. self.log will be populated
with the output.
"""
oshelper.Helper.registry = [(helper_class.__name__, helper_class)]
chipsec_util._cs = chipset.cs()
util = chipsec_util.ChipsecUtil()
util.VERBOSE = True
util.set_logfile(self.log_file)
err_code = util.main(["chipsec_utils.py"] + arg.split())
logger.logger().close()
self.log = open(self.log_file).read()
self.assertEqual(err_code, 0)
def test_acpi_xsdt_list(self):
class ACPIHelper(mock_helper.TestHelper):
RSDP_DESCRIPTOR = ("RSD PTR " + # Signature
struct.pack("<B", 0x1) + # Checksum
"TEST00" + # OEMID
struct.pack("<B", 0x2) + # Revision
struct.pack("<I", 0x200) + # RSDT Address
struct.pack("<I", 0x0) + # Length
struct.pack("<Q", 0x100) + # XSDT Address
struct.pack("<B", 0x0) + # Extended Checksum
"AAA") # Reserved
XSDT_DESCRIPTOR = ("XSDT" + # Signature
struct.pack("<I", 0x32) + # Length
struct.pack("<B", 0x1) + # Revision
struct.pack("<B", 0x1) + # Checksum
"OEMIDT" + # OEMID
"OEMTBLID" + # OEM Table ID
"OEMR" + # OEM Revision
"CRID" + # Creator ID
"CRRV" + # Creator Revision
struct.pack("<Q", 0x400)) # Address of table
EBDA_ADDRESS = 0x96000
EBDA_PADDING = 0x100
RSDP_ADDRESS = EBDA_ADDRESS + EBDA_PADDING
def read_phys_mem(self, pa_hi, pa_lo, length):
if pa_lo == 0x40E:
return struct.pack("<H", self.EBDA_ADDRESS >> 4)
elif pa_lo >= self.EBDA_ADDRESS and \
pa_lo < self.RSDP_ADDRESS + len(self.RSDP_DESCRIPTOR):
mem = "\x00" * self.EBDA_PADDING + self.RSDP_DESCRIPTOR
offset = pa_lo - self.EBDA_ADDRESS
return mem[offset:offset+length]
elif pa_lo == 0x100:
return self.XSDT_DESCRIPTOR[:length]
elif pa_lo == 0x400:
return "EFGH"
self._chipsec_util("acpi list", ACPIHelper)
self.assertIn("EFGH: 0x0000000000000400", self.log)
def test_acpi_rsdt_list(self):
class ACPIHelper(mock_helper.TestHelper):
RSDP_DESCRIPTOR = ("RSD PTR " + # Signature
struct.pack("<B", 0x1) + # Checksum
"TEST00" + # OEMID
struct.pack("<B", 0x0) + # Revision
struct.pack("<I", 0x200)) # RSDT Address
RSDT_DESCRIPTOR = ("RSDT" + # Signature
struct.pack("<I", 0x28) + # Length
struct.pack("<B", 0x1) + # Revision
struct.pack("<B", 0x1) + # Checksum
"OEMIDT" + # OEMID
"OEMTBLID" + # OEM Table ID
"OEMR" + # OEM Revision
"CRID" + # Creator ID
"CRRV" + # Creator Revision
struct.pack("<I", 0x300)) # Address of table
def read_phys_mem(self, pa_hi, pa_lo, length):
if pa_lo == 0xE0000:
return self.RSDP_DESCRIPTOR[:length]
elif pa_lo == 0x200:
return self.RSDT_DESCRIPTOR[:length]
elif pa_lo == 0x300:
return "ABCD"
else:
return "\xFF" * length
self._chipsec_util("acpi list", ACPIHelper)
self.assertIn("ABCD: 0x0000000000000300", self.log)
def test_platform(self):
self._chipsec_util("platform")
def test_cmos_dump(self):
"""Test to verify the output of 'cmos dump'.
Check that we only access CMOS IO ports.
"""
class CMOSHelper(mock_helper.TestHelper):
def read_io_port(self, io_port, size):
if io_port < 0x70 or io_port > 0x73:
raise Exception("Reading outside CMOS IO port")
return io_port
def write_io_port(self, io_port, value, size):
if io_port < 0x70 or io_port > 0x73:
raise Exception("Writing outside CMOS IO port")
self._chipsec_util("cmos dump", CMOSHelper)
def test_msr(self):
class MSRHelper(mock_helper.TestHelper):
def get_threads_count(self):
return 1
def read_msr(self, thread_id, msr_addr):
if msr_addr == 0x2FF:
return [0x1234, 0xcdef]
else:
return [0x0, 0x0]
self._chipsec_util("msr 0x2FF", MSRHelper)
self.assertIn("EAX=00001234, EDX=0000CDEF", self.log)
def test_gdt(self):
class GDTHelper(mock_helper.TestHelper):
def get_descriptor_table(self, cpu_thread_id, desc_table_code):
return (63, 0x1000, 0x0)
def read_phys_mem(self, pa_hi, pa_lo, length):
return "\xff" * length
self._chipsec_util("gdt 0", GDTHelper)
self.assertIn("# of entries : 4", self.log)
def test_spi_info(self):
"""Test to verify the ouput of 'spi info'.
Validates that BC and FRAP are correctly read.
"""
class SPIHelper(mock_helper.TestHelper):
RCBA_ADDR = 0xFED0000
SPIBAR_ADDR = RCBA_ADDR + 0x3800
SPIBAR_END = SPIBAR_ADDR + 0x200
FRAP = SPIBAR_ADDR + 0x50
FREG0 = SPIBAR_ADDR + 0x54
LPC_BRIDGE_DEVICE = (0, 0x1F, 0)
def read_pci_reg(self, bus, device, function, address, size):
if (bus, device, function) == self.LPC_BRIDGE_DEVICE:
if address == 0xF0:
return self.RCBA_ADDR
elif address == 0xDC:
return 0xDEADBEEF
else:
raise Exception("Unexpected PCI read")
else:
return super(SPIHelper, self).read_pci_reg(bus, device,
function,
address, size)
def read_mmio_reg(self, pa, size):
if pa == self.FREG0:
return 0x11111111
elif pa == self.FREG0 + 4:
return 0x22222222
elif pa == self.FRAP:
return 0xEEEEEEEE
elif pa >= self.SPIBAR_ADDR and pa < self.SPIBAR_END:
return 0x0
else:
raise Exception("Unexpected address")
def write_mmio_reg(self, pa, size, value):
if pa < self.SPIBAR_ADDR or pa > self.SPIBAR_END:
raise Exception("Write to outside of SPIBAR")
self._chipsec_util("spi info", SPIHelper)
self.assertIn("BC = 0xDEADBEEF", self.log)
self.assertIn("FRAP = 0xEEEEEEEE", self.log)