|
|
1.1 root 1: // Basic x86 asm functions and function defs.
2: //
3: // Copyright (C) 2008,2009 Kevin O'Connor <[email protected]>
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));
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: // Atomically enable irqs and sleep until an irq; then re-disable irqs.
40: static inline void wait_irq(void)
41: {
42: asm volatile("sti ; hlt ; cli ; cld": : :"memory");
43: }
44:
45: static inline void nop(void)
46: {
47: asm volatile("nop");
48: }
49:
50: static inline void hlt(void)
51: {
52: asm volatile("hlt");
53: }
54:
55: static inline void wbinvd(void)
56: {
57: asm volatile("wbinvd");
58: }
59:
60: #define CPUID_MSR (1 << 5)
61: #define CPUID_APIC (1 << 9)
62: #define CPUID_MTRR (1 << 12)
63: static inline void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
64: {
65: asm("cpuid"
66: : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
67: : "0" (index));
68: }
69:
70: static inline u64 rdmsr(u32 index)
71: {
72: u64 ret;
73: asm ("rdmsr" : "=A"(ret) : "c"(index));
74: return ret;
75: }
76:
77: static inline void wrmsr(u32 index, u64 val)
78: {
79: asm volatile ("wrmsr" : : "c"(index), "A"(val));
80: }
81:
82: static inline u64 rdtscll(void)
83: {
84: u64 val;
85: asm volatile("rdtsc" : "=A" (val));
86: return val;
87: }
88:
89: static inline u32 __ffs(u32 word)
90: {
91: asm("bsf %1,%0"
92: : "=r" (word)
93: : "rm" (word));
94: return word;
95: }
96: static inline u32 __fls(u32 word)
97: {
98: asm("bsr %1,%0"
99: : "=r" (word)
100: : "rm" (word));
101: return word;
102: }
103:
104: static inline u32 getesp() {
105: u32 esp;
106: asm("movl %%esp, %0" : "=rm"(esp));
107: return esp;
108: }
109:
110: static inline void writel(void *addr, u32 val) {
111: *(volatile u32 *)addr = val;
112: }
113: static inline void writew(void *addr, u16 val) {
114: *(volatile u16 *)addr = val;
115: }
116: static inline void writeb(void *addr, u8 val) {
117: *(volatile u8 *)addr = val;
118: }
119: static inline u32 readl(const void *addr) {
120: return *(volatile const u32 *)addr;
121: }
122: static inline u16 readw(const void *addr) {
123: return *(volatile const u16 *)addr;
124: }
125: static inline u8 readb(const void *addr) {
126: return *(volatile const u8 *)addr;
127: }
128:
129: #define call16_simpint(nr, peax, pflags) do { \
130: ASSERT16(); \
131: asm volatile( \
132: "stc\n" \
133: "int %2\n" \
134: "pushfl\n" \
135: "popl %1\n" \
136: "cli\n" \
137: "cld" \
138: : "+a"(*peax), "=r"(*pflags) \
139: : "i"(nr) \
140: : "cc", "memory"); \
141: } while (0)
142:
143: // GDT bit manipulation
144: #define GDT_BASE(v) ((((u64)(v) & 0xff000000) << 32) \
145: | (((u64)(v) & 0x00ffffff) << 16))
146: #define GDT_LIMIT(v) ((((u64)(v) & 0x000f0000) << 32) \
147: | (((u64)(v) & 0x0000ffff) << 0))
148: #define GDT_CODE (0x9bULL << 40) // Code segment - P,R,A bits also set
149: #define GDT_DATA (0x93ULL << 40) // Data segment - W,A bits also set
150: #define GDT_B (0x1ULL << 54) // Big flag
151: #define GDT_G (0x1ULL << 55) // Granularity flag
152:
153: struct descloc_s {
154: u16 length;
155: u32 addr;
156: } PACKED;
157:
158: // util.c
159: struct bregs;
160: inline void call16(struct bregs *callregs);
161: inline void call16big(struct bregs *callregs);
162: inline void __call16_int(struct bregs *callregs, u16 offset);
163: #define call16_int(nr, callregs) do { \
164: extern void irq_trampoline_ ##nr (); \
165: __call16_int((callregs), (u32)&irq_trampoline_ ##nr ); \
166: } while (0)
167: void check_irqs();
168: u8 checksum_far(u16 buf_seg, void *buf_far, u32 len);
169: u8 checksum(void *buf, u32 len);
170: size_t strlen(const char *s);
171: int memcmp(const void *s1, const void *s2, size_t n);
172: int strcmp(const char *s1, const char *s2);
173: inline void memset_far(u16 d_seg, void *d_far, u8 c, size_t len);
174: inline void memset16_far(u16 d_seg, void *d_far, u16 c, size_t len);
175: void *memset(void *s, int c, size_t n);
176: inline void memcpy_far(u16 d_seg, void *d_far
177: , u16 s_seg, const void *s_far, size_t len);
178: void *memcpy(void *d1, const void *s1, size_t len);
179: #if MODE16 == 0
180: #define memcpy __builtin_memcpy
181: #endif
182: void iomemcpy(void *d, const void *s, u32 len);
183: void *memmove(void *d, const void *s, size_t len);
184: char *strtcpy(char *dest, const char *src, size_t len);
185: void biosusleep(u32 usec);
186: int get_keystroke(int msec);
187:
188: // stacks.c
189: inline u32 stack_hop(u32 eax, u32 edx, u32 ecx, void *func);
190: extern struct thread_info MainThread;
191: void thread_setup();
192: struct thread_info *getCurThread();
193: void yield();
194: void run_thread(void (*func)(void*), void *data);
195: void wait_threads();
196: void start_preempt();
197: void finish_preempt();
198: void check_preempt();
199:
200: // output.c
201: void debug_serial_setup();
202: void panic(const char *fmt, ...)
203: __attribute__ ((format (printf, 1, 2)))
204: __attribute__ ((noreturn));
205: void printf(const char *fmt, ...)
206: __attribute__ ((format (printf, 1, 2)));
207: void __dprintf(const char *fmt, ...)
208: __attribute__ ((format (printf, 1, 2)));
209: int snprintf(char *str, size_t size, const char *fmt, ...)
210: __attribute__ ((format (printf, 3, 4)));
211: #define dprintf(lvl, fmt, args...) do { \
212: if (CONFIG_DEBUG_LEVEL && (lvl) <= CONFIG_DEBUG_LEVEL) \
213: __dprintf((fmt) , ##args ); \
214: } while (0)
215: void __debug_enter(struct bregs *regs, const char *fname);
216: void __debug_stub(struct bregs *regs, int lineno, const char *fname);
217: void __debug_isr(const char *fname);
218: #define debug_enter(regs, lvl) do { \
219: if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \
220: __debug_enter((regs), __func__); \
221: } while (0)
222: #define debug_isr(lvl) do { \
223: if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \
224: __debug_isr(__func__); \
225: } while (0)
226: #define debug_stub(regs) \
227: __debug_stub((regs), __LINE__, __func__)
228: void hexdump(const void *d, int len);
229:
230: // kbd.c
231: void kbd_setup();
232: void handle_15c2(struct bregs *regs);
233: void process_key(u8 key);
234:
235: // mouse.c
236: void mouse_setup();
237: void process_mouse(u8 data);
238:
239: // system.c
240: extern u32 RamSize;
241: extern u64 RamSizeOver4G;
242: void mathcp_setup();
243:
244: // serial.c
245: void serial_setup();
246: void lpt_setup();
247:
248: // clock.c
249: static inline int check_time(u64 end) {
250: return (s64)(rdtscll() - end) > 0;
251: }
252: void timer_setup();
253: void ndelay(u32 count);
254: void udelay(u32 count);
255: void mdelay(u32 count);
256: void nsleep(u32 count);
257: void usleep(u32 count);
258: void msleep(u32 count);
259: u64 calc_future_tsc(u32 msecs);
260: u64 calc_future_tsc_usec(u32 usecs);
261: void handle_1583(struct bregs *regs);
262: void handle_1586(struct bregs *regs);
263: void useRTC();
264: void releaseRTC();
265:
266: // apm.c
267: void VISIBLE16 handle_1553(struct bregs *regs);
268:
269: // pcibios.c
270: void handle_1ab1(struct bregs *regs);
271:
272: // shadow.c
273: void make_bios_writable();
274: void make_bios_readonly();
275:
276: // pciinit.c
277: void pci_setup(void);
278:
279: // smm.c
280: void smm_init();
281:
282: // smp.c
283: extern u32 CountCPUs;
284: extern u32 MaxCountCPUs;
285: void wrmsr_smp(u32 index, u64 val);
286: void smp_probe(void);
287: void smp_probe_setup(void);
288:
289: // coreboot.c
290: struct cbfs_file;
291: struct cbfs_file *cbfs_findprefix(const char *prefix, struct cbfs_file *last);
292: u32 cbfs_datasize(struct cbfs_file *file);
293: const char *cbfs_filename(struct cbfs_file *file);
294: int cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen);
295: int cbfs_copy_optionrom(void *dst, u32 maxlen, u32 vendev);
296: void cbfs_run_payload(struct cbfs_file *file);
297:
298: void coreboot_copy_biostable();
299: void coreboot_setup();
300:
301: // vgahooks.c
302: extern int VGAbdf;
303: void handle_155f();
304: void vgahook_setup(const char *vendor, const char *part);
305:
306: // optionroms.c
307: void call_bcv(u16 seg, u16 ip);
308: void optionrom_setup();
309: void vga_setup();
310: void s3_resume_vga_init();
311: extern u32 RomEnd;
312:
313: // resume.c
314: void init_dma();
315:
316: // pnpbios.c
317: #define PNP_SIGNATURE 0x506e5024 // $PnP
318: u16 get_pnp_offset();
319: void pnp_setup();
320:
321: // pmm.c
322: extern struct zone_s ZoneLow, ZoneHigh, ZoneFSeg, ZoneTmpLow, ZoneTmpHigh;
323: void malloc_setup();
324: void malloc_finalize();
325: void *pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align);
326: int pmm_free(void *data);
327: void pmm_setup();
328: void pmm_finalize();
329: #define PMM_DEFAULT_HANDLE 0xFFFFFFFF
330: // Minimum alignment of malloc'd memory
331: #define MALLOC_MIN_ALIGN 16
332: // Helper functions for memory allocation.
333: static inline void *malloc_low(u32 size) {
334: return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
335: }
336: static inline void *malloc_high(u32 size) {
337: return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
338: }
339: static inline void *malloc_fseg(u32 size) {
340: return pmm_malloc(&ZoneFSeg, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
341: }
342: static inline void *malloc_tmphigh(u32 size) {
343: return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
344: }
345: static inline void *memalign_low(u32 align, u32 size) {
346: return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, align);
347: }
348: static inline void *memalign_high(u32 align, u32 size) {
349: return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, align);
350: }
351: static inline void *memalign_tmphigh(u32 align, u32 size) {
352: return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, align);
353: }
354: static inline void free(void *data) {
355: pmm_free(data);
356: }
357:
358: // mtrr.c
359: void mtrr_setup(void);
360:
361: // romlayout.S
362: void reset_vector() __attribute__ ((noreturn));
363:
364: // misc.c
365: extern u8 BiosChecksum;
366:
367: // version (auto generated file out/version.c)
368: extern const char VERSION[];
369:
370: // XXX - optimize
371: #define ntohl(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | \
372: (((x)&0xff0000) >> 8) | (((x)&0xff000000) >> 24))
373: #define htonl(x) ntohl(x)
374: #define ntohs(x) ((((x)&0xff)<<8) | (((x)&0xff00)>>8))
375: #define htons(x) ntohs(x)
376:
377: #endif // util.h
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.