diff options
author | Thomas Heijligen <thomas.heijligen@secunet.com> | 2022-01-20 14:33:56 +0100 |
---|---|---|
committer | Nico Huber <nico.h@gmx.de> | 2022-03-12 16:46:39 +0000 |
commit | a2aa33e24c8ad7cf1e4ce9dffb1b35a69b34e610 (patch) | |
tree | 355a57c61469a233585d58613db0a14ad4692dca | |
parent | 6f63f20b33cec95cc05eaa574db4bd8fb65c3268 (diff) | |
download | flashrom-a2aa33e24c8ad7cf1e4ce9dffb1b35a69b34e610.tar.gz flashrom-a2aa33e24c8ad7cf1e4ce9dffb1b35a69b34e610.tar.bz2 flashrom-a2aa33e24c8ad7cf1e4ce9dffb1b35a69b34e610.zip |
hwaccess_x86_io: refactor rget_io_perms()
Abstract the different I/O Port permission methods in own functions.
Change-Id: If4b2f8c2532f3732086ee1d479da6ae6693f9a42
Signed-off-by: Thomas Heijligen <thomas.heijligen@secunet.com>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/61275
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
-rw-r--r-- | hwaccess_x86_io.c | 136 |
1 files changed, 92 insertions, 44 deletions
diff --git a/hwaccess_x86_io.c b/hwaccess_x86_io.c index 635b27ec..e891d98d 100644 --- a/hwaccess_x86_io.c +++ b/hwaccess_x86_io.c @@ -2,6 +2,8 @@ * This file is part of the flashrom project. * * Copyright (C) 2009,2010 Carl-Daniel Hailfinger + * Copyright (C) 2022 secunet Security Networks AG + * (Written by Thomas Heijligen <thomas.heijligen@secunet.com) * * 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 @@ -14,70 +16,116 @@ * GNU General Public License for more details. */ +/* + * This file implements x86 I/O port permission handling. + * + * For this purpose the platform specific code is encapsuled in two functions + * and compiled only on the respective platform. `platform_get_io_perms()` is + * called to get the permissions and `platform_release_io_perms()` is called for + * releasing those. + */ + #include <errno.h> #include <string.h> -#if !defined (__DJGPP__) && !defined(__LIBPAYLOAD__) -/* No file access needed/possible to get hardware access permissions. */ -#include <unistd.h> -#include <fcntl.h> -#endif -#include "hwaccess_x86_io.h" #include "flash.h" +#include "hwaccess_x86_io.h" -#if USE_IOPERM -#include <sys/io.h> -#endif +#if defined(__DJGPP__) || defined(__LIBPAYLOAD) /* DJGPP, libpayload */ +static int platform_get_io_perms(void) +{ + return 0; +} -#if USE_DEV_IO -int io_fd; +static int platform_release_io_perms(void *p) +{ + return 0; +} #endif -#if !(defined(__DJGPP__) || defined(__LIBPAYLOAD__)) -static int release_io_perms(void *p) +#if defined(__sun) /* SunOS */ +#include <sys/sysi86.h> + +static int platform_get_io_perms(void) +{ + return sysi86(SI86V86, V86SC_IOPL, PS_IOPL); +} + +static int platform_release_io_perms(void *p) { -#if defined (__sun) sysi86(SI86V86, V86SC_IOPL, 0); -#elif USE_DEV_IO - close(io_fd); -#elif USE_IOPERM - ioperm(0, 65536, 0); -#elif USE_IOPL - iopl(0); -#endif return 0; } +#endif -/* Get I/O permissions with automatic permission release on shutdown. */ -int rget_io_perms(void) +#if USE_DEV_IO /* FreeBSD, DragonFlyBSD */ +#include <fcntl.h> +#include <unistd.h> + +int io_fd; + +static int platform_get_io_perms(void) +{ + io_fd = open("/dev/io", O_RDWR); + return (io_fd >= 0 ? 0 : -1); +} + +static int platform_release_io_perms(void *p) { - #if defined (__sun) - if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) { -#elif USE_DEV_IO - if ((io_fd = open("/dev/io", O_RDWR)) < 0) { -#elif USE_IOPERM - if (ioperm(0, 65536, 1) != 0) { -#elif USE_IOPL - if (iopl(3) != 0) { + close(io_fd); + return 0; +} #endif - msg_perr("ERROR: Could not get I/O privileges (%s).\n", strerror(errno)); - msg_perr("You need to be root.\n"); - msg_perr("On OpenBSD set securelevel=-1 in /etc/rc.securelevel and\n" - "reboot, or reboot into single user mode.\n"); - msg_perr("On NetBSD reboot into single user mode or make sure\n" - "that your kernel configuration has the option INSECURE enabled.\n"); - return 1; - } else { - register_shutdown(release_io_perms, NULL); - } + +#if USE_IOPERM /* GNU Hurd */ +#include <sys/io.h> + +static int platform_get_io_perms(void) +{ + return ioperm(0, 65536, 1); +} + +static int platform_release_io_perms(void *p) +{ + ioperm(0, 65536, 0); return 0; } +#endif -#else +#if USE_IOPL /* Linux, Darwin, NetBSD, OpenBSD */ +static int platform_get_io_perms(void) +{ + return iopl(3); +} -/* DJGPP and libpayload environments have full PCI port I/O permissions by default. */ -int rget_io_perms(void) +static int platform_release_io_perms(void *p) { + iopl(0); return 0; } #endif + +/** + * @brief Get access to the x86 I/O ports + * + * This function abstracts the platform dependent function to get access to the + * x86 I/O ports and musst be called before using IN[B/W/L] or OUT[B/W/L]. + * It registers a shutdown function to release those privileges. + * + * @return 0 on success, platform specific number on failure + */ +int rget_io_perms(void) +{ + if (platform_get_io_perms() == 0) { + register_shutdown(platform_release_io_perms, NULL); + return 0; + } + msg_perr("ERROR: Could not get I/O privileges (%s).\n", strerror(errno)); + msg_perr("Make sure you are root. If you are root, your kernel may still\n" + "prevent access based on security policies.\n"); + msg_perr("On OpenBSD set securelevel=-1 in /etc/rc.securelevel and\n" + "reboot, or reboot into single user mode.\n"); + msg_perr("On NetBSD reboot into single user mode or make sure\n" + "that your kernel configuration has the option INSECURE enabled.\n"); + return 1; +} |