Message ID | 1370240557-7183-1-git-send-email-ivan.hu@canonical.com |
---|---|
State | Rejected |
Headers | show |
wrong commit, please ignore this patch. Ivan On 06/03/2013 02:22 PM, Ivan Hu wrote: > This utility get information by the uefi runtime service QueryVariableInfo > and GetVariable which provides the below infomations: > 1. Maximum variable storage size > 2. Remaining variable storage size > 3. Maximum variable size > 4. The variable number gets from the the memory location > EFI_VARIABLE_NON_VOLATILE | > EFI_VARIABLE_BOOTSERVICE_ACCESS | > EFI_VARIABLE_HARDWARE_ERROR_RECORD attribute and used size. > > Signed-off-by: Ivan Hu <ivan.hu@canonical.com> > --- > src/Makefile.am | 3 +- > src/uefi/uefivarinfo/uefivarinfo.c | 223 ++++++++++++++++++++++++++++++++++++ > 2 files changed, 225 insertions(+), 1 deletion(-) > create mode 100644 src/uefi/uefivarinfo/uefivarinfo.c > > diff --git a/src/Makefile.am b/src/Makefile.am > index b57e57c..1f52c47 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -82,7 +82,8 @@ fwts_SOURCES = main.c \ > uefi/uefirttime/uefirttime.c \ > uefi/uefirtvariable/uefirtvariable.c \ > uefi/uefirtmisc/uefirtmisc.c \ > - uefi/securebootcert/securebootcert.c > + uefi/securebootcert/securebootcert.c \ > + uefi/uefivarinfo/uefivarinfo.c > > fwts_LDFLAGS = -ljson -lm > > diff --git a/src/uefi/uefivarinfo/uefivarinfo.c b/src/uefi/uefivarinfo/uefivarinfo.c > new file mode 100644 > index 0000000..27a94cc > --- /dev/null > +++ b/src/uefi/uefivarinfo/uefivarinfo.c > @@ -0,0 +1,223 @@ > +/* > + * Copyright (C) 2013 Canonical > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. > + * > + */ > + > +#include <inttypes.h> > +#include <stdio.h> > +#include <stddef.h> > +#include <sys/ioctl.h> > +#include <fcntl.h> > + > +#include "fwts.h" > +#include "fwts_uefi.h" > +#include "efi_runtime.h" > +#include "fwts_efi_module.h" > + > +#define MAX_DATA_LENGTH 1024 > + > +static int fd; > + > +static int uefivarinfo_init(fwts_framework *fw) > +{ > + if (fwts_firmware_detect() != FWTS_FIRMWARE_UEFI) { > + fwts_log_info(fw, "Cannot detect any UEFI firmware. Aborted."); > + return FWTS_ABORTED; > + } > + > + if (fwts_lib_efi_runtime_load_module(fw) != FWTS_OK) { > + fwts_log_info(fw, "Cannot load efi_runtime module. Aborted."); > + return FWTS_ABORTED; > + } > + > + fd = open("/dev/efi_runtime", O_RDONLY); > + if (fd == -1) { > + fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted."); > + return FWTS_ABORTED; > + } > + > + return FWTS_OK; > +} > + > +static int uefivarinfo_deinit(fwts_framework *fw) > +{ > + close(fd); > + fwts_lib_efi_runtime_unload_module(fw); > + > + return FWTS_OK; > +} > + > +static int do_checkvariables( > + fwts_framework *fw, > + uint64_t *usedvars, > + uint64_t *usedvarssize) > +{ > + long ioret; > + uint64_t status; > + > + struct efi_getnextvariablename getnextvariablename; > + uint64_t variablenamesize = MAX_DATA_LENGTH; > + uint16_t variablename[MAX_DATA_LENGTH]; > + EFI_GUID vendorguid; > + > + uint32_t attributestest; > + struct efi_getvariable getvariable; > + getvariable.Attributes = &attributestest; > + getvariable.status = &status; > + > + getnextvariablename.VariableNameSize = &variablenamesize; > + getnextvariablename.VariableName = variablename; > + getnextvariablename.VendorGuid = &vendorguid; > + getnextvariablename.status = &status; > + > + *usedvars = 0; > + *usedvarssize = 0; > + > + /* > + * To start the search, need to pass a Null-terminated string > + * in VariableName > + */ > + variablename[0] = '\0'; > + while (true) { > + variablenamesize = MAX_DATA_LENGTH; > + ioret = ioctl(fd, EFI_RUNTIME_GET_NEXTVARIABLENAME, &getnextvariablename); > + > + if (ioret == -1) { > + > + /* no next variable was found*/ > + if (*getnextvariablename.status == EFI_NOT_FOUND) > + break; > + > + fwts_failed(fw, LOG_LEVEL_HIGH, > + "UEFIRuntimeGetNextVariableName", > + "Failed to get next variable name with UEFI " > + "runtime service."); > + fwts_uefi_print_status_info(fw, status); > + return FWTS_ERROR; > + } > + > + (*usedvars)++; > + > + uint8_t data[MAX_DATA_LENGTH]; > + uint64_t getdatasize = sizeof(data); > + > + getvariable.VariableName = variablename; > + getvariable.VendorGuid = &vendorguid; > + getvariable.DataSize = &getdatasize; > + getvariable.Data = data; > + > + ioret = ioctl(fd, EFI_RUNTIME_GET_VARIABLE, &getvariable); > + if (ioret == -1) { > + fwts_failed(fw, LOG_LEVEL_HIGH, > + "UEFIRuntimeGetVariable", > + "Failed to get variable with UEFI " > + "runtime service."); > + fwts_uefi_print_status_info(fw, status); > + return FWTS_ERROR; > + } > + > + (*usedvarssize) += getdatasize; > + > + }; > + > + return FWTS_OK; > + > +} > + > +static int do_queryvariableinfo( > + uint64_t *status, > + uint64_t *maxvarstoragesize, > + uint64_t *remvarstoragesize, > + uint64_t *maxvariablesize) > +{ > + long ioret; > + struct efi_queryvariableinfo queryvariableinfo; > + > + queryvariableinfo.Attributes = FWTS_UEFI_VAR_NON_VOLATILE | > + FWTS_UEFI_VAR_BOOTSERVICE_ACCESS | > + FWTS_UEFI_VAR_RUNTIME_ACCESS; > + queryvariableinfo.MaximumVariableStorageSize = maxvarstoragesize; > + queryvariableinfo.RemainingVariableStorageSize = remvarstoragesize; > + queryvariableinfo.MaximumVariableSize = maxvariablesize; > + queryvariableinfo.status = status; > + > + ioret = ioctl(fd, EFI_RUNTIME_QUERY_VARIABLEINFO, &queryvariableinfo); > + > + if (ioret == -1) > + return FWTS_ERROR; > + > + 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, > + "Not support the QueryVariableInfo UEFI " > + "runtime interface: 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_failed(fw, LOG_LEVEL_HIGH, > + "UEFIRuntimeQueryVariableInfo", > + "Failed to query variable info with UEFI " > + "runtime service."); > + fwts_uefi_print_status_info(fw, status); > + return FWTS_ERROR; > + } > + } > + > + fwts_log_info_verbatum(fw, "UEFI NVRAM storage:"); > + fwts_log_info_verbatum(fw, " Maximum storage: %8" PRIu64 " bytes", maxvarstoragesize); > + fwts_log_info_verbatum(fw, " Remaining storage: %8" PRIu64 " bytes", remvarstoragesize); > + fwts_log_info_verbatum(fw, " Maximum variable size: %8" PRIu64 " bytes", maxvarstoragesize); > + > + if (do_checkvariables(fw, &usedvars, &usedvarssize) != FWTS_ERROR) { > + fwts_log_info_verbatum(fw, "Currently used:"); > + fwts_log_info_verbatum(fw, " %" PRIu64 " variables, storage used: %" PRIu64 " bytes", usedvars, usedvarssize); > + } > + > + return FWTS_OK; > +} > + > +static fwts_framework_minor_test uefivarinfo_tests[] = { > + { uefivarinfo_test1, "UEFI varaiable info query." }, > + { NULL, NULL } > +}; > + > +static fwts_framework_ops uefivarinfo_ops = { > + .description = "UEFI varaiable info query.", > + .init = uefivarinfo_init, > + .deinit = uefivarinfo_deinit, > + .minor_tests = uefivarinfo_tests > +}; > + > +FWTS_REGISTER("uefivarinfo", &uefivarinfo_ops, FWTS_TEST_ANYTIME, FWTS_FLAG_UTILS | FWTS_FLAG_ROOT_PRIV); >
diff --git a/src/Makefile.am b/src/Makefile.am index b57e57c..1f52c47 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -82,7 +82,8 @@ fwts_SOURCES = main.c \ uefi/uefirttime/uefirttime.c \ uefi/uefirtvariable/uefirtvariable.c \ uefi/uefirtmisc/uefirtmisc.c \ - uefi/securebootcert/securebootcert.c + uefi/securebootcert/securebootcert.c \ + uefi/uefivarinfo/uefivarinfo.c fwts_LDFLAGS = -ljson -lm diff --git a/src/uefi/uefivarinfo/uefivarinfo.c b/src/uefi/uefivarinfo/uefivarinfo.c new file mode 100644 index 0000000..27a94cc --- /dev/null +++ b/src/uefi/uefivarinfo/uefivarinfo.c @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2013 Canonical + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include <inttypes.h> +#include <stdio.h> +#include <stddef.h> +#include <sys/ioctl.h> +#include <fcntl.h> + +#include "fwts.h" +#include "fwts_uefi.h" +#include "efi_runtime.h" +#include "fwts_efi_module.h" + +#define MAX_DATA_LENGTH 1024 + +static int fd; + +static int uefivarinfo_init(fwts_framework *fw) +{ + if (fwts_firmware_detect() != FWTS_FIRMWARE_UEFI) { + fwts_log_info(fw, "Cannot detect any UEFI firmware. Aborted."); + return FWTS_ABORTED; + } + + if (fwts_lib_efi_runtime_load_module(fw) != FWTS_OK) { + fwts_log_info(fw, "Cannot load efi_runtime module. Aborted."); + return FWTS_ABORTED; + } + + fd = open("/dev/efi_runtime", O_RDONLY); + if (fd == -1) { + fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted."); + return FWTS_ABORTED; + } + + return FWTS_OK; +} + +static int uefivarinfo_deinit(fwts_framework *fw) +{ + close(fd); + fwts_lib_efi_runtime_unload_module(fw); + + return FWTS_OK; +} + +static int do_checkvariables( + fwts_framework *fw, + uint64_t *usedvars, + uint64_t *usedvarssize) +{ + long ioret; + uint64_t status; + + struct efi_getnextvariablename getnextvariablename; + uint64_t variablenamesize = MAX_DATA_LENGTH; + uint16_t variablename[MAX_DATA_LENGTH]; + EFI_GUID vendorguid; + + uint32_t attributestest; + struct efi_getvariable getvariable; + getvariable.Attributes = &attributestest; + getvariable.status = &status; + + getnextvariablename.VariableNameSize = &variablenamesize; + getnextvariablename.VariableName = variablename; + getnextvariablename.VendorGuid = &vendorguid; + getnextvariablename.status = &status; + + *usedvars = 0; + *usedvarssize = 0; + + /* + * To start the search, need to pass a Null-terminated string + * in VariableName + */ + variablename[0] = '\0'; + while (true) { + variablenamesize = MAX_DATA_LENGTH; + ioret = ioctl(fd, EFI_RUNTIME_GET_NEXTVARIABLENAME, &getnextvariablename); + + if (ioret == -1) { + + /* no next variable was found*/ + if (*getnextvariablename.status == EFI_NOT_FOUND) + break; + + fwts_failed(fw, LOG_LEVEL_HIGH, + "UEFIRuntimeGetNextVariableName", + "Failed to get next variable name with UEFI " + "runtime service."); + fwts_uefi_print_status_info(fw, status); + return FWTS_ERROR; + } + + (*usedvars)++; + + uint8_t data[MAX_DATA_LENGTH]; + uint64_t getdatasize = sizeof(data); + + getvariable.VariableName = variablename; + getvariable.VendorGuid = &vendorguid; + getvariable.DataSize = &getdatasize; + getvariable.Data = data; + + ioret = ioctl(fd, EFI_RUNTIME_GET_VARIABLE, &getvariable); + if (ioret == -1) { + fwts_failed(fw, LOG_LEVEL_HIGH, + "UEFIRuntimeGetVariable", + "Failed to get variable with UEFI " + "runtime service."); + fwts_uefi_print_status_info(fw, status); + return FWTS_ERROR; + } + + (*usedvarssize) += getdatasize; + + }; + + return FWTS_OK; + +} + +static int do_queryvariableinfo( + uint64_t *status, + uint64_t *maxvarstoragesize, + uint64_t *remvarstoragesize, + uint64_t *maxvariablesize) +{ + long ioret; + struct efi_queryvariableinfo queryvariableinfo; + + queryvariableinfo.Attributes = FWTS_UEFI_VAR_NON_VOLATILE | + FWTS_UEFI_VAR_BOOTSERVICE_ACCESS | + FWTS_UEFI_VAR_RUNTIME_ACCESS; + queryvariableinfo.MaximumVariableStorageSize = maxvarstoragesize; + queryvariableinfo.RemainingVariableStorageSize = remvarstoragesize; + queryvariableinfo.MaximumVariableSize = maxvariablesize; + queryvariableinfo.status = status; + + ioret = ioctl(fd, EFI_RUNTIME_QUERY_VARIABLEINFO, &queryvariableinfo); + + if (ioret == -1) + return FWTS_ERROR; + + 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, + "Not support the QueryVariableInfo UEFI " + "runtime interface: 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_failed(fw, LOG_LEVEL_HIGH, + "UEFIRuntimeQueryVariableInfo", + "Failed to query variable info with UEFI " + "runtime service."); + fwts_uefi_print_status_info(fw, status); + return FWTS_ERROR; + } + } + + fwts_log_info_verbatum(fw, "UEFI NVRAM storage:"); + fwts_log_info_verbatum(fw, " Maximum storage: %8" PRIu64 " bytes", maxvarstoragesize); + fwts_log_info_verbatum(fw, " Remaining storage: %8" PRIu64 " bytes", remvarstoragesize); + fwts_log_info_verbatum(fw, " Maximum variable size: %8" PRIu64 " bytes", maxvarstoragesize); + + if (do_checkvariables(fw, &usedvars, &usedvarssize) != FWTS_ERROR) { + fwts_log_info_verbatum(fw, "Currently used:"); + fwts_log_info_verbatum(fw, " %" PRIu64 " variables, storage used: %" PRIu64 " bytes", usedvars, usedvarssize); + } + + return FWTS_OK; +} + +static fwts_framework_minor_test uefivarinfo_tests[] = { + { uefivarinfo_test1, "UEFI varaiable info query." }, + { NULL, NULL } +}; + +static fwts_framework_ops uefivarinfo_ops = { + .description = "UEFI varaiable info query.", + .init = uefivarinfo_init, + .deinit = uefivarinfo_deinit, + .minor_tests = uefivarinfo_tests +}; + +FWTS_REGISTER("uefivarinfo", &uefivarinfo_ops, FWTS_TEST_ANYTIME, FWTS_FLAG_UTILS | FWTS_FLAG_ROOT_PRIV);
This utility get information by the uefi runtime service QueryVariableInfo and GetVariable which provides the below infomations: 1. Maximum variable storage size 2. Remaining variable storage size 3. Maximum variable size 4. The variable number gets from the the memory location EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD attribute and used size. Signed-off-by: Ivan Hu <ivan.hu@canonical.com> --- src/Makefile.am | 3 +- src/uefi/uefivarinfo/uefivarinfo.c | 223 ++++++++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 src/uefi/uefivarinfo/uefivarinfo.c