cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

kunit_config.py (2418B)


      1# SPDX-License-Identifier: GPL-2.0
      2#
      3# Builds a .config from a kunitconfig.
      4#
      5# Copyright (C) 2019, Google LLC.
      6# Author: Felix Guo <felixguoxiuping@gmail.com>
      7# Author: Brendan Higgins <brendanhiggins@google.com>
      8
      9from dataclasses import dataclass
     10import re
     11from typing import List, Set
     12
     13CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_(\w+) is not set$'
     14CONFIG_PATTERN = r'^CONFIG_(\w+)=(\S+|".*")$'
     15
     16@dataclass(frozen=True)
     17class KconfigEntry:
     18	name: str
     19	value: str
     20
     21	def __str__(self) -> str:
     22		if self.value == 'n':
     23			return f'# CONFIG_{self.name} is not set'
     24		return f'CONFIG_{self.name}={self.value}'
     25
     26
     27class KconfigParseError(Exception):
     28	"""Error parsing Kconfig defconfig or .config."""
     29
     30
     31class Kconfig:
     32	"""Represents defconfig or .config specified using the Kconfig language."""
     33
     34	def __init__(self) -> None:
     35		self._entries = []  # type: List[KconfigEntry]
     36
     37	def entries(self) -> Set[KconfigEntry]:
     38		return set(self._entries)
     39
     40	def add_entry(self, entry: KconfigEntry) -> None:
     41		self._entries.append(entry)
     42
     43	def is_subset_of(self, other: 'Kconfig') -> bool:
     44		other_dict = {e.name: e.value for e in other.entries()}
     45		for a in self.entries():
     46			b = other_dict.get(a.name)
     47			if b is None:
     48				if a.value == 'n':
     49					continue
     50				return False
     51			if a.value != b:
     52				return False
     53		return True
     54
     55	def merge_in_entries(self, other: 'Kconfig') -> None:
     56		if other.is_subset_of(self):
     57			return
     58		self._entries = list(self.entries().union(other.entries()))
     59
     60	def write_to_file(self, path: str) -> None:
     61		with open(path, 'a+') as f:
     62			for entry in self.entries():
     63				f.write(str(entry) + '\n')
     64
     65def parse_file(path: str) -> Kconfig:
     66	with open(path, 'r') as f:
     67		return parse_from_string(f.read())
     68
     69def parse_from_string(blob: str) -> Kconfig:
     70	"""Parses a string containing Kconfig entries."""
     71	kconfig = Kconfig()
     72	is_not_set_matcher = re.compile(CONFIG_IS_NOT_SET_PATTERN)
     73	config_matcher = re.compile(CONFIG_PATTERN)
     74	for line in blob.split('\n'):
     75		line = line.strip()
     76		if not line:
     77			continue
     78
     79		match = config_matcher.match(line)
     80		if match:
     81			entry = KconfigEntry(match.group(1), match.group(2))
     82			kconfig.add_entry(entry)
     83			continue
     84
     85		empty_match = is_not_set_matcher.match(line)
     86		if empty_match:
     87			entry = KconfigEntry(empty_match.group(1), 'n')
     88			kconfig.add_entry(entry)
     89			continue
     90
     91		if line[0] == '#':
     92			continue
     93		raise KconfigParseError('Failed to parse: ' + line)
     94	return kconfig