Move CMOS handling into separate files in accessors
[coreboot.git] / util / nvramtool / accessors / cmos-hw-unix.c
1 #include <assert.h>
2 #include "cmos_lowlevel.h"
3
4 #if defined(__FreeBSD__)
5 #include <sys/types.h>
6 #include <machine/cpufunc.h>
7 #define OUTB(x, y) do { u_int tmp = (y); outb(tmp, (x)); } while (0)
8 #define OUTW(x, y) do { u_int tmp = (y); outw(tmp, (x)); } while (0)
9 #define OUTL(x, y) do { u_int tmp = (y); outl(tmp, (x)); } while (0)
10 #define INB(x) __extension__ ({ u_int tmp = (x); inb(tmp); })
11 #define INW(x) __extension__ ({ u_int tmp = (x); inw(tmp); })
12 #define INL(x) __extension__ ({ u_int tmp = (x); inl(tmp); })
13 #else
14 #if defined(__GLIBC__)
15 #include <sys/io.h>
16 #endif
17 #if (defined(__MACH__) && defined(__APPLE__))
18 #include <DirectIO/darwinio.h>
19 #endif
20 #define OUTB outb
21 #define OUTW outw
22 #define OUTL outl
23 #define INB  inb
24 #define INW  inw
25 #define INL  inl
26 #endif
27
28 static void cmos_hal_init(void* data);
29 static unsigned char cmos_hal_read(unsigned addr);
30 static void cmos_hal_write(unsigned addr, unsigned char value);
31 static void cmos_set_iopl(int level);
32
33 /* no need to initialize anything */
34 static void cmos_hal_init(__attribute__((unused)) void *data)
35 {
36 }
37
38 static unsigned char cmos_hal_read(unsigned index)
39 {
40         unsigned short port_0, port_1;
41
42         assert(!verify_cmos_byte_index(index));
43
44         if (index < 128) {
45                 port_0 = 0x70;
46                 port_1 = 0x71;
47         } else {
48                 port_0 = 0x72;
49                 port_1 = 0x73;
50         }
51
52         OUTB(index, port_0);
53         return INB(port_1);
54 }
55
56 static void cmos_hal_write(unsigned index, unsigned char value)
57 {
58         unsigned short port_0, port_1;
59
60         assert(!verify_cmos_byte_index(index));
61
62         if (index < 128) {
63                 port_0 = 0x70;
64                 port_1 = 0x71;
65         } else {
66                 port_0 = 0x72;
67                 port_1 = 0x73;
68         }
69
70         OUTB(index, port_0);
71         OUTB(value, port_1);
72 }
73
74
75 /****************************************************************************
76  * cmos_set_iopl
77  *
78  * Set the I/O privilege level of the executing process.  Root privileges are
79  * required for performing this action.  A sufficient I/O privilege level
80  * allows the process to access x86 I/O address space and to disable/reenable
81  * interrupts while executing in user space.  Messing with the I/O privilege
82  * level is therefore somewhat dangerous.
83  ****************************************************************************/
84 static void cmos_set_iopl(int level)
85 {
86 #if defined(__FreeBSD__)
87         static int io_fd = -1;
88 #endif
89
90         assert((level >= 0) && (level <= 3));
91
92 #if defined(__FreeBSD__)
93         if (level == 0) {
94                 if (io_fd != -1) {
95                         close(io_fd);
96                         io_fd = -1;
97                 }
98         } else {
99                 if (io_fd == -1) {
100                         io_fd = open("/dev/io", O_RDWR);
101                         if (io_fd < 0) {
102                                 perror("/dev/io");
103                                 exit(1);
104                         }
105                 }
106         }
107 #else
108         if (iopl(level)) {
109                 fprintf(stderr, "%s: iopl() system call failed.  "
110                         "You must be root to do this.\n", prog_name);
111                 exit(1);
112         }
113 #endif
114 }
115
116 cmos_access_t cmos_hal = {
117         .init = cmos_hal_init,
118         .read = cmos_hal_read,
119         .write = cmos_hal_write,
120         .set_iopl = cmos_set_iopl,
121 };
122