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