1#!/usr/bin/env python3

2

3 import array

4 import uuid

5 import fcntl

6 import struct

7 import os

8 from argparse import ArgumentParser

9

10

11 DEFAULT_MEI_NODE = "mei0"

12

13

14 class MEI_INTERFACE:

15

16 IOCTL_MEI_CONNECT_CLIENT = 0xC0104801

17

18 def __init__(self):

19 self._mei_obj = None

20

21 def _get_mei(self):

22 path = "/dev"

23 devices = os.listdir(path)

24 if DEFAULT_MEI_NODE in devices:

25 return os.path.join(path, DEFAULT_MEI_NODE)

26 for device in devices:

27 if device.find("mei") != -1:

28 return os.path.join(path, device)

29

30 def open(self):

31 mei_path = self._get_mei()

32 if mei_path is None:

33 raise SystemExit("MEI interface not found")

34 print("connecting to {}".format(mei_path))

35 self._mei_obj = os.open(mei_path, os.O_RDWR)

36

37 def connect(self, str_uuid):

38 obj_uuid = uuid.UUID(str_uuid)

39 array_data = array.array("b", obj_uuid.bytes_le)

40 fcntl.ioctl(

41 self._mei_obj, self.IOCTL_MEI_CONNECT_CLIENT, array_data, 1

42 )

43 max_length, version = struct.unpack("<IB", array_data.tobytes()[:5])

44 return max_length, version

45

46 def write(self, msg_id):

47 data_write = struct.pack("I", msg_id)

48 result = os.write(self._mei_obj, data_write)

49 return result

50

51 def read(self, size):

52 data = os.read(self._mei_obj, size)

53 return data

54

55 def close(self):

56 os.close(self._mei_obj)

57

58

59 def get_mei_firmware_version():

60 # This is a fixed uuid to connect to MEI

61 # https://github.com/intel/lms/blob/388f115b2aeb3ea11499971c65f828daefd32c47/MEIClient/Include/HECI_if.h#L32

62 mei_fw_uuid = "8e6a6715-9abc-4043-88ef-9e39c6f63e0f"

63 # This is a request code for firmware version

64 mei_fw_ver_req = 0x000002FF

65 # The length of firmware version is alway 28

66 mei_fw_ver_rep_length = 28

67 print("Collecting MEI firmware data through MEI interface..\n")

68 try:

69 mei_interface = MEI_INTERFACE()

70 mei_interface.open()

71 mei_interface.connect(mei_fw_uuid)

72 mei_interface.write(mei_fw_ver_req)

73 raw_fw_ver = mei_interface.read(mei_fw_ver_rep_length)

74

75 str_ver = struct.unpack("4BH2B2HH2B2HH2B2H", raw_fw_ver)

76 str_ver = "%d.%d.%d.%d" % (

77 str_ver[5],

78 str_ver[4],

79 str_ver[8],

80 str_ver[7],

81 )

82 print("MEI firmware version: {}".format(str_ver))

83 except Exception as err:

84 err_msg = (

85 "Unable to retrieve MEI firmware version" " due to {}".format(err)

86 )

87 raise SystemExit(err_msg)

88 finally:

89 if mei_interface._mei_obj is not None: 89 ↛ 90 line 89 didn't jump to line 90 because the condition on line 89 was never true

90 mei_interface.close()

91

92

93 if __name__ == "__main__":

94 parser = ArgumentParser(

95 prog="MEI Testing Tool",

96 description="This is a tool to help you perform" " the MEI testing",

97 )

98 parser.add_argument(

99 "--get-version",

100 action="store_true",

101 help="Get the MEI version via MEI interface",

102 )

103 args = parser.parse_args()

104 if args.get_version:

105 get_mei_firmware_version()