Home | History | Annotate | Download | only in include
      1 /* ----------------------------------------------------------------------- *
      2  *
      3  *   Copyright 2002-2009 H. Peter Anvin - All Rights Reserved
      4  *   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
      5  *
      6  *   Permission is hereby granted, free of charge, to any person
      7  *   obtaining a copy of this software and associated documentation
      8  *   files (the "Software"), to deal in the Software without
      9  *   restriction, including without limitation the rights to use,
     10  *   copy, modify, merge, publish, distribute, sublicense, and/or
     11  *   sell copies of the Software, and to permit persons to whom
     12  *   the Software is furnished to do so, subject to the following
     13  *   conditions:
     14  *
     15  *   The above copyright notice and this permission notice shall
     16  *   be included in all copies or substantial portions of the Software.
     17  *
     18  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     19  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
     20  *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     21  *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     22  *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     23  *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     24  *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     25  *   OTHER DEALINGS IN THE SOFTWARE.
     26  *
     27  * ----------------------------------------------------------------------- */
     28 
     29 /*
     30  * com32.h
     31  *
     32  * Common declarations for com32 programs.
     33  */
     34 
     35 #ifndef _COM32_H
     36 #define _COM32_H
     37 
     38 #include <stdint.h>
     39 #include <stdbool.h>
     40 #include <stddef.h>
     41 #include <klibc/compiler.h>	/* For __cdecl */
     42 
     43 /*
     44  * This structure defines the register frame used by the
     45  * system call interface.
     46  *
     47  * The syscall interface is:
     48  *
     49  * __intcall(interrupt_#, source_regs, return_regs)
     50  * __farcall(seg, offs, source_regs, return_regs)
     51  */
     52 typedef union {
     53     uint32_t l;
     54     uint16_t w[2];
     55     uint8_t b[4];
     56 } reg32_t;
     57 
     58 typedef struct {
     59     uint16_t gs;		/* Offset  0 */
     60     uint16_t fs;		/* Offset  2 */
     61     uint16_t es;		/* Offset  4 */
     62     uint16_t ds;		/* Offset  6 */
     63 
     64     reg32_t edi;		/* Offset  8 */
     65     reg32_t esi;		/* Offset 12 */
     66     reg32_t ebp;		/* Offset 16 */
     67     reg32_t _unused_esp;	/* Offset 20 */
     68     reg32_t ebx;		/* Offset 24 */
     69     reg32_t edx;		/* Offset 28 */
     70     reg32_t ecx;		/* Offset 32 */
     71     reg32_t eax;		/* Offset 36 */
     72 
     73     reg32_t eflags;		/* Offset 40 */
     74 } com32sys_t;
     75 
     76 /* EFLAGS definitions */
     77 #define EFLAGS_CF		0x00000001
     78 #define EFLAGS_PF		0x00000004
     79 #define EFLAGS_AF		0x00000010
     80 #define EFLAGS_ZF		0x00000040
     81 #define EFLAGS_SF		0x00000080
     82 #define EFLAGS_TF		0x00000100
     83 #define EFLAGS_IF		0x00000200
     84 #define EFLAGS_DF		0x00000400
     85 #define EFLAGS_OF		0x00000800
     86 #define EFLAGS_IOPL		0x00003000
     87 #define EFLAGS_NT		0x00004000
     88 #define EFLAGS_RF		0x00010000
     89 #define EFLAGS_VM		0x00020000
     90 #define EFLAGS_AC		0x00040000
     91 #define EFLAGS_VIF		0x00080000
     92 #define EFLAGS_VIP		0x00100000
     93 #define EFLAGS_ID		0x00200000
     94 
     95 struct com32_pmapi;
     96 
     97 extern struct com32_sys_args {
     98     uint32_t cs_sysargs;
     99     char *cs_cmdline;
    100     void __cdecl (*cs_intcall)(uint8_t, const com32sys_t *, com32sys_t *);
    101     void *cs_bounce;
    102     uint32_t cs_bounce_size;
    103     void __cdecl (*cs_farcall)(uint32_t, const com32sys_t *, com32sys_t *);
    104     int __cdecl (*cs_cfarcall)(uint32_t, const void *, uint32_t);
    105     uint32_t cs_memsize;
    106     const char *cs_name;
    107     const struct com32_pmapi *cs_pm;
    108 } __com32;
    109 
    110 /*
    111  * System call wrapper functions
    112  */
    113 void __intcall(uint8_t __i, const com32sys_t * __sr, com32sys_t * __dr);
    114 void __farcall(uint16_t __cs, uint16_t __ip,
    115 	       const com32sys_t * __sr, com32sys_t * __dr);
    116 int __cfarcall(uint16_t __cs, uint16_t __ip,
    117 	       const void *__stack, uint32_t __stack_size);
    118 extern const com32sys_t __com32_zero_regs;
    119 
    120 /*
    121  * Lowmem allocation functions
    122  */
    123 void *lmalloc(size_t);
    124 void *lzalloc(size_t);
    125 void lfree(void *);
    126 char *lstrdup(const char *);
    127 
    128 /*
    129  * These functions convert between linear pointers in the range
    130  * 0..0xFFFFF and real-mode style SEG:OFFS pointers.  Note that a
    131  * 32-bit linear pointer is not compatible with a SEG:OFFS pointer
    132  * stored in two consecutive 16-bit words.
    133  *
    134  * Use OFFS_WRT() if you want to compute an offset relative to a
    135  * specific segment.  OFFS_VALID() will return whether or not the
    136  * pointer is actually reachable from the target segment.
    137  */
    138 #if defined(CORE_DEBUG) && (defined(__COM32__) || defined(__SYSLINUX_CORE__))
    139 __noreturn __bad_SEG(const volatile void *);
    140 
    141 static inline uint16_t SEG(const volatile void *__p)
    142 {
    143     if (__unlikely((uintptr_t)__p > 0xfffff))
    144 	__bad_SEG(__p);
    145 
    146     return (uint16_t) (((uintptr_t) __p) >> 4);
    147 }
    148 #else
    149 static inline uint16_t SEG(const volatile void *__p)
    150 {
    151     return (uint16_t) (((uintptr_t) __p) >> 4);
    152 }
    153 #endif
    154 
    155 static inline uint16_t OFFS(const volatile void *__p)
    156 {
    157     /* The double cast here is to shut up gcc */
    158     return (uint16_t) (uintptr_t) __p & 0x000F;
    159 }
    160 
    161 static inline uint16_t OFFS_WRT(const volatile void *__p, uint16_t __seg)
    162 {
    163     return (uint16_t) ((uintptr_t) __p - ((uintptr_t) __seg << 4));
    164 }
    165 
    166 #define OFFS_VALID(p,s) _OFFS_VALID((p), sizeof *(p), (s))
    167 
    168 static inline bool _OFFS_VALID(const volatile void *__p, size_t __s,
    169 			       uint16_t __seg)
    170 {
    171     uintptr_t __segstart = (uintptr_t)__seg << 4;
    172     uintptr_t __offs  = (uintptr_t)__p - __segstart;
    173 
    174     return __offs <= 0x10000-__s;
    175 }
    176 
    177 static inline void *MK_PTR(uint16_t __seg, uint16_t __offs)
    178 {
    179     return (void *)(unsigned long)((__seg << 4) + __offs);
    180 }
    181 
    182 /* Some tools to handle 16:16 far pointers in memory */
    183 
    184 struct __far_ptr {
    185     union {
    186 	uint32_t ptr;
    187 	struct {
    188 	    uint16_t offs, seg;
    189 	};
    190     };
    191 } __attribute__ ((packed));
    192 
    193 typedef struct __far_ptr far_ptr_t;
    194 
    195 static inline void *GET_PTR(far_ptr_t __fptr)
    196 {
    197     return MK_PTR(__fptr.seg, __fptr.offs);
    198 }
    199 
    200 static inline far_ptr_t FAR_PTR(void *__ptr)
    201 {
    202     far_ptr_t __fptr;
    203 
    204     __fptr.offs = OFFS(__ptr);
    205     __fptr.seg  = SEG(__ptr);
    206     return __fptr;
    207 }
    208 
    209 extern const char *com32_cmdline(void);
    210 
    211 #endif /* _COM32_H */
    212