Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


imported SEABIOS source tree
[palacios.git] / bios / seabios / src / util.h
1 // Basic x86 asm functions and function defs.
2 //
3 // Copyright (C) 2008-2010  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6 #ifndef __UTIL_H
7 #define __UTIL_H
8
9 #include "types.h" // u32
10
11 static inline void irq_disable(void)
12 {
13     asm volatile("cli": : :"memory");
14 }
15
16 static inline void irq_enable(void)
17 {
18     asm volatile("sti": : :"memory");
19 }
20
21 static inline unsigned long irq_save(void)
22 {
23     unsigned long flags;
24     asm volatile("pushfl ; popl %0" : "=g" (flags): :"memory");
25     irq_disable();
26     return flags;
27 }
28
29 static inline void irq_restore(unsigned long flags)
30 {
31     asm volatile("pushl %0 ; popfl" : : "g" (flags) : "memory", "cc");
32 }
33
34 static inline void cpu_relax(void)
35 {
36     asm volatile("rep ; nop": : :"memory");
37 }
38
39 static inline void nop(void)
40 {
41     asm volatile("nop");
42 }
43
44 static inline void hlt(void)
45 {
46     asm volatile("hlt": : :"memory");
47 }
48
49 static inline void wbinvd(void)
50 {
51     asm volatile("wbinvd": : :"memory");
52 }
53
54 #define CPUID_MSR (1 << 5)
55 #define CPUID_APIC (1 << 9)
56 #define CPUID_MTRR (1 << 12)
57 static inline void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
58 {
59     asm("cpuid"
60         : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
61         : "0" (index));
62 }
63
64 static inline u32 getcr0(void) {
65     u32 cr0;
66     asm("movl %%cr0, %0" : "=r"(cr0));
67     return cr0;
68 }
69 static inline void setcr0(u32 cr0) {
70     asm("movl %0, %%cr0" : : "r"(cr0));
71 }
72
73 static inline u64 rdmsr(u32 index)
74 {
75     u64 ret;
76     asm ("rdmsr" : "=A"(ret) : "c"(index));
77     return ret;
78 }
79
80 static inline void wrmsr(u32 index, u64 val)
81 {
82     asm volatile ("wrmsr" : : "c"(index), "A"(val));
83 }
84
85 static inline u64 rdtscll(void)
86 {
87     u64 val;
88     asm volatile("rdtsc" : "=A" (val));
89     return val;
90 }
91
92 static inline u32 __ffs(u32 word)
93 {
94     asm("bsf %1,%0"
95         : "=r" (word)
96         : "rm" (word));
97     return word;
98 }
99 static inline u32 __fls(u32 word)
100 {
101     asm("bsr %1,%0"
102         : "=r" (word)
103         : "rm" (word));
104     return word;
105 }
106
107 static inline u16 __htons_constant(u16 val) {
108     return (val<<8) | (val>>8);
109 }
110 static inline u32 __htonl_constant(u32 val) {
111     return (val<<24) | ((val&0xff00)<<8) | ((val&0xff0000)>>8) | (val>>24);
112 }
113 static inline u32 __htonl(u32 val) {
114     asm("bswapl %0" : "+r"(val));
115     return val;
116 }
117 #define htonl(x) (__builtin_constant_p((u32)(x)) ? __htonl_constant(x) : __htonl(x))
118 #define ntohl(x) htonl(x)
119 #define htons(x) __htons_constant(x)
120 #define ntohs(x) htons(x)
121
122 static inline u16 cpu_to_le16(u16 x)
123 {
124     return x;
125 }
126
127 static inline u32 cpu_to_le32(u32 x)
128 {
129     return x;
130 }
131
132 static inline u32 getesp(void) {
133     u32 esp;
134     asm("movl %%esp, %0" : "=rm"(esp));
135     return esp;
136 }
137
138 static inline void writel(void *addr, u32 val) {
139     *(volatile u32 *)addr = val;
140 }
141 static inline void writew(void *addr, u16 val) {
142     *(volatile u16 *)addr = val;
143 }
144 static inline void writeb(void *addr, u8 val) {
145     *(volatile u8 *)addr = val;
146 }
147 static inline u32 readl(const void *addr) {
148     return *(volatile const u32 *)addr;
149 }
150 static inline u16 readw(const void *addr) {
151     return *(volatile const u16 *)addr;
152 }
153 static inline u8 readb(const void *addr) {
154     return *(volatile const u8 *)addr;
155 }
156
157 #define call16_simpint(nr, peax, pflags) do {                           \
158         ASSERT16();                                                     \
159         asm volatile(                                                   \
160             "pushl %%ebp\n"                                             \
161             "sti\n"                                                     \
162             "stc\n"                                                     \
163             "int %2\n"                                                  \
164             "pushfl\n"                                                  \
165             "popl %1\n"                                                 \
166             "cli\n"                                                     \
167             "cld\n"                                                     \
168             "popl %%ebp"                                                \
169             : "+a"(*peax), "=c"(*pflags)                                \
170             : "i"(nr)                                                   \
171             : "ebx", "edx", "esi", "edi", "cc", "memory");              \
172     } while (0)
173
174 // GDT bits
175 #define GDT_CODE     (0x9bULL << 40) // Code segment - P,R,A bits also set
176 #define GDT_DATA     (0x93ULL << 40) // Data segment - W,A bits also set
177 #define GDT_B        (0x1ULL << 54)  // Big flag
178 #define GDT_G        (0x1ULL << 55)  // Granularity flag
179 // GDT bits for segment base
180 #define GDT_BASE(v)  ((((u64)(v) & 0xff000000) << 32)           \
181                       | (((u64)(v) & 0x00ffffff) << 16))
182 // GDT bits for segment limit (0-1Meg)
183 #define GDT_LIMIT(v) ((((u64)(v) & 0x000f0000) << 32)   \
184                       | (((u64)(v) & 0x0000ffff) << 0))
185 // GDT bits for segment limit (0-4Gig in 4K chunks)
186 #define GDT_GRANLIMIT(v) (GDT_G | GDT_LIMIT((v) >> 12))
187
188 struct descloc_s {
189     u16 length;
190     u32 addr;
191 } PACKED;
192
193 // util.c
194 struct bregs;
195 inline void call16(struct bregs *callregs);
196 inline void call16big(struct bregs *callregs);
197 inline void __call16_int(struct bregs *callregs, u16 offset);
198 #define call16_int(nr, callregs) do {                           \
199         extern void irq_trampoline_ ##nr ();                    \
200         __call16_int((callregs), (u32)&irq_trampoline_ ##nr );  \
201     } while (0)
202 u8 checksum_far(u16 buf_seg, void *buf_far, u32 len);
203 u8 checksum(void *buf, u32 len);
204 size_t strlen(const char *s);
205 int memcmp(const void *s1, const void *s2, size_t n);
206 int strcmp(const char *s1, const char *s2);
207 inline void memset_far(u16 d_seg, void *d_far, u8 c, size_t len);
208 inline void memset16_far(u16 d_seg, void *d_far, u16 c, size_t len);
209 void *memset(void *s, int c, size_t n);
210 void memset_fl(void *ptr, u8 val, size_t size);
211 inline void memcpy_far(u16 d_seg, void *d_far
212                        , u16 s_seg, const void *s_far, size_t len);
213 void memcpy_fl(void *d_fl, const void *s_fl, size_t len);
214 void *memcpy(void *d1, const void *s1, size_t len);
215 #if MODESEGMENT == 0
216 #define memcpy __builtin_memcpy
217 #endif
218 void iomemcpy(void *d, const void *s, u32 len);
219 void *memmove(void *d, const void *s, size_t len);
220 char *strtcpy(char *dest, const char *src, size_t len);
221 char *strchr(const char *s, int c);
222 void nullTrailingSpace(char *buf);
223 int get_keystroke(int msec);
224
225 // stacks.c
226 u32 call32(void *func, u32 eax, u32 errret);
227 inline u32 stack_hop(u32 eax, u32 edx, void *func);
228 extern struct thread_info MainThread;
229 extern int CanPreempt;
230 struct thread_info *getCurThread(void);
231 void yield(void);
232 void wait_irq(void);
233 void run_thread(void (*func)(void*), void *data);
234 void wait_threads(void);
235 struct mutex_s { u32 isLocked; };
236 void mutex_lock(struct mutex_s *mutex);
237 void mutex_unlock(struct mutex_s *mutex);
238 void start_preempt(void);
239 void finish_preempt(void);
240 int wait_preempt(void);
241 void check_preempt(void);
242
243 // output.c
244 void debug_serial_setup(void);
245 void panic(const char *fmt, ...)
246     __attribute__ ((format (printf, 1, 2))) __noreturn;
247 void printf(const char *fmt, ...)
248     __attribute__ ((format (printf, 1, 2)));
249 int snprintf(char *str, size_t size, const char *fmt, ...)
250     __attribute__ ((format (printf, 3, 4)));
251 char * znprintf(size_t size, const char *fmt, ...)
252     __attribute__ ((format (printf, 2, 3)));
253 void __dprintf(const char *fmt, ...)
254     __attribute__ ((format (printf, 1, 2)));
255 void __debug_enter(struct bregs *regs, const char *fname);
256 void __debug_isr(const char *fname);
257 void __debug_stub(struct bregs *regs, int lineno, const char *fname);
258 void __warn_invalid(struct bregs *regs, int lineno, const char *fname);
259 void __warn_unimplemented(struct bregs *regs, int lineno, const char *fname);
260 void __warn_internalerror(int lineno, const char *fname);
261 void __warn_noalloc(int lineno, const char *fname);
262 void __warn_timeout(int lineno, const char *fname);
263 void __set_invalid(struct bregs *regs, int lineno, const char *fname);
264 void __set_unimplemented(struct bregs *regs, int lineno, const char *fname);
265 void __set_code_invalid(struct bregs *regs, u32 linecode, const char *fname);
266 void __set_code_unimplemented(struct bregs *regs, u32 linecode
267                               , const char *fname);
268 void hexdump(const void *d, int len);
269
270 #define dprintf(lvl, fmt, args...) do {                         \
271         if (CONFIG_DEBUG_LEVEL && (lvl) <= CONFIG_DEBUG_LEVEL)  \
272             __dprintf((fmt) , ##args );                         \
273     } while (0)
274 #define debug_enter(regs, lvl) do {                     \
275         if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL)       \
276             __debug_enter((regs), __func__);            \
277     } while (0)
278 #define debug_isr(lvl) do {                             \
279         if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL)       \
280             __debug_isr(__func__);                      \
281     } while (0)
282 #define debug_stub(regs)                        \
283     __debug_stub((regs), __LINE__, __func__)
284 #define warn_invalid(regs)                      \
285     __warn_invalid((regs), __LINE__, __func__)
286 #define warn_unimplemented(regs)                        \
287     __warn_unimplemented((regs), __LINE__, __func__)
288 #define warn_internalerror()                    \
289     __warn_internalerror(__LINE__, __func__)
290 #define warn_noalloc()                          \
291     __warn_noalloc(__LINE__, __func__)
292 #define warn_timeout()                          \
293     __warn_timeout(__LINE__, __func__)
294 #define set_invalid(regs)                       \
295     __set_invalid((regs), __LINE__, __func__)
296 #define set_code_invalid(regs, code)                                    \
297     __set_code_invalid((regs), (code) | (__LINE__ << 8), __func__)
298 #define set_unimplemented(regs)                         \
299     __set_unimplemented((regs), __LINE__, __func__)
300 #define set_code_unimplemented(regs, code)                              \
301     __set_code_unimplemented((regs), (code) | (__LINE__ << 8), __func__)
302
303 // kbd.c
304 void kbd_setup(void);
305 void handle_15c2(struct bregs *regs);
306 void process_key(u8 key);
307
308 // mouse.c
309 void mouse_setup(void);
310 void process_mouse(u8 data);
311
312 // system.c
313 extern u32 RamSize;
314 extern u64 RamSizeOver4G;
315 void mathcp_setup(void);
316
317 // serial.c
318 void serial_setup(void);
319 void lpt_setup(void);
320
321 // clock.c
322 #define PIT_TICK_RATE 1193180   // Underlying HZ of PIT
323 #define PIT_TICK_INTERVAL 65536 // Default interval for 18.2Hz timer
324 static inline int check_tsc(u64 end) {
325     return (s64)(rdtscll() - end) > 0;
326 }
327 void timer_setup(void);
328 void ndelay(u32 count);
329 void udelay(u32 count);
330 void mdelay(u32 count);
331 void nsleep(u32 count);
332 void usleep(u32 count);
333 void msleep(u32 count);
334 u64 calc_future_tsc(u32 msecs);
335 u64 calc_future_tsc_usec(u32 usecs);
336 u32 calc_future_timer_ticks(u32 count);
337 u32 calc_future_timer(u32 msecs);
338 int check_timer(u32 end);
339 void handle_1583(struct bregs *regs);
340 void handle_1586(struct bregs *regs);
341 void useRTC(void);
342 void releaseRTC(void);
343
344 // apm.c
345 void apm_shutdown(void);
346 void handle_1553(struct bregs *regs);
347
348 // pcibios.c
349 void handle_1ab1(struct bregs *regs);
350 void bios32_setup(void);
351
352 // shadow.c
353 void make_bios_writable(void);
354 void make_bios_readonly(void);
355 void qemu_prep_reset(void);
356
357 // pciinit.c
358 extern const u8 pci_irqs[4];
359 void pci_setup(void);
360
361 // smm.c
362 void smm_init(void);
363
364 // smp.c
365 extern u32 CountCPUs;
366 extern u32 MaxCountCPUs;
367 void wrmsr_smp(u32 index, u64 val);
368 void smp_probe(void);
369
370 // coreboot.c
371 extern const char *CBvendor, *CBpart;
372 struct cbfs_file;
373 struct cbfs_file *cbfs_finddatafile(const char *fname);
374 struct cbfs_file *cbfs_findprefix(const char *prefix, struct cbfs_file *last);
375 u32 cbfs_datasize(struct cbfs_file *file);
376 const char *cbfs_filename(struct cbfs_file *file);
377 int cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen);
378 void cbfs_run_payload(struct cbfs_file *file);
379 void coreboot_copy_biostable(void);
380 void cbfs_payload_setup(void);
381 void coreboot_setup(void);
382
383 // biostable.c
384 void copy_pir(void *pos);
385 void copy_mptable(void *pos);
386 void copy_acpi_rsdp(void *pos);
387 void copy_smbios(void *pos);
388
389 // vgahooks.c
390 void handle_155f(struct bregs *regs);
391 struct pci_device;
392 void vgahook_setup(struct pci_device *pci);
393
394 // optionroms.c
395 void call_bcv(u16 seg, u16 ip);
396 void optionrom_setup(void);
397 void vga_setup(void);
398 void s3_resume_vga_init(void);
399 extern u32 RomEnd;
400 extern int ScreenAndDebug;
401
402 // bootsplash.c
403 void enable_vga_console(void);
404 void enable_bootsplash(void);
405 void disable_bootsplash(void);
406
407 // resume.c
408 extern int HaveRunPost;
409 void init_dma(void);
410
411 // pnpbios.c
412 #define PNP_SIGNATURE 0x506e5024 // $PnP
413 u16 get_pnp_offset(void);
414 void pnp_setup(void);
415
416 // pmm.c
417 extern struct zone_s ZoneLow, ZoneHigh, ZoneFSeg, ZoneTmpLow, ZoneTmpHigh;
418 void malloc_setup(void);
419 void malloc_fixupreloc(void);
420 void malloc_finalize(void);
421 void *pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align);
422 int pmm_free(void *data);
423 void pmm_setup(void);
424 void pmm_finalize(void);
425 #define PMM_DEFAULT_HANDLE 0xFFFFFFFF
426 // Minimum alignment of malloc'd memory
427 #define MALLOC_MIN_ALIGN 16
428 // Helper functions for memory allocation.
429 static inline void *malloc_low(u32 size) {
430     return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
431 }
432 static inline void *malloc_high(u32 size) {
433     return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
434 }
435 static inline void *malloc_fseg(u32 size) {
436     return pmm_malloc(&ZoneFSeg, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
437 }
438 static inline void *malloc_tmplow(u32 size) {
439     return pmm_malloc(&ZoneTmpLow, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
440 }
441 static inline void *malloc_tmphigh(u32 size) {
442     return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
443 }
444 static inline void *malloc_tmp(u32 size) {
445     void *ret = malloc_tmphigh(size);
446     if (ret)
447         return ret;
448     return malloc_tmplow(size);
449 }
450 static inline void *memalign_low(u32 align, u32 size) {
451     return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, align);
452 }
453 static inline void *memalign_high(u32 align, u32 size) {
454     return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, align);
455 }
456 static inline void *memalign_tmplow(u32 align, u32 size) {
457     return pmm_malloc(&ZoneTmpLow, PMM_DEFAULT_HANDLE, size, align);
458 }
459 static inline void *memalign_tmphigh(u32 align, u32 size) {
460     return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, align);
461 }
462 static inline void *memalign_tmp(u32 align, u32 size) {
463     void *ret = memalign_tmphigh(align, size);
464     if (ret)
465         return ret;
466     return memalign_tmplow(align, size);
467 }
468 static inline void free(void *data) {
469     pmm_free(data);
470 }
471
472 // mtrr.c
473 void mtrr_setup(void);
474
475 // romlayout.S
476 void reset_vector(void) __noreturn;
477
478 // misc.c
479 extern u8 BiosChecksum;
480
481 // version (auto generated file out/version.c)
482 extern const char VERSION[];
483
484 #endif // util.h