1# Copyright 2014 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""A server that serves MSR values over TCP. Takes a port as its sole parameter. 6 7The reference client for this server is msr_power_monitor.MsrPowerMonitor. 8 9Must be run as Administrator. We use TCP instead of named pipes or another IPC 10to avoid dealing with the pipe security mechanisms. We take the port as a 11parameter instead of choosing one, because it's hard to communicate the port 12number across integrity levels. 13 14Requires WinRing0 to be installed in the Python directory. 15msr_power_monitor.MsrPowerMonitor does this if needed. 16""" 17 18import argparse 19import ctypes 20import os 21import SocketServer 22import struct 23import sys 24try: 25 import win32api # pylint: disable=import-error 26 import win32file # pylint: disable=import-error 27except ImportError: 28 win32api = None 29 win32file = None 30 31 32WINRING0_STATUS_MESSAGES = ( 33 'No error', 34 'Unsupported platform', 35 'Driver not loaded. You may need to run as Administrator', 36 'Driver not found', 37 'Driver unloaded by other process', 38 'Driver not loaded because of executing on Network Drive', 39 'Unknown error', 40) 41 42 43# The DLL initialization is global, so put it in a global variable. 44_winring0 = None 45 46 47class WinRing0Error(OSError): 48 pass 49 50 51def _WinRing0Path(): 52 python_is_64_bit = sys.maxsize > 2 ** 32 53 dll_file_name = 'WinRing0x64.dll' if python_is_64_bit else 'WinRing0.dll' 54 return os.path.join(os.path.dirname(sys.executable), dll_file_name) 55 56 57def _Initialize(): 58 global _winring0 59 if not _winring0: 60 winring0 = ctypes.WinDLL(_WinRing0Path()) 61 if not winring0.InitializeOls(): 62 winring0_status = winring0.GetDllStatus() 63 raise WinRing0Error(winring0_status, 64 'Unable to initialize WinRing0: %s' % 65 WINRING0_STATUS_MESSAGES[winring0_status]) 66 _winring0 = winring0 67 68 69def _Deinitialize(): 70 global _winring0 71 if _winring0: 72 _winring0.DeinitializeOls() 73 _winring0 = None 74 75 76def _ReadMsr(msr_number): 77 low = ctypes.c_uint() 78 high = ctypes.c_uint() 79 _winring0.Rdmsr(ctypes.c_uint(msr_number), 80 ctypes.byref(low), ctypes.byref(high)) 81 return high.value << 32 | low.value 82 83 84class MsrRequestHandler(SocketServer.StreamRequestHandler): 85 def handle(self): 86 msr_number = struct.unpack('I', self.rfile.read(4))[0] 87 self.wfile.write(struct.pack('Q', _ReadMsr(msr_number))) 88 89 90def main(): 91 parser = argparse.ArgumentParser() 92 parser.add_argument('pipe_name', type=str) 93 args = parser.parse_args() 94 95 _Initialize() 96 try: 97 SocketServer.TCPServer.allow_reuse_address = True 98 server_address = ('127.0.0.1', 0) 99 server = SocketServer.TCPServer(server_address, MsrRequestHandler) 100 handle = win32file.CreateFile(args.pipe_name, 101 win32file.GENERIC_WRITE, 102 0, None, 103 win32file.OPEN_EXISTING, 104 0, None) 105 _, port = server.server_address 106 win32file.WriteFile(handle, str(port)) 107 win32api.CloseHandle(handle) 108 server.serve_forever() 109 finally: 110 _Deinitialize() 111 112 113if __name__ == '__main__': 114 main() 115