mirror of
				https://review.coreboot.org/flashrom.git
				synced 2025-10-31 05:10:41 +01:00 
			
		
		
		
	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>
This commit is contained in:
		 Thomas Heijligen
					Thomas Heijligen
				
			
				
					committed by
					
						 Nico Huber
						Nico Huber
					
				
			
			
				
	
			
			
			 Nico Huber
						Nico Huber
					
				
			
						parent
						
							6f63f20b33
						
					
				
				
					commit
					a2aa33e24c
				
			| @@ -2,6 +2,8 @@ | |||||||
|  * This file is part of the flashrom project. |  * This file is part of the flashrom project. | ||||||
|  * |  * | ||||||
|  * Copyright (C) 2009,2010 Carl-Daniel Hailfinger |  * 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 |  * 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 |  * it under the terms of the GNU General Public License as published by | ||||||
| @@ -14,70 +16,116 @@ | |||||||
|  * GNU General Public License for more details. |  * 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 <errno.h> | ||||||
| #include <string.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 "flash.h" | ||||||
|  | #include "hwaccess_x86_io.h" | ||||||
|  |  | ||||||
| #if USE_IOPERM | #if defined(__DJGPP__) || defined(__LIBPAYLOAD) /* DJGPP, libpayload */ | ||||||
| #include <sys/io.h> | static int platform_get_io_perms(void) | ||||||
| #endif | { | ||||||
|  | 	return 0; | ||||||
| #if USE_DEV_IO | } | ||||||
| int io_fd; |  | ||||||
| #endif | static int platform_release_io_perms(void *p) | ||||||
|  | { | ||||||
| #if !(defined(__DJGPP__) || defined(__LIBPAYLOAD__)) | 	return 0; | ||||||
| static int release_io_perms(void *p) | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #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); | 	sysi86(SI86V86, V86SC_IOPL, 0); | ||||||
| #elif USE_DEV_IO | 	return 0; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #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) | ||||||
|  | { | ||||||
| 	close(io_fd); | 	close(io_fd); | ||||||
| #elif USE_IOPERM | 	return 0; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #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); | 	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); | 	iopl(0); | ||||||
| #endif |  | ||||||
| 	return 0; | 	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) | int rget_io_perms(void) | ||||||
| { | { | ||||||
| 	#if defined (__sun) | 	if (platform_get_io_perms() == 0) { | ||||||
| 	if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) { | 		register_shutdown(platform_release_io_perms, NULL); | ||||||
| #elif USE_DEV_IO | 		return 0; | ||||||
| 	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); |  | ||||||
| 	} | 	} | ||||||
| 	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 |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user