amd-debug-tools 0.2.3__py3-none-any.whl → 0.2.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
amd_debug/__init__.py CHANGED
@@ -42,4 +42,4 @@ def launch_tool(tool_name):
42
42
  return tools[tool_name]()
43
43
  else:
44
44
  print(f"\033[91mUnknown exe: {tool_name}\033[0m")
45
- return False
45
+ return 1
amd_debug/bios.py CHANGED
@@ -122,7 +122,7 @@ def parse_args():
122
122
  return args
123
123
 
124
124
 
125
- def main():
125
+ def main() -> None|int:
126
126
  """Main function"""
127
127
  args = parse_args()
128
128
  ret = False
@@ -135,4 +135,6 @@ def main():
135
135
  elif args.command == "version":
136
136
  print(version())
137
137
  show_log_info()
138
- return ret
138
+ if ret is False:
139
+ return 1
140
+ return
amd_debug/installer.py CHANGED
@@ -446,7 +446,7 @@ def parse_args():
446
446
  return parser.parse_args()
447
447
 
448
448
 
449
- def install_dep_superset() -> bool:
449
+ def install_dep_superset() -> None|int:
450
450
  """Install all python supserset dependencies"""
451
451
  args = parse_args()
452
452
  tool = Installer(tool_debug=args.tool_debug)
@@ -465,4 +465,6 @@ def install_dep_superset() -> bool:
465
465
  if ret:
466
466
  print_color("All dependencies installed", "✅")
467
467
  show_log_info()
468
- return ret
468
+ if ret is False:
469
+ return 1
470
+ return
amd_debug/kernel.py CHANGED
@@ -115,24 +115,16 @@ def sscanf_bios_args(line):
115
115
 
116
116
  converted_args = []
117
117
  arg_index = 0
118
- for specifier in format_specifiers:
118
+ for _specifier in format_specifiers:
119
119
  if arg_index < len(arguments):
120
120
  value = arguments[arg_index]
121
121
  if value == "Unknown":
122
122
  converted_args.append(-1)
123
- elif specifier.lower() == "x":
123
+ else:
124
124
  try:
125
125
  converted_args.append(int(value, 16))
126
126
  except ValueError:
127
127
  return None
128
- else: # Decimal conversion
129
- try:
130
- converted_args.append(int(value))
131
- except ValueError:
132
- try:
133
- converted_args.append(int(value, 16))
134
- except ValueError:
135
- return None
136
128
  arg_index += 1
137
129
  else:
138
130
  break
@@ -595,6 +595,9 @@ class PrerequisiteValidator(AmdTool):
595
595
  with open(target, "rb") as r:
596
596
  r.seek(0x70)
597
597
  found = struct.unpack("<I", r.read(4))[0] & BIT(21)
598
+ except FileNotFoundError:
599
+ self.db.record_prereq("FADT check unavailable", "🚦")
600
+ return True
598
601
  except PermissionError:
599
602
  self.db.record_prereq("FADT check unavailable", "🚦")
600
603
  return True
@@ -1142,26 +1145,13 @@ class PrerequisiteValidator(AmdTool):
1142
1145
  found_iommu = True
1143
1146
  debug_str += f"Found IOMMU {dev.sys_path}\n"
1144
1147
  break
1148
+
1149
+ # User turned off IOMMU, no problems
1145
1150
  if not found_iommu:
1146
1151
  self.db.record_prereq("IOMMU disabled", "✅")
1147
1152
  return True
1148
- p = os.path.join("/", "sys", "firmware", "acpi", "tables", "IVRS")
1149
- with open(p, "rb") as f:
1150
- data = f.read()
1151
- if len(data) < 40:
1152
- raise ValueError(
1153
- "IVRS table appears too small to contain virtualization info."
1154
- )
1155
- virt_info = struct.unpack_from("I", data, 36)[0]
1156
- debug_str += f"Virtualization info: 0x{virt_info:x}"
1157
- found_dmar = (virt_info & 0x2) != 0
1158
- self.db.record_debug(debug_str)
1159
- if not found_dmar:
1160
- self.db.record_prereq(
1161
- "IOMMU is misconfigured: Pre-boot DMA protection not enabled", "❌"
1162
- )
1163
- self.failures += [DMArNotEnabled()]
1164
- return False
1153
+
1154
+ # Look for MSFT0201 in DSDT/SSDT
1165
1155
  for dev in self.pyudev.list_devices(subsystem="acpi"):
1166
1156
  if "MSFT0201" in dev.sys_path:
1167
1157
  found_acpi = True
@@ -1171,13 +1161,39 @@ class PrerequisiteValidator(AmdTool):
1171
1161
  )
1172
1162
  self.failures += [MissingIommuACPI("MSFT0201")]
1173
1163
  return False
1174
- # check that policy is bound to it
1164
+
1165
+ # Check that policy is bound to it
1175
1166
  for dev in self.pyudev.list_devices(subsystem="platform"):
1176
1167
  if "MSFT0201" in dev.sys_path:
1177
1168
  p = os.path.join(dev.sys_path, "iommu")
1178
1169
  if not os.path.exists(p):
1179
1170
  self.failures += [MissingIommuPolicy("MSFT0201")]
1180
1171
  return False
1172
+
1173
+ # Check pre-boot DMA
1174
+ p = os.path.join("/", "sys", "firmware", "acpi", "tables", "IVRS")
1175
+ with open(p, "rb") as f:
1176
+ data = f.read()
1177
+ if len(data) < 40:
1178
+ raise ValueError(
1179
+ "IVRS table appears too small to contain virtualization info."
1180
+ )
1181
+ virt_info = struct.unpack_from("I", data, 36)[0]
1182
+ debug_str += f"IVRS: Virtualization info: 0x{virt_info:x}\n"
1183
+ found_ivrs_dmar = (virt_info & 0x2) != 0
1184
+
1185
+ # check for MSFT0201 in IVRS (alternative to pre-boot DMA)
1186
+ target_bytes = "MSFT0201".encode("utf-8")
1187
+ found_ivrs_msft0201 = data.find(target_bytes) != -1
1188
+ debug_str += f"IVRS: Found MSFT0201: {found_ivrs_msft0201}"
1189
+
1190
+ self.db.record_debug(debug_str)
1191
+ if not found_ivrs_dmar and not found_ivrs_msft0201:
1192
+ self.db.record_prereq(
1193
+ "IOMMU is misconfigured: Pre-boot DMA protection not enabled", "❌"
1194
+ )
1195
+ self.failures += [DMArNotEnabled()]
1196
+ return False
1181
1197
  self.db.record_prereq("IOMMU properly configured", "✅")
1182
1198
  return True
1183
1199
 
@@ -1187,6 +1203,8 @@ class PrerequisiteValidator(AmdTool):
1187
1203
  return True
1188
1204
  if self.cpu_model not in [0x74, 0x78]:
1189
1205
  return True
1206
+ if not self.smu_version:
1207
+ return True
1190
1208
  if version.parse(self.smu_version) > version.parse("76.60.0"):
1191
1209
  return True
1192
1210
  if version.parse(self.smu_version) < version.parse("76.18.0"):
amd_debug/pstate.py CHANGED
@@ -300,15 +300,17 @@ def parse_args():
300
300
  return parser.parse_args()
301
301
 
302
302
 
303
- def main():
303
+ def main() -> None|int:
304
304
  """Main function"""
305
305
  args = parse_args()
306
306
  ret = False
307
307
  if args.command == "version":
308
308
  print(version())
309
- return True
309
+ return
310
310
  elif args.command == "triage":
311
311
  triage = AmdPstateTriage(args.tool_debug)
312
312
  ret = triage.run()
313
313
  show_log_info()
314
- return ret
314
+ if ret is False:
315
+ return 1
316
+ return
amd_debug/s2idle.py CHANGED
@@ -120,7 +120,7 @@ def prompt_report_arguments(since, until, fname, fmt, report_debug) -> str:
120
120
  if report_debug is None:
121
121
  inp = (
122
122
  input(
123
- f"{Headers.ReportDebugDescription} ({colorize_choices(Defaults.boolean_choices, "true")})? "
123
+ f"{Headers.ReportDebugDescription} ({colorize_choices(Defaults.boolean_choices, 'true')})? "
124
124
  )
125
125
  .lower()
126
126
  .capitalize()
@@ -394,7 +394,7 @@ def parse_args():
394
394
  return parser.parse_args()
395
395
 
396
396
 
397
- def main():
397
+ def main() -> None|int:
398
398
  """Main function"""
399
399
  args = parse_args()
400
400
  ret = False
@@ -429,8 +429,10 @@ def main():
429
429
  )
430
430
  elif args.action == "version":
431
431
  print(version())
432
- return True
432
+ return
433
433
  else:
434
434
  sys.exit("no action specified")
435
435
  show_log_info()
436
- return ret
436
+ if ret is False:
437
+ return 1
438
+ return
amd_debug/validator.py CHANGED
@@ -443,11 +443,10 @@ class SleepValidator(AmdTool):
443
443
  """Check for hardware sleep state"""
444
444
  # try from kernel 6.4's suspend stats interface first because it works
445
445
  # even with kernel lockdown
446
- if not self.hw_sleep_duration:
447
- p = os.path.join("/", "sys", "power", "suspend_stats", "last_hw_sleep")
448
- if os.path.exists(p):
449
- self.hw_sleep_duration = int(read_file(p)) / 10**6
450
- if not self.hw_sleep_duration:
446
+ p = os.path.join("/", "sys", "power", "suspend_stats", "last_hw_sleep")
447
+ if os.path.exists(p):
448
+ self.hw_sleep_duration = int(read_file(p)) / 10**6
449
+ if not os.path.exists(p) and not self.hw_sleep_duration:
451
450
  p = os.path.join("/", "sys", "kernel", "debug", "amd_pmc", "smu_fw_info")
452
451
  try:
453
452
  val = read_file(p)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amd-debug-tools
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary: debug tools for AMD systems
5
5
  Author-email: Mario Limonciello <superm1@kernel.org>
6
6
  License-Expression: MIT
@@ -1,45 +1,45 @@
1
- launcher.py,sha256=_Gs0W8tUB2wkTy5Nz4qEzG0VqQcnO7xuIQj0GwV_KbY,968
1
+ launcher.py,sha256=M8kT9DtyZoQgZaKWDbSBu4jsS6tZF1gWko3sovNVyag,947
2
2
  test_acpi.py,sha256=wtS43Rz95h7YEEJBeFa6Mswaeo4syBZrw4hY8i0YbJY,3117
3
3
  test_batteries.py,sha256=nN5pfP5El7Whypq3HHEpW8bufdf5EWSTVGbayfNQYP4,3360
4
- test_bios.py,sha256=GBAXE_rXd2G-JE0XJ8AvYcF9Me6LTyQQQ8h0Ib3cpxQ,8981
4
+ test_bios.py,sha256=ZPqI5X0QpEJBNJP-i5gNZzlbOlVSpznH4uv34esSqD8,8984
5
5
  test_common.py,sha256=fb16Oilh5ga6VgF-UgBj6azoYzZnPrS7KpECQ3nCwlg,16335
6
6
  test_database.py,sha256=q5ZjI5u20f7ki6iCY5o1iPi0YOvPz1_W0LTDraU8mN4,10040
7
7
  test_display.py,sha256=hHggv-zBthF1BlwWWSjzAm7BBw1DWcElwil5xAuz87g,5822
8
8
  test_failures.py,sha256=H1UxXeVjhJs9-j9yas4vwAha676GX1Es7Kz8RN2B590,6845
9
9
  test_installer.py,sha256=oDMCvaKqqAWjTggltacnasQ-s1gyUvXPDcNrCUGnux4,10216
10
- test_kernel.py,sha256=RW-eLbae02Bhwfu1cegqA1pTj6AS5IqD5lLe-6T0Rjo,7871
11
- test_launcher.py,sha256=govYHL0Cpj9d5msteV5SfR7Covft31rJuzRkDeytHcY,1461
12
- test_prerequisites.py,sha256=VXN822W-7ZZHXZkJYH5MeKsDVBC-ttUZggYlcoPjVyM,83335
10
+ test_kernel.py,sha256=xw7zpLcZjiRLWvO7vyHQ03_CjmKd_Np8ULhc-WhUV6A,7872
11
+ test_launcher.py,sha256=80xVbidrbx8ixMt_x5Uvfn7nFnB637nX69yIZTifyuk,1511
12
+ test_prerequisites.py,sha256=5fHtdMSGMf7sjDykIUfOP2h7XOAe-jNhJoZ0Vll5B58,84982
13
13
  test_pstate.py,sha256=a9oAJ9-LANX32XNQhplz6Y75VNYc__QqoSBKIrwvANg,6058
14
- test_s2idle.py,sha256=6NaqGp9VOLr_Tr3KczSvfSo3M882aYEbSvRV9xvUMcA,33534
14
+ test_s2idle.py,sha256=YpFGpH84xvjI9mY6uBSKapa74hZnG8ZwBShXsJXpmyQ,33540
15
15
  test_sleep_report.py,sha256=ANuxYi_C1oSKAi4xUU2wBu4SwJtcZA7VPpazBe3_WUQ,6922
16
16
  test_validator.py,sha256=-MfrWfhwef_aRqOSD_dJGhH0shsghhtOBgzeijzyLW4,33975
17
17
  test_wake.py,sha256=6zi5GVFHQKU1sTWw3O5-aGriB9uu5713QLn4l2wjhpM,7152
18
- amd_debug/__init__.py,sha256=aOtpIEKGLUStrh0e4qgilHW7HgF4Od-r9pOoZ87NwAM,1105
18
+ amd_debug/__init__.py,sha256=3wZxCDY3KPpfIxMz4vGmp6jUAB2GF4VTK4Xb86vy8c4,1101
19
19
  amd_debug/acpi.py,sha256=fkD3Sov8cRT5ryPlakRlT7Z9jiCLT9x_MPWxt3xU_tc,3161
20
20
  amd_debug/battery.py,sha256=WN-6ys9PHCZIwg7PdwyBOa62GjBp8WKG0v1YZt5_W5s,3122
21
- amd_debug/bios.py,sha256=wmPKDsTZeQqsHjWpv-YHdgRNlCtFdzHQ6jJf0H3hjN8,3971
21
+ amd_debug/bios.py,sha256=nVIDYqyyKiIO21nyS8lV-qB3ypBJOSIKIuVYFOVoBuw,4017
22
22
  amd_debug/common.py,sha256=H9tIRlRFOMwe0d3f2-vXQeK2rJl5Z1WJzkpQM9ivpOc,10347
23
23
  amd_debug/database.py,sha256=GkRg3cmaNceyQ2_hy0MBAlMbnTDPHo2co2o4ObWpnQg,10621
24
24
  amd_debug/display.py,sha256=5L9x9tI_UoulHpIvuxuVASRtdXta7UCW_JjTb5StEB0,953
25
25
  amd_debug/failures.py,sha256=z4O4Q-akv3xYGssSZFCqE0cDE4P9F_aw1hxil3McoD4,22910
26
- amd_debug/installer.py,sha256=r6r_nVWv8qYdrqAvnAzQhRiS5unBDOkXsqUfHvFK8uM,14249
27
- amd_debug/kernel.py,sha256=UAlxlXNuZxtHVtrfCmTp12YombVaUs4mizOxwuXTX2M,12038
28
- amd_debug/prerequisites.py,sha256=r4_IFTL-1YcPptlt6Nump7iscRx1bBCGF33hqNQB0X0,49867
29
- amd_debug/pstate.py,sha256=akGdJkIxBp0bx3AeGv6ictNxwv8m0j9vQ2IZB0Jx3dM,9518
26
+ amd_debug/installer.py,sha256=tNWhlfxQEA30guk-fzMvcc237hf_PARVQuHaH3sTp4A,14287
27
+ amd_debug/kernel.py,sha256=HpX-QRh8tgkvqKnExfo2JrYqfcbMY8GNgDrC2VVV0Oc,11638
28
+ amd_debug/prerequisites.py,sha256=E5_VpRd2mHiNYQBf13JqsoA5iiJS13wxcH3RERS_qJw,50502
29
+ amd_debug/pstate.py,sha256=lLRsayKi7KOXZCQ6Zjm2pNaobpjLXcgLHXZ9Zt40Fd4,9559
30
30
  amd_debug/s2idle-hook,sha256=LLiaqPtGd0qetu9n6EYxKHZaIdHpVQDONdOuSc0pfFg,1695
31
- amd_debug/s2idle.py,sha256=Ei5ONnJyHz9aQbstRZYnofhJ_sJOAOZQxLgIuWfvcng,13218
31
+ amd_debug/s2idle.py,sha256=lr1wcuJcpvI5pL2gNHqrc7n5E7EYCztvaAYYFPMlGYk,13259
32
32
  amd_debug/sleep_report.py,sha256=hhqu711AKtjeYF2xmGcejyCyyPtmq4-gC_hROUCrC0g,17317
33
- amd_debug/validator.py,sha256=nZ5UpvvsABw4yTea_pZ8DHaLbSoM5VHz3uvlrdWAb34,33444
33
+ amd_debug/validator.py,sha256=-rPqPnYAM1Vevw7vxIbGNPKo1bCRo48IpCBi3Y72-Cw,33419
34
34
  amd_debug/wake.py,sha256=xT8WrFrN6voCmXWo5dsn4mQ7iR2QJxHrrYBd3EREG-Q,3936
35
35
  amd_debug/bash/amd-s2idle,sha256=g_cle1ElCJpwE4wcLezL6y-BdasDKTnNMhrtzKLE9ks,1142
36
36
  amd_debug/templates/html,sha256=JfGhpmHIB2C2GItdGI1kuC8uayqEVgrpQvAWAj35eZ4,14580
37
37
  amd_debug/templates/md,sha256=r8X2aehnH2gzj0WHYTZ5K9wAqC5y39i_3nkDORSC0uM,787
38
38
  amd_debug/templates/stdout,sha256=hyoOJ96K2dJfnWRWhyCuariLKbEHXvs9mstV_g5aMdI,469
39
39
  amd_debug/templates/txt,sha256=nNdsvbPFOhGdL7VA-_4k5aN3nB-6ouGQt6AsWst7T3w,649
40
- amd_debug_tools-0.2.3.dist-info/licenses/LICENSE,sha256=RBlZI6r3MRGzymI2VDX2iW__D2APDbMhu_Xg5t6BWeo,1066
41
- amd_debug_tools-0.2.3.dist-info/METADATA,sha256=-DdxkPvWEXMifkgAjfyNIpleo_rHFPIH8nS6v3AWJTk,6877
42
- amd_debug_tools-0.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
43
- amd_debug_tools-0.2.3.dist-info/entry_points.txt,sha256=HC11T2up0pPfroAn6Pg5M2jOZXhkWIipToJ1YPTKqu8,116
44
- amd_debug_tools-0.2.3.dist-info/top_level.txt,sha256=XYjxExbUTEtiIlag_5iQvZSVOC1EIxhKM4NLklReQ0k,234
45
- amd_debug_tools-0.2.3.dist-info/RECORD,,
40
+ amd_debug_tools-0.2.5.dist-info/licenses/LICENSE,sha256=RBlZI6r3MRGzymI2VDX2iW__D2APDbMhu_Xg5t6BWeo,1066
41
+ amd_debug_tools-0.2.5.dist-info/METADATA,sha256=Dkhw4XQncTgjECNEa3Nk6HCYBzqa5lPAS_IbIli7cvA,6877
42
+ amd_debug_tools-0.2.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
43
+ amd_debug_tools-0.2.5.dist-info/entry_points.txt,sha256=HC11T2up0pPfroAn6Pg5M2jOZXhkWIipToJ1YPTKqu8,116
44
+ amd_debug_tools-0.2.5.dist-info/top_level.txt,sha256=XYjxExbUTEtiIlag_5iQvZSVOC1EIxhKM4NLklReQ0k,234
45
+ amd_debug_tools-0.2.5.dist-info/RECORD,,
launcher.py CHANGED
@@ -28,7 +28,6 @@ def main():
28
28
  f"Missing dependency: {e}\n"
29
29
  f"Run ./install_deps.py to install dependencies."
30
30
  )
31
- return False
32
31
 
33
32
 
34
33
  if __name__ == "__main__":
test_bios.py CHANGED
@@ -194,7 +194,7 @@ class TestAmdBios(unittest.TestCase):
194
194
  mock_amd_bios.assert_called_once_with(None, True)
195
195
  mock_app.set_tracing.assert_called_once_with(True)
196
196
  mock_show_log_info.assert_called_once()
197
- self.assertTrue(result)
197
+ self.assertIsNone(result)
198
198
 
199
199
  @patch("amd_debug.bios.AmdBios")
200
200
  @patch("amd_debug.bios.parse_args")
@@ -217,7 +217,7 @@ class TestAmdBios(unittest.TestCase):
217
217
  mock_amd_bios.assert_called_once_with("test.log", True)
218
218
  mock_app.run.assert_called_once()
219
219
  mock_show_log_info.assert_called_once()
220
- self.assertTrue(result)
220
+ self.assertIsNone(result)
221
221
 
222
222
  @patch("amd_debug.bios.parse_args")
223
223
  @patch("amd_debug.bios.version")
@@ -235,7 +235,7 @@ class TestAmdBios(unittest.TestCase):
235
235
  mock_parse_args.assert_called_once()
236
236
  mock_version.assert_called_once()
237
237
  mock_show_log_info.assert_called_once()
238
- self.assertEqual(result, False)
238
+ self.assertEqual(result, 1)
239
239
 
240
240
  @patch("amd_debug.bios.parse_args")
241
241
  @patch("amd_debug.bios.show_log_info")
@@ -247,4 +247,4 @@ class TestAmdBios(unittest.TestCase):
247
247
 
248
248
  mock_parse_args.assert_called_once()
249
249
  mock_show_log_info.assert_called_once()
250
- self.assertFalse(result)
250
+ self.assertEqual(result, 1)
test_kernel.py CHANGED
@@ -85,7 +85,7 @@ class TestKernelLog(unittest.TestCase):
85
85
 
86
86
  # test a real post code line
87
87
  line = 'ex_trace_args: " POST CODE: %X ACPI TIMER: %X TIME: %d.%d ms\\n", b0003f33, 83528798, 0, 77, 0, 0'
88
- expected_output = "POST CODE: B0003F33 ACPI TIMER: 83528798 TIME: 0.77 ms"
88
+ expected_output = "POST CODE: B0003F33 ACPI TIMER: 83528798 TIME: 0.119 ms"
89
89
  result = sscanf_bios_args(line)
90
90
  self.assertEqual(result, expected_output)
91
91
 
test_launcher.py CHANGED
@@ -26,10 +26,11 @@ class TestLauncher(unittest.TestCase):
26
26
  """Test launching as unknown exe"""
27
27
 
28
28
  with patch("builtins.print") as mock_print:
29
- amd_debug.launch_tool("unknown_exe.py")
29
+ result = amd_debug.launch_tool("unknown_exe.py")
30
30
  mock_print.assert_called_once_with(
31
31
  "\033[91mUnknown exe: unknown_exe.py\033[0m"
32
32
  )
33
+ self.assertIsNotNone(result)
33
34
 
34
35
  def test_launcher_amd_s2idle(self):
35
36
  """Test launching amd_s2idle"""
test_prerequisites.py CHANGED
@@ -143,6 +143,16 @@ class TestPrerequisiteValidator(unittest.TestCase):
143
143
  result = self.validator.check_port_pm_override()
144
144
  self.assertTrue(result)
145
145
 
146
+ @patch("amd_debug.prerequisites.version.parse")
147
+ def test_check_port_pm_override_smu_version_missing(self, mock_version_parse):
148
+ """Test check_port_pm_override with SMU version undefined"""
149
+ self.validator.cpu_family = 0x19
150
+ self.validator.cpu_model = 0x74
151
+ mock_version_parse.side_effect = lambda v: v if isinstance(v, str) else None
152
+ self.validator.smu_version = ""
153
+ result = self.validator.check_port_pm_override()
154
+ self.assertTrue(result)
155
+
146
156
  @patch("amd_debug.prerequisites.version.parse")
147
157
  def test_check_port_pm_override_smu_version_too_low(self, mock_version_parse):
148
158
  """Test check_port_pm_override with SMU version < 76.18.0"""
@@ -185,15 +195,18 @@ class TestPrerequisiteValidator(unittest.TestCase):
185
195
  new_callable=unittest.mock.mock_open,
186
196
  read_data=b"\x00" * 45,
187
197
  )
188
- def test_check_iommu_no_dma_protection(self, _mock_open):
189
- """Test check_iommu when DMA protection is not enabled"""
198
+ @patch("amd_debug.prerequisites.os.path.exists", return_value=True)
199
+ def test_check_iommu_no_dma_protection_no_msft0201(self, _mock_open, _mock_exists):
200
+ """Test check_iommu when DMA protection is not enabled and no MSFT0201 in IVRS"""
190
201
  self.validator.cpu_family = 0x1A
191
202
  self.validator.cpu_model = 0x20
192
203
  iommu_device = MagicMock(sys_path="/sys/devices/iommu")
204
+ acpi_device = MagicMock(sys_path="/sys/devices/acpi/MSFT0201")
205
+ platform_device = MagicMock(sys_path="/sys/devices/platform/MSFT0201")
193
206
  self.mock_pyudev.list_devices.side_effect = [
194
207
  [iommu_device],
195
- [],
196
- [],
208
+ [acpi_device],
209
+ [platform_device],
197
210
  ]
198
211
  result = self.validator.check_iommu()
199
212
  self.assertFalse(result)
@@ -204,6 +217,27 @@ class TestPrerequisiteValidator(unittest.TestCase):
204
217
  "IOMMU is misconfigured: Pre-boot DMA protection not enabled", "❌"
205
218
  )
206
219
 
220
+ @patch(
221
+ "amd_debug.prerequisites.open",
222
+ new_callable=unittest.mock.mock_open,
223
+ read_data=b"\x00" * 45 + "MSFT0201".encode("utf-8"),
224
+ )
225
+ @patch("amd_debug.prerequisites.os.path.exists", return_value=True)
226
+ def test_check_iommu_no_dma_protection_BUT_msft0201(self, _mock_open, _mock_exists):
227
+ """Test check_iommu when DMA protection is not enabled BUT MSFT0201 is in IVRS"""
228
+ self.validator.cpu_family = 0x1A
229
+ self.validator.cpu_model = 0x20
230
+ iommu_device = MagicMock(sys_path="/sys/devices/iommu")
231
+ acpi_device = MagicMock(sys_path="/sys/devices/acpi/MSFT0201")
232
+ platform_device = MagicMock(sys_path="/sys/devices/platform/MSFT0201")
233
+ self.mock_pyudev.list_devices.side_effect = [
234
+ [iommu_device],
235
+ [acpi_device],
236
+ [platform_device],
237
+ ]
238
+ result = self.validator.check_iommu()
239
+ self.assertTrue(result)
240
+
207
241
  @patch(
208
242
  "amd_debug.prerequisites.open",
209
243
  new_callable=unittest.mock.mock_open,
@@ -798,8 +832,7 @@ class TestPrerequisiteValidator(unittest.TestCase):
798
832
  self.assertFalse(result)
799
833
  self.assertTrue(any(isinstance(f, FadtWrong) for f in self.validator.failures))
800
834
 
801
- @patch("amd_debug.prerequisites.os.path.exists", return_value=False)
802
- def test_check_fadt_file_not_found(self, mock_path_exists):
835
+ def test_check_fadt_file_not_found(self):
803
836
  """Test check_fadt when FADT file is not found"""
804
837
  self.mock_kernel_log.match_line.return_value = False
805
838
  result = self.validator.check_fadt()
test_s2idle.py CHANGED
@@ -180,7 +180,7 @@ class TestMainFunction(unittest.TestCase):
180
180
  mock_report.assert_called_once_with(
181
181
  "2023-01-01", "2023-02-01", None, "html", False, False
182
182
  )
183
- self.assertTrue(result)
183
+ self.assertIsNone(result)
184
184
 
185
185
  @patch("amd_debug.s2idle.relaunch_sudo")
186
186
  @patch("amd_debug.s2idle.run_test_cycle")
@@ -207,7 +207,7 @@ class TestMainFunction(unittest.TestCase):
207
207
  mock_test.assert_called_once_with(
208
208
  None, None, "5", "txt", None, False, False, False, False, False
209
209
  )
210
- self.assertTrue(result)
210
+ self.assertIsNone(result)
211
211
 
212
212
  @patch("amd_debug.s2idle.version")
213
213
  def test_main_version(self, mock_version):
@@ -220,7 +220,7 @@ class TestMainFunction(unittest.TestCase):
220
220
  result = main()
221
221
  mock_version.assert_called_once()
222
222
  mock_print.assert_called_once_with("1.0.0")
223
- self.assertTrue(result)
223
+ self.assertIsNone(result)
224
224
 
225
225
  def test_main_no_action(self):
226
226
  """Test main function with no action specified"""