176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef REALMODE_H
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define REALMODE_H
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdint.h>
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <registers.h>
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/uaccess.h>
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Data structures and type definitions
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1376d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL2_OR_LATER );
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Declaration of variables in .data16
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * To place a variable in the .data16 segment, declare it using the
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * pattern:
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   int __data16 ( foo );
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   #define foo __use_data16 ( foo );
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   extern uint32_t __data16 ( bar );
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   #define bar __use_data16 ( bar );
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   static long __data16 ( baz ) = 0xff000000UL;
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   #define baz __use_data16 ( baz );
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * i.e. take a normal declaration, add __data16() around the variable
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * name, and add a line saying "#define <name> __use_data16 ( <name> )
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * You can then access them just like any other variable, for example
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   int x = foo + bar;
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This magic is achieved at a cost of only around 7 extra bytes per
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * group of accesses to .data16 variables.  When using KEEP_IT_REAL,
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * there is no extra cost.
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * You should place variables in .data16 when they need to be accessed
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * by real-mode code.  Real-mode assembly (e.g. as created by
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * REAL_CODE()) can access these variables via the usual data segment.
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * You can therefore write something like
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   static uint16_t __data16 ( foo );
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   #define foo __use_data16 ( foo )
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   int bar ( void ) {
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *     __asm__ __volatile__ ( REAL_CODE ( "int $0xff\n\t"
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *                                        "movw %ax, foo" )
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *                            : : );
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *     return foo;
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   }
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Variables may also be placed in .text16 using __text16 and
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * __use_text16.  Some variables (e.g. chained interrupt vectors) fit
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * most naturally in .text16; most should be in .data16.
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * If you have only a pointer to a magic symbol within .data16 or
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * .text16, rather than the symbol itself, you can attempt to extract
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the underlying symbol name using __from_data16() or
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * __from_text16().  This is not for the faint-hearted; check the
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * assembler output to make sure that it's doing the right thing.
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copy data to base memory
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v dest_seg		Destination segment
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v dest_off		Destination offset
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v src		Source
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v len		Length
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline __always_inline void
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmancopy_to_real ( unsigned int dest_seg, unsigned int dest_off,
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	       void *src, size_t n ) {
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	copy_to_user ( real_to_user ( dest_seg, dest_off ), 0, src, n );
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copy data to base memory
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v dest		Destination
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v src_seg		Source segment
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v src_off		Source offset
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v len		Length
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline __always_inline void
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmancopy_from_real ( void *dest, unsigned int src_seg,
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		 unsigned int src_off, size_t n ) {
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	copy_from_user ( dest, real_to_user ( src_seg, src_off ), 0, n );
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Write a single variable to base memory
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v var		Variable to write
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v dest_seg		Destination segment
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v dest_off		Destination offset
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define put_real( var, dest_seg, dest_off ) \
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	copy_to_real ( (dest_seg), (dest_off), &(var), sizeof (var) )
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Read a single variable from base memory
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v var		Variable to read
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v src_seg		Source segment
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v src_off		Source offset
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define get_real( var, src_seg, src_off ) \
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	copy_from_real ( &(var), (src_seg), (src_off), sizeof (var) )
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * REAL_CODE ( asm_code_str )
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This can be used in inline assembly to create a fragment of code
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * that will execute in real mode.  For example: to write a character
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * to the BIOS console using INT 10, you would do something like:
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *     __asm__ __volatile__ ( REAL_CODE ( "int $0x16" )
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *			      : "=a" ( character ) : "a" ( 0x0000 ) );
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* REALMODE_H */
128