From a2aa33e24c8ad7cf1e4ce9dffb1b35a69b34e610 Mon Sep 17 00:00:00 2001 From: Thomas Heijligen Date: Thu, 20 Jan 2022 14:33:56 +0100 Subject: 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 Reviewed-on: https://review.coreboot.org/c/flashrom/+/61275 Tested-by: build bot (Jenkins) Reviewed-by: Edward O'Callaghan Reviewed-by: Nico Huber Reviewed-by: Angel Pons --- hwaccess_x86_io.c | 136 ++++++++++++++++++++++++++++++++++++------------------ 1 file 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 #include -#if !defined (__DJGPP__) && !defined(__LIBPAYLOAD__) -/* No file access needed/possible to get hardware access permissions. */ -#include -#include -#endif -#include "hwaccess_x86_io.h" #include "flash.h" +#include "hwaccess_x86_io.h" -#if USE_IOPERM -#include -#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 + +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 +#include + +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 + +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; +} -- cgit v1.2.3