static int check_fw_support(fwts_framework *fw, uint64_t status) { if ((status == EFI_INVALID_PARAMETER) && ((attributes & FWTS_UEFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) || (attributes & FWTS_UEFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) || (attributes & FWTS_UEFI_VARIABLE_APPEND_WRITE))) { fwts_uefi_print_status_info(fw, status); fwts_skipped(fw, "EFI_INVALID_PARAMETER shall be returned, " "when firmware doesn't support these operations " "with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, " "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS " "or EFI_VARIABLE_APPEND_WRITE attributes is set."); return FWTS_SKIP; } if (status == EFI_OUT_OF_RESOURCES) { fwts_uefi_print_status_info(fw, status); fwts_skipped(fw, "Run out of resources for SetVariable " "UEFI runtime interface: cannot test."); fwts_advice(fw, "Firmware may reclaim some resources " "after rebooting. Reboot and test " "again may be helpful to continue " "the test."); return FWTS_SKIP; } return FWTS_OK; }
static int uefivarinfo_test1(fwts_framework *fw) { uint64_t status; uint64_t remvarstoragesize; uint64_t maxvariablesize; uint64_t maxvarstoragesize; uint64_t usedvars; uint64_t usedvarssize; if (do_queryvariableinfo(&status, &maxvarstoragesize, &remvarstoragesize, &maxvariablesize) == FWTS_ERROR) { if (status == EFI_UNSUPPORTED) { fwts_skipped(fw, "QueryVariableInfo UEFI runtime interface not supported: cannot test."); fwts_advice(fw, "Firmware also needs to check if the revision " "of system table is correct or not. Linux " "kernel returns EFI_UNSUPPORTED as well, if " "the FirmwareRevision of system table is less " "than EFI_2_00_SYSTEM_TABLE_REVISION."); return FWTS_SKIP; } else { fwts_log_info(fw, "Failed to query variable info with UEFI runtime service."); fwts_uefi_print_status_info(fw, status); return FWTS_ERROR; } } fwts_log_info_verbatim(fw, "UEFI NVRAM storage:"); fwts_log_info_verbatim(fw, " Maximum storage: %8" PRIu64 " bytes", maxvarstoragesize); fwts_log_info_verbatim(fw, " Remaining storage: %8" PRIu64 " bytes", remvarstoragesize); fwts_log_info_verbatim(fw, " Maximum variable size: %8" PRIu64 " bytes", maxvariablesize); if (do_checkvariables(fw, &usedvars, &usedvarssize, maxvariablesize) == FWTS_OK) { fwts_log_info_verbatim(fw, "Currently used:"); fwts_log_info_verbatim(fw, " %" PRIu64 " variables, storage used: %" PRIu64 " bytes", usedvars, usedvarssize); } return FWTS_OK; }
static int mcfg_test1(fwts_framework *fw) { int nr, i; fwts_acpi_table_mcfg *mcfg = (fwts_acpi_table_mcfg*)mcfg_table->data; fwts_acpi_mcfg_configuration *config; bool failed = false; ssize_t mcfg_size; const char *memory_map_name; memory_map_name = fwts_memory_map_name(fw->firmware_type); fwts_log_info(fw, "This test tries to validate the MCFG table by comparing the first " "16 bytes in the MMIO mapped config space with the 'traditional' config " "space of the first PCI device (root bridge). The MCFG data is only " "trusted if it is marked reserved in the %s", memory_map_name); fwts_log_nl(fw); if ((memory_map_list = fwts_memory_map_table_load(fw)) == NULL) { /* Not fatal, just means test will be less comprehensive */ fwts_log_warning(fw, "No memory map table found"); } else { fwts_memory_map_table_dump(fw, memory_map_list); fwts_log_nl(fw); } mcfg_size = mcfg_table->length; mcfg_size -= sizeof(fwts_acpi_table_mcfg); if (mcfg_size < 0) { fwts_failed(fw, LOG_LEVEL_HIGH, "MCFGInvalidSize", "Invalid MCFG ACPI table size: got %zd bytes expecting more", mcfg_size + sizeof(fwts_acpi_table_mcfg)); fwts_advice(fw, "MCFG table must be least %zd bytes (header size) with " "multiples of %zd bytes for each MCFG entry.", sizeof(fwts_acpi_table_mcfg), sizeof(fwts_acpi_mcfg_configuration)); return FWTS_ERROR; } nr = mcfg_size / sizeof(fwts_acpi_mcfg_configuration); if (!nr) { fwts_failed(fw, LOG_LEVEL_MEDIUM, "MCFGNoEntries", "No MCFG ACPI table entries"); return FWTS_ERROR; } if (mcfg_size != (ssize_t)(nr * sizeof(fwts_acpi_mcfg_configuration))) { fwts_failed(fw, LOG_LEVEL_HIGH, "MCFGInvalidSize2", "MCFG table is not a multiple of record size"); return FWTS_ERROR; } fwts_log_info(fw, "MCFG table found, size is %zd bytes (excluding header) (%i entries).", mcfg_size, nr); if (mcfg == NULL) { fwts_failed(fw, LOG_LEVEL_HIGH, "MCFGInvalidTable", "Invalid MCFG ACPI table"); return FWTS_ERROR; } if (memory_map_list == NULL) fwts_failed(fw, LOG_LEVEL_MEDIUM, "MMapUnreadable", "Cannot check MCFG MMIO space against memory map table: could not read memory map table."); config = &mcfg->configuration[0]; for (i = 0; i < nr; i++, config++) { fwts_log_info_verbatim(fw, "Configuration Entry #%d:", i); fwts_log_info_verbatim(fw, " Base Address : 0x%" PRIx64, config->base_address); fwts_log_info_verbatim(fw, " Segment : %" PRIu8, config->pci_segment_group_number); fwts_log_info_verbatim(fw, " Start bus : %" PRIu8, config->start_bus_number); fwts_log_info_verbatim(fw, " End bus : %" PRIu8, config->end_bus_number); if ((memory_map_list != NULL) && (!fwts_memory_map_is_reserved(memory_map_list, config->base_address))) { fwts_failed(fw, LOG_LEVEL_LOW, "MCFGMMIONotReserved", "MCFG MMIO config space at 0x%" PRIx64 " is not reserved in the memory map table", config->base_address); fwts_advice(fw, "The PCI Express specification states that the " "PCI Express configuration space should " "be defined in the MCFG table and *maybe* " "optionally defined in the %s if ACPI MCFG is " "present. Linux checks if the region is reserved " "in the memory map table and will reject the " "MMCONFIG if there is a discrepency between MCFG " "and the memory map table for the PCI Express region. " "[See arch/x86/pci/mmconfig-shared.c pci_mmcfg_reject_broken()]. " "It is recommended that this is defined in the " "%s table for Linux.", memory_map_name, memory_map_name); failed = true; } } if (!failed) fwts_passed(fw, "MCFG MMIO config space is reserved in memory map table."); return FWTS_OK; }
static int dt_sysinfo_check_ref_plat_compatible(fwts_framework *fw) { int node, compat_len, model_len; node = fdt_path_offset(fw->fdt, "/"); if (node < 0) { fwts_failed(fw, LOG_LEVEL_HIGH, "DTRootNodeMissing", "root device tree node is missing"); return FWTS_ERROR; } if (fdt_node_check_compatible(fw->fdt, node, op_powernv)) { fwts_failed(fw, LOG_LEVEL_HIGH, "DTCompatibleMissing", "DeviceTree failed validation, could not find" " the \"compatible\" property of \"%s\" in the " "root of the device tree", "ibm,powernv"); return FWTS_ERROR; } else { const char *model_buf, *compat_buf; char *orig_model_buf, *tmp_model_buf; compat_buf = fdt_getprop(fw->fdt, node, "compatible", &compat_len); model_buf = fdt_getprop(fw->fdt, node, "model", &model_len); if (!model_buf || !compat_buf) { fwts_failed(fw,LOG_LEVEL_HIGH, "DTSysInfoCheck", "Cannot read the properties for OpenPOWER" " Reference Compatible check"); return FWTS_ERROR; } /* need modifiable memory */ /* save original ptr to free */ tmp_model_buf = orig_model_buf = strdup(model_buf); if (!tmp_model_buf) { fwts_failed(fw, LOG_LEVEL_HIGH, "DTSysInfoCheck", "Unable to get memory for model" " compare for OpenPOWER" " Reference Compatible check"); return FWTS_ERROR; } tmp_model_buf = hidewhitespace(tmp_model_buf); if (!(strcmp(model_buf, tmp_model_buf) == 0)) { fwts_warning(fw, "DTSysInfoCheck" " See further advice in the log."); fwts_log_nl(fw); fwts_log_info_verbatim(fw, "DTSysInfoCheck" " Check the root \"model\" property" " from the device tree %s \"%s\".", DT_FS_PATH, model_buf); fwts_advice(fw, "Check the root \"model\" property" " from the device tree %s, " "there are whitespace inconsistentencies" " between the \"model\" property and " " the trimmed value of \"%s\", report" " this as a possible bug." " Run \"hexdump -C model\"" " from the \"%s\" directory to view" " the raw contents of the property.", DT_FS_PATH, tmp_model_buf, DT_FS_PATH); } if (machine_matches_reference_model(fw, compat_buf, compat_len, tmp_model_buf)) { fwts_passed(fw, "OpenPOWER Reference " "Compatible passed"); } else { fwts_failed(fw, LOG_LEVEL_HIGH, "DTOpenPOWERReferenceFailed", "Unable to find an OpenPOWER supported" " match"); /* adding verbatim to show proper string */ fwts_log_info_verbatim(fw, "Unable to find an OpenPOWER reference" " match for \"%s\"", tmp_model_buf); free(orig_model_buf); return FWTS_ERROR; } free(orig_model_buf); } return FWTS_OK; }