static int microcode_deinit(fwts_framework *fw) { FWTS_UNUSED(fw); fwts_klog_free(klog); return FWTS_OK; }
static int ebda_deinit(fwts_framework *fw) { FWTS_UNUSED(fw); fwts_klog_free(memory_map); return FWTS_OK; }
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; }