diff options
author | Michael Brown | 2005-03-08 19:53:11 +0100 |
---|---|---|
committer | Michael Brown | 2005-03-08 19:53:11 +0100 |
commit | 3d6123e69ab879c72ff489afc5bf93ef0b7a94ce (patch) | |
tree | 9f3277569153a550fa8d81ebd61bd88f266eb8da /src/arch/i386/include | |
download | ipxe-3d6123e69ab879c72ff489afc5bf93ef0b7a94ce.tar.gz ipxe-3d6123e69ab879c72ff489afc5bf93ef0b7a94ce.tar.xz ipxe-3d6123e69ab879c72ff489afc5bf93ef0b7a94ce.zip |
Initial revision
Diffstat (limited to 'src/arch/i386/include')
-rw-r--r-- | src/arch/i386/include/bits/byteswap.h | 45 | ||||
-rw-r--r-- | src/arch/i386/include/bits/cpu.h | 243 | ||||
-rw-r--r-- | src/arch/i386/include/bits/elf.h | 91 | ||||
-rw-r--r-- | src/arch/i386/include/bits/elf_x.h | 5 | ||||
-rw-r--r-- | src/arch/i386/include/bits/eltorito.h | 3 | ||||
-rw-r--r-- | src/arch/i386/include/bits/endian.h | 9 | ||||
-rw-r--r-- | src/arch/i386/include/bits/string.h | 99 | ||||
-rw-r--r-- | src/arch/i386/include/callbacks_arch.h | 243 | ||||
-rw-r--r-- | src/arch/i386/include/hidemem.h | 21 | ||||
-rw-r--r-- | src/arch/i386/include/hooks.h | 9 | ||||
-rw-r--r-- | src/arch/i386/include/io.h | 246 | ||||
-rw-r--r-- | src/arch/i386/include/latch.h | 10 | ||||
-rw-r--r-- | src/arch/i386/include/limits.h | 59 | ||||
-rw-r--r-- | src/arch/i386/include/pic8259.h | 96 | ||||
-rw-r--r-- | src/arch/i386/include/pxe_callbacks.h | 33 | ||||
-rw-r--r-- | src/arch/i386/include/pxe_types.h | 35 | ||||
-rw-r--r-- | src/arch/i386/include/realmode.h | 124 | ||||
-rw-r--r-- | src/arch/i386/include/segoff.h | 41 | ||||
-rw-r--r-- | src/arch/i386/include/setjmp.h | 12 | ||||
-rw-r--r-- | src/arch/i386/include/stdint.h | 16 | ||||
-rw-r--r-- | src/arch/i386/include/vga.h | 228 |
21 files changed, 1668 insertions, 0 deletions
diff --git a/src/arch/i386/include/bits/byteswap.h b/src/arch/i386/include/bits/byteswap.h new file mode 100644 index 00000000..1bc84fda --- /dev/null +++ b/src/arch/i386/include/bits/byteswap.h @@ -0,0 +1,45 @@ +#ifndef ETHERBOOT_BITS_BYTESWAP_H +#define ETHERBOOT_BITS_BYTESWAP_H + +static inline uint16_t __i386_bswap_16(uint16_t x) +{ + __asm__("xchgb %b0,%h0\n\t" + : "=q" (x) + : "0" (x)); + return x; +} + +static inline uint32_t __i386_bswap_32(uint32_t x) +{ + __asm__("xchgb %b0,%h0\n\t" + "rorl $16,%0\n\t" + "xchgb %b0,%h0" + : "=q" (x) + : "0" (x)); + return x; +} + + +#define __bswap_constant_16(x) \ + ((uint16_t)((((uint16_t)(x) & 0x00ff) << 8) | \ + (((uint16_t)(x) & 0xff00) >> 8))) + +#define __bswap_constant_32(x) \ + ((uint32_t)((((uint32_t)(x) & 0x000000ffU) << 24) | \ + (((uint32_t)(x) & 0x0000ff00U) << 8) | \ + (((uint32_t)(x) & 0x00ff0000U) >> 8) | \ + (((uint32_t)(x) & 0xff000000U) >> 24))) + +#define __bswap_16(x) \ + ((uint16_t)(__builtin_constant_p(x) ? \ + __bswap_constant_16(x) : \ + __i386_bswap_16(x))) + + +#define __bswap_32(x) \ + ((uint32_t)(__builtin_constant_p(x) ? \ + __bswap_constant_32(x) : \ + __i386_bswap_32(x))) + + +#endif /* ETHERBOOT_BITS_BYTESWAP_H */ diff --git a/src/arch/i386/include/bits/cpu.h b/src/arch/i386/include/bits/cpu.h new file mode 100644 index 00000000..2e9b27ba --- /dev/null +++ b/src/arch/i386/include/bits/cpu.h @@ -0,0 +1,243 @@ +#ifndef I386_BITS_CPU_H +#define I386_BITS_CPU_H + + +/* Sample usage: CPU_FEATURE_P(cpu.x86_capability, FPU) */ +#define CPU_FEATURE_P(CAP, FEATURE) \ + (!!(CAP[(X86_FEATURE_##FEATURE)/32] & ((X86_FEATURE_##FEATURE) & 0x1f))) + +#define NCAPINTS 4 /* Currently we have 4 32-bit words worth of info */ + +/* Intel-defined CPU features, CPUID level 0x00000001, word 0 */ +#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */ +#define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */ +#define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */ +#define X86_FEATURE_PSE (0*32+ 3) /* Page Size Extensions */ +#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */ +#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers, RDMSR, WRMSR */ +#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */ +#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Architecture */ +#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */ +#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */ +#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */ +#define X86_FEATURE_MTRR (0*32+12) /* Memory Type Range Registers */ +#define X86_FEATURE_PGE (0*32+13) /* Page Global Enable */ +#define X86_FEATURE_MCA (0*32+14) /* Machine Check Architecture */ +#define X86_FEATURE_CMOV (0*32+15) /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */ +#define X86_FEATURE_PAT (0*32+16) /* Page Attribute Table */ +#define X86_FEATURE_PSE36 (0*32+17) /* 36-bit PSEs */ +#define X86_FEATURE_PN (0*32+18) /* Processor serial number */ +#define X86_FEATURE_CLFLSH (0*32+19) /* Supports the CLFLUSH instruction */ +#define X86_FEATURE_DTES (0*32+21) /* Debug Trace Store */ +#define X86_FEATURE_ACPI (0*32+22) /* ACPI via MSR */ +#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */ +#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */ + /* of FPU context), and CR4.OSFXSR available */ +#define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */ +#define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */ +#define X86_FEATURE_SELFSNOOP (0*32+27) /* CPU self snoop */ +#define X86_FEATURE_HT (0*32+28) /* Hyper-Threading */ +#define X86_FEATURE_ACC (0*32+29) /* Automatic clock control */ +#define X86_FEATURE_IA64 (0*32+30) /* IA-64 processor */ + +/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ +/* Don't duplicate feature flags which are redundant with Intel! */ +#define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */ +#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ +#define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */ +#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */ +#define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */ + +/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ +#define X86_FEATURE_RECOVERY (2*32+ 0) /* CPU in recovery mode */ +#define X86_FEATURE_LONGRUN (2*32+ 1) /* Longrun power control */ +#define X86_FEATURE_LRTI (2*32+ 3) /* LongRun table interface */ + +/* Other features, Linux-defined mapping, word 3 */ +/* This range is used for feature bits which conflict or are synthesized */ +#define X86_FEATURE_CXMMX (3*32+ 0) /* Cyrix MMX extensions */ +#define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */ +#define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */ +#define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */ + +#define MAX_X86_VENDOR_ID 16 +struct cpuinfo_x86 { + uint8_t x86; /* CPU family */ + uint8_t x86_model; + uint8_t x86_mask; + + int cpuid_level; /* Maximum supported CPUID level, -1=no CPUID */ + unsigned x86_capability[NCAPINTS]; + char x86_vendor_id[MAX_X86_VENDOR_ID]; +}; + + +#define X86_VENDOR_INTEL 0 +#define X86_VENDOR_CYRIX 1 +#define X86_VENDOR_AMD 2 +#define X86_VENDOR_UMC 3 +#define X86_VENDOR_NEXGEN 4 +#define X86_VENDOR_CENTAUR 5 +#define X86_VENDOR_RISE 6 +#define X86_VENDOR_TRANSMETA 7 +#define X86_VENDOR_NSC 8 +#define X86_VENDOR_UNKNOWN 0xff + +/* + * EFLAGS bits + */ +#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */ +#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */ +#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */ +#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */ +#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */ +#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */ +#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */ +#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */ +#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */ +#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */ +#define X86_EFLAGS_NT 0x00004000 /* Nested Task */ +#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */ +#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */ +#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */ +#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */ +#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ +#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ + +/* + * Generic CPUID function + */ +static inline void cpuid(int op, + unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) +{ + __asm__("cpuid" + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (op)); +} + +/* + * CPUID functions returning a single datum + */ +static inline unsigned int cpuid_eax(unsigned int op) +{ + unsigned int eax; + + __asm__("cpuid" + : "=a" (eax) + : "0" (op) + : "bx", "cx", "dx"); + return eax; +} +static inline unsigned int cpuid_ebx(unsigned int op) +{ + unsigned int eax, ebx; + + __asm__("cpuid" + : "=a" (eax), "=b" (ebx) + : "0" (op) + : "cx", "dx" ); + return ebx; +} +static inline unsigned int cpuid_ecx(unsigned int op) +{ + unsigned int eax, ecx; + + __asm__("cpuid" + : "=a" (eax), "=c" (ecx) + : "0" (op) + : "bx", "dx" ); + return ecx; +} +static inline unsigned int cpuid_edx(unsigned int op) +{ + unsigned int eax, edx; + + __asm__("cpuid" + : "=a" (eax), "=d" (edx) + : "0" (op) + : "bx", "cx"); + return edx; +} + +/* + * Intel CPU features in CR4 + */ +#define X86_CR4_VME 0x0001 /* enable vm86 extensions */ +#define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */ +#define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */ +#define X86_CR4_DE 0x0008 /* enable debugging extensions */ +#define X86_CR4_PSE 0x0010 /* enable page size extensions */ +#define X86_CR4_PAE 0x0020 /* enable physical address extensions */ +#define X86_CR4_MCE 0x0040 /* Machine check enable */ +#define X86_CR4_PGE 0x0080 /* enable global pages */ +#define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */ +#define X86_CR4_OSFXSR 0x0200 /* enable fast FPU save and restore */ +#define X86_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */ + + +#define MSR_K6_EFER 0xC0000080 +/* EFER bits: */ +#define _EFER_SCE 0 /* SYSCALL/SYSRET */ +#define _EFER_LME 8 /* Long mode enable */ +#define _EFER_LMA 10 /* Long mode active (read-only) */ +#define _EFER_NX 11 /* No execute enable */ + +#define EFER_SCE (1<<_EFER_SCE) +#define EFER_LME (1<<EFER_LME) +#define EFER_LMA (1<<EFER_LMA) +#define EFER_NX (1<<_EFER_NX) + +#define rdmsr(msr,val1,val2) \ + __asm__ __volatile__("rdmsr" \ + : "=a" (val1), "=d" (val2) \ + : "c" (msr)) + +#define wrmsr(msr,val1,val2) \ + __asm__ __volatile__("wrmsr" \ + : /* no outputs */ \ + : "c" (msr), "a" (val1), "d" (val2)) + + +#define read_cr0() ({ \ + unsigned int __dummy; \ + __asm__( \ + "movl %%cr0, %0\n\t" \ + :"=r" (__dummy)); \ + __dummy; \ +}) +#define write_cr0(x) \ + __asm__("movl %0,%%cr0": :"r" (x)); + +#define read_cr3() ({ \ + unsigned int __dummy; \ + __asm__( \ + "movl %%cr3, %0\n\t" \ + :"=r" (__dummy)); \ + __dummy; \ +}) +#define write_cr3x(x) \ + __asm__("movl %0,%%cr3": :"r" (x)); + + +#define read_cr4() ({ \ + unsigned int __dummy; \ + __asm__( \ + "movl %%cr4, %0\n\t" \ + :"=r" (__dummy)); \ + __dummy; \ +}) +#define write_cr4x(x) \ + __asm__("movl %0,%%cr4": :"r" (x)); + + +extern struct cpuinfo_x86 cpu_info; +#ifdef CONFIG_X86_64 +extern void cpu_setup(void); +#else +#define cpu_setup() do {} while(0) +#endif + +#endif /* I386_BITS_CPU_H */ diff --git a/src/arch/i386/include/bits/elf.h b/src/arch/i386/include/bits/elf.h new file mode 100644 index 00000000..dad9c7b8 --- /dev/null +++ b/src/arch/i386/include/bits/elf.h @@ -0,0 +1,91 @@ +#ifndef I386_BITS_ELF_H +#define I386_BITS_ELF_H + +#include "cpu.h" + +#ifdef CONFIG_X86_64 +/* ELF Defines for the 64bit version of the current architecture */ +#define EM_CURRENT_64 EM_X86_64 +#define EM_CURRENT_64_PRESENT ( \ + CPU_FEATURE_P(cpu_info.x86_capability, LM) && \ + CPU_FEATURE_P(cpu_info.x86_capability, PAE) && \ + CPU_FEATURE_P(cpu_info.x86_capability, PSE)) + +#define ELF_CHECK_X86_64_ARCH(x) \ + (EM_CURRENT_64_PRESENT && ((x).e_machine == EM_X86_64)) +#define __unused_i386 +#else +#define ELF_CHECK_X86_64_ARCH(x) 0 +#define __unused_i386 __unused +#endif + + +/* ELF Defines for the current architecture */ +#define EM_CURRENT EM_386 +#define ELFDATA_CURRENT ELFDATA2LSB + +#define ELF_CHECK_I386_ARCH(x) \ + (((x).e_machine == EM_386) || ((x).e_machine == EM_486)) + +#define ELF_CHECK_ARCH(x) \ + ((ELF_CHECK_I386_ARCH(x) || ELF_CHECK_X86_64_ARCH(x)) && \ + ((x).e_entry <= 0xffffffffUL)) + +#ifdef IMAGE_FREEBSD +/* + * FreeBSD has this rather strange "feature" of its design. + * At some point in its evolution, FreeBSD started to rely + * externally on private/static/debug internal symbol information. + * That is, some of the interfaces that software uses to access + * and work with the FreeBSD kernel are made available not + * via the shared library symbol information (the .DYNAMIC section) + * but rather the debug symbols. This means that any symbol, not + * just publicly defined symbols can be (and are) used by system + * tools to make the system work. (such as top, swapinfo, swapon, + * etc) + * + * Even worse, however, is the fact that standard ELF loaders do + * not know how to load the symbols since they are not within + * an ELF PT_LOAD section. The kernel needs these symbols to + * operate so the following changes/additions to the boot + * loading of EtherBoot have been made to get the kernel to load. + * All of the changes are within IMAGE_FREEBSD such that the + * extra/changed code only compiles when FREEBSD support is + * enabled. + */ + +/* + * Section header for FreeBSD (debug symbol kludge!) support + */ +typedef struct { + Elf32_Word sh_name; /* Section name (index into the + section header string table). */ + Elf32_Word sh_type; /* Section type. */ + Elf32_Word sh_flags; /* Section flags. */ + Elf32_Addr sh_addr; /* Address in memory image. */ + Elf32_Off sh_offset; /* Offset in file. */ + Elf32_Size sh_size; /* Size in bytes. */ + Elf32_Word sh_link; /* Index of a related section. */ + Elf32_Word sh_info; /* Depends on section type. */ + Elf32_Size sh_addralign; /* Alignment in bytes. */ + Elf32_Size sh_entsize; /* Size of each entry in section. */ +} Elf32_Shdr; + +/* sh_type */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ + +/* + * Module information subtypes (for the metadata that we need to build) + */ +#define MODINFO_END 0x0000 /* End of list */ +#define MODINFO_NAME 0x0001 /* Name of module (string) */ +#define MODINFO_TYPE 0x0002 /* Type of module (string) */ +#define MODINFO_METADATA 0x8000 /* Module-specfic */ + +#define MODINFOMD_SSYM 0x0003 /* start of symbols */ +#define MODINFOMD_ESYM 0x0004 /* end of symbols */ + +#endif /* IMAGE_FREEBSD */ + +#endif /* I386_BITS_ELF_H */ diff --git a/src/arch/i386/include/bits/elf_x.h b/src/arch/i386/include/bits/elf_x.h new file mode 100644 index 00000000..86c67250 --- /dev/null +++ b/src/arch/i386/include/bits/elf_x.h @@ -0,0 +1,5 @@ +#define ARCH_ELF_CLASS ELFCLASS32 +#define ARCH_ELF_DATA ELFDATA2LSB +#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_386 || (x)==EM_486) +typedef Elf32_Ehdr Elf_ehdr; +typedef Elf32_Phdr Elf_phdr; diff --git a/src/arch/i386/include/bits/eltorito.h b/src/arch/i386/include/bits/eltorito.h new file mode 100644 index 00000000..d43e9aac --- /dev/null +++ b/src/arch/i386/include/bits/eltorito.h @@ -0,0 +1,3 @@ +#ifndef ELTORITO_PLATFORM +#define ELTORITO_PLATFORM ELTORITO_PLATFORM_X86 +#endif /* ELTORITO_PLATFORM */ diff --git a/src/arch/i386/include/bits/endian.h b/src/arch/i386/include/bits/endian.h new file mode 100644 index 00000000..b23b233a --- /dev/null +++ b/src/arch/i386/include/bits/endian.h @@ -0,0 +1,9 @@ +#ifndef ETHERBOOT_BITS_ENDIAN_H +#define ETHERBOOT_BITS_ENDIAN_H + +#define __BYTE_ORDER __LITTLE_ENDIAN + +#define le32_to_cpup(x) (*(uint32_t *)(x)) +#define cpu_to_le16p(x) (*(uint16_t*)(x)) + +#endif /* ETHERBOOT_BITS_ENDIAN_H */ diff --git a/src/arch/i386/include/bits/string.h b/src/arch/i386/include/bits/string.h new file mode 100644 index 00000000..3743d011 --- /dev/null +++ b/src/arch/i386/include/bits/string.h @@ -0,0 +1,99 @@ +#ifndef ETHERBOOT_BITS_STRING_H +#define ETHERBOOT_BITS_STRING_H +/* + * Taken from Linux /usr/include/asm/string.h + * All except memcpy, memmove, memset and memcmp removed. + */ + +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + + +#define __HAVE_ARCH_MEMMOVE +static inline void * memmove(void * dest,const void * src, size_t n) +{ +int d0, d1, d2; +if (dest<src) +__asm__ __volatile__( + "cld\n\t" + "rep\n\t" + "movsb" + : "=&c" (d0), "=&S" (d1), "=&D" (d2) + :"0" (n),"1" (src),"2" (dest) + : "memory"); +else +__asm__ __volatile__( + "std\n\t" + "rep\n\t" + "movsb\n\t" + "cld" + : "=&c" (d0), "=&S" (d1), "=&D" (d2) + :"0" (n), + "1" (n-1+(const char *)src), + "2" (n-1+(char *)dest) + :"memory"); +return dest; +} + +#define __HAVE_ARCH_MEMSET +static inline void *memset(void *s, int c,size_t count) +{ +int d0, d1; +__asm__ __volatile__( + "cld\n\t" + "rep\n\t" + "stosb" + : "=&c" (d0), "=&D" (d1) + :"a" (c),"1" (s),"0" (count) + :"memory"); +return s; +} + +#define __HAVE_ARCH_STRNCMP +static inline int strncmp(const char * cs,const char * ct,size_t count) +{ +register int __res; +int d0, d1, d2; +__asm__ __volatile__( + "1:\tdecl %3\n\t" + "js 2f\n\t" + "lodsb\n\t" + "scasb\n\t" + "jne 3f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\txorl %%eax,%%eax\n\t" + "jmp 4f\n" + "3:\tsbbl %%eax,%%eax\n\t" + "orb $1,%%al\n" + "4:" + :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2) + :"1" (cs),"2" (ct),"3" (count)); +return __res; +} + +#define __HAVE_ARCH_STRLEN +static inline size_t strlen(const char * s) +{ +int d0; +register int __res; +__asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "notl %0\n\t" + "decl %0" + :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); +return __res; +} + +#endif /* ETHERBOOT_BITS_STRING_H */ diff --git a/src/arch/i386/include/callbacks_arch.h b/src/arch/i386/include/callbacks_arch.h new file mode 100644 index 00000000..f9cba488 --- /dev/null +++ b/src/arch/i386/include/callbacks_arch.h @@ -0,0 +1,243 @@ +/* Callout/callback interface for Etherboot + * + * This file provides the mechanisms for making calls from Etherboot + * to external programs and vice-versa. + * + * Initial version by Michael Brown <mbrown@fensystems.co.uk>, January 2004. + * + * $Id$ + */ + +#ifndef CALLBACKS_ARCH_H +#define CALLBACKS_ARCH_H + +/* Skip the definitions that won't make sense to the assembler */ +#ifndef ASSEMBLY + +/* Struct to hold general-purpose register values. PUSHAL and POPAL + * can work directly with this structure; do not change the order of + * registers. + */ +typedef struct { + union { + uint16_t di; + uint32_t edi; + }; + union { + uint16_t si; + uint32_t esi; + }; + union { + uint16_t bp; + uint32_t ebp; + }; + union { + uint16_t sp; + uint32_t esp; + }; + union { + struct { + uint8_t bl; + uint8_t bh; + } PACKED; + uint16_t bx; + uint32_t ebx; + }; + union { + struct { + uint8_t dl; + uint8_t dh; + } PACKED; + uint16_t dx; + uint32_t edx; + }; + union { + struct { + uint8_t cl; + uint8_t ch; + } PACKED; + uint16_t cx; + uint32_t ecx; + }; + union { + struct { + uint8_t al; + uint8_t ah; + } PACKED; + uint16_t ax; + uint32_t eax; + }; +} regs_t; + +/* Struct to hold segment register values. Don't change the order; + * many bits of assembly code rely on it. + */ +typedef struct { + uint16_t cs; + uint16_t ss; + uint16_t ds; + uint16_t es; + uint16_t fs; + uint16_t gs; +} PACKED seg_regs_t; + +/* Struct for a GDT descriptor */ +typedef struct { + uint16_t limit; + uint32_t address; + uint16_t padding; +} PACKED gdt_descriptor_t; + +/* Struct for a GDT entry. Use GDT_SEGMENT() to fill it in. + */ +typedef struct { + uint16_t limit_0_15; + uint16_t base_0_15; + uint8_t base_16_23; + uint8_t accessed__type__sflag__dpl__present; + uint8_t limit_16_19__avl__size__granularity; + uint8_t base_24_31; +} PACKED gdt_segment_t; + +#define GDT_SEGMENT(base,limit,type,sflag,dpl,avl,size,granularity) \ + ( (gdt_segment_t) { \ + ( (limit) & 0xffff ), \ + ( (base) & 0xffff ), \ + ( ( (base) >> 16 ) & 0xff ), \ + ( ( 1 << 0 ) | ( (type) << 1 ) | \ + ( (sflag) << 4 ) | ( (dpl) << 5 ) | ( 1 << 7 ) ), \ + ( ( (limit) >> 16 ) | \ + ( (avl) << 4 ) | ( (size) << 5 ) | ( (granularity) << 7 ) ),\ + ( (base) >> 24 ) \ + } ) +#define GDT_SEGMENT_BASE(gdt_segment) \ + ( (gdt_segment)->base_0_15 | \ + (gdt_segment)->base_16_23 << 16 | \ + (gdt_segment)->base_24_31 << 24 ) +#define GDT_SEGMENT_LIMIT(gdt_segment) \ + ( (gdt_segment)->limit_0_15 | \ + ( ( (gdt_segment)->limit_16_19__avl__size__granularity \ + & 0xf ) << 16 ) ) +#define GDT_SEGMENT_GRANULARITY(gdt_segment) \ + ( ( (gdt_segment)->limit_16_19__avl__size__granularity \ + & 0x80 ) >> 7 ) +#define GDT_SEGMENT_TYPE(gdt_segment) \ + ( ( (gdt_segment)->accessed__type__sflag__dpl__present & 0x0e ) >> 1 ) +#define GDT_SEGMENT_SIZE(gdt_segment) \ + ( ( (gdt_segment)->limit_16_19__avl__size__granularity \ + & 0x60 ) >> 5 ) + +#define GDT_TYPE_DATA (0x0) +#define GDT_TYPE_STACK (0x2) +#define GDT_TYPE_WRITEABLE (0x1) +#define GDT_TYPE_CODE (0x6) +#define GDT_TYPE_EXEC_ONLY_CODE (0x4) +#define GDT_TYPE_CONFORMING (0x1) +#define GDT_SFLAG_SYSTEM (0) +#define GDT_SFLAG_NORMAL (1) +#define GDT_AVL_NORMAL (0) +#define GDT_SIZE_16BIT (0x0) +#define GDT_SIZE_32BIT (0x2) +#define GDT_SIZE_64BIT (0x1) +#define GDT_SIZE_UNKNOWN (0x3) +#define GDT_GRANULARITY_SMALL (0) +#define GDT_GRANULARITY_LARGE (1) +#define GDT_SEGMENT_NORMAL(base,limit,type,size,granularity) \ + GDT_SEGMENT ( base, limit, type, \ + GDT_SFLAG_NORMAL, 0, GDT_AVL_NORMAL, \ + size, granularity ) + +/* Protected mode code segment */ +#define GDT_SEGMENT_PMCS(base) GDT_SEGMENT_NORMAL ( \ + base, 0xfffff, GDT_TYPE_CODE | GDT_TYPE_CONFORMING, \ + GDT_SIZE_32BIT, GDT_GRANULARITY_LARGE ) +#define GDT_SEGMENT_PMCS_PHYS GDT_SEGMENT_PMCS(0) +/* Protected mode data segment */ +#define GDT_SEGMENT_PMDS(base) GDT_SEGMENT_NORMAL ( \ + base, 0xfffff, GDT_TYPE_DATA | GDT_TYPE_WRITEABLE, \ + GDT_SIZE_32BIT, GDT_GRANULARITY_LARGE ) +#define GDT_SEGMENT_PMDS_PHYS GDT_SEGMENT_PMDS(0) +/* Real mode code segment */ +/* Not sure if there's any reason to use GDT_TYPE_EXEC_ONLY_CODE + * instead of just GDT_TYPE_CODE, but that's what our old GDT did and + * it worked, so I'm not changing it. + */ +#define GDT_SEGMENT_RMCS(base) GDT_SEGMENT_NORMAL ( \ + base, 0xffff, GDT_TYPE_EXEC_ONLY_CODE | GDT_TYPE_CONFORMING, \ + GDT_SIZE_16BIT, GDT_GRANULARITY_SMALL ) +/* Real mode data segment */ +#define GDT_SEGMENT_RMDS(base) GDT_SEGMENT_NORMAL ( \ + base, 0xffff, GDT_TYPE_DATA | GDT_TYPE_WRITEABLE, \ + GDT_SIZE_16BIT, GDT_GRANULARITY_SMALL ) +/* Long mode code segment */ +#define GDT_SEGMENT_LMCS(base) GDT_SEGMENT_NORMAL ( \ + base, 0xfffff, GDT_TYPE_CODE | GDT_TYPE_CONFORMING, \ + GDT_SIZE_64BIT, GDT_GRANULARITY_LARGE ) +#define GDT_SEGMENT_LMCS_PHYS GDT_SEGMENT_LMCS(0) +/* Long mode data segment */ +/* AFIACT, GDT_SIZE_64BIT applies only to code segments */ +#define GDT_SEGMENT_LMDS(base) GDT_SEGMENT_NORMAL ( \ + base, 0xfffff, GDT_TYPE_DATA | GDT_TYPE_WRITEABLE, \ + GDT_SIZE_32BIT, GDT_GRANULARITY_LARGE ) +#define GDT_SEGMENT_LMDS_PHYS GDT_SEGMENT_LMDS(0) + +/* Template for creating GDT structures (including segment register + * lists), suitable for passing as parameters to external_call(). + */ +#define GDT_STRUCT_t(num_segments) \ + struct { \ + gdt_descriptor_t descriptor; \ + gdt_segment_t segments[num_segments]; \ + } PACKED +/* And utility function for filling it in */ +#define GDT_ADJUST(structure) { \ + (structure)->descriptor.address = \ + virt_to_phys(&((structure)->descriptor.limit)); \ + (structure)->descriptor.limit = \ + sizeof((structure)->segments) + 8 - 1; \ + (structure)->descriptor.padding = 0; \ +} + +/* Data passed in to in_call() by assembly wrapper. + */ +typedef struct { + regs_t regs; + seg_regs_t seg_regs; + gdt_descriptor_t gdt_desc; + uint32_t flags; + struct { + uint32_t offset; + uint32_t segment; + } ret_addr; +} PACKED i386_pm_in_call_data_t; + +typedef struct { + seg_regs_t seg_regs; + union { + uint16_t pad; + uint16_t prefix_sp; + }; + uint16_t flags; + struct { + uint16_t offset; + uint16_t segment; + } ret_addr; + uint32_t orig_opcode; +} PACKED i386_rm_in_call_data_t; + +typedef struct { + i386_pm_in_call_data_t *pm; + i386_rm_in_call_data_t *rm; +} i386_in_call_data_t; +#define in_call_data_t i386_in_call_data_t + +/* Function prototypes + */ +extern int install_rm_callback_interface ( void *address, size_t available ); + +#endif /* ASSEMBLY */ + +#define RM_IN_CALL (0) +#define RM_IN_CALL_FAR (2) + +#endif /* CALLBACKS_ARCH_H */ diff --git a/src/arch/i386/include/hidemem.h b/src/arch/i386/include/hidemem.h new file mode 100644 index 00000000..600a8692 --- /dev/null +++ b/src/arch/i386/include/hidemem.h @@ -0,0 +1,21 @@ +#ifndef HIDEMEM_H +#define HIDEMEM_H + +#include "segoff.h" + +extern int install_e820mangler ( void *new_mangler ); +extern int hide_etherboot ( void ); +extern int unhide_etherboot ( void ); + +/* Symbols in e820mangler.S */ +extern void e820mangler ( void ); +extern void _intercept_int15 ( void ); +extern segoff_t _intercepted_int15; +typedef struct { + uint32_t start; + uint32_t length; +} exclude_range_t; +extern exclude_range_t _hide_memory[2]; +extern uint16_t e820mangler_size; + +#endif /* HIDEMEM_H */ diff --git a/src/arch/i386/include/hooks.h b/src/arch/i386/include/hooks.h new file mode 100644 index 00000000..0764edaf --- /dev/null +++ b/src/arch/i386/include/hooks.h @@ -0,0 +1,9 @@ +#ifndef ETHERBOOT_I386_HOOKS_H +#define ETHERBOOT_I386_HOOKS_H + +void arch_main(in_call_data_t *data, va_list params); +void arch_on_exit(int status); +#define arch_relocate_to(addr) +void arch_relocated_from ( uint32_t old_addr ); + +#endif /* ETHERBOOT_I386_HOOKS_H */ diff --git a/src/arch/i386/include/io.h b/src/arch/i386/include/io.h new file mode 100644 index 00000000..e351a0c1 --- /dev/null +++ b/src/arch/i386/include/io.h @@ -0,0 +1,246 @@ +#ifndef ETHERBOOT_IO_H +#define ETHERBOOT_IO_H + + +/* Amount of relocation etherboot is experiencing */ +extern unsigned long virt_offset; + +/* Don't require identity mapped physical memory, + * osloader.c is the only valid user at the moment. + */ +static inline unsigned long virt_to_phys(volatile const void *virt_addr) +{ + return ((unsigned long)virt_addr) + virt_offset; +} + +static inline void *phys_to_virt(unsigned long phys_addr) +{ + return (void *)(phys_addr - virt_offset); +} + +/* virt_to_bus converts an addresss inside of etherboot [_start, _end] + * into a memory access cards can use. + */ +#define virt_to_bus virt_to_phys + + +/* bus_to_virt reverses virt_to_bus, the address must be output + * from virt_to_bus to be valid. This function does not work on + * all bus addresses. + */ +#define bus_to_virt phys_to_virt + +/* ioremap converts a random 32bit bus address into something + * etherboot can access. + */ +static inline void *ioremap(unsigned long bus_addr, unsigned long length __unused) +{ + return bus_to_virt(bus_addr); +} + +/* iounmap cleans up anything ioremap had to setup */ +static inline void iounmap(void *virt_addr __unused) +{ + return; +} + +/* + * This file contains the definitions for the x86 IO instructions + * inb/inw/inl/outb/outw/outl and the "string versions" of the same + * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" + * versions of the single-IO instructions (inb_p/inw_p/..). + * + * This file is not meant to be obfuscating: it's just complicated + * to (a) handle it all in a way that makes gcc able to optimize it + * as well as possible and (b) trying to avoid writing the same thing + * over and over again with slight variations and possibly making a + * mistake somewhere. + */ + +/* + * Thanks to James van Artsdalen for a better timing-fix than + * the two short jumps: using outb's to a nonexistent port seems + * to guarantee better timings even on fast machines. + * + * On the other hand, I'd like to be sure of a non-existent port: + * I feel a bit unsafe about using 0x80 (should be safe, though) + * + * Linus + */ + +#ifdef SLOW_IO_BY_JUMPING +#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:") +#else +#define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80") +#endif + +#ifdef REALLY_SLOW_IO +#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } +#else +#define SLOW_DOWN_IO __SLOW_DOWN_IO +#endif + +/* + * readX/writeX() are used to access memory mapped devices. On some + * architectures the memory mapped IO stuff needs to be accessed + * differently. On the x86 architecture, we just read/write the + * memory location directly. + */ +#define readb(addr) (*(volatile unsigned char *) (addr)) +#define readw(addr) (*(volatile unsigned short *) (addr)) +#define readl(addr) (*(volatile unsigned int *) (addr)) + +#define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b)) +#define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b)) +#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)) + +#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) +#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) + +/* + * Force strict CPU ordering. + * And yes, this is required on UP too when we're talking + * to devices. + * + * For now, "wmb()" doesn't actually do anything, as all + * Intel CPU's follow what Intel calls a *Processor Order*, + * in which all writes are seen in the program order even + * outside the CPU. + * + * I expect future Intel CPU's to have a weaker ordering, + * but I'd also expect them to finally get their act together + * and add some real memory barriers if so. + * + * Some non intel clones support out of order store. wmb() ceases to be a + * nop for these. + */ + +#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory") +#define rmb() mb() +#define wmb() mb(); + + +/* + * Talk about misusing macros.. + */ + +#define __OUT1(s,x) \ +extern void __out##s(unsigned x value, unsigned short port); \ +extern inline void __out##s(unsigned x value, unsigned short port) { + +#define __OUT2(s,s1,s2) \ +__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" + +#define __OUT(s,s1,x) \ +__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); } \ +__OUT1(s##c,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); } \ +__OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \ +__OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); SLOW_DOWN_IO; } + +#define __IN1(s,x) \ +extern unsigned x __in##s(unsigned short port); \ +extern inline unsigned x __in##s(unsigned short port) { unsigned x _v; + +#define __IN2(s,s1,s2) \ +__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" + +#define __IN(s,s1,x,i...) \ +__IN1(s,x) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \ +__IN1(s##c,x) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); return _v; } \ +__IN1(s##_p,x) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \ +__IN1(s##c_p,x) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); SLOW_DOWN_IO; return _v; } + +#define __INS(s) \ +extern void ins##s(unsigned short port, void * addr, unsigned long count); \ +extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \ +{ __asm__ __volatile__ ("cld ; rep ; ins" #s \ +: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } + +#define __OUTS(s) \ +extern void outs##s(unsigned short port, const void * addr, unsigned long count); \ +extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ +{ __asm__ __volatile__ ("cld ; rep ; outs" #s \ +: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } + +__IN(b,"", char) +__IN(w,"",short) +__IN(l,"", long) + +__OUT(b,"b",char) +__OUT(w,"w",short) +__OUT(l,,int) + +__INS(b) +__INS(w) +__INS(l) + +__OUTS(b) +__OUTS(w) +__OUTS(l) + +/* + * Note that due to the way __builtin_constant_p() works, you + * - can't use it inside a inline function (it will never be true) + * - you don't have to worry about side effects within the __builtin.. + */ +#define outb(val,port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __outbc((val),(port)) : \ + __outb((val),(port))) + +#define inb(port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __inbc(port) : \ + __inb(port)) + +#define outb_p(val,port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __outbc_p((val),(port)) : \ + __outb_p((val),(port))) + +#define inb_p(port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __inbc_p(port) : \ + __inb_p(port)) + +#define outw(val,port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __outwc((val),(port)) : \ + __outw((val),(port))) + +#define inw(port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __inwc(port) : \ + __inw(port)) + +#define outw_p(val,port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __outwc_p((val),(port)) : \ + __outw_p((val),(port))) + +#define inw_p(port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __inwc_p(port) : \ + __inw_p(port)) + +#define outl(val,port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __outlc((val),(port)) : \ + __outl((val),(port))) + +#define inl(port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __inlc(port) : \ + __inl(port)) + +#define outl_p(val,port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __outlc_p((val),(port)) : \ + __outl_p((val),(port))) + +#define inl_p(port) \ +((__builtin_constant_p((port)) && (port) < 256) ? \ + __inlc_p(port) : \ + __inl_p(port)) + +#endif /* ETHERBOOT_IO_H */ diff --git a/src/arch/i386/include/latch.h b/src/arch/i386/include/latch.h new file mode 100644 index 00000000..38a8bd21 --- /dev/null +++ b/src/arch/i386/include/latch.h @@ -0,0 +1,10 @@ +#ifndef LATCH_H +#define LATCH_H + +#define TICKS_PER_SEC 18 + +/* For different calibrators of the TSC move the declaration of + * sleep_latch and the definitions of it's length here... + */ + +#endif /* LATCH_H */ diff --git a/src/arch/i386/include/limits.h b/src/arch/i386/include/limits.h new file mode 100644 index 00000000..f13db267 --- /dev/null +++ b/src/arch/i386/include/limits.h @@ -0,0 +1,59 @@ +#ifndef LIMITS_H +#define LIMITS_H 1 + +/* Number of bits in a `char' */ +#define CHAR_BIT 8 + +/* Minimum and maximum values a `signed char' can hold */ +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 + +/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */ +#define UCHAR_MAX 255 + +/* Minimum and maximum values a `char' can hold */ +#define CHAR_MIN SCHAR_MIN +#define CHAR_MAX SCHAR_MAX + +/* Minimum and maximum values a `signed short int' can hold */ +#define SHRT_MIN (-32768) +#define SHRT_MAX 32767 + +/* Maximum value an `unsigned short' can hold. (Minimum is 0.) */ +#define USHRT_MAX 65535 + + +/* Minimum and maximum values a `signed int' can hold */ +#define INT_MIN (-INT_MAX - 1) +#define INT_MAX 2147483647 + +/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ +#define UINT_MAX 4294967295U + + +/* Minimum and maximum values a `signed int' can hold */ +#define INT_MAX 2147483647 +#define INT_MIN (-INT_MAX - 1) + + +/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ +#define UINT_MAX 4294967295U + + +/* Minimum and maximum values a `signed long' can hold */ +#define LONG_MAX 2147483647 +#define LONG_MIN (-LONG_MAX - 1L) + +/* Maximum value an `unsigned long' can hold. (Minimum is 0.) */ +#define ULONG_MAX 4294967295UL + +/* Minimum and maximum values a `signed long long' can hold */ +#define LLONG_MAX 9223372036854775807LL +#define LLONG_MIN (-LONG_MAX - 1LL) + + +/* Maximum value an `unsigned long long' can hold. (Minimum is 0.) */ +#define ULLONG_MAX 18446744073709551615ULL + + +#endif /* LIMITS_H */ diff --git a/src/arch/i386/include/pic8259.h b/src/arch/i386/include/pic8259.h new file mode 100644 index 00000000..694e9d13 --- /dev/null +++ b/src/arch/i386/include/pic8259.h @@ -0,0 +1,96 @@ +/* + * Basic support for controlling the 8259 Programmable Interrupt Controllers. + * + * Initially written by Michael Brown (mcb30). + */ + +#ifndef PIC8259_H +#define PIC8259_H + +/* For segoff_t */ +#include "segoff.h" + +#define IRQ_PIC_CUTOFF (8) + +/* 8259 register locations */ +#define PIC1_ICW1 (0x20) +#define PIC1_OCW2 (0x20) +#define PIC1_OCW3 (0x20) +#define PIC1_ICR (0x20) +#define PIC1_IRR (0x20) +#define PIC1_ISR (0x20) +#define PIC1_ICW2 (0x21) +#define PIC1_ICW3 (0x21) +#define PIC1_ICW4 (0x21) +#define PIC1_IMR (0x21) +#define PIC2_ICW1 (0xa0) +#define PIC2_OCW2 (0xa0) +#define PIC2_OCW3 (0xa0) +#define PIC2_ICR (0xa0) +#define PIC2_IRR (0xa0) +#define PIC2_ISR (0xa0) +#define PIC2_ICW2 (0xa1) +#define PIC2_ICW3 (0xa1) +#define PIC2_ICW4 (0xa1) +#define PIC2_IMR (0xa1) + +/* Register command values */ +#define OCW3_ID (0x08) +#define OCW3_READ_IRR (0x03) +#define OCW3_READ_ISR (0x02) +#define ICR_EOI_NON_SPECIFIC (0x20) +#define ICR_EOI_NOP (0x40) +#define ICR_EOI_SPECIFIC (0x60) +#define ICR_EOI_SET_PRIORITY (0xc0) + +/* Macros to enable/disable IRQs */ +#define IMR_REG(x) ( (x) < IRQ_PIC_CUTOFF ? PIC1_IMR : PIC2_IMR ) +#define IMR_BIT(x) ( 1 << ( (x) % IRQ_PIC_CUTOFF ) ) +#define irq_enabled(x) ( ( inb ( IMR_REG(x) ) & IMR_BIT(x) ) == 0 ) +#define enable_irq(x) outb ( inb( IMR_REG(x) ) & ~IMR_BIT(x), IMR_REG(x) ) +#define disable_irq(x) outb ( inb( IMR_REG(x) ) | IMR_BIT(x), IMR_REG(x) ) + +/* Macros for acknowledging IRQs */ +#define ICR_REG(x) ( (x) < IRQ_PIC_CUTOFF ? PIC1_ICR : PIC2_ICR ) +#define ICR_VALUE(x) ( (x) % IRQ_PIC_CUTOFF ) +#define CHAINED_IRQ 2 + +/* Utility macros to convert IRQ numbers to INT numbers and INT vectors */ +#define IRQ_INT(x) ( (x)<IRQ_PIC_CUTOFF ? (x)+0x08 : (x)-IRQ_PIC_CUTOFF+0x70 ) +#define INT_VECTOR(x) ( (segoff_t*) phys_to_virt( 4 * (x) ) ) +#define IRQ_VECTOR(x) ( INT_VECTOR ( IRQ_INT(x) ) ) + +/* Other constants */ +typedef uint8_t irq_t; +#define IRQ_MAX (15) +#define IRQ_NONE (0xff) + +/* Function prototypes + */ +int install_irq_handler ( irq_t irq, segoff_t *handler, + uint8_t *previously_enabled, + segoff_t *previous_handler ); +int remove_irq_handler ( irq_t irq, segoff_t *handler, + uint8_t *previously_enabled, + segoff_t *previous_handler ); +int install_trivial_irq_handler ( irq_t irq ); +int remove_trivial_irq_handler ( irq_t irq ); +int trivial_irq_triggered ( irq_t irq ); +int copy_trivial_irq_handler ( void *target, size_t target_size ); +void send_non_specific_eoi ( irq_t irq ); +void send_specific_eoi ( irq_t irq ); +void fake_irq ( irq_t irq ); +#ifdef DEBUG_IRQ +void dump_irq_status ( void ); +#else +#define dump_irq_status() +#endif + +/* Other code (e.g. undi.c) needs to know the size of the trivial IRQ + * handler code, so we put prototypes and the size macro here. + */ +extern void _trivial_irq_handler ( void ); +extern void _trivial_irq_handler_end ( void ); +#define TRIVIAL_IRQ_HANDLER_SIZE FRAGMENT_SIZE(_trivial_irq_handler) + +#endif /* PIC8259_H */ diff --git a/src/arch/i386/include/pxe_callbacks.h b/src/arch/i386/include/pxe_callbacks.h new file mode 100644 index 00000000..9b941931 --- /dev/null +++ b/src/arch/i386/include/pxe_callbacks.h @@ -0,0 +1,33 @@ +/* Header for pxe_callbacks.c. + */ + +#ifndef PXE_CALLBACKS_H +#define PXE_CALLBACKS_H + +#include "etherboot.h" +#include "segoff.h" +#include "pxe.h" + +typedef struct { + segoff_t orig_retaddr; + uint16_t opcode; + segoff_t segoff; +} PACKED pxe_call_params_t; + +/* + * These values are hard-coded into the PXE spec + */ +#define PXE_LOAD_SEGMENT (0x0000) +#define PXE_LOAD_OFFSET (0x7c00) +#define PXE_LOAD_ADDRESS ( ( PXE_LOAD_SEGMENT << 4 ) + PXE_LOAD_OFFSET ) + +/* Function prototypes + */ +extern pxe_stack_t * install_pxe_stack ( void *base ); +extern void use_undi_ds_for_rm_stack ( uint16_t ds ); +extern int hook_pxe_stack ( void ); +extern int unhook_pxe_stack ( void ); +extern void remove_pxe_stack ( void ); +extern int xstartpxe ( void ); + +#endif /* PXE_CALLBACKS_H */ diff --git a/src/arch/i386/include/pxe_types.h b/src/arch/i386/include/pxe_types.h new file mode 100644 index 00000000..7b093e6a --- /dev/null +++ b/src/arch/i386/include/pxe_types.h @@ -0,0 +1,35 @@ +/* + * Architecture-specific portion of pxe.h for Etherboot + * + * This file has to define the types SEGOFF16_t, SEGDESC_t and + * SEGSEL_t for use in other PXE structures. See pxe.h for details. + */ + +#ifndef PXE_TYPES_H +#define PXE_TYPES_H + +/* SEGOFF16_t defined in separate header + */ +#include "segoff.h" +typedef segoff_t I386_SEGOFF16_t; +#define SEGOFF16_t I386_SEGOFF16_t + +#define IS_NULL_SEGOFF16(x) ( ( (x).segment == 0 ) && ( (x).offset == 0 ) ) +#define SEGOFF16_TO_PTR(x) ( VIRTUAL( (x).segment, (x).offset ) ) +#define PTR_TO_SEGOFF16(ptr,segoff16) \ + (segoff16).segment = SEGMENT(ptr); \ + (segoff16).offset = OFFSET(ptr); + +typedef struct { + uint16_t Seg_Addr; + uint32_t Phy_Addr; + uint16_t Seg_Size; +} PACKED I386_SEGDESC_t; /* PACKED is required, otherwise gcc pads + * this out to 12 bytes - + * mbrown@fensystems.co.uk (mcb30) 17/5/03 */ +#define SEGDESC_t I386_SEGDESC_t + +typedef uint16_t I386_SEGSEL_t; +#define SEGSEL_t I386_SEGSEL_t + +#endif /* PXE_TYPES_H */ diff --git a/src/arch/i386/include/realmode.h b/src/arch/i386/include/realmode.h new file mode 100644 index 00000000..eca92b9b --- /dev/null +++ b/src/arch/i386/include/realmode.h @@ -0,0 +1,124 @@ +/* Real-mode interface + */ + +#ifndef ASSEMBLY + +#include "etherboot.h" +#include "segoff.h" + +typedef union { + struct { + union { + uint8_t l; + uint8_t byte; + }; + uint8_t h; + } PACKED; + uint16_t word; +} PACKED reg16_t; + +typedef union { + reg16_t w; + uint32_t dword; +} PACKED reg32_t; + +/* Macros to help with defining inline real-mode trampoline fragments. + */ +#define RM_XSTR(x) #x /* Macro hackery needed to stringify */ +#define RM_STR(x) RM_XSTR(x) +#define RM_FRAGMENT(name, asm_code_str) \ + extern void name ( void ); \ + extern void name ## _end (void); \ + __asm__( \ + ".section \".text16\"\n\t" \ + ".code16\n\t" \ + ".arch i386\n\t" \ + ".globl " #name " \n\t" \ + #name ":\n\t" \ + asm_code_str "\n\t" \ + ".globl " #name "_end\n\t" \ + #name "_end:\n\t" \ + ".code32\n\t" \ + ".previous\n\t" \ + ) + +#define FRAGMENT_SIZE(fragment) ( (size_t) ( ( (void*) fragment ## _end )\ + - ( (void*) (fragment) ) ) ) + +/* Data structures in _prot_to_real and _real_to_prot. These + * structures are accessed by assembly code as well as C code. + */ +typedef struct { + uint32_t esp; + uint16_t cs; + uint16_t ss; + uint32_t r2p_params; +} PACKED prot_to_real_params_t; + +typedef struct { + uint32_t ret_addr; + uint32_t esp; + uint32_t ebx; + uint32_t esi; + uint32_t edi; + uint32_t ebp; + uint32_t out_stack; + uint32_t out_stack_len; +} PACKED real_to_prot_params_t; + +/* Function prototypes: realmode.c + */ +#define real_call( fragment, in_stack, out_stack ) \ + _real_call ( fragment, FRAGMENT_SIZE(fragment), \ + (void*)(in_stack), \ + ( (in_stack) == NULL ? 0 : sizeof(*(in_stack)) ), \ + (void*)(out_stack), \ + ( (out_stack) == NULL ? 0 : sizeof(*(out_stack)) ) ) +extern uint16_t _real_call ( void *fragment, int fragment_len, + void *in_stack, int in_stack_len, + void *out_stack, int out_stack_len ); +/* Function prototypes: realmode_asm.S + */ +extern void rm_callback_interface; +extern uint16_t rm_callback_interface_size; +extern uint32_t rm_etherboot_location; +extern void _rm_in_call ( void ); +extern void _rm_in_call_far ( void ); + +extern void _prot_to_real_prefix ( void ); +extern void _prot_to_real_prefix_end ( void ); +extern uint16_t prot_to_real_prefix_size; + +extern void _real_to_prot_suffix ( void ); +extern void _real_to_prot_suffix_end ( void ); +extern uint16_t real_to_prot_suffix_size; + +/* PXE assembler bits */ +extern void pxe_callback_interface; +extern uint16_t pxe_callback_interface_size; +extern void _pxe_in_call_far ( void ); +extern void _pxenv_in_call_far ( void ); +extern void _pxe_intercept_int1a ( void ); +extern segoff_t _pxe_intercepted_int1a; +extern segoff_t _pxe_pxenv_location; + +/* Global variables + */ +extern uint32_t real_mode_stack; +extern size_t real_mode_stack_size; +extern int lock_real_mode_stack; + + +/* Function prototypes from basemem.c + */ +#ifdef LINUXBIOS +/* A silly hard code that let's the code compile and work. + * When this becomes a problem feel free to implement + * something better. + */ +static inline void allot_real_mode_stack(void) { real_mode_stack = 0x7c00; } +#else +void allot_real_mode_stack(void); +#endif + +#endif /* ASSEMBLY */ diff --git a/src/arch/i386/include/segoff.h b/src/arch/i386/include/segoff.h new file mode 100644 index 00000000..822ddd33 --- /dev/null +++ b/src/arch/i386/include/segoff.h @@ -0,0 +1,41 @@ +/* + * Segment:offset types and macros + * + * Initially written by Michael Brown (mcb30). + */ + +#ifndef SEGOFF_H +#define SEGOFF_H + +#include <stdint.h> +#include <osdep.h> +#include <io.h> + +/* Segment:offset structure. Note that the order within the structure + * is offset:segment. + */ +typedef struct { + uint16_t offset; + uint16_t segment; +} segoff_t; + +/* Macros for converting from virtual to segment:offset addresses, + * when we don't actually care which of the many isomorphic results we + * get. + */ +#ifdef DEBUG_SEGMENT +uint16_t SEGMENT ( const void * const ptr ) { + uint32_t phys = virt_to_phys ( ptr ); + if ( phys > 0xfffff ) { + printf ( "FATAL ERROR: segment address out of range\n" ); + } + return phys >> 4; +} +#else +#define SEGMENT(x) ( virt_to_phys ( x ) >> 4 ) +#endif +#define OFFSET(x) ( virt_to_phys ( x ) & 0xf ) +#define SEGOFF(x) { OFFSET(x), SEGMENT(x) } +#define VIRTUAL(x,y) ( phys_to_virt ( ( ( x ) << 4 ) + ( y ) ) ) + +#endif /* SEGOFF_H */ diff --git a/src/arch/i386/include/setjmp.h b/src/arch/i386/include/setjmp.h new file mode 100644 index 00000000..ed2be270 --- /dev/null +++ b/src/arch/i386/include/setjmp.h @@ -0,0 +1,12 @@ +#ifndef ETHERBOOT_SETJMP_H +#define ETHERBOOT_SETJMP_H + + +/* Define a type for use by setjmp and longjmp */ +#define JBLEN 6 +typedef unsigned long jmp_buf[JBLEN]; + +extern int setjmp (jmp_buf env); +extern void longjmp (jmp_buf env, int val); + +#endif /* ETHERBOOT_SETJMP_H */ diff --git a/src/arch/i386/include/stdint.h b/src/arch/i386/include/stdint.h new file mode 100644 index 00000000..42b04830 --- /dev/null +++ b/src/arch/i386/include/stdint.h @@ -0,0 +1,16 @@ +#ifndef STDINT_H +#define STDINT_H + +typedef unsigned size_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; +typedef unsigned long long uint64_t; + +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed long int32_t; +typedef signed long long int64_t; + +#endif /* STDINT_H */ diff --git a/src/arch/i386/include/vga.h b/src/arch/i386/include/vga.h new file mode 100644 index 00000000..01fc39d8 --- /dev/null +++ b/src/arch/i386/include/vga.h @@ -0,0 +1,228 @@ +/* + * + * modified + * by Steve M. Gehlbach <steve@kesa.com> + * + * Originally from linux/drivers/video/vga16.c by + * Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz> + * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz> + * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm + * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> + * + */ + +#ifndef VGA_H_INCL +#define VGA_H_INCL 1 + +//#include <cpu/p5/io.h> + +#define u8 unsigned char +#define u16 unsigned short +#define u32 unsigned int +#define __u32 u32 + +#define VERROR -1 +#define CHAR_HEIGHT 16 +#define LINES 25 +#define COLS 80 + +// macros for writing to vga regs +#define write_crtc(data,addr) outb(addr,CRT_IC); outb(data,CRT_DC) +#define write_att(data,addr) inb(IS1_RC); inb(0x80); outb(addr,ATT_IW); inb(0x80); outb(data,ATT_IW); inb(0x80) +#define write_seq(data,addr) outb(addr,SEQ_I); outb(data,SEQ_D) +#define write_gra(data,addr) outb(addr,GRA_I); outb(data,GRA_D) +u8 read_seq_b(u16 addr); +u8 read_gra_b(u16 addr); +u8 read_crtc_b(u16 addr); +u8 read_att_b(u16 addr); + + +#ifdef VGA_HARDWARE_FIXUP +void vga_hardware_fixup(void); +#else +#define vga_hardware_fixup() do{} while(0) +#endif + +#define SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */ +#define SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */ +#define SYNC_EXT 4 /* external sync */ +#define SYNC_COMP_HIGH_ACT 8 /* composite sync high active */ +#define SYNC_BROADCAST 16 /* broadcast video timings */ + /* vtotal = 144d/288n/576i => PAL */ + /* vtotal = 121d/242n/484i => NTSC */ + +#define SYNC_ON_GREEN 32 /* sync on green */ + +#define VMODE_NONINTERLACED 0 /* non interlaced */ +#define VMODE_INTERLACED 1 /* interlaced */ +#define VMODE_DOUBLE 2 /* double scan */ +#define VMODE_MASK 255 + +#define VMODE_YWRAP 256 /* ywrap instead of panning */ +#define VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */ +#define VMODE_CONUPDATE 512 /* don't update x/yoffset */ + +/* VGA data register ports */ +#define CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */ +#define CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */ +#define ATT_R 0x3C1 /* Attribute Controller Data Read Register */ +#define GRA_D 0x3CF /* Graphics Controller Data Register */ +#define SEQ_D 0x3C5 /* Sequencer Data Register */ + +#define MIS_R 0x3CC // Misc Output Read Register +#define MIS_W 0x3C2 // Misc Output Write Register + +#define IS1_RC 0x3DA /* Input Status Register 1 - color emulation */ +#define IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */ +#define PEL_D 0x3C9 /* PEL Data Register */ +#define PEL_MSK 0x3C6 /* PEL mask register */ + +/* EGA-specific registers */ +#define GRA_E0 0x3CC /* Graphics enable processor 0 */ +#define GRA_E1 0x3CA /* Graphics enable processor 1 */ + + +/* VGA index register ports */ +#define CRT_IC 0x3D4 /* CRT Controller Index - color emulation */ +#define CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */ +#define ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */ +#define GRA_I 0x3CE /* Graphics Controller Index */ +#define SEQ_I 0x3C4 /* Sequencer Index */ +#define PEL_IW 0x3C8 /* PEL Write Index */ +#define PEL_IR 0x3C7 /* PEL Read Index */ + +/* standard VGA indexes max counts */ +#define CRTC_C 25 /* 25 CRT Controller Registers sequentially set*/ + // the remainder are not in the par array +#define ATT_C 21 /* 21 Attribute Controller Registers */ +#define GRA_C 9 /* 9 Graphics Controller Registers */ +#define SEQ_C 5 /* 5 Sequencer Registers */ +#define MIS_C 1 /* 1 Misc Output Register */ + +#define CRTC_H_TOTAL 0 +#define CRTC_H_DISP 1 +#define CRTC_H_BLANK_START 2 +#define CRTC_H_BLANK_END 3 +#define CRTC_H_SYNC_START 4 +#define CRTC_H_SYNC_END 5 +#define CRTC_V_TOTAL 6 +#define CRTC_OVERFLOW 7 +#define CRTC_PRESET_ROW 8 +#define CRTC_MAX_SCAN 9 +#define CRTC_CURSOR_START 0x0A +#define CRTC_CURSOR_END 0x0B +#define CRTC_START_HI 0x0C +#define CRTC_START_LO 0x0D +#define CRTC_CURSOR_HI 0x0E +#define CRTC_CURSOR_LO 0x0F +#define CRTC_V_SYNC_START 0x10 +#define CRTC_V_SYNC_END 0x11 +#define CRTC_V_DISP_END 0x12 +#define CRTC_OFFSET 0x13 +#define CRTC_UNDERLINE 0x14 +#define CRTC_V_BLANK_START 0x15 +#define CRTC_V_BLANK_END 0x16 +#define CRTC_MODE 0x17 +#define CRTC_LINE_COMPARE 0x18 + +#define ATC_MODE 0x10 +#define ATC_OVERSCAN 0x11 +#define ATC_PLANE_ENABLE 0x12 +#define ATC_PEL 0x13 +#define ATC_COLOR_PAGE 0x14 + +#define SEQ_CLOCK_MODE 0x01 +#define SEQ_PLANE_WRITE 0x02 +#define SEQ_CHARACTER_MAP 0x03 +#define SEQ_MEMORY_MODE 0x04 + +#define GDC_SR_VALUE 0x00 +#define GDC_SR_ENABLE 0x01 +#define GDC_COMPARE_VALUE 0x02 +#define GDC_DATA_ROTATE 0x03 +#define GDC_PLANE_READ 0x04 +#define GDC_MODE 0x05 +#define GDC_MISC 0x06 +#define GDC_COMPARE_MASK 0x07 +#define GDC_BIT_MASK 0x08 + +// text attributes +#define VGA_ATTR_CLR_RED 0x4 +#define VGA_ATTR_CLR_GRN 0x2 +#define VGA_ATTR_CLR_BLU 0x1 +#define VGA_ATTR_CLR_YEL (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN) +#define VGA_ATTR_CLR_CYN (VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU) +#define VGA_ATTR_CLR_MAG (VGA_ATTR_CLR_BLU | VGA_ATTR_CLR_RED) +#define VGA_ATTR_CLR_BLK 0 +#define VGA_ATTR_CLR_WHT (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU) +#define VGA_ATTR_BNK 0x80 +#define VGA_ATTR_ITN 0x08 + +/* + * vga register parameters + * these are copied to the + * registers. + * + */ +struct vga_par { + u8 crtc[CRTC_C]; + u8 atc[ATT_C]; + u8 gdc[GRA_C]; + u8 seq[SEQ_C]; + u8 misc; // the misc register, MIS_W + u8 vss; +}; + + +/* Interpretation of offset for color fields: All offsets are from the right, + * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you + * can use the offset as right argument to <<). A pixel afterwards is a bit + * stream and is written to video memory as that unmodified. This implies + * big-endian byte order if bits_per_pixel is greater than 8. + */ +struct fb_bitfield { + __u32 offset; /* beginning of bitfield */ + __u32 length; /* length of bitfield */ + __u32 msb_right; /* != 0 : Most significant bit is */ + /* right */ +}; + +struct screeninfo { + __u32 xres; /* visible resolution */ + __u32 yres; + __u32 xres_virtual; /* virtual resolution */ + __u32 yres_virtual; + __u32 xoffset; /* offset from virtual to visible */ + __u32 yoffset; /* resolution */ + + __u32 bits_per_pixel; /* guess what */ + __u32 grayscale; /* != 0 Graylevels instead of colors */ + + struct fb_bitfield red; /* bitfield in fb mem if true color, */ + struct fb_bitfield green; /* else only length is significant */ + struct fb_bitfield blue; + struct fb_bitfield transp; /* transparency */ + + __u32 nonstd; /* != 0 Non standard pixel format */ + + __u32 activate; /* see FB_ACTIVATE_* */ + + __u32 height; /* height of picture in mm */ + __u32 width; /* width of picture in mm */ + + __u32 accel_flags; /* acceleration flags (hints) */ + + /* Timing: All values in pixclocks, except pixclock (of course) */ + __u32 pixclock; /* pixel clock in ps (pico seconds) */ + __u32 left_margin; /* time from sync to picture */ + __u32 right_margin; /* time from picture to sync */ + __u32 upper_margin; /* time from sync to picture */ + __u32 lower_margin; + __u32 hsync_len; /* length of horizontal sync */ + __u32 vsync_len; /* length of vertical sync */ + __u32 sync; /* sync polarity */ + __u32 vmode; /* interlaced etc */ + __u32 reserved[6]; /* Reserved for future compatibility */ +}; + +#endif |