您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

realmode.h 3.5KB

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