1 /*
2  * This file is part of the flashrom project.
3  *
4  * Copyright (C) 2009 Carl-Daniel Hailfinger
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15 
16 /*
17  * Header file for hardware access and OS abstraction. Included from flash.h.
18  */
19 
20 #ifndef __HWACCESS_H__
21 #define __HWACCESS_H__ 1
22 
23 #include "platform.h"
24 
25 #if NEED_PCI == 1
26 /*
27  * libpci headers use the variable name "index" which triggers shadowing
28  * warnings on systems which have the index() function in a default #include
29  * or as builtin.
30  */
31 #define index shadow_workaround_index
32 
33 #if !defined (__NetBSD__)
34 #include <pci/pci.h>
35 #else
36 #include <pciutils/pci.h>
37 #endif
38 
39 #undef index
40 #endif /* NEED_PCI == 1 */
41 
42 #define ___constant_swab8(x) ((uint8_t) (				\
43 	(((uint8_t)(x) & (uint8_t)0xffU))))
44 
45 #define ___constant_swab16(x) ((uint16_t) (				\
46 	(((uint16_t)(x) & (uint16_t)0x00ffU) << 8) |			\
47 	(((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
48 
49 #define ___constant_swab32(x) ((uint32_t) (				\
50 	(((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) |		\
51 	(((uint32_t)(x) & (uint32_t)0x0000ff00UL) <<  8) |		\
52 	(((uint32_t)(x) & (uint32_t)0x00ff0000UL) >>  8) |		\
53 	(((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
54 
55 #define ___constant_swab64(x) ((uint64_t) (				\
56 	(((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) |	\
57 	(((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) |	\
58 	(((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) |	\
59 	(((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) <<  8) |	\
60 	(((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >>  8) |	\
61 	(((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) |	\
62 	(((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) |	\
63 	(((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
64 
65 #if defined (__FLASHROM_BIG_ENDIAN__)
66 
67 #define cpu_to_le(bits)							\
68 static inline uint##bits##_t cpu_to_le##bits(uint##bits##_t val)	\
69 {									\
70 	return ___constant_swab##bits(val);				\
71 }
72 
73 cpu_to_le(8)
74 cpu_to_le(16)
75 cpu_to_le(32)
76 cpu_to_le(64)
77 
78 #define cpu_to_be8
79 #define cpu_to_be16
80 #define cpu_to_be32
81 #define cpu_to_be64
82 
83 #elif defined (__FLASHROM_LITTLE_ENDIAN__)
84 
85 #define cpu_to_be(bits)							\
86 static inline uint##bits##_t cpu_to_be##bits(uint##bits##_t val)	\
87 {									\
88 	return ___constant_swab##bits(val);				\
89 }
90 
91 cpu_to_be(8)
92 cpu_to_be(16)
93 cpu_to_be(32)
94 cpu_to_be(64)
95 
96 #define cpu_to_le8
97 #define cpu_to_le16
98 #define cpu_to_le32
99 #define cpu_to_le64
100 
101 #endif /* __FLASHROM_BIG_ENDIAN__ / __FLASHROM_LITTLE_ENDIAN__ */
102 
103 #define be_to_cpu8 cpu_to_be8
104 #define be_to_cpu16 cpu_to_be16
105 #define be_to_cpu32 cpu_to_be32
106 #define be_to_cpu64 cpu_to_be64
107 #define le_to_cpu8 cpu_to_le8
108 #define le_to_cpu16 cpu_to_le16
109 #define le_to_cpu32 cpu_to_le32
110 #define le_to_cpu64 cpu_to_le64
111 
112 #if NEED_RAW_ACCESS == 1
113 #if IS_X86
114 
115 /* sys/io.h provides iopl(2) and x86 I/O port access functions (inb, outb etc).
116  * It is included in glibc (thus available also on debian/kFreeBSD) but also in other libcs that mimic glibc,
117  * e.g. musl and uclibc. Because we cannot detect the libc or existence of the header or of the instructions
118  * themselves safely in here we use some heuristic below:
119  * On Android we don't have the header file and no way for I/O port access at all. However, sys/glibc-syscalls.h
120  * refers to an iopl implementation and we therefore include at least that one for now. On non-Android we assume
121  * that a Linux system's libc has a suitable sys/io.h or (on non-Linux) we depend on glibc to offer it. */
122 #if defined(__ANDROID__)
123 #include <sys/glibc-syscalls.h>
124 #elif defined(__linux__) || defined(__GLIBC__)
125 #include <sys/io.h>
126 #endif
127 
128 #define __FLASHROM_HAVE_OUTB__ 1
129 
130 /* for iopl and outb under Solaris */
131 #if defined (__sun)
132 #include <sys/sysi86.h>
133 #include <sys/psw.h>
134 #include <asm/sunddi.h>
135 #endif
136 
137 /* Clarification about OUTB/OUTW/OUTL argument order:
138  * OUT[BWL](val, port)
139  */
140 
141 #if defined(__FreeBSD__) || defined(__DragonFly__)
142   /* Note that Debian/kFreeBSD (FreeBSD kernel with glibc) has conflicting
143    * out[bwl] definitions in machine/cpufunc.h and sys/io.h at least in some
144    * versions. Use machine/cpufunc.h only for plain FreeBSD/DragonFlyBSD.
145    */
146   #include <sys/types.h>
147   #include <machine/cpufunc.h>
148   #define OUTB(x, y) do { u_int outb_tmp = (y); outb(outb_tmp, (x)); } while (0)
149   #define OUTW(x, y) do { u_int outw_tmp = (y); outw(outw_tmp, (x)); } while (0)
150   #define OUTL(x, y) do { u_int outl_tmp = (y); outl(outl_tmp, (x)); } while (0)
151   #define INB(x) __extension__ ({ u_int inb_tmp = (x); inb(inb_tmp); })
152   #define INW(x) __extension__ ({ u_int inw_tmp = (x); inw(inw_tmp); })
153   #define INL(x) __extension__ ({ u_int inl_tmp = (x); inl(inl_tmp); })
154 #else
155 
156 #if defined (__sun)
157   /* Note different order for outb */
158   #define OUTB(x,y) outb(y, x)
159   #define OUTW(x,y) outw(y, x)
160   #define OUTL(x,y) outl(y, x)
161   #define INB  inb
162   #define INW  inw
163   #define INL  inl
164 #else
165 
166 #ifdef __DJGPP__
167 
168 #include <pc.h>
169 
170   #define OUTB(x,y) outportb(y, x)
171   #define OUTW(x,y) outportw(y, x)
172   #define OUTL(x,y) outportl(y, x)
173 
174   #define INB  inportb
175   #define INW  inportw
176   #define INL  inportl
177 
178 #else
179 
180 #if defined(__MACH__) && defined(__APPLE__)
181     /* Header is part of the DirectHW library. */
182     #include <DirectHW/DirectHW.h>
183 #endif
184 
185   /* This is the usual glibc interface. */
186   #define OUTB outb
187   #define OUTW outw
188   #define OUTL outl
189   #define INB  inb
190   #define INW  inw
191   #define INL  inl
192 #endif
193 #endif
194 #endif
195 
196 #if defined(__NetBSD__) || defined (__OpenBSD__)
197   #if defined(__i386__) || defined(__x86_64__)
198     #include <sys/types.h>
199     #include <machine/sysarch.h>
200     #if defined(__NetBSD__)
201       #if defined(__i386__)
202         #define iopl i386_iopl
203       #elif defined(__x86_64__)
204         #define iopl x86_64_iopl
205       #endif
206     #elif defined (__OpenBSD__)
207       #if defined(__i386__)
208         #define iopl i386_iopl
209       #elif defined(__amd64__)
210         #define iopl amd64_iopl
211       #endif
212     #endif
213 
outb(uint8_t value,uint16_t port)214 static inline void outb(uint8_t value, uint16_t port)
215 {
216 	__asm__ volatile ("outb %b0,%w1": :"a" (value), "Nd" (port));
217 }
218 
inb(uint16_t port)219 static inline uint8_t inb(uint16_t port)
220 {
221 	uint8_t value;
222 	__asm__ volatile ("inb %w1,%0":"=a" (value):"Nd" (port));
223 	return value;
224 }
225 
outw(uint16_t value,uint16_t port)226 static inline void outw(uint16_t value, uint16_t port)
227 {
228 	__asm__ volatile ("outw %w0,%w1": :"a" (value), "Nd" (port));
229 }
230 
inw(uint16_t port)231 static inline uint16_t inw(uint16_t port)
232 {
233 	uint16_t value;
234 	__asm__ volatile ("inw %w1,%0":"=a" (value):"Nd" (port));
235 	return value;
236 }
237 
outl(uint32_t value,uint16_t port)238 static inline void outl(uint32_t value, uint16_t port)
239 {
240 	__asm__ volatile ("outl %0,%w1": :"a" (value), "Nd" (port));
241 }
242 
inl(uint16_t port)243 static inline uint32_t inl(uint16_t port)
244 {
245 	uint32_t value;
246 	__asm__ volatile ("inl %1,%0":"=a" (value):"Nd" (port));
247 	return value;
248 }
249   #endif
250 #endif
251 
252 #if !(defined(__MACH__) && defined(__APPLE__)) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined(__DragonFly__) && !defined(__LIBPAYLOAD__)
253 typedef struct { uint32_t hi, lo; } msr_t;
254 msr_t rdmsr(int addr);
255 int wrmsr(int addr, msr_t msr);
256 #endif
257 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
258 /* FreeBSD already has conflicting definitions for wrmsr/rdmsr. */
259 #undef rdmsr
260 #undef wrmsr
261 #define rdmsr freebsd_rdmsr
262 #define wrmsr freebsd_wrmsr
263 typedef struct { uint32_t hi, lo; } msr_t;
264 msr_t freebsd_rdmsr(int addr);
265 int freebsd_wrmsr(int addr, msr_t msr);
266 #endif
267 #if defined(__LIBPAYLOAD__)
268 #include <arch/io.h>
269 #include <arch/msr.h>
270 typedef struct { uint32_t hi, lo; } msr_t;
271 msr_t libpayload_rdmsr(int addr);
272 int libpayload_wrmsr(int addr, msr_t msr);
273 #undef rdmsr
274 #define rdmsr libpayload_rdmsr
275 #define wrmsr libpayload_wrmsr
276 #endif
277 
278 #elif IS_PPC
279 
280 /* PCI port I/O is not yet implemented on PowerPC. */
281 
282 #elif IS_MIPS
283 
284 /* PCI port I/O is not yet implemented on MIPS. */
285 
286 #elif IS_SPARC
287 
288 /* PCI port I/O is not yet implemented on SPARC. */
289 
290 #elif IS_ARM
291 
292 /* Non memory mapped I/O is not supported on ARM. */
293 
294 #elif IS_ARC
295 
296 /* Non memory mapped I/O is not supported on ARC. */
297 
298 #else
299 
300 #error Unknown architecture, please check if it supports PCI port IO.
301 
302 #endif /* IS_* */
303 #endif /* NEED_RAW_ACCESS == 1 */
304 
305 #endif /* !__HWACCESS_H__ */
306