1
// Basic x86 asm functions and function defs.
3
// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
5
// This file may be distributed under the terms of the GNU LGPLv3 license.
9
#include "types.h" // u32
11
static inline void irq_disable(void)
13
asm volatile("cli": : :"memory");
16
static inline void irq_enable(void)
18
asm volatile("sti": : :"memory");
21
static inline unsigned long irq_save(void)
24
asm volatile("pushfl ; popl %0" : "=g" (flags): :"memory");
29
static inline void irq_restore(unsigned long flags)
31
asm volatile("pushl %0 ; popfl" : : "g" (flags) : "memory", "cc");
34
static inline void cpu_relax(void)
36
asm volatile("rep ; nop": : :"memory");
39
static inline void nop(void)
44
static inline void hlt(void)
46
asm volatile("hlt": : :"memory");
49
static inline void wbinvd(void)
51
asm volatile("wbinvd": : :"memory");
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)
60
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
64
static inline u64 rdmsr(u32 index)
67
asm ("rdmsr" : "=A"(ret) : "c"(index));
71
static inline void wrmsr(u32 index, u64 val)
73
asm volatile ("wrmsr" : : "c"(index), "A"(val));
76
static inline u64 rdtscll(void)
79
asm volatile("rdtsc" : "=A" (val));
83
static inline u32 __ffs(u32 word)
90
static inline u32 __fls(u32 word)
98
static inline u16 __htons_constant(u16 val) {
99
return (val<<8) | (val>>8);
101
static inline u32 __htonl_constant(u32 val) {
102
return (val<<24) | ((val&0xff00)<<8) | ((val&0xff0000)>>8) | (val>>24);
104
static inline u32 __htonl(u32 val) {
105
asm("bswapl %0" : "+r"(val));
108
#define htonl(x) (__builtin_constant_p((u32)(x)) ? __htonl_constant(x) : __htonl(x))
109
#define ntohl(x) htonl(x)
110
#define htons(x) __htons_constant(x)
111
#define ntohs(x) htons(x)
113
static inline u32 getesp(void) {
115
asm("movl %%esp, %0" : "=rm"(esp));
119
static inline void writel(void *addr, u32 val) {
120
*(volatile u32 *)addr = val;
122
static inline void writew(void *addr, u16 val) {
123
*(volatile u16 *)addr = val;
125
static inline void writeb(void *addr, u8 val) {
126
*(volatile u8 *)addr = val;
128
static inline u32 readl(const void *addr) {
129
return *(volatile const u32 *)addr;
131
static inline u16 readw(const void *addr) {
132
return *(volatile const u16 *)addr;
134
static inline u8 readb(const void *addr) {
135
return *(volatile const u8 *)addr;
138
#define call16_simpint(nr, peax, pflags) do { \
150
: "+a"(*peax), "=c"(*pflags) \
152
: "ebx", "edx", "esi", "edi", "cc", "memory"); \
155
// GDT bit manipulation
156
#define GDT_BASE(v) ((((u64)(v) & 0xff000000) << 32) \
157
| (((u64)(v) & 0x00ffffff) << 16))
158
#define GDT_LIMIT(v) ((((u64)(v) & 0x000f0000) << 32) \
159
| (((u64)(v) & 0x0000ffff) << 0))
160
#define GDT_CODE (0x9bULL << 40) // Code segment - P,R,A bits also set
161
#define GDT_DATA (0x93ULL << 40) // Data segment - W,A bits also set
162
#define GDT_B (0x1ULL << 54) // Big flag
163
#define GDT_G (0x1ULL << 55) // Granularity flag
172
inline void call16(struct bregs *callregs);
173
inline void call16big(struct bregs *callregs);
174
inline void __call16_int(struct bregs *callregs, u16 offset);
175
#define call16_int(nr, callregs) do { \
176
extern void irq_trampoline_ ##nr (); \
177
__call16_int((callregs), (u32)&irq_trampoline_ ##nr ); \
179
u8 checksum_far(u16 buf_seg, void *buf_far, u32 len);
180
u8 checksum(void *buf, u32 len);
181
size_t strlen(const char *s);
182
int memcmp(const void *s1, const void *s2, size_t n);
183
int strcmp(const char *s1, const char *s2);
184
inline void memset_far(u16 d_seg, void *d_far, u8 c, size_t len);
185
inline void memset16_far(u16 d_seg, void *d_far, u16 c, size_t len);
186
void *memset(void *s, int c, size_t n);
187
inline void memcpy_far(u16 d_seg, void *d_far
188
, u16 s_seg, const void *s_far, size_t len);
189
void memcpy_fl(void *d_fl, const void *s_fl, size_t len);
190
void *memcpy(void *d1, const void *s1, size_t len);
192
#define memcpy __builtin_memcpy
194
void iomemcpy(void *d, const void *s, u32 len);
195
void *memmove(void *d, const void *s, size_t len);
196
char *strtcpy(char *dest, const char *src, size_t len);
197
int get_keystroke(int msec);
200
inline u32 stack_hop(u32 eax, u32 edx, void *func);
201
extern struct thread_info MainThread;
202
void thread_setup(void);
203
struct thread_info *getCurThread(void);
206
void run_thread(void (*func)(void*), void *data);
207
void wait_threads(void);
208
struct mutex_s { u32 isLocked; };
209
void mutex_lock(struct mutex_s *mutex);
210
void mutex_unlock(struct mutex_s *mutex);
211
void start_preempt(void);
212
void finish_preempt(void);
213
int wait_preempt(void);
214
void check_preempt(void);
217
void debug_serial_setup(void);
218
void panic(const char *fmt, ...)
219
__attribute__ ((format (printf, 1, 2))) __noreturn;
220
void printf(const char *fmt, ...)
221
__attribute__ ((format (printf, 1, 2)));
222
int snprintf(char *str, size_t size, const char *fmt, ...)
223
__attribute__ ((format (printf, 3, 4)));
224
void __dprintf(const char *fmt, ...)
225
__attribute__ ((format (printf, 1, 2)));
226
void __debug_enter(struct bregs *regs, const char *fname);
227
void __debug_isr(const char *fname);
228
void __debug_stub(struct bregs *regs, int lineno, const char *fname);
229
void __warn_invalid(struct bregs *regs, int lineno, const char *fname);
230
void __warn_unimplemented(struct bregs *regs, int lineno, const char *fname);
231
void __warn_internalerror(int lineno, const char *fname);
232
void __warn_noalloc(int lineno, const char *fname);
233
void __warn_timeout(int lineno, const char *fname);
234
void __set_invalid(struct bregs *regs, int lineno, const char *fname);
235
void __set_unimplemented(struct bregs *regs, int lineno, const char *fname);
236
void __set_code_invalid(struct bregs *regs, u32 linecode, const char *fname);
237
void __set_code_unimplemented(struct bregs *regs, u32 linecode
238
, const char *fname);
239
void hexdump(const void *d, int len);
241
#define dprintf(lvl, fmt, args...) do { \
242
if (CONFIG_DEBUG_LEVEL && (lvl) <= CONFIG_DEBUG_LEVEL) \
243
__dprintf((fmt) , ##args ); \
245
#define debug_enter(regs, lvl) do { \
246
if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \
247
__debug_enter((regs), __func__); \
249
#define debug_isr(lvl) do { \
250
if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \
251
__debug_isr(__func__); \
253
#define debug_stub(regs) \
254
__debug_stub((regs), __LINE__, __func__)
255
#define warn_invalid(regs) \
256
__warn_invalid((regs), __LINE__, __func__)
257
#define warn_unimplemented(regs) \
258
__warn_unimplemented((regs), __LINE__, __func__)
259
#define warn_internalerror() \
260
__warn_internalerror(__LINE__, __func__)
261
#define warn_noalloc() \
262
__warn_noalloc(__LINE__, __func__)
263
#define warn_timeout() \
264
__warn_timeout(__LINE__, __func__)
265
#define set_invalid(regs) \
266
__set_invalid((regs), __LINE__, __func__)
267
#define set_code_invalid(regs, code) \
268
__set_code_invalid((regs), (code) | (__LINE__ << 8), __func__)
269
#define set_unimplemented(regs) \
270
__set_unimplemented((regs), __LINE__, __func__)
271
#define set_code_unimplemented(regs, code) \
272
__set_code_unimplemented((regs), (code) | (__LINE__ << 8), __func__)
275
void kbd_setup(void);
276
void handle_15c2(struct bregs *regs);
277
void process_key(u8 key);
280
void mouse_setup(void);
281
void process_mouse(u8 data);
285
extern u64 RamSizeOver4G;
286
void mathcp_setup(void);
289
void serial_setup(void);
290
void lpt_setup(void);
293
#define PIT_TICK_RATE 1193180 // Underlying HZ of PIT
294
#define PIT_TICK_INTERVAL 65536 // Default interval for 18.2Hz timer
295
static inline int check_tsc(u64 end) {
296
return (s64)(rdtscll() - end) > 0;
298
void timer_setup(void);
299
void ndelay(u32 count);
300
void udelay(u32 count);
301
void mdelay(u32 count);
302
void nsleep(u32 count);
303
void usleep(u32 count);
304
void msleep(u32 count);
305
u64 calc_future_tsc(u32 msecs);
306
u64 calc_future_tsc_usec(u32 usecs);
307
u32 calc_future_timer_ticks(u32 count);
308
u32 calc_future_timer(u32 msecs);
309
int check_timer(u32 end);
310
void handle_1583(struct bregs *regs);
311
void handle_1586(struct bregs *regs);
313
void releaseRTC(void);
316
void handle_1553(struct bregs *regs);
319
void handle_1ab1(struct bregs *regs);
320
void bios32_setup(void);
323
void make_bios_writable(void);
324
void make_bios_readonly(void);
327
void pci_setup(void);
333
extern u32 CountCPUs;
334
extern u32 MaxCountCPUs;
335
void wrmsr_smp(u32 index, u64 val);
336
void smp_probe(void);
337
void smp_probe_setup(void);
341
struct cbfs_file *cbfs_findprefix(const char *prefix, struct cbfs_file *last);
342
u32 cbfs_datasize(struct cbfs_file *file);
343
const char *cbfs_filename(struct cbfs_file *file);
344
int cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen);
345
int cbfs_copy_optionrom(void *dst, u32 maxlen, u32 vendev);
346
void cbfs_run_payload(struct cbfs_file *file);
348
void coreboot_copy_biostable(void);
349
void coreboot_setup(void);
353
void handle_155f(struct bregs *regs);
354
void vgahook_setup(const char *vendor, const char *part);
357
void call_bcv(u16 seg, u16 ip);
358
void optionrom_setup(void);
359
void vga_setup(void);
360
void s3_resume_vga_init(void);
367
#define PNP_SIGNATURE 0x506e5024 // $PnP
368
u16 get_pnp_offset(void);
369
void pnp_setup(void);
372
extern struct zone_s ZoneLow, ZoneHigh, ZoneFSeg, ZoneTmpLow, ZoneTmpHigh;
373
void malloc_setup(void);
374
void malloc_finalize(void);
375
void *pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align);
376
int pmm_free(void *data);
377
void pmm_setup(void);
378
void pmm_finalize(void);
379
#define PMM_DEFAULT_HANDLE 0xFFFFFFFF
380
// Minimum alignment of malloc'd memory
381
#define MALLOC_MIN_ALIGN 16
382
// Helper functions for memory allocation.
383
static inline void *malloc_low(u32 size) {
384
return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
386
static inline void *malloc_high(u32 size) {
387
return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
389
static inline void *malloc_fseg(u32 size) {
390
return pmm_malloc(&ZoneFSeg, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
392
static inline void *malloc_tmphigh(u32 size) {
393
return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
395
static inline void *malloc_tmp(u32 size) {
396
void *ret = malloc_tmphigh(size);
399
return pmm_malloc(&ZoneTmpLow, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
401
static inline void *memalign_low(u32 align, u32 size) {
402
return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, align);
404
static inline void *memalign_high(u32 align, u32 size) {
405
return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, align);
407
static inline void *memalign_tmphigh(u32 align, u32 size) {
408
return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, align);
410
static inline void free(void *data) {
415
void mtrr_setup(void);
418
void reset_vector(void) __noreturn;
421
extern u8 BiosChecksum;
423
// version (auto generated file out/version.c)
424
extern const char VERSION[];