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