11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci# Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci# Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci# found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci"""A server that serves MSR values over TCP. Takes a port as its sole parameter. 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciThe reference client for this server is msr_power_monitor.MsrPowerMonitor. 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMust be run as Administrator. We use TCP instead of named pipes or another IPC 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccito avoid dealing with the pipe security mechanisms. We take the port as a 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciparameter instead of choosing one, because it's hard to communicate the port 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinumber across integrity levels. 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciRequires WinRing0 to be installed in the Python directory. 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccimsr_power_monitor.MsrPowerMonitor does this if needed. 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci""" 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport argparse 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport ctypes 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport os 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport SocketServer 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport struct 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport sys 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciWINRING0_STATUS_MESSAGES = ( 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'No error', 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'Unsupported platform', 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'Driver not loaded. You may need to run as Administrator', 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'Driver not found', 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'Driver unloaded by other process', 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'Driver not loaded because of executing on Network Drive', 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'Unknown error', 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci) 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci# The DLL initialization is global, so put it in a global variable. 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci_winring0 = None 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass WinRing0Error(OSError): 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pass 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef _WinRing0Path(): 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci python_is_64_bit = sys.maxsize > 2 ** 32 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci dll_file_name = 'WinRing0x64.dll' if python_is_64_bit else 'WinRing0.dll' 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return os.path.join(os.path.dirname(sys.executable), dll_file_name) 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef _Initialize(): 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci global _winring0 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if not _winring0: 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci winring0 = ctypes.WinDLL(_WinRing0Path()) 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if not winring0.InitializeOls(): 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci winring0_status = winring0.GetDllStatus() 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci raise WinRing0Error(winring0_status, 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 'Unable to initialize WinRing0: %s' % 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci WINRING0_STATUS_MESSAGES[winring0_status]) 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci _winring0 = winring0 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef _Deinitialize(): 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci global _winring0 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if _winring0: 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci _winring0.DeinitializeOls() 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci _winring0 = None 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef _ReadMsr(msr_number): 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci low = ctypes.c_uint() 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci high = ctypes.c_uint() 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci _winring0.Rdmsr(ctypes.c_uint(msr_number), 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ctypes.byref(low), ctypes.byref(high)) 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return high.value << 32 | low.value 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass MsrRequestHandler(SocketServer.StreamRequestHandler): 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def handle(self): 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci msr_number = struct.unpack('I', self.rfile.read(4))[0] 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.wfile.write(struct.pack('Q', _ReadMsr(msr_number))) 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef main(): 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci parser = argparse.ArgumentParser() 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci parser.add_argument('port', type=int) 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci args = parser.parse_args() 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci _Initialize() 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci try: 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SocketServer.TCPServer.allow_reuse_address = True 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci server_address = ('127.0.0.1', args.port) 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci server = SocketServer.TCPServer(server_address, MsrRequestHandler) 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci server.serve_forever() 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci finally: 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci _Deinitialize() 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciif __name__ == '__main__': 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci main() 101