Automatically release I/O permissions on shutdown

Get_io_perms() is renamed to rget_io_perms() and automatically registers
a function to release I/O permissions on shutdown.

Actually release I/O permissions on Solaris and iopl()-supporting
operating systems like Linux.

This patch fixes quite a few programmers which forgot to release I/O
permissions on shutdown, and it simplifies the shutdown and error
handling code for all others.

Do not call exit(1) if I/O permissions are denied and return an error
instead. This part of the patch was written by Niklas Söderlund.

Corresponding to flashrom svn r1551.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Signed-off-by: Niklas Söderlund <niso@kth.se>
Acked-by: Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
diff --git a/hwaccess.c b/hwaccess.c
index e182167..c18a110 100644
--- a/hwaccess.c
+++ b/hwaccess.c
@@ -45,11 +45,27 @@
 int io_fd;
 #endif
 
-void get_io_perms(void)
+int release_io_perms(void *p)
+{
+#if defined(__DJGPP__) || defined(__LIBPAYLOAD__)
+#else
+#if defined (__sun) && (defined(__i386) || defined(__amd64))
+	sysi86(SI86V86, V86SC_IOPL, 0);
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__)
+	close(io_fd);
+#else 
+	iopl(0);
+#endif
+#endif
+	return 0;
+}
+
+/* Get I/O permissions with automatic permission release on shutdown. */
+int rget_io_perms(void)
 {
 #if defined(__DJGPP__) || defined(__LIBPAYLOAD__)
 	/* We have full permissions by default. */
-	return;
+	return 0;
 #else
 #if defined (__sun) && (defined(__i386) || defined(__amd64))
 	if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) {
@@ -65,15 +81,11 @@
 			   "and reboot, or reboot into \n");
 		msg_perr("single user mode.\n");
 #endif
-		exit(1);
+		return 1;
+	} else {
+		register_shutdown(release_io_perms, NULL);
 	}
-#endif
-}
-
-void release_io_perms(void)
-{
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-	close(io_fd);
+	return 0;
 #endif
 }
 
@@ -89,13 +101,9 @@
 }
 
 /* PCI port I/O is not yet implemented on PowerPC. */
-void get_io_perms(void)
+int rget_io_perms(void)
 {
-}
-
-/* PCI port I/O is not yet implemented on PowerPC. */
-void release_io_perms(void)
-{
+	return 0;
 }
 
 #elif defined (__mips) || defined (__mips__) || defined (_mips) || defined (mips)
@@ -108,13 +116,9 @@
 }
 
 /* PCI port I/O is not yet implemented on MIPS. */
-void get_io_perms(void)
+int rget_io_perms(void)
 {
-}
-
-/* PCI port I/O is not yet implemented on MIPS. */
-void release_io_perms(void)
-{
+	return 0;
 }
 
 #elif defined (__arm__)
@@ -123,12 +127,9 @@
 {
 }
 
-void get_io_perms(void)
+int rget_io_perms(void)
 {
-}
-
-void release_io_perms(void)
-{
+	return 0;
 }
 
 #else