diff --git a/hwaccess_x86_io.c b/hwaccess_x86_io.c index 635b27ec8..e891d98d7 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 USE_DEV_IO -int io_fd; -#endif - -#if !(defined(__DJGPP__) || defined(__LIBPAYLOAD__)) -static int release_io_perms(void *p) +#if defined(__DJGPP__) || defined(__LIBPAYLOAD) /* DJGPP, libpayload */ +static int platform_get_io_perms(void) +{ + return 0; +} + +static int platform_release_io_perms(void *p) +{ + return 0; +} +#endif + +#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 + return 0; +} +#endif + +#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) +{ close(io_fd); -#elif USE_IOPERM + return 0; +} +#endif + +#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); -#elif USE_IOPL + return 0; +} +#endif + +#if USE_IOPL /* Linux, Darwin, NetBSD, OpenBSD */ +static int platform_get_io_perms(void) +{ + return iopl(3); +} + +static int platform_release_io_perms(void *p) +{ iopl(0); -#endif return 0; } +#endif -/* Get I/O permissions with automatic permission release on shutdown. */ +/** + * @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 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) { -#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 (platform_get_io_perms() == 0) { + register_shutdown(platform_release_io_perms, NULL); + return 0; } - 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; } - -#else - -/* DJGPP and libpayload environments have full PCI port I/O permissions by default. */ -int rget_io_perms(void) -{ - return 0; -} -#endif