/* * fwts_summary_init() * free up summary lists */ void fwts_summary_deinit(void) { int i; for (i = 0; i < SUMMARY_MAX; i++) if (fwts_summaries[i]) fwts_list_free(fwts_summaries[i], fwts_summary_item_free); }
static int s4_init(fwts_framework *fw) { fwts_list* swap_devs; swap_devs = fwts_file_open_and_read("/proc/swaps"); if (fwts_text_list_strstr(swap_devs, "/dev/") == NULL) { fwts_list_free(swap_devs, free); fwts_failed(fw, LOG_LEVEL_MEDIUM, "NoSwap", "Cannot run hibernate test - machine appears to have NO swap."); return FWTS_ERROR; } fwts_list_free(swap_devs, free); if (fwts_wakealarm_test_firing(fw, 1)) { fwts_log_error(fw, "Cannot automatically wake machine up - aborting S4 test."); fwts_failed(fw, LOG_LEVEL_MEDIUM, "BadWakeAlarmS4", "Check if wakealarm works reliably for S4 tests."); return FWTS_ERROR; } return FWTS_OK; }
/* * fwts_acpi_deinit() * Close ACPIA engine and free method namespace */ int fwts_acpi_deinit(fwts_framework *fw) { int ret = FWTS_ERROR; FWTS_UNUSED(fw); if (fwts_acpi_initialized) { fwts_list_free(fwts_object_names, free); fwts_object_names = NULL; ret = fwts_acpica_deinit(); fwts_acpi_initialized = false; } return ret; }
static int s4_hibernate(fwts_framework *fw, int *klog_errors, int *hw_errors, int *pm_errors, int *klog_oopses, int *klog_warn_ons, int *failed_alloc_image, int percent) { fwts_list *klog_pre, *klog_post, *klog_diff; fwts_hwinfo hwinfo1, hwinfo2; int status; int duration; int differences; int rc = FWTS_OK; char *command = NULL; char *quirks = NULL; fwts_pm_method_vars *fwts_settings; int (*do_s4)(fwts_pm_method_vars *, const int, int*, const char*); fwts_settings = calloc(1, sizeof(fwts_pm_method_vars)); if (fwts_settings == NULL) return FWTS_OUT_OF_MEMORY; fwts_settings->fw = fw; if (fw->pm_method == FWTS_PM_UNDEFINED) { /* Autodetection */ fwts_log_info(fw, "Detecting the power method."); detect_pm_method(fwts_settings); } switch (fw->pm_method) { #if FWTS_ENABLE_LOGIND case FWTS_PM_LOGIND: fwts_log_info(fw, "Using logind as the default power method."); if (fwts_logind_init_proxy(fwts_settings) != 0) { fwts_log_error(fw, "Failure to connect to Logind."); rc = FWTS_ERROR; goto tidy; } do_s4 = &wrap_logind_do_s4; break; #endif case FWTS_PM_PMUTILS: fwts_log_info(fw, "Using pm-utils as the default power method."); do_s4 = &wrap_pmutils_do_s4; break; case FWTS_PM_SYSFS: fwts_log_info(fw, "Using sysfs as the default power method."); do_s4 = &wrap_sysfs_do_s4; break; default: /* This should never happen */ fwts_log_info(fw, "Using sysfs as the default power method."); do_s4 = &wrap_sysfs_do_s4; break; } if (s4_device_check) fwts_hwinfo_get(fw, &hwinfo1); if (fw->pm_method == FWTS_PM_PMUTILS) { /* Format up pm-hibernate command with optional quirking arguments */ if ((command = fwts_realloc_strcat(NULL, PM_HIBERNATE)) == NULL) { rc = FWTS_OUT_OF_MEMORY; goto tidy; } /* For now we only support quirks with pm-utils */ if (s4_quirks) { if ((command = fwts_realloc_strcat(command, " ")) == NULL) { rc = FWTS_OUT_OF_MEMORY; goto tidy; } if ((quirks = fwts_args_comma_list(s4_quirks)) == NULL) { rc = FWTS_OUT_OF_MEMORY; goto tidy; } if ((command = fwts_realloc_strcat(command, quirks)) == NULL) { rc = FWTS_OUT_OF_MEMORY; goto tidy; } } } fwts_wakealarm_trigger(fw, s4_sleep_delay); /* Do s4 here */ if ((klog_pre = fwts_klog_read()) == NULL) fwts_log_error(fw, "S4: hibernate: Cannot read kernel log."); status = do_s4(fwts_settings, percent, &duration, command); if ((klog_post = fwts_klog_read()) == NULL) fwts_log_error(fw, "S4: hibernate: Cannot re-read kernel log."); if (s4_device_check) { int i; for (i = 0; i < s4_device_check_delay; i++) { char buffer[80]; snprintf(buffer, sizeof(buffer), "(Waiting %d/%d seconds)", i+1, s4_device_check_delay); fwts_progress_message(fw, percent, buffer); sleep(1); } fwts_progress_message(fw, percent, "(Checking devices)"); fwts_hwinfo_get(fw, &hwinfo2); fwts_hwinfo_compare(fw, &hwinfo1, &hwinfo2, &differences); fwts_hwinfo_free(&hwinfo1); fwts_hwinfo_free(&hwinfo2); if (differences > 0) { fwts_failed(fw, LOG_LEVEL_HIGH, "DevConfigDiffAfterS4", "Found %d differences in device configuation during S4 cycle.", differences); (*hw_errors)++; } } fwts_progress_message(fw, percent, "(Checking for errors)"); klog_diff = fwts_klog_find_changes(klog_pre, klog_post); s4_check_log(fw, klog_diff, klog_errors, klog_oopses, klog_warn_ons); fwts_progress_message(fw, percent, "(Checking for PM errors)"); /* Add in error check for pm-hibernate status */ if ((status > 0) && (status < 128)) { fwts_failed(fw, LOG_LEVEL_HIGH, "PMActionFailedPreS4", "pm-action failed before trying to put the system " "in the requested power saving state."); (*pm_errors)++; } else if (status == 128) { fwts_failed(fw, LOG_LEVEL_HIGH, "PMActionPowerStateS4", "pm-action tried to put the machine in the requested " "power state but failed."); (*pm_errors)++; } else if (status > 128) { fwts_failed(fw, LOG_LEVEL_HIGH, "PMActionFailedS4", "pm-action encountered an error and also failed to " "enter the requested power saving state."); (*pm_errors)++; } if (fwts_klog_regex_find(fw, klog_diff, "Freezing user space processes.*done") < 1) { fwts_failed(fw, LOG_LEVEL_HIGH, "UserSpaceTaskFreeze", "Failed to freeze user space processes."); (*pm_errors)++; } if (fwts_klog_regex_find(fw, klog_diff, "Freezing remaining freezable tasks.*done") < 1) { fwts_failed(fw, LOG_LEVEL_HIGH, "KernelTaskFreeze", "Failed to freeze remaining non-user space processes."); (*pm_errors)++; } if ((fwts_klog_regex_find(fw, klog_diff, "PM: freeze of devices complete") < 1) && (fwts_klog_regex_find(fw, klog_diff, "PM: late freeze of devices complete") < 1)) { fwts_failed(fw, LOG_LEVEL_HIGH, "DeviceFreeze", "Failed to freeze devices."); (*pm_errors)++; } if (fwts_klog_regex_find(fw, klog_diff, "PM: Allocated.*kbytes") < 1) { fwts_failed(fw, LOG_LEVEL_HIGH, "HibernateImageAlloc", "Failed to allocate memory for hibernate image."); *failed_alloc_image = 1; (*pm_errors)++; } if (fwts_klog_regex_find(fw, klog_diff, "PM: Image restored successfully") < 1) { fwts_failed(fw, LOG_LEVEL_HIGH, "HibernateImageRestore", "Failed to restore hibernate image."); (*pm_errors)++; } fwts_klog_free(klog_pre); fwts_klog_free(klog_post); fwts_list_free(klog_diff, NULL); tidy: free(command); free(quirks); free_pm_method_vars(fwts_settings); return rc; }
static int crs_test1(fwts_framework *fw) { fwts_list *klog; int day, mon, year; char *cmdline; if ((cmdline = fwts_get("/proc/cmdline")) == NULL) { fwts_log_error(fw, "Cannot read /proc/cmdline"); return FWTS_ERROR; } if (crs_get_bios_date(fw, &day, &mon, &year) != FWTS_OK) { fwts_log_error(fw, "Cannot determine age of BIOS."); free(cmdline); return FWTS_ERROR; } if ((klog = fwts_klog_read()) == NULL) { fwts_log_error(fw, "Cannot read kernel log."); free(cmdline); return FWTS_ERROR; } if (fwts_klog_regex_find(fw, klog, "PCI: Ignoring host bridge windows from ACPI;") > 0) { if (strstr(cmdline, "pci=nocrs") != NULL) { fwts_skipped(fw, "Kernel was booted with pci=nocrs, Ignoring host bridge windows _CRS settings from ACPI, skipping test."); } else { if (year == 0) { fwts_failed(fw, LOG_LEVEL_MEDIUM, "BIOSTooOld", "The kernel could not determine the BIOS age " "and has assumed that your BIOS is too old to correctly " "specify the host bridge MMIO aperture using _CRS."); fwts_log_advice(fw, "You can override this by booting with \"pci=use_crs\"."); } else if (year < 2008) { fwts_passed(fw, "The kernel has detected an old BIOS (%d/%d/%d) " "and has assumed that your BIOS is too old to correctly " "specify the host bridge MMIO aperture using _CRS.", mon, day, year); fwts_log_advice(fw, "You can override this by booting with \"pci=use_crs\"."); } else { fwts_failed(fw, LOG_LEVEL_MEDIUM, "HostBridgeWindows", "The kernel is ignoring host bridge windows from ACPI for some unknown reason. " "pci=nocrs has not been used as a boot parameter and the BIOS may be recent enough " "to support this (%d/%d/%d)", mon, day, year); } } } else if (fwts_klog_regex_find(fw, klog, "PCI: Using host bridge windows from ACPI;") > 0) { if (strstr(cmdline, "pci=use_crs") != NULL) { if (year == 0) { fwts_failed(fw, LOG_LEVEL_MEDIUM, "BIOSNoReleaseDate", "The BIOS does not seem to have release date, hence pci=use_crs was required."); } else if (year < 2008) { fwts_passed(fw, "The BIOS is relatively old (%d/%d/%d) and hence pci=use_crs was required to " "enable host bridge windows _CRS settings from ACPI.", mon, day, year); } else { fwts_failed(fw, LOG_LEVEL_LOW, "BIOSSupportBridgeWindows", "Kernel was booted with pci=use_crs but this may be uncessary as " "the BIOS is new enough to support automatic bridge windows configuring using _CRS from ACPI. " "However, the workaround may be necessary because _CRS is incorrect or not implemented in the " "DSDT."); } } else { fwts_passed(fw, "The kernel has detected a BIOS newer than the end of 2007 (%d/%d/%d) " "and has assumed that your BIOS can correctly " "specify the host bridge MMIO aperture using _CRS. If this does not work " "correctly you can override this by booting with \"pci=nocrs\".", mon, day, year); } } else { fwts_skipped(fw, "Cannot find host bridge message in kernel log, skipping test."); } fwts_list_free(klog, free); free(cmdline); return FWTS_OK; }
static int get_mtrrs(void) { struct mtrr_entry *entry; FILE *fp; char line[4096]; if ((mtrr_list = fwts_list_new()) == NULL) return FWTS_ERROR; if ((fp = fopen("/proc/mtrr", "r")) == NULL) { fwts_list_free(mtrr_list, free); return FWTS_ERROR; } while (!feof(fp)) { char *ptr1, *ptr2; if (fgets(line, sizeof(line), fp) == NULL) break; if ((entry = calloc(1, sizeof(struct mtrr_entry))) == NULL) { fwts_list_free(mtrr_list, free); fclose(fp); return FWTS_ERROR; } /* * Put all text to lower case since the output * from /proc/mtrr is variable upper/lower case * across kernel versions so forcing to lower * saves comparing for upper/lower case variants. */ for (ptr1 = line; *ptr1; ptr1++) *ptr1 = tolower(*ptr1); /* Parse the following: * reg01: base=0x080000000 ( 2048MB), size= 1024MB, count=1: write-back */ /* Get register, in decimal */ if (strncmp(line, "reg", 3)) { free(entry); continue; } entry->reg = strtoul(line + 3, NULL, 10); /* Get base, in hex */ if ((ptr1 = strstr(line, "base=0x")) == NULL) { free(entry); continue; } entry->start = strtoull(ptr1 + 5, NULL, 16); /* Get size, in decimal */ if ((ptr1 = strstr(line, "size=")) == NULL) { free(entry); continue; } entry->size = strtoull(ptr1 + 5, &ptr2, 10); if (ptr2 && (*ptr2 == 'm')) entry->size *= 1024 * 1024; if (ptr2 && (*ptr2 == 'k')) entry->size *= 1024; entry->end = entry->start + entry->size; if (strstr(line, "write-back")) entry->type = WRITE_BACK; else if (strstr(line, "uncachable")) entry->type = UNCACHED; else if (strstr(line, "write-through")) entry->type = WRITE_THROUGH; else if (strstr(line, "write-combining")) entry->type = WRITE_COMBINING; else if (strstr(line, "write-protect")) entry->type = WRITE_PROTECT; else entry->type = UNKNOWN; fwts_list_append(mtrr_list, entry); } fclose(fp); return FWTS_OK; }