123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- /* 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 */
|