From d6bb828b017eaf89d5a4c52803ebc0029725383b Mon Sep 17 00:00:00 2001 From: Carl-Daniel Hailfinger Date: Sat, 21 Jul 2012 17:27:08 +0000 Subject: Automatically release I/O permissions on shutdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Niklas Söderlund Acked-by: Michael Karcher --- atahpt.c | 4 ++-- drkaiser.c | 4 ++-- gfxnvidia.c | 4 ++-- hwaccess.c | 55 ++++++++++++++++++++++++++++--------------------------- internal.c | 4 ++-- nic3com.c | 4 ++-- nicintel.c | 7 +++---- nicintel_spi.c | 4 ++-- nicnatsemi.c | 4 ++-- nicrealtek.c | 4 ++-- ogp_spi.c | 4 ++-- programmer.h | 3 +-- rayer_spi.c | 3 ++- satamv.c | 5 ++--- satasii.c | 4 ++-- 15 files changed, 56 insertions(+), 57 deletions(-) diff --git a/atahpt.c b/atahpt.c index 41a82cb..f410fe4 100644 --- a/atahpt.c +++ b/atahpt.c @@ -60,7 +60,6 @@ static int atahpt_shutdown(void *data) { /* Flash access is disabled automatically by PCI restore. */ pci_cleanup(pacc); - release_io_perms(); return 0; } @@ -68,7 +67,8 @@ int atahpt_init(void) { uint32_t reg32; - get_io_perms(); + if (rget_io_perms()) + return 1; io_base_addr = pcidev_init(PCI_BASE_ADDRESS_4, ata_hpt); diff --git a/drkaiser.c b/drkaiser.c index a3844b8..259530a 100644 --- a/drkaiser.c +++ b/drkaiser.c @@ -60,7 +60,6 @@ static int drkaiser_shutdown(void *data) physunmap(drkaiser_bar, DRKAISER_MEMMAP_SIZE); /* Flash write is disabled automatically by PCI restore. */ pci_cleanup(pacc); - release_io_perms(); return 0; }; @@ -68,7 +67,8 @@ int drkaiser_init(void) { uint32_t addr; - get_io_perms(); + if (rget_io_perms()) + return 1; addr = pcidev_init(PCI_BASE_ADDRESS_2, drkaiser_pcidev); diff --git a/gfxnvidia.c b/gfxnvidia.c index ddf82e7..782d692 100644 --- a/gfxnvidia.c +++ b/gfxnvidia.c @@ -84,7 +84,6 @@ static int gfxnvidia_shutdown(void *data) * by PCI restore. */ pci_cleanup(pacc); - release_io_perms(); return 0; } @@ -92,7 +91,8 @@ int gfxnvidia_init(void) { uint32_t reg32; - get_io_perms(); + if (rget_io_perms()) + return 1; io_base_addr = pcidev_init(PCI_BASE_ADDRESS_0, gfx_nvidia); diff --git a/hwaccess.c b/hwaccess.c index e182167..c18a110 100644 --- a/hwaccess.c +++ b/hwaccess.c @@ -45,11 +45,27 @@ static inline void sync_primitive(void) 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 @@ void get_io_perms(void) "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 @@ static inline void sync_primitive(void) } /* PCI port I/O is not yet implemented on PowerPC. */ -void get_io_perms(void) -{ -} - -/* PCI port I/O is not yet implemented on PowerPC. */ -void release_io_perms(void) +int rget_io_perms(void) { + return 0; } #elif defined (__mips) || defined (__mips__) || defined (_mips) || defined (mips) @@ -108,13 +116,9 @@ static inline void sync_primitive(void) } /* PCI port I/O is not yet implemented on MIPS. */ -void get_io_perms(void) -{ -} - -/* PCI port I/O is not yet implemented on MIPS. */ -void release_io_perms(void) +int rget_io_perms(void) { + return 0; } #elif defined (__arm__) @@ -123,12 +127,9 @@ static inline void sync_primitive(void) { } -void get_io_perms(void) -{ -} - -void release_io_perms(void) +int rget_io_perms(void) { + return 0; } #else diff --git a/internal.c b/internal.c index c99ca1f..bf1ca8c 100644 --- a/internal.c +++ b/internal.c @@ -159,7 +159,6 @@ enum chipbustype internal_buses_supported = BUS_NONE; static int internal_shutdown(void *data) { - release_io_perms(); return 0; } @@ -226,7 +225,8 @@ int internal_init(void) } free(arg); - get_io_perms(); + if (rget_io_perms()) + return 1; if (register_shutdown(internal_shutdown, NULL)) return 1; diff --git a/nic3com.c b/nic3com.c index a137c64..f4fb6fe 100644 --- a/nic3com.c +++ b/nic3com.c @@ -82,13 +82,13 @@ static int nic3com_shutdown(void *data) } pci_cleanup(pacc); - release_io_perms(); return 0; } int nic3com_init(void) { - get_io_perms(); + if (rget_io_perms()) + return 1; io_base_addr = pcidev_init(PCI_BASE_ADDRESS_0, nics_3com); diff --git a/nicintel.c b/nicintel.c index 813049c..1c6d409 100644 --- a/nicintel.c +++ b/nicintel.c @@ -64,7 +64,6 @@ static int nicintel_shutdown(void *data) physunmap(nicintel_control_bar, NICINTEL_CONTROL_MEMMAP_SIZE); physunmap(nicintel_bar, NICINTEL_MEMMAP_SIZE); pci_cleanup(pacc); - release_io_perms(); return 0; } @@ -73,9 +72,10 @@ int nicintel_init(void) uintptr_t addr; /* Needed only for PCI accesses on some platforms. - * FIXME: Refactor that into get_mem_perms/get_io_perms/get_pci_perms? + * FIXME: Refactor that into get_mem_perms/rget_io_perms/get_pci_perms? */ - get_io_perms(); + if (rget_io_perms()) + return 1; /* No need to check for errors, pcidev_init() will not return in case * of errors. @@ -118,7 +118,6 @@ error_out_unmap: physunmap(nicintel_bar, NICINTEL_MEMMAP_SIZE); error_out: pci_cleanup(pacc); - release_io_perms(); return 1; } diff --git a/nicintel_spi.c b/nicintel_spi.c index 7a02cda..531576c 100644 --- a/nicintel_spi.c +++ b/nicintel_spi.c @@ -159,7 +159,6 @@ static int nicintel_spi_shutdown(void *data) physunmap(nicintel_spibar, 4096); pci_cleanup(pacc); - release_io_perms(); return 0; } @@ -168,7 +167,8 @@ int nicintel_spi_init(void) { uint32_t tmp; - get_io_perms(); + if (rget_io_perms()) + return 1; io_base_addr = pcidev_init(PCI_BASE_ADDRESS_0, nics_intel_spi); diff --git a/nicnatsemi.c b/nicnatsemi.c index 4646867..7cdd2fe 100644 --- a/nicnatsemi.c +++ b/nicnatsemi.c @@ -54,13 +54,13 @@ static const struct par_programmer par_programmer_nicnatsemi = { static int nicnatsemi_shutdown(void *data) { pci_cleanup(pacc); - release_io_perms(); return 0; } int nicnatsemi_init(void) { - get_io_perms(); + if (rget_io_perms()) + return 1; io_base_addr = pcidev_init(PCI_BASE_ADDRESS_0, nics_natsemi); diff --git a/nicrealtek.c b/nicrealtek.c index 61e07d8..afc3d0f 100644 --- a/nicrealtek.c +++ b/nicrealtek.c @@ -56,13 +56,13 @@ static int nicrealtek_shutdown(void *data) { /* FIXME: We forgot to disable software access again. */ pci_cleanup(pacc); - release_io_perms(); return 0; } int nicrealtek_init(void) { - get_io_perms(); + if (rget_io_perms()) + return 1; io_base_addr = pcidev_init(PCI_BASE_ADDRESS_0, nics_realtek); diff --git a/ogp_spi.c b/ogp_spi.c index 2966024..13091b4 100644 --- a/ogp_spi.c +++ b/ogp_spi.c @@ -99,7 +99,6 @@ static int ogp_spi_shutdown(void *data) { physunmap(ogp_spibar, 4096); pci_cleanup(pacc); - release_io_perms(); return 0; } @@ -129,7 +128,8 @@ int ogp_spi_init(void) return 1; } - get_io_perms(); + if (rget_io_perms()) + return 1; io_base_addr = pcidev_init(PCI_BASE_ADDRESS_0, ogp_spi); diff --git a/programmer.h b/programmer.h index 6f07dd0..f511c71 100644 --- a/programmer.h +++ b/programmer.h @@ -302,8 +302,7 @@ struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device); struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device, uint16_t card_vendor, uint16_t card_device); #endif -void get_io_perms(void); -void release_io_perms(void); +int rget_io_perms(void); #if CONFIG_INTERNAL == 1 extern int is_laptop; extern int laptop_ok; diff --git a/rayer_spi.c b/rayer_spi.c index 584a6a0..8e48e6e 100644 --- a/rayer_spi.c +++ b/rayer_spi.c @@ -168,7 +168,8 @@ int rayer_spi_init(void) rayer_miso_bit = 4; } - get_io_perms(); + if (rget_io_perms()) + return 1; /* Get the initial value before writing to any line. */ lpt_outbyte = INB(lpt_iobase); diff --git a/satamv.c b/satamv.c index 70deb06..afcabaf 100644 --- a/satamv.c +++ b/satamv.c @@ -61,7 +61,6 @@ static int satamv_shutdown(void *data) { physunmap(mv_bar, 0x20000); pci_cleanup(pacc); - release_io_perms(); return 0; } @@ -86,7 +85,8 @@ int satamv_init(void) uintptr_t addr; uint32_t tmp; - get_io_perms(); + if (rget_io_perms()) + return 1; /* BAR0 has all internal registers memory mapped. */ /* No need to check for errors, pcidev_init() will not return in case @@ -162,7 +162,6 @@ int satamv_init(void) error_out: pci_cleanup(pacc); - release_io_perms(); return 1; } diff --git a/satasii.c b/satasii.c index aae76f3..0bea942 100644 --- a/satasii.c +++ b/satasii.c @@ -62,7 +62,6 @@ static int satasii_shutdown(void *data) { physunmap(sii_bar, SATASII_MEMMAP_SIZE); pci_cleanup(pacc); - release_io_perms(); return 0; } @@ -71,7 +70,8 @@ int satasii_init(void) uint32_t addr; uint16_t reg_offset; - get_io_perms(); + if (rget_io_perms()) + return 1; pcidev_init(PCI_BASE_ADDRESS_0, satas_sii); -- cgit v1.1