mirror of
https://github.com/chipsec/chipsec
synced 2026-06-08 13:31:00 +00:00
ac2ca7264f
UEFI shell. 2. Decompression of images in SPI flash parsing is only supported in Windows. 3. UEFI - Support for IA32 and i586 (Quark) 4. Added capability to use modules from an arbitrary path with the -I / --import command line option 5. Module functionality encapsulated in class inheriting BaseModule 6. Fixed loading platform specific configuration 7. Fixed issue with modules which run on multiple logical CPUs hanging on Bay Trail (Windows/Linux). The issue still exist when running from UEFI shell 8. Added template for a module - module_template.py 9. Added options to flush log files 10. Added ability to define custom platforms Driver changes: 1. Windows - Added IOCTL_ALLOC_PHYSMEM to allocate physical memory buffer 2. Linux - Fix wrpci defect
546 lines
21 KiB
Python
546 lines
21 KiB
Python
#!/usr/local/bin/python
|
|
#CHIPSEC: Platform Security Assessment Framework
|
|
#Copyright (c) 2010-2014, Intel Corporation
|
|
#
|
|
#This program is free software; you can redistribute it and/or
|
|
#modify it under the terms of the GNU General Public License
|
|
#as published by the Free Software Foundation; Version 2.
|
|
#
|
|
#This program is distributed in the hope that it will be useful,
|
|
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
#GNU General Public License for more details.
|
|
#
|
|
#You should have received a copy of the GNU General Public License
|
|
#along with this program; if not, write to the Free Software
|
|
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
#
|
|
#Contact information:
|
|
#chipsec@intel.com
|
|
#
|
|
|
|
|
|
|
|
#
|
|
## \addtogroup core
|
|
# __chipsec_main.py__ -- main application logic and automation functions
|
|
#
|
|
|
|
__version__ = '1.1.0'
|
|
|
|
|
|
import os
|
|
import re
|
|
import sys
|
|
import fnmatch
|
|
import time
|
|
import traceback
|
|
|
|
import errno
|
|
import chipsec.file
|
|
import chipsec.module
|
|
|
|
_importlib = True
|
|
try:
|
|
import importlib
|
|
except ImportError:
|
|
_importlib = False
|
|
#import zipfile
|
|
|
|
from chipsec.logger import logger
|
|
|
|
|
|
CHIPSEC_FOLDER = os.path.abspath(chipsec.file.get_main_dir())
|
|
version=" "
|
|
VERSION_FILE = os.path.join( CHIPSEC_FOLDER , "VERSION" )
|
|
if os.path.exists( VERSION_FILE ):
|
|
with open(VERSION_FILE, "r") as verFile:
|
|
version = verFile.read()
|
|
|
|
def get_chipsec_version():
|
|
return "%s"% (__version__)
|
|
|
|
logger().log( '' )
|
|
logger().log( "################################################################\n"
|
|
"## ##\n"
|
|
"## CHIPSEC: Platform Hardware Security Assessment Framework ##\n"
|
|
"## ##\n"
|
|
"################################################################" )
|
|
logger().log( "Version %s \n" %get_chipsec_version() )
|
|
|
|
|
|
|
|
from chipsec.helper.oshelper import OsHelperError
|
|
from chipsec.chipset import cs, Chipset_Code, CHIPSET_ID_UNKNOWN, CHIPSET_ID_COMMON, UnknownChipsetError, AVAILABLE_MODULES, DISABLED_MODULES
|
|
_cs = cs()
|
|
|
|
from chipsec.file import *
|
|
|
|
VERBOSE = False
|
|
CHIPSEC_LOADED_AS_EXE = chipsec.file.main_is_frozen()
|
|
USER_MODULE_TAGS = []
|
|
|
|
##################################################################################
|
|
# Module API
|
|
##################################################################################
|
|
|
|
ZIP_MODULES_RE = None
|
|
def f_mod(x):
|
|
return ( x.find('__init__') == -1 and ZIP_MODULES_RE.match(x) )
|
|
|
|
def map_modname(x):
|
|
return (x.rpartition('.')[0]).replace('/','.')
|
|
#return ((x.split('/', 2)[2]).rpartition('.')[0]).replace('/','.')
|
|
|
|
def map_pass(x):
|
|
return x
|
|
|
|
Import_Path = "chipsec.modules."
|
|
Modules_Path = os.path.join(CHIPSEC_FOLDER,"chipsec","modules")
|
|
IMPORT_PATHS = []
|
|
|
|
Loaded_Modules = []
|
|
_list_tags = False
|
|
AVAILABLE_TAGS = []
|
|
|
|
MODPATH_RE = re.compile("^\w+(\.\w+)*$")
|
|
|
|
def isModuleDisabled(module_path):
|
|
try:
|
|
if(len(DISABLED_MODULES)>0):
|
|
if(module_path in DISABLED_MODULES[_cs.id]):
|
|
return True
|
|
except KeyError, msg:
|
|
logger().log(str(msg))
|
|
return False
|
|
|
|
def import_module(module_path):
|
|
module = None
|
|
if not MODPATH_RE.match(module_path):
|
|
logger().error( "Invalid module path: %s" % module_path )
|
|
else:
|
|
try:
|
|
module = importlib.import_module( module_path )
|
|
# Support for older Python < 2.5
|
|
#if _importlib:
|
|
# module = importlib.import_module( module_path )
|
|
#else:
|
|
# #module = __import__(module_path)
|
|
# exec 'import ' + module_path
|
|
except BaseException, msg:
|
|
logger().error( "Exception occurred during import of %s: '%s'" % (module_path, str(msg)) )
|
|
if logger().VERBOSE: logger().log_bad(traceback.format_exc())
|
|
return module
|
|
|
|
def verify_module_tags(module):
|
|
run_it = True
|
|
if len(USER_MODULE_TAGS) > 0 or _list_tags:
|
|
run_it = False
|
|
module_tags= module.get_tags()
|
|
for mt in module_tags:
|
|
if _list_tags:
|
|
if mt not in AVAILABLE_TAGS: AVAILABLE_TAGS.append(mt)
|
|
elif mt in USER_MODULE_TAGS:
|
|
run_it = True
|
|
return run_it
|
|
|
|
|
|
def old_run_module( module_path, module_argv ):
|
|
module_path = module_path.replace( os.sep, '.' )
|
|
module = import_module(module_path)
|
|
if module == None and _importlib: return None
|
|
run_it = True
|
|
if len(USER_MODULE_TAGS) > 0 or _list_tags:
|
|
run_it = False
|
|
module_tags=[]
|
|
try:
|
|
module_tags = getattr( module, 'TAGS' )
|
|
# Support for older Python < 2.5
|
|
#if _importlib:
|
|
# module_tags = getattr( module, 'TAGS' )
|
|
#else:
|
|
# exec ('module_tags = ' +module_path + '.TAGS')
|
|
except:
|
|
#logger().log(module_path)
|
|
#logger().log_bad(traceback.format_exc())
|
|
pass
|
|
for mt in module_tags:
|
|
if _list_tags:
|
|
if mt not in AVAILABLE_TAGS: AVAILABLE_TAGS.append(mt)
|
|
elif mt in USER_MODULE_TAGS:
|
|
run_it = True
|
|
|
|
if module_argv:
|
|
logger().log( "[*] Module arguments (%d):" % len(module_argv) )
|
|
logger().log( module_argv )
|
|
else:
|
|
module_argv = []
|
|
|
|
|
|
if run_it:
|
|
try:
|
|
result = False
|
|
result = getattr( module, 'run' )( module_argv )
|
|
# Support for older Python < 2.5
|
|
#if _importlib:
|
|
# result = getattr( module, 'run' )( module_argv )
|
|
#else:
|
|
# exec ('result = ' + module_path + '.run(module_argv)')
|
|
return result
|
|
except (None,Exception) , msg:
|
|
if logger().VERBOSE: logger().log_bad(traceback.format_exc())
|
|
logger().log_error_check( "Exception occurred during %s.run(): '%s'" % (module_path, str(msg)) )
|
|
return None
|
|
else:
|
|
from chipsec.module_common import ModuleResult
|
|
return ModuleResult.SKIPPED
|
|
|
|
|
|
|
|
def run_module( modx, module_argv ):
|
|
from chipsec.module_common import ModuleResult
|
|
result = None
|
|
try:
|
|
if not modx.do_import(): return ModuleResult.ERROR
|
|
if not _list_tags: logger().log( "[*] Module path: %s" % modx.get_location() )
|
|
|
|
if verify_module_tags( modx ):
|
|
result = modx.run( module_argv )
|
|
else:
|
|
return ModuleResult.SKIPPED
|
|
except (None,Exception) , msg:
|
|
result = ModuleResult.ERROR
|
|
if logger().VERBOSE: logger().log_bad(traceback.format_exc())
|
|
logger().log_error_check( "Exception occurred during %s.run(): '%s'" % (modx.get_name(), str(msg)) )
|
|
return result
|
|
|
|
##
|
|
# full_path can be one of three things:
|
|
# 1. the actual full path to the py or pyc file i.e. c:\some_path\chipsec\modules\common\bios_wp.py
|
|
# 2. a path to the pyc file inside a zip file i.e. chipsec/modules/common/bios_wp.pyc
|
|
# 3. the name of the module i.e. chipsec.modules.common.bios_wp
|
|
def get_module_name(full_path):
|
|
name = full_path
|
|
# case #1, the full path: remove prefix
|
|
if full_path.startswith(CHIPSEC_FOLDER+os.path.sep):
|
|
name = full_path.replace ( CHIPSEC_FOLDER+os.path.sep, '')
|
|
else:
|
|
for path in IMPORT_PATHS:
|
|
if full_path.startswith(os.path.abspath(path)+os.path.sep):
|
|
name = full_path.replace ( os.path.abspath(path)+os.path.sep, '')
|
|
# case #1 and #2: remove the extension
|
|
if name.lower().endswith('.py') : name = name[:-3]
|
|
if name.lower().endswith('.pyc'): name = name[:-4]
|
|
# case #1: replace slashes with dots
|
|
name = name.replace( os.path.sep, '.' )
|
|
# case #2: when in a zip it is always forward slash
|
|
name = name.replace( '/', '.' )
|
|
|
|
# Add 'chipsec.modules.' if shor module name was provided and alternative import paths were not specified
|
|
if [] == IMPORT_PATHS and not name.startswith( Import_Path ):
|
|
name = Import_Path + name
|
|
|
|
return name
|
|
|
|
|
|
|
|
#
|
|
# module_path is a file path relative to chipsec
|
|
# E.g. chipsec/modules/common/module.py
|
|
#
|
|
def load_module( module_path, module_argv ):
|
|
module_name = get_module_name(module_path)
|
|
module = chipsec.module.Module(module_name)
|
|
|
|
if module not in Loaded_Modules:
|
|
Loaded_Modules.append( (module,module_argv) )
|
|
if not _list_tags: logger().log( "[+] loaded %s" % module.get_name() )
|
|
return True
|
|
|
|
# @TODO: Fix it!
|
|
def unload_module( module_path ):
|
|
if module_path in Loaded_Modules:
|
|
Loaded_Modules.remove( module_path )
|
|
return True
|
|
|
|
def load_modules_from_path( from_path ):
|
|
if logger().VERBOSE: logger().log_bad( os.path.abspath( from_path ) )
|
|
for dirname, subdirs, mod_fnames in os.walk( os.path.abspath( from_path ) ):
|
|
for modx in mod_fnames:
|
|
if fnmatch.fnmatch( modx, '*.py' ) and not fnmatch.fnmatch( modx, '__init__.py' ):
|
|
load_module( os.path.join( dirname, modx ), None )
|
|
|
|
def load_my_modules():
|
|
#
|
|
# Step 1.
|
|
# Load modules common to all supported platforms
|
|
#
|
|
common_path = os.path.join( Modules_Path, 'common' )
|
|
logger().log( "[*] loading common modules from \"%s\" .." % common_path.replace(os.getcwd(),'.') )
|
|
load_modules_from_path( common_path )
|
|
#
|
|
# Step 2.
|
|
# Load platform-specific modules from the corresponding platform module directory
|
|
#
|
|
chipset_path = os.path.join( Modules_Path, _cs.code.lower() )
|
|
if (CHIPSET_ID_UNKNOWN != _cs.id) and os.path.exists( chipset_path ):
|
|
logger().log( "[*] loading platform specific modules from \"%s\" .." % chipset_path.replace(os.getcwd(),'.') )
|
|
load_modules_from_path( chipset_path )
|
|
else:
|
|
logger().log( "[*] No platform specific modules to load" )
|
|
#
|
|
# Step 3.
|
|
# Enumerate all modules from the root module directory
|
|
# Load modules which support current platform (register themselves with AVAILABLE_MODULES[current_platform_id])
|
|
#
|
|
logger().log( "[*] loading modules from \"%s\" .." % Modules_Path.replace(os.getcwd(),'.') )
|
|
for modx in os.listdir( os.path.abspath( Modules_Path ) ):
|
|
if fnmatch.fnmatch(modx, '*.py') and not fnmatch.fnmatch(modx, '__init__.py'):
|
|
import_modx = Import_Path + modx.split('.')[0]
|
|
try:
|
|
__import__( import_modx )
|
|
except BaseException, e:
|
|
logger().log_bad("Failed to import module %s : %s"%(import_modx,str(e)))
|
|
raise
|
|
# removed temporary
|
|
#if isModuleDisabled(modx):
|
|
# AVAILABLE_MODULES[ _cs.id ][modx.split('.')[0]] = "invalidmodule." + modx.split('.')[0]
|
|
for modx in AVAILABLE_MODULES[ CHIPSET_ID_COMMON ]:
|
|
load_module( os.path.join( os.path.abspath( Modules_Path ), modx + '.py' ), None )
|
|
try:
|
|
for modx in AVAILABLE_MODULES[ _cs.id ]:
|
|
load_module( os.path.join( os.path.abspath( Modules_Path ), modx + '.py' ), None )
|
|
except KeyError:
|
|
pass
|
|
#print Loaded_Modules
|
|
|
|
def load_user_modules():
|
|
for import_path in IMPORT_PATHS:
|
|
logger().log( "[*] loading modules from \"%s\" .." % import_path )
|
|
load_modules_from_path(import_path)
|
|
|
|
def clear_loaded_modules():
|
|
del Loaded_Modules[:]
|
|
|
|
|
|
def print_loaded_modules():
|
|
if Loaded_Modules == []:
|
|
logger().log( "No modules have been loaded" )
|
|
for (modx,modx_argv) in Loaded_Modules:
|
|
logger().log( modx )
|
|
|
|
|
|
def run_loaded_modules():
|
|
from chipsec.module_common import ModuleResult
|
|
|
|
failed = []
|
|
errors = []
|
|
warnings = []
|
|
passed = []
|
|
skipped = []
|
|
executed = 0
|
|
|
|
if not _list_tags: logger().log( "[*] running loaded modules .." )
|
|
|
|
t = time.time()
|
|
for (modx,modx_argv) in Loaded_Modules:
|
|
executed += 1
|
|
if not _list_tags: logger().start_module( modx.get_name( ) )
|
|
result = run_module( modx, modx_argv )
|
|
if result == ModuleResult.DEPRECATED:
|
|
logger().log_warning( 'Module %s does not inherit BaseModule class. Attempting to locate run function..' % str(modx) )
|
|
result = old_run_module( modx.get_name(), modx_argv )
|
|
if not _list_tags: logger().end_module( modx.get_name() )
|
|
|
|
if None == result or ModuleResult.ERROR == result:
|
|
errors.append( modx )
|
|
elif False == result or ModuleResult.FAILED == result:
|
|
failed.append( modx )
|
|
elif True == result or ModuleResult.PASSED == result:
|
|
passed.append( modx )
|
|
elif ModuleResult.WARNING == result:
|
|
warnings.append( modx )
|
|
elif ModuleResult.SKIPPED == result:
|
|
skipped.append( modx )
|
|
|
|
if not _list_tags:
|
|
logger().log( "" )
|
|
logger().log( "[CHIPSEC] *************************** SUMMARY ***************************" )
|
|
logger().log( "[CHIPSEC] Time elapsed %.3f" % (time.time()-t) )
|
|
logger().log( "[CHIPSEC] Modules total %d" % executed )
|
|
logger().log( "[CHIPSEC] Modules failed to run %d:" % len(errors) )
|
|
for mod in errors: logger().error( str(mod) )
|
|
logger().log( "[CHIPSEC] Modules passed %d:" % len(passed) )
|
|
for fmod in passed: logger().log_passed( str(fmod) )
|
|
logger().log( "[CHIPSEC] Modules failed %d:" % len(failed) )
|
|
for fmod in failed: logger().log_failed( str(fmod) )
|
|
logger().log( "[CHIPSEC] Modules with warnings %d:" % len(warnings) )
|
|
for fmod in warnings: logger().log_warning( str(fmod) )
|
|
logger().log( "[CHIPSEC] Modules skipped %d:" % len(skipped) )
|
|
for fmod in skipped: logger().log_skipped( str(fmod) )
|
|
logger().log( "[CHIPSEC] *****************************************************************" )
|
|
logger().log( "[CHIPSEC] Version: %s"% get_chipsec_version() )
|
|
else:
|
|
logger().log( "[*] Available tags are:" )
|
|
for at in AVAILABLE_TAGS: logger().log(" %s"%at)
|
|
|
|
return len(failed)
|
|
|
|
|
|
|
|
##################################################################################
|
|
# Running all chipset configuration security checks
|
|
##################################################################################
|
|
|
|
def run_all_modules():
|
|
if CHIPSEC_LOADED_AS_EXE:
|
|
import zipfile
|
|
myzip = zipfile.ZipFile( os.path.join(CHIPSEC_FOLDER, "library.zip" ))
|
|
global ZIP_MODULES_RE
|
|
ZIP_MODULES_RE = re.compile("^chipsec\/modules\/\w+\.pyc$|^chipsec\/modules\/common\/(\w+\/)*\w+\.pyc$|^chipsec\/modules\/"+_cs.code.lower()+"\/\w+\.pyc$", re.IGNORECASE|re.VERBOSE)
|
|
zip_modules = []
|
|
zip_modules.extend( map(map_pass, filter(f_mod, myzip.namelist())) )
|
|
logger().log( "Loaded modules from ZIP:" )
|
|
for zmodx in zip_modules:
|
|
module_name = get_module_name(zmodx)
|
|
mod = chipsec.module.Module(module_name)
|
|
logger().log(mod.get_name())
|
|
Loaded_Modules.append( (mod,None) )
|
|
else:
|
|
load_my_modules()
|
|
load_user_modules()
|
|
return run_loaded_modules()
|
|
|
|
|
|
|
|
|
|
def usage():
|
|
print "\nUSAGE: %.65s [options]" % sys.argv[0]
|
|
print "OPTIONS:"
|
|
print "-m --module specify module to run (example: -m common.bios)"
|
|
print "-a --module_args additional module arguments, format is 'arg0,arg1..'"
|
|
print "-v --verbose verbose mode"
|
|
print "-l --log output to log file"
|
|
print "\nADVANCED OPTIONS:"
|
|
print "-p --platform explicitly specify platform code. Should be among the supported platforms:"
|
|
print " [ %s ]" % (" | ".join( ["%.4s" % c for c in Chipset_Code]))
|
|
print "-n --no_driver chipsec won't need kernel mode functions so don't load chipsec driver"
|
|
print "-i --ignore_platform run chipsec even if the platform is not recognized"
|
|
print "-e --exists chipsec service has already been manually installed and started (driver loaded)."
|
|
print "-x --xml specify filename for xml output (JUnit style)."
|
|
print "-t --moduletype run tests of a specific type (tag)."
|
|
print " --list_tags list all the available options for -t,--moduletype"
|
|
print "-I --import specify additional path to load modules from"
|
|
|
|
##################################################################################
|
|
# Entry point for command-line execution
|
|
##################################################################################
|
|
|
|
if __name__ == "__main__":
|
|
import getopt
|
|
|
|
try:
|
|
opts, args = getopt.getopt(sys.argv[1:], "ip:m:ho:vea:nl:t:x:I:",
|
|
["ignore_platform", "platform=", "module=", "help", "output=",
|
|
"verbose", "exists", "module_args=", "no_driver", "log=",
|
|
"moduletype=", "xml=","list_tags", "include"])
|
|
except getopt.GetoptError, err:
|
|
print str(err)
|
|
usage()
|
|
sys.exit(errno.EINVAL)
|
|
|
|
_output = 'chipsec.log'
|
|
_module = None
|
|
_module_argv = None
|
|
_platform = None
|
|
_start_svc = True
|
|
_no_driver = False
|
|
_unkownPlatform = True
|
|
_list_tags = False
|
|
|
|
for o, a in opts:
|
|
if o in ("-v", "--verbose"):
|
|
logger().VERBOSE = True
|
|
logger().log( "[*] Verbose mode is ON (-v command-line option or chipsec_main.logger().VERBOSE in Python console)" )
|
|
elif o in ("-h", "--help"):
|
|
usage()
|
|
sys.exit(0)
|
|
elif o in ("-o", "--output"):
|
|
_output = a
|
|
elif o in ("-p", "--platform"):
|
|
_platform = a.upper()
|
|
elif o in ("-m", "--module"):
|
|
#_module = a.lower()
|
|
_module = a
|
|
elif o in ("-a", "--module_args"):
|
|
_module_argv = a.split(',')
|
|
elif o in ("-e", "--exists"):
|
|
_start_svc = False
|
|
elif o in ("-i", "--ignore_platform"):
|
|
logger().log( "[*] Ignoring unsupported platform warning and continue execution" )
|
|
_unkownPlatform = False
|
|
elif o in ("-l", "--log"):
|
|
logger().log( "[*] Output to log file '%s' (--log option or chipsec_main.logger().set_log_file in Python console)" % a )
|
|
logger().set_log_file( a )
|
|
elif o in ("-t", "--moduletype"):
|
|
usertags = a.upper().split(",")
|
|
for tag in usertags:
|
|
USER_MODULE_TAGS.append(tag)
|
|
elif o in ("-n", "--no_driver"):
|
|
_no_driver = True
|
|
elif o in ("-x", "--xml"):
|
|
logger().set_xml_file(a)
|
|
elif o in ("--list_tags"):
|
|
_list_tags = True
|
|
elif o in ("-I","--import"):
|
|
IMPORT_PATHS.append(a)
|
|
else:
|
|
assert False, "unknown option"
|
|
|
|
for import_path in IMPORT_PATHS:
|
|
sys.path.append(os.path.abspath( import_path ) )
|
|
|
|
# If no driver needed, we won't start/stop service
|
|
if _no_driver: _start_svc = False
|
|
|
|
try:
|
|
# If no driver needed, we won't initialize chipset with automatic platform detection
|
|
if not _no_driver: _cs.init( _platform, _start_svc )
|
|
except UnknownChipsetError , msg:
|
|
logger().error( "Platform is not supported (%s)." % str(msg) )
|
|
if _unkownPlatform:
|
|
logger().error( 'To run anyways please use -i command-line option\n\n' )
|
|
if logger().VERBOSE: logger().log_bad(traceback.format_exc())
|
|
sys.exit( errno.ENODEV )
|
|
logger().warn("Platform dependent functionality is likely to be incorrect")
|
|
except OsHelperError as os_helper_error:
|
|
logger().error(str(os_helper_error))
|
|
if logger().VERBOSE: logger().log_bad(traceback.format_exc())
|
|
sys.exit(os_helper_error.errorcode)
|
|
|
|
logger().log( " " )
|
|
logger().log( "OS : %s %s %s %s" % (_cs.helper.os_system, _cs.helper.os_release, _cs.helper.os_version, _cs.helper.os_machine) )
|
|
logger().log( "Platform: %s\n VID: %04X\n DID: %04X" % (_cs.longname, _cs.vid, _cs.did))
|
|
logger().log( "CHIPSEC : %s"% get_chipsec_version() )
|
|
logger().xmlAux.add_test_suite_property( "OS", "%s %s %s %s" % (_cs.helper.os_system, _cs.helper.os_release, _cs.helper.os_version, _cs.helper.os_machine) )
|
|
logger().xmlAux.add_test_suite_property( "Platform", "%s, VID: %04X, DID: %04X" % (_cs.longname, _cs.vid, _cs.did) )
|
|
logger().xmlAux.add_test_suite_property( "CHIPSEC", "%s"% get_chipsec_version() )
|
|
logger().log( " " )
|
|
|
|
if logger().VERBOSE: logger().log("[*] Running from %s" % os.getcwd())
|
|
|
|
modules_failed = 0
|
|
if _module:
|
|
load_module( _module, _module_argv )
|
|
modules_failed = run_loaded_modules()
|
|
#unload_module( _module );
|
|
else:
|
|
modules_failed = run_all_modules()
|
|
|
|
logger().saveXML()
|
|
|
|
_cs.destroy( _start_svc )
|
|
del _cs
|
|
|
|
sys.exit(-modules_failed)
|