diff mbox

efi: enable module loading to load legacy or new efi driver

Message ID 1468428381-30363-1-git-send-email-colin.king@canonical.com
State Accepted
Headers show

Commit Message

Colin Ian King July 13, 2016, 4:46 p.m. UTC
From: Colin Ian King <colin.king@canonical.com>

The name of the efi module and the device is going to change once
the driver lands upstream in the kernel.  So make the module loading
more flexible to cater for legacy and the new upstream'd kernel driver.

Also abstract out the efi test device driver name and provide a thin
open/close device abstraction layer so we can keep the device name
out of the tests.

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 src/lib/include/fwts_efi_module.h        |   2 +
 src/lib/src/fwts_efi_module.c            | 202 ++++++++++++++++++++++++-------
 src/uefi/uefirtauthvar/uefirtauthvar.c   |   6 +-
 src/uefi/uefirtmisc/uefirtmisc.c         |   6 +-
 src/uefi/uefirttime/uefirttime.c         |   6 +-
 src/uefi/uefirtvariable/uefirtvariable.c |   6 +-
 src/uefi/uefivarinfo/uefivarinfo.c       |   6 +-
 7 files changed, 176 insertions(+), 58 deletions(-)

Comments

Alex Hung July 14, 2016, 7:24 a.m. UTC | #1
On 2016-07-14 12:46 AM, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> The name of the efi module and the device is going to change once
> the driver lands upstream in the kernel.  So make the module loading
> more flexible to cater for legacy and the new upstream'd kernel driver.
>
> Also abstract out the efi test device driver name and provide a thin
> open/close device abstraction layer so we can keep the device name
> out of the tests.
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
>   src/lib/include/fwts_efi_module.h        |   2 +
>   src/lib/src/fwts_efi_module.c            | 202 ++++++++++++++++++++++++-------
>   src/uefi/uefirtauthvar/uefirtauthvar.c   |   6 +-
>   src/uefi/uefirtmisc/uefirtmisc.c         |   6 +-
>   src/uefi/uefirttime/uefirttime.c         |   6 +-
>   src/uefi/uefirtvariable/uefirtvariable.c |   6 +-
>   src/uefi/uefivarinfo/uefivarinfo.c       |   6 +-
>   7 files changed, 176 insertions(+), 58 deletions(-)
>
> diff --git a/src/lib/include/fwts_efi_module.h b/src/lib/include/fwts_efi_module.h
> index ec8eceb..73c4ba6 100644
> --- a/src/lib/include/fwts_efi_module.h
> +++ b/src/lib/include/fwts_efi_module.h
> @@ -22,5 +22,7 @@
>
>   int fwts_lib_efi_runtime_load_module(fwts_framework *fw);
>   int fwts_lib_efi_runtime_unload_module(fwts_framework *fw);
> +int fwts_lib_efi_runtime_open(void);
> +int fwts_lib_efi_runtime_close(int fd);
>
>   #endif
> diff --git a/src/lib/src/fwts_efi_module.c b/src/lib/src/fwts_efi_module.c
> index b3e0bdb..f95ee63 100644
> --- a/src/lib/src/fwts_efi_module.c
> +++ b/src/lib/src/fwts_efi_module.c
> @@ -21,90 +21,206 @@
>   #include <string.h>
>   #include <sys/types.h>
>   #include <sys/stat.h>
> +#include <fcntl.h>
>   #include <unistd.h>
>
>   #include "fwts_pipeio.h"
>
> -static bool module_already_loaded = false;
> +static char *efi_dev_name = NULL;
> +static char *module_name = NULL;
>
> -static int check_module_loaded(void)
> +/*
> + *  check_module_loaded()
> + *	check if a given module is loaded
> + */
> +static int check_module_loaded(
> +	fwts_framework *fw,
> +	char *module,
> +	bool *loaded)
>   {
>   	FILE *fp;
>
> -	module_already_loaded = false;
> +	*loaded = false;
> +
>   	if ((fp = fopen("/proc/modules", "r")) != NULL) {
>   		char buffer[1024];
>
>   		while (fgets(buffer, sizeof(buffer), fp) != NULL) {
> -			if (strstr(buffer, "efi_runtime") != NULL) {
> -				module_already_loaded = true;
> +			if (strstr(buffer, module)) {
> +				*loaded = true;
>   				break;
>   			}
>   		}
>   		fclose(fp);
>   		return FWTS_OK;
>   	}
> +	fwts_log_error(fw, "Could not open /proc/modules to check if efi module '%s' is loaded.", module);
> +
>   	return FWTS_ERROR;
>   }
>
> -int fwts_lib_efi_runtime_load_module(fwts_framework *fw)
> +/*
> + *  check_module_loaded_no_dev()
> + *	sanity check - we don't have a device so we definitely should
> + *	not have the module loaded either
> + */
> +static int check_module_loaded_no_dev(
> +	fwts_framework *fw,
> +	char *module)
>   {
> -	struct stat statbuf;
> +	bool loaded;
>
> -	if (check_module_loaded() != FWTS_OK) {
> -		fwts_log_error(fw, "Could not open /proc/modules for checking module loaded.");
> +	if (check_module_loaded(fw, module, &loaded) != FWTS_OK)
> +		return FWTS_ERROR;
> +	if (loaded) {
> +		fwts_log_error(fw, "Module '%s' is already loaded, but device not available.", module);
>   		return FWTS_ERROR;
>   	}
> +	return FWTS_OK;
> +}
>
> -	if (!module_already_loaded) {
> -		int status;
> -
> -		if (fwts_exec("modprobe efi_runtime", &status) != FWTS_OK) {
> -			fwts_log_error(fw, "Load efi_runtime module error.");
> -			return FWTS_ERROR;
> -		} else {
> -			(void)check_module_loaded();
> -			if (!module_already_loaded) {
> -				fwts_log_error(fw, "Could not load efi_runtime module.");
> -				return FWTS_ERROR;
> -			}
> -		}
> -	}
> +/*
> + *  check_device()
> + *	check if the device exists and is a char dev
> + */
> +static int check_device(char *devname)
> +{
> +	struct stat statbuf;
>
> -	if (stat("/dev/efi_runtime", &statbuf)) {
> -		fwts_log_error(fw, "Loaded efi_runtime module but /dev/efi_runtime is not present.");
> +	if (stat(devname, &statbuf))
>   		return FWTS_ERROR;
> +
> +	if (S_ISCHR(statbuf.st_mode)) {
> +		efi_dev_name = devname;
> +		return FWTS_OK;
>   	}
> +	return FWTS_ERROR;
> +}
> +
> +/*
> + *  load_module()
> + *	load the module and check if the device appears
> + */
> +static int load_module(
> +	fwts_framework *fw,
> +	char *module,
> +	char *devname)
> +{
> +	int status;
> +	char cmd[80];
> +	bool loaded;
> +
> +	snprintf(cmd, sizeof(cmd), "modprobe %s", module);
>
> -	if (!S_ISCHR(statbuf.st_mode)) {
> -		fwts_log_error(fw, "Loaded efi_runtime module but /dev/efi_runtime is not a char device.");
> +	if (fwts_exec(cmd, &status) != FWTS_OK)
> +		return FWTS_ERROR;
> +
> +	if (check_module_loaded(fw, module, &loaded) != FWTS_OK)
>   		return FWTS_ERROR;
> -	}
> +
> +	if (!loaded)
> +		return FWTS_ERROR;
> +
> +	if (check_device(devname) != FWTS_OK)
> +		return FWTS_ERROR;
> +
> +	module_name = module;
>
>   	return FWTS_OK;
>   }
>
> +/*
> + *  fwts_lib_efi_runtime_load_module()
> + *	load the runtime module, for historical reasons
> + *	we have two names for the module and the device
> + *	it creates
> + */
> +int fwts_lib_efi_runtime_load_module(fwts_framework *fw)
> +{
> +	efi_dev_name = NULL;
> +	module_name = NULL;
> +
> +	/* Check if dev is already available */
> +	if (check_device("/dev/efi_test") == FWTS_OK)
> +		return FWTS_OK;
> +	if (check_device("/dev/efi_runtime") == FWTS_OK)
> +		return FWTS_OK;
> +
> +	/* Since the devices can't be found, the module should be not loaded */
> +	if (check_module_loaded_no_dev(fw, "efi_test") != FWTS_OK)
> +		return FWTS_ERROR;
> +	if (check_module_loaded_no_dev(fw, "efi_runtime") != FWTS_OK)
> +		return FWTS_ERROR;
> +
> +	/* Now try to load the module */
> +
> +	if (load_module(fw, "efi_test", "/dev/efi_test") == FWTS_OK)
> +		return FWTS_OK;
> +	if (load_module(fw, "efi_runtime", "/dev/efi_runtime") == FWTS_OK)
> +		return FWTS_OK;
> +
> +	fwts_log_error(fw, "Failed to load efi test module.");
> +	return FWTS_ERROR;
> +}
>
> +/*
> + *  fwts_lib_efi_runtime_unload_module()
> + *	unload the runtile module
> + */
>   int fwts_lib_efi_runtime_unload_module(fwts_framework *fw)
>   {
> -	if (check_module_loaded() != FWTS_OK) {
> -		fwts_log_error(fw, "Could not open /proc/modules for checking module loaded.");
> +	bool loaded;
> +	int status;
> +	char cmd[80], *tmp_name = module_name;
> +
> +	efi_dev_name = NULL;
> +
> +	/* No module, not much to do */
> +	if (!module_name)
> +		return FWTS_OK;
> +
> +	module_name = NULL;
> +
> +	/* If it is not loaded, no need to unload it */
> +	if (check_module_loaded(fw, tmp_name, &loaded) != FWTS_OK)
> +		return FWTS_ERROR;
> +	if (!loaded)
> +		return FWTS_OK;
> +
> +	snprintf(cmd, sizeof(cmd), "modprobe -r %s", tmp_name);
> +	if (fwts_exec(cmd, &status) != FWTS_OK) {
> +		fwts_log_error(fw, "Failed to unload module '%s'.", tmp_name);
>   		return FWTS_ERROR;
>   	}
> -	if (module_already_loaded) {
> -		int status;
> -
> -		if (fwts_exec("modprobe -r efi_runtime", &status) != FWTS_OK) {
> -			fwts_log_error(fw, "Unload efi_runtime module error.");
> -			return FWTS_ERROR;
> -		} else {
> -			(void)check_module_loaded();
> -			if (module_already_loaded) {
> -				fwts_log_error(fw, "Could not unload efi_runtime module.");
> -				return FWTS_ERROR;
> -			}
> -		}
> +
> +	/* Module should not be loaded at this point */
> +	if (check_module_loaded(fw, tmp_name, &loaded) != FWTS_OK)
> +		return FWTS_ERROR;
> +	if (loaded) {
> +		fwts_log_error(fw, "Failed to unload module '%s'.", tmp_name);
> +		return FWTS_ERROR;
>   	}
>
>   	return FWTS_OK;
>   }
> +
> +/*
> + *  fwts_lib_efi_runtime_open()
> + *	open the device
> + */
> +int fwts_lib_efi_runtime_open(void)
> +{
> +	if (!efi_dev_name)
> +		return -1;
> +
> +	return open(efi_dev_name, O_WRONLY | O_RDWR);
> +}
> +
> +/*
> + *  fwts_lib_efi_runtime_close()
> + *	close the device
> + */
> +int fwts_lib_efi_runtime_close(int fd)
> +{
> +	return close(fd);
> +}
> diff --git a/src/uefi/uefirtauthvar/uefirtauthvar.c b/src/uefi/uefirtauthvar/uefirtauthvar.c
> index ed23a8e..cdfd7aa 100644
> --- a/src/uefi/uefirtauthvar/uefirtauthvar.c
> +++ b/src/uefi/uefirtauthvar/uefirtauthvar.c
> @@ -123,9 +123,9 @@ static int uefirtauthvar_init(fwts_framework *fw)
>   		return FWTS_ABORTED;
>   	}
>
> -	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
> +	fd = fwts_lib_efi_runtime_open();
>   	if (fd == -1) {
> -		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
> +		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
>   		return FWTS_ABORTED;
>   	}
>
> @@ -136,7 +136,7 @@ static int uefirtauthvar_init(fwts_framework *fw)
>
>   static int uefirtauthvar_deinit(fwts_framework *fw)
>   {
> -	close(fd);
> +	fwts_lib_efi_runtime_close(fd);
>   	fwts_lib_efi_runtime_unload_module(fw);
>
>   	return FWTS_OK;
> diff --git a/src/uefi/uefirtmisc/uefirtmisc.c b/src/uefi/uefirtmisc/uefirtmisc.c
> index 347b2b1..d06e2a1 100644
> --- a/src/uefi/uefirtmisc/uefirtmisc.c
> +++ b/src/uefi/uefirtmisc/uefirtmisc.c
> @@ -55,9 +55,9 @@ static int uefirtmisc_init(fwts_framework *fw)
>   		return FWTS_ABORTED;
>   	}
>
> -	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
> +	fd = fwts_lib_efi_runtime_open();
>   	if (fd == -1) {
> -		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
> +		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
>   		return FWTS_ABORTED;
>   	}
>
> @@ -68,7 +68,7 @@ static int uefirtmisc_deinit(fwts_framework *fw)
>   {
>   	FWTS_UNUSED(fw);
>
> -	close(fd);
> +	fwts_lib_efi_runtime_close(fd);
>   	fwts_lib_efi_runtime_unload_module(fw);
>
>   	return FWTS_OK;
> diff --git a/src/uefi/uefirttime/uefirttime.c b/src/uefi/uefirttime/uefirttime.c
> index f79e2da..55e9d19 100644
> --- a/src/uefi/uefirttime/uefirttime.c
> +++ b/src/uefi/uefirttime/uefirttime.c
> @@ -179,9 +179,9 @@ static int uefirttime_init(fwts_framework *fw)
>   		return FWTS_ABORTED;
>   	}
>
> -	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
> +	fd = fwts_lib_efi_runtime_open();
>   	if (fd == -1) {
> -		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
> +		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
>   		return FWTS_ABORTED;
>   	}
>
> @@ -192,7 +192,7 @@ static int uefirttime_deinit(fwts_framework *fw)
>   {
>   	FWTS_UNUSED(fw);
>
> -	close(fd);
> +	fwts_lib_efi_runtime_close(fd);
>   	fwts_lib_efi_runtime_unload_module(fw);
>
>   	return FWTS_OK;
> diff --git a/src/uefi/uefirtvariable/uefirtvariable.c b/src/uefi/uefirtvariable/uefirtvariable.c
> index f60dbad..2adc064 100644
> --- a/src/uefi/uefirtvariable/uefirtvariable.c
> +++ b/src/uefi/uefirtvariable/uefirtvariable.c
> @@ -101,9 +101,9 @@ static int uefirtvariable_init(fwts_framework *fw)
>   		return FWTS_ABORTED;
>   	}
>
> -	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
> +	fd = fwts_lib_efi_runtime_open();
>   	if (fd == -1) {
> -		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
> +		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
>   		return FWTS_ABORTED;
>   	}
>
> @@ -114,7 +114,7 @@ static int uefirtvariable_init(fwts_framework *fw)
>
>   static int uefirtvariable_deinit(fwts_framework *fw)
>   {
> -	close(fd);
> +	fwts_lib_efi_runtime_close(fd);
>   	fwts_lib_efi_runtime_unload_module(fw);
>
>   	return FWTS_OK;
> diff --git a/src/uefi/uefivarinfo/uefivarinfo.c b/src/uefi/uefivarinfo/uefivarinfo.c
> index 22afe53..24798a9 100644
> --- a/src/uefi/uefivarinfo/uefivarinfo.c
> +++ b/src/uefi/uefivarinfo/uefivarinfo.c
> @@ -46,9 +46,9 @@ static int uefivarinfo_init(fwts_framework *fw)
>   		return FWTS_ABORTED;
>   	}
>
> -	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
> +	fd = fwts_lib_efi_runtime_open();
>   	if (fd == -1) {
> -		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
> +		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
>   		return FWTS_ABORTED;
>   	}
>
> @@ -57,7 +57,7 @@ static int uefivarinfo_init(fwts_framework *fw)
>
>   static int uefivarinfo_deinit(fwts_framework *fw)
>   {
> -	close(fd);
> +	fwts_lib_efi_runtime_close(fd);
>   	fwts_lib_efi_runtime_unload_module(fw);
>
>   	return FWTS_OK;
>

Acked-by: Alex Hung <alex.hung@canonical.com>
Ivan Hu July 25, 2016, 5:46 a.m. UTC | #2
On 2016年07月14日 00:46, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> The name of the efi module and the device is going to change once
> the driver lands upstream in the kernel.  So make the module loading
> more flexible to cater for legacy and the new upstream'd kernel driver.
>
> Also abstract out the efi test device driver name and provide a thin
> open/close device abstraction layer so we can keep the device name
> out of the tests.
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
>  src/lib/include/fwts_efi_module.h        |   2 +
>  src/lib/src/fwts_efi_module.c            | 202 ++++++++++++++++++++++++-------
>  src/uefi/uefirtauthvar/uefirtauthvar.c   |   6 +-
>  src/uefi/uefirtmisc/uefirtmisc.c         |   6 +-
>  src/uefi/uefirttime/uefirttime.c         |   6 +-
>  src/uefi/uefirtvariable/uefirtvariable.c |   6 +-
>  src/uefi/uefivarinfo/uefivarinfo.c       |   6 +-
>  7 files changed, 176 insertions(+), 58 deletions(-)
>
> diff --git a/src/lib/include/fwts_efi_module.h b/src/lib/include/fwts_efi_module.h
> index ec8eceb..73c4ba6 100644
> --- a/src/lib/include/fwts_efi_module.h
> +++ b/src/lib/include/fwts_efi_module.h
> @@ -22,5 +22,7 @@
>
>  int fwts_lib_efi_runtime_load_module(fwts_framework *fw);
>  int fwts_lib_efi_runtime_unload_module(fwts_framework *fw);
> +int fwts_lib_efi_runtime_open(void);
> +int fwts_lib_efi_runtime_close(int fd);
>
>  #endif
> diff --git a/src/lib/src/fwts_efi_module.c b/src/lib/src/fwts_efi_module.c
> index b3e0bdb..f95ee63 100644
> --- a/src/lib/src/fwts_efi_module.c
> +++ b/src/lib/src/fwts_efi_module.c
> @@ -21,90 +21,206 @@
>  #include <string.h>
>  #include <sys/types.h>
>  #include <sys/stat.h>
> +#include <fcntl.h>
>  #include <unistd.h>
>
>  #include "fwts_pipeio.h"
>
> -static bool module_already_loaded = false;
> +static char *efi_dev_name = NULL;
> +static char *module_name = NULL;
>
> -static int check_module_loaded(void)
> +/*
> + *  check_module_loaded()
> + *	check if a given module is loaded
> + */
> +static int check_module_loaded(
> +	fwts_framework *fw,
> +	char *module,
> +	bool *loaded)
>  {
>  	FILE *fp;
>
> -	module_already_loaded = false;
> +	*loaded = false;
> +
>  	if ((fp = fopen("/proc/modules", "r")) != NULL) {
>  		char buffer[1024];
>
>  		while (fgets(buffer, sizeof(buffer), fp) != NULL) {
> -			if (strstr(buffer, "efi_runtime") != NULL) {
> -				module_already_loaded = true;
> +			if (strstr(buffer, module)) {
> +				*loaded = true;
>  				break;
>  			}
>  		}
>  		fclose(fp);
>  		return FWTS_OK;
>  	}
> +	fwts_log_error(fw, "Could not open /proc/modules to check if efi module '%s' is loaded.", module);
> +
>  	return FWTS_ERROR;
>  }
>
> -int fwts_lib_efi_runtime_load_module(fwts_framework *fw)
> +/*
> + *  check_module_loaded_no_dev()
> + *	sanity check - we don't have a device so we definitely should
> + *	not have the module loaded either
> + */
> +static int check_module_loaded_no_dev(
> +	fwts_framework *fw,
> +	char *module)
>  {
> -	struct stat statbuf;
> +	bool loaded;
>
> -	if (check_module_loaded() != FWTS_OK) {
> -		fwts_log_error(fw, "Could not open /proc/modules for checking module loaded.");
> +	if (check_module_loaded(fw, module, &loaded) != FWTS_OK)
> +		return FWTS_ERROR;
> +	if (loaded) {
> +		fwts_log_error(fw, "Module '%s' is already loaded, but device not available.", module);
>  		return FWTS_ERROR;
>  	}
> +	return FWTS_OK;
> +}
>
> -	if (!module_already_loaded) {
> -		int status;
> -
> -		if (fwts_exec("modprobe efi_runtime", &status) != FWTS_OK) {
> -			fwts_log_error(fw, "Load efi_runtime module error.");
> -			return FWTS_ERROR;
> -		} else {
> -			(void)check_module_loaded();
> -			if (!module_already_loaded) {
> -				fwts_log_error(fw, "Could not load efi_runtime module.");
> -				return FWTS_ERROR;
> -			}
> -		}
> -	}
> +/*
> + *  check_device()
> + *	check if the device exists and is a char dev
> + */
> +static int check_device(char *devname)
> +{
> +	struct stat statbuf;
>
> -	if (stat("/dev/efi_runtime", &statbuf)) {
> -		fwts_log_error(fw, "Loaded efi_runtime module but /dev/efi_runtime is not present.");
> +	if (stat(devname, &statbuf))
>  		return FWTS_ERROR;
> +
> +	if (S_ISCHR(statbuf.st_mode)) {
> +		efi_dev_name = devname;
> +		return FWTS_OK;
>  	}
> +	return FWTS_ERROR;
> +}
> +
> +/*
> + *  load_module()
> + *	load the module and check if the device appears
> + */
> +static int load_module(
> +	fwts_framework *fw,
> +	char *module,
> +	char *devname)
> +{
> +	int status;
> +	char cmd[80];
> +	bool loaded;
> +
> +	snprintf(cmd, sizeof(cmd), "modprobe %s", module);
>
> -	if (!S_ISCHR(statbuf.st_mode)) {
> -		fwts_log_error(fw, "Loaded efi_runtime module but /dev/efi_runtime is not a char device.");
> +	if (fwts_exec(cmd, &status) != FWTS_OK)
> +		return FWTS_ERROR;
> +
> +	if (check_module_loaded(fw, module, &loaded) != FWTS_OK)
>  		return FWTS_ERROR;
> -	}
> +
> +	if (!loaded)
> +		return FWTS_ERROR;
> +
> +	if (check_device(devname) != FWTS_OK)
> +		return FWTS_ERROR;
> +
> +	module_name = module;
>
>  	return FWTS_OK;
>  }
>
> +/*
> + *  fwts_lib_efi_runtime_load_module()
> + *	load the runtime module, for historical reasons
> + *	we have two names for the module and the device
> + *	it creates
> + */
> +int fwts_lib_efi_runtime_load_module(fwts_framework *fw)
> +{
> +	efi_dev_name = NULL;
> +	module_name = NULL;
> +
> +	/* Check if dev is already available */
> +	if (check_device("/dev/efi_test") == FWTS_OK)
> +		return FWTS_OK;
> +	if (check_device("/dev/efi_runtime") == FWTS_OK)
> +		return FWTS_OK;
> +
> +	/* Since the devices can't be found, the module should be not loaded */
> +	if (check_module_loaded_no_dev(fw, "efi_test") != FWTS_OK)
> +		return FWTS_ERROR;
> +	if (check_module_loaded_no_dev(fw, "efi_runtime") != FWTS_OK)
> +		return FWTS_ERROR;
> +
> +	/* Now try to load the module */
> +
> +	if (load_module(fw, "efi_test", "/dev/efi_test") == FWTS_OK)
> +		return FWTS_OK;
> +	if (load_module(fw, "efi_runtime", "/dev/efi_runtime") == FWTS_OK)
> +		return FWTS_OK;
> +
> +	fwts_log_error(fw, "Failed to load efi test module.");
> +	return FWTS_ERROR;
> +}
>
> +/*
> + *  fwts_lib_efi_runtime_unload_module()
> + *	unload the runtile module
> + */
>  int fwts_lib_efi_runtime_unload_module(fwts_framework *fw)
>  {
> -	if (check_module_loaded() != FWTS_OK) {
> -		fwts_log_error(fw, "Could not open /proc/modules for checking module loaded.");
> +	bool loaded;
> +	int status;
> +	char cmd[80], *tmp_name = module_name;
> +
> +	efi_dev_name = NULL;
> +
> +	/* No module, not much to do */
> +	if (!module_name)
> +		return FWTS_OK;
> +
> +	module_name = NULL;
> +
> +	/* If it is not loaded, no need to unload it */
> +	if (check_module_loaded(fw, tmp_name, &loaded) != FWTS_OK)
> +		return FWTS_ERROR;
> +	if (!loaded)
> +		return FWTS_OK;
> +
> +	snprintf(cmd, sizeof(cmd), "modprobe -r %s", tmp_name);
> +	if (fwts_exec(cmd, &status) != FWTS_OK) {
> +		fwts_log_error(fw, "Failed to unload module '%s'.", tmp_name);
>  		return FWTS_ERROR;
>  	}
> -	if (module_already_loaded) {
> -		int status;
> -
> -		if (fwts_exec("modprobe -r efi_runtime", &status) != FWTS_OK) {
> -			fwts_log_error(fw, "Unload efi_runtime module error.");
> -			return FWTS_ERROR;
> -		} else {
> -			(void)check_module_loaded();
> -			if (module_already_loaded) {
> -				fwts_log_error(fw, "Could not unload efi_runtime module.");
> -				return FWTS_ERROR;
> -			}
> -		}
> +
> +	/* Module should not be loaded at this point */
> +	if (check_module_loaded(fw, tmp_name, &loaded) != FWTS_OK)
> +		return FWTS_ERROR;
> +	if (loaded) {
> +		fwts_log_error(fw, "Failed to unload module '%s'.", tmp_name);
> +		return FWTS_ERROR;
>  	}
>
>  	return FWTS_OK;
>  }
> +
> +/*
> + *  fwts_lib_efi_runtime_open()
> + *	open the device
> + */
> +int fwts_lib_efi_runtime_open(void)
> +{
> +	if (!efi_dev_name)
> +		return -1;
> +
> +	return open(efi_dev_name, O_WRONLY | O_RDWR);
> +}
> +
> +/*
> + *  fwts_lib_efi_runtime_close()
> + *	close the device
> + */
> +int fwts_lib_efi_runtime_close(int fd)
> +{
> +	return close(fd);
> +}
> diff --git a/src/uefi/uefirtauthvar/uefirtauthvar.c b/src/uefi/uefirtauthvar/uefirtauthvar.c
> index ed23a8e..cdfd7aa 100644
> --- a/src/uefi/uefirtauthvar/uefirtauthvar.c
> +++ b/src/uefi/uefirtauthvar/uefirtauthvar.c
> @@ -123,9 +123,9 @@ static int uefirtauthvar_init(fwts_framework *fw)
>  		return FWTS_ABORTED;
>  	}
>
> -	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
> +	fd = fwts_lib_efi_runtime_open();
>  	if (fd == -1) {
> -		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
> +		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
>  		return FWTS_ABORTED;
>  	}
>
> @@ -136,7 +136,7 @@ static int uefirtauthvar_init(fwts_framework *fw)
>
>  static int uefirtauthvar_deinit(fwts_framework *fw)
>  {
> -	close(fd);
> +	fwts_lib_efi_runtime_close(fd);
>  	fwts_lib_efi_runtime_unload_module(fw);
>
>  	return FWTS_OK;
> diff --git a/src/uefi/uefirtmisc/uefirtmisc.c b/src/uefi/uefirtmisc/uefirtmisc.c
> index 347b2b1..d06e2a1 100644
> --- a/src/uefi/uefirtmisc/uefirtmisc.c
> +++ b/src/uefi/uefirtmisc/uefirtmisc.c
> @@ -55,9 +55,9 @@ static int uefirtmisc_init(fwts_framework *fw)
>  		return FWTS_ABORTED;
>  	}
>
> -	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
> +	fd = fwts_lib_efi_runtime_open();
>  	if (fd == -1) {
> -		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
> +		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
>  		return FWTS_ABORTED;
>  	}
>
> @@ -68,7 +68,7 @@ static int uefirtmisc_deinit(fwts_framework *fw)
>  {
>  	FWTS_UNUSED(fw);
>
> -	close(fd);
> +	fwts_lib_efi_runtime_close(fd);
>  	fwts_lib_efi_runtime_unload_module(fw);
>
>  	return FWTS_OK;
> diff --git a/src/uefi/uefirttime/uefirttime.c b/src/uefi/uefirttime/uefirttime.c
> index f79e2da..55e9d19 100644
> --- a/src/uefi/uefirttime/uefirttime.c
> +++ b/src/uefi/uefirttime/uefirttime.c
> @@ -179,9 +179,9 @@ static int uefirttime_init(fwts_framework *fw)
>  		return FWTS_ABORTED;
>  	}
>
> -	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
> +	fd = fwts_lib_efi_runtime_open();
>  	if (fd == -1) {
> -		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
> +		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
>  		return FWTS_ABORTED;
>  	}
>
> @@ -192,7 +192,7 @@ static int uefirttime_deinit(fwts_framework *fw)
>  {
>  	FWTS_UNUSED(fw);
>
> -	close(fd);
> +	fwts_lib_efi_runtime_close(fd);
>  	fwts_lib_efi_runtime_unload_module(fw);
>
>  	return FWTS_OK;
> diff --git a/src/uefi/uefirtvariable/uefirtvariable.c b/src/uefi/uefirtvariable/uefirtvariable.c
> index f60dbad..2adc064 100644
> --- a/src/uefi/uefirtvariable/uefirtvariable.c
> +++ b/src/uefi/uefirtvariable/uefirtvariable.c
> @@ -101,9 +101,9 @@ static int uefirtvariable_init(fwts_framework *fw)
>  		return FWTS_ABORTED;
>  	}
>
> -	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
> +	fd = fwts_lib_efi_runtime_open();
>  	if (fd == -1) {
> -		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
> +		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
>  		return FWTS_ABORTED;
>  	}
>
> @@ -114,7 +114,7 @@ static int uefirtvariable_init(fwts_framework *fw)
>
>  static int uefirtvariable_deinit(fwts_framework *fw)
>  {
> -	close(fd);
> +	fwts_lib_efi_runtime_close(fd);
>  	fwts_lib_efi_runtime_unload_module(fw);
>
>  	return FWTS_OK;
> diff --git a/src/uefi/uefivarinfo/uefivarinfo.c b/src/uefi/uefivarinfo/uefivarinfo.c
> index 22afe53..24798a9 100644
> --- a/src/uefi/uefivarinfo/uefivarinfo.c
> +++ b/src/uefi/uefivarinfo/uefivarinfo.c
> @@ -46,9 +46,9 @@ static int uefivarinfo_init(fwts_framework *fw)
>  		return FWTS_ABORTED;
>  	}
>
> -	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
> +	fd = fwts_lib_efi_runtime_open();
>  	if (fd == -1) {
> -		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
> +		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
>  		return FWTS_ABORTED;
>  	}
>
> @@ -57,7 +57,7 @@ static int uefivarinfo_init(fwts_framework *fw)
>
>  static int uefivarinfo_deinit(fwts_framework *fw)
>  {
> -	close(fd);
> +	fwts_lib_efi_runtime_close(fd);
>  	fwts_lib_efi_runtime_unload_module(fw);
>
>  	return FWTS_OK;
>

Build and test with efi_test driver and efi_runtime driver, both work fine.
Thanks Colin.

Acked-by: Ivan Hu <ivan.hu@canonical.com>
diff mbox

Patch

diff --git a/src/lib/include/fwts_efi_module.h b/src/lib/include/fwts_efi_module.h
index ec8eceb..73c4ba6 100644
--- a/src/lib/include/fwts_efi_module.h
+++ b/src/lib/include/fwts_efi_module.h
@@ -22,5 +22,7 @@ 
 
 int fwts_lib_efi_runtime_load_module(fwts_framework *fw);
 int fwts_lib_efi_runtime_unload_module(fwts_framework *fw);
+int fwts_lib_efi_runtime_open(void);
+int fwts_lib_efi_runtime_close(int fd);
 
 #endif
diff --git a/src/lib/src/fwts_efi_module.c b/src/lib/src/fwts_efi_module.c
index b3e0bdb..f95ee63 100644
--- a/src/lib/src/fwts_efi_module.c
+++ b/src/lib/src/fwts_efi_module.c
@@ -21,90 +21,206 @@ 
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <fcntl.h>
 #include <unistd.h>
 
 #include "fwts_pipeio.h"
 
-static bool module_already_loaded = false;
+static char *efi_dev_name = NULL;
+static char *module_name = NULL;
 
-static int check_module_loaded(void)
+/*
+ *  check_module_loaded()
+ *	check if a given module is loaded
+ */
+static int check_module_loaded(
+	fwts_framework *fw,
+	char *module,
+	bool *loaded)
 {
 	FILE *fp;
 
-	module_already_loaded = false;
+	*loaded = false;
+
 	if ((fp = fopen("/proc/modules", "r")) != NULL) {
 		char buffer[1024];
 
 		while (fgets(buffer, sizeof(buffer), fp) != NULL) {
-			if (strstr(buffer, "efi_runtime") != NULL) {
-				module_already_loaded = true;
+			if (strstr(buffer, module)) {
+				*loaded = true;
 				break;
 			}
 		}
 		fclose(fp);
 		return FWTS_OK;
 	}
+	fwts_log_error(fw, "Could not open /proc/modules to check if efi module '%s' is loaded.", module);
+
 	return FWTS_ERROR;
 }
 
-int fwts_lib_efi_runtime_load_module(fwts_framework *fw)
+/*
+ *  check_module_loaded_no_dev()
+ *	sanity check - we don't have a device so we definitely should
+ *	not have the module loaded either
+ */
+static int check_module_loaded_no_dev(
+	fwts_framework *fw,
+	char *module)
 {
-	struct stat statbuf;
+	bool loaded;
 
-	if (check_module_loaded() != FWTS_OK) {
-		fwts_log_error(fw, "Could not open /proc/modules for checking module loaded.");
+	if (check_module_loaded(fw, module, &loaded) != FWTS_OK)
+		return FWTS_ERROR;
+	if (loaded) {
+		fwts_log_error(fw, "Module '%s' is already loaded, but device not available.", module);
 		return FWTS_ERROR;
 	}
+	return FWTS_OK;
+}
 
-	if (!module_already_loaded) {
-		int status;
-
-		if (fwts_exec("modprobe efi_runtime", &status) != FWTS_OK) {
-			fwts_log_error(fw, "Load efi_runtime module error.");
-			return FWTS_ERROR;
-		} else {
-			(void)check_module_loaded();
-			if (!module_already_loaded) {
-				fwts_log_error(fw, "Could not load efi_runtime module.");
-				return FWTS_ERROR;
-			}
-		}
-	}
+/*
+ *  check_device()
+ *	check if the device exists and is a char dev
+ */
+static int check_device(char *devname)
+{
+	struct stat statbuf;
 
-	if (stat("/dev/efi_runtime", &statbuf)) {
-		fwts_log_error(fw, "Loaded efi_runtime module but /dev/efi_runtime is not present.");
+	if (stat(devname, &statbuf))
 		return FWTS_ERROR;
+
+	if (S_ISCHR(statbuf.st_mode)) {
+		efi_dev_name = devname;
+		return FWTS_OK;
 	}
+	return FWTS_ERROR;
+}
+
+/*
+ *  load_module()
+ *	load the module and check if the device appears
+ */
+static int load_module(
+	fwts_framework *fw,
+	char *module,
+	char *devname)
+{
+	int status;
+	char cmd[80];
+	bool loaded;
+
+	snprintf(cmd, sizeof(cmd), "modprobe %s", module);
 
-	if (!S_ISCHR(statbuf.st_mode)) {
-		fwts_log_error(fw, "Loaded efi_runtime module but /dev/efi_runtime is not a char device.");
+	if (fwts_exec(cmd, &status) != FWTS_OK)
+		return FWTS_ERROR;
+
+	if (check_module_loaded(fw, module, &loaded) != FWTS_OK)
 		return FWTS_ERROR;
-	}
+
+	if (!loaded)
+		return FWTS_ERROR;
+
+	if (check_device(devname) != FWTS_OK)
+		return FWTS_ERROR;
+
+	module_name = module;
 
 	return FWTS_OK;
 }
 
+/*
+ *  fwts_lib_efi_runtime_load_module()
+ *	load the runtime module, for historical reasons
+ *	we have two names for the module and the device
+ *	it creates
+ */
+int fwts_lib_efi_runtime_load_module(fwts_framework *fw)
+{
+	efi_dev_name = NULL;
+	module_name = NULL;
+
+	/* Check if dev is already available */
+	if (check_device("/dev/efi_test") == FWTS_OK)
+		return FWTS_OK;
+	if (check_device("/dev/efi_runtime") == FWTS_OK)
+		return FWTS_OK;
+
+	/* Since the devices can't be found, the module should be not loaded */
+	if (check_module_loaded_no_dev(fw, "efi_test") != FWTS_OK)
+		return FWTS_ERROR;
+	if (check_module_loaded_no_dev(fw, "efi_runtime") != FWTS_OK)
+		return FWTS_ERROR;
+
+	/* Now try to load the module */
+
+	if (load_module(fw, "efi_test", "/dev/efi_test") == FWTS_OK)
+		return FWTS_OK;
+	if (load_module(fw, "efi_runtime", "/dev/efi_runtime") == FWTS_OK)
+		return FWTS_OK;
+
+	fwts_log_error(fw, "Failed to load efi test module.");
+	return FWTS_ERROR;
+}
 
+/*
+ *  fwts_lib_efi_runtime_unload_module()
+ *	unload the runtile module
+ */
 int fwts_lib_efi_runtime_unload_module(fwts_framework *fw)
 {
-	if (check_module_loaded() != FWTS_OK) {
-		fwts_log_error(fw, "Could not open /proc/modules for checking module loaded.");
+	bool loaded;
+	int status;
+	char cmd[80], *tmp_name = module_name;
+
+	efi_dev_name = NULL;
+
+	/* No module, not much to do */
+	if (!module_name)
+		return FWTS_OK;
+
+	module_name = NULL;
+
+	/* If it is not loaded, no need to unload it */
+	if (check_module_loaded(fw, tmp_name, &loaded) != FWTS_OK)
+		return FWTS_ERROR;
+	if (!loaded)
+		return FWTS_OK;
+
+	snprintf(cmd, sizeof(cmd), "modprobe -r %s", tmp_name);
+	if (fwts_exec(cmd, &status) != FWTS_OK) {
+		fwts_log_error(fw, "Failed to unload module '%s'.", tmp_name);
 		return FWTS_ERROR;
 	}
-	if (module_already_loaded) {
-		int status;
-
-		if (fwts_exec("modprobe -r efi_runtime", &status) != FWTS_OK) {
-			fwts_log_error(fw, "Unload efi_runtime module error.");
-			return FWTS_ERROR;
-		} else {
-			(void)check_module_loaded();
-			if (module_already_loaded) {
-				fwts_log_error(fw, "Could not unload efi_runtime module.");
-				return FWTS_ERROR;
-			}
-		}
+
+	/* Module should not be loaded at this point */
+	if (check_module_loaded(fw, tmp_name, &loaded) != FWTS_OK)
+		return FWTS_ERROR;
+	if (loaded) {
+		fwts_log_error(fw, "Failed to unload module '%s'.", tmp_name);
+		return FWTS_ERROR;
 	}
 
 	return FWTS_OK;
 }
+
+/*
+ *  fwts_lib_efi_runtime_open()
+ *	open the device
+ */
+int fwts_lib_efi_runtime_open(void)
+{
+	if (!efi_dev_name)
+		return -1;
+
+	return open(efi_dev_name, O_WRONLY | O_RDWR);
+}
+
+/*
+ *  fwts_lib_efi_runtime_close()
+ *	close the device
+ */
+int fwts_lib_efi_runtime_close(int fd)
+{
+	return close(fd);
+}
diff --git a/src/uefi/uefirtauthvar/uefirtauthvar.c b/src/uefi/uefirtauthvar/uefirtauthvar.c
index ed23a8e..cdfd7aa 100644
--- a/src/uefi/uefirtauthvar/uefirtauthvar.c
+++ b/src/uefi/uefirtauthvar/uefirtauthvar.c
@@ -123,9 +123,9 @@  static int uefirtauthvar_init(fwts_framework *fw)
 		return FWTS_ABORTED;
 	}
 
-	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
+	fd = fwts_lib_efi_runtime_open();
 	if (fd == -1) {
-		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
+		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
 		return FWTS_ABORTED;
 	}
 
@@ -136,7 +136,7 @@  static int uefirtauthvar_init(fwts_framework *fw)
 
 static int uefirtauthvar_deinit(fwts_framework *fw)
 {
-	close(fd);
+	fwts_lib_efi_runtime_close(fd);
 	fwts_lib_efi_runtime_unload_module(fw);
 
 	return FWTS_OK;
diff --git a/src/uefi/uefirtmisc/uefirtmisc.c b/src/uefi/uefirtmisc/uefirtmisc.c
index 347b2b1..d06e2a1 100644
--- a/src/uefi/uefirtmisc/uefirtmisc.c
+++ b/src/uefi/uefirtmisc/uefirtmisc.c
@@ -55,9 +55,9 @@  static int uefirtmisc_init(fwts_framework *fw)
 		return FWTS_ABORTED;
 	}
 
-	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
+	fd = fwts_lib_efi_runtime_open();
 	if (fd == -1) {
-		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
+		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
 		return FWTS_ABORTED;
 	}
 
@@ -68,7 +68,7 @@  static int uefirtmisc_deinit(fwts_framework *fw)
 {
 	FWTS_UNUSED(fw);
 
-	close(fd);
+	fwts_lib_efi_runtime_close(fd);
 	fwts_lib_efi_runtime_unload_module(fw);
 
 	return FWTS_OK;
diff --git a/src/uefi/uefirttime/uefirttime.c b/src/uefi/uefirttime/uefirttime.c
index f79e2da..55e9d19 100644
--- a/src/uefi/uefirttime/uefirttime.c
+++ b/src/uefi/uefirttime/uefirttime.c
@@ -179,9 +179,9 @@  static int uefirttime_init(fwts_framework *fw)
 		return FWTS_ABORTED;
 	}
 
-	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
+	fd = fwts_lib_efi_runtime_open();
 	if (fd == -1) {
-		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
+		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
 		return FWTS_ABORTED;
 	}
 
@@ -192,7 +192,7 @@  static int uefirttime_deinit(fwts_framework *fw)
 {
 	FWTS_UNUSED(fw);
 
-	close(fd);
+	fwts_lib_efi_runtime_close(fd);
 	fwts_lib_efi_runtime_unload_module(fw);
 
 	return FWTS_OK;
diff --git a/src/uefi/uefirtvariable/uefirtvariable.c b/src/uefi/uefirtvariable/uefirtvariable.c
index f60dbad..2adc064 100644
--- a/src/uefi/uefirtvariable/uefirtvariable.c
+++ b/src/uefi/uefirtvariable/uefirtvariable.c
@@ -101,9 +101,9 @@  static int uefirtvariable_init(fwts_framework *fw)
 		return FWTS_ABORTED;
 	}
 
-	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
+	fd = fwts_lib_efi_runtime_open();
 	if (fd == -1) {
-		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
+		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
 		return FWTS_ABORTED;
 	}
 
@@ -114,7 +114,7 @@  static int uefirtvariable_init(fwts_framework *fw)
 
 static int uefirtvariable_deinit(fwts_framework *fw)
 {
-	close(fd);
+	fwts_lib_efi_runtime_close(fd);
 	fwts_lib_efi_runtime_unload_module(fw);
 
 	return FWTS_OK;
diff --git a/src/uefi/uefivarinfo/uefivarinfo.c b/src/uefi/uefivarinfo/uefivarinfo.c
index 22afe53..24798a9 100644
--- a/src/uefi/uefivarinfo/uefivarinfo.c
+++ b/src/uefi/uefivarinfo/uefivarinfo.c
@@ -46,9 +46,9 @@  static int uefivarinfo_init(fwts_framework *fw)
 		return FWTS_ABORTED;
 	}
 
-	fd = open("/dev/efi_runtime", O_WRONLY | O_RDWR);
+	fd = fwts_lib_efi_runtime_open();
 	if (fd == -1) {
-		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
+		fwts_log_info(fw, "Cannot open EFI test driver. Aborted.");
 		return FWTS_ABORTED;
 	}
 
@@ -57,7 +57,7 @@  static int uefivarinfo_init(fwts_framework *fw)
 
 static int uefivarinfo_deinit(fwts_framework *fw)
 {
-	close(fd);
+	fwts_lib_efi_runtime_close(fd);
 	fwts_lib_efi_runtime_unload_module(fw);
 
 	return FWTS_OK;