You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

realmode.h 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #ifndef REALMODE_H
  2. #define REALMODE_H
  3. #include <stdint.h>
  4. #include <registers.h>
  5. #include <ipxe/uaccess.h>
  6. /*
  7. * Data structures and type definitions
  8. *
  9. */
  10. FILE_LICENCE ( GPL2_OR_LATER );
  11. /*
  12. * Declaration of variables in .data16
  13. *
  14. * To place a variable in the .data16 segment, declare it using the
  15. * pattern:
  16. *
  17. * int __data16 ( foo );
  18. * #define foo __use_data16 ( foo );
  19. *
  20. * extern uint32_t __data16 ( bar );
  21. * #define bar __use_data16 ( bar );
  22. *
  23. * static long __data16 ( baz ) = 0xff000000UL;
  24. * #define baz __use_data16 ( baz );
  25. *
  26. * i.e. take a normal declaration, add __data16() around the variable
  27. * name, and add a line saying "#define <name> __use_data16 ( <name> )
  28. *
  29. * You can then access them just like any other variable, for example
  30. *
  31. * int x = foo + bar;
  32. *
  33. * This magic is achieved at a cost of only around 7 extra bytes per
  34. * group of accesses to .data16 variables. When using KEEP_IT_REAL,
  35. * there is no extra cost.
  36. *
  37. * You should place variables in .data16 when they need to be accessed
  38. * by real-mode code. Real-mode assembly (e.g. as created by
  39. * REAL_CODE()) can access these variables via the usual data segment.
  40. * You can therefore write something like
  41. *
  42. * static uint16_t __data16 ( foo );
  43. * #define foo __use_data16 ( foo )
  44. *
  45. * int bar ( void ) {
  46. * __asm__ __volatile__ ( REAL_CODE ( "int $0xff\n\t"
  47. * "movw %ax, foo" )
  48. * : : );
  49. * return foo;
  50. * }
  51. *
  52. * Variables may also be placed in .text16 using __text16 and
  53. * __use_text16. Some variables (e.g. chained interrupt vectors) fit
  54. * most naturally in .text16; most should be in .data16.
  55. *
  56. * If you have only a pointer to a magic symbol within .data16 or
  57. * .text16, rather than the symbol itself, you can attempt to extract
  58. * the underlying symbol name using __from_data16() or
  59. * __from_text16(). This is not for the faint-hearted; check the
  60. * assembler output to make sure that it's doing the right thing.
  61. */
  62. /**
  63. * Copy data to base memory
  64. *
  65. * @v dest_seg Destination segment
  66. * @v dest_off Destination offset
  67. * @v src Source
  68. * @v len Length
  69. */
  70. static inline __always_inline void
  71. copy_to_real ( unsigned int dest_seg, unsigned int dest_off,
  72. void *src, size_t n ) {
  73. copy_to_user ( real_to_user ( dest_seg, dest_off ), 0, src, n );
  74. }
  75. /**
  76. * Copy data to base memory
  77. *
  78. * @v dest Destination
  79. * @v src_seg Source segment
  80. * @v src_off Source offset
  81. * @v len Length
  82. */
  83. static inline __always_inline void
  84. copy_from_real ( void *dest, unsigned int src_seg,
  85. unsigned int src_off, size_t n ) {
  86. copy_from_user ( dest, real_to_user ( src_seg, src_off ), 0, n );
  87. }
  88. /**
  89. * Write a single variable to base memory
  90. *
  91. * @v var Variable to write
  92. * @v dest_seg Destination segment
  93. * @v dest_off Destination offset
  94. */
  95. #define put_real( var, dest_seg, dest_off ) \
  96. copy_to_real ( (dest_seg), (dest_off), &(var), sizeof (var) )
  97. /**
  98. * Read a single variable from base memory
  99. *
  100. * @v var Variable to read
  101. * @v src_seg Source segment
  102. * @v src_off Source offset
  103. */
  104. #define get_real( var, src_seg, src_off ) \
  105. copy_from_real ( &(var), (src_seg), (src_off), sizeof (var) )
  106. /*
  107. * REAL_CODE ( asm_code_str )
  108. *
  109. * This can be used in inline assembly to create a fragment of code
  110. * that will execute in real mode. For example: to write a character
  111. * to the BIOS console using INT 10, you would do something like:
  112. *
  113. * __asm__ __volatile__ ( REAL_CODE ( "int $0x16" )
  114. * : "=a" ( character ) : "a" ( 0x0000 ) );
  115. *
  116. */
  117. #endif /* REALMODE_H */