Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

realmode.h 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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_OR_UBDL );
  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. * Convert segment:offset address to user buffer
  64. *
  65. * @v segment Real-mode segment
  66. * @v offset Real-mode offset
  67. * @ret buffer User buffer
  68. */
  69. static inline __always_inline userptr_t
  70. real_to_user ( unsigned int segment, unsigned int offset ) {
  71. return ( phys_to_user ( ( segment << 4 ) + offset ) );
  72. }
  73. /**
  74. * Copy data to base memory
  75. *
  76. * @v dest_seg Destination segment
  77. * @v dest_off Destination offset
  78. * @v src Source
  79. * @v len Length
  80. */
  81. static inline __always_inline void
  82. copy_to_real ( unsigned int dest_seg, unsigned int dest_off,
  83. void *src, size_t n ) {
  84. copy_to_user ( real_to_user ( dest_seg, dest_off ), 0, src, n );
  85. }
  86. /**
  87. * Copy data to base memory
  88. *
  89. * @v dest Destination
  90. * @v src_seg Source segment
  91. * @v src_off Source offset
  92. * @v len Length
  93. */
  94. static inline __always_inline void
  95. copy_from_real ( void *dest, unsigned int src_seg,
  96. unsigned int src_off, size_t n ) {
  97. copy_from_user ( dest, real_to_user ( src_seg, src_off ), 0, n );
  98. }
  99. /**
  100. * Write a single variable to base memory
  101. *
  102. * @v var Variable to write
  103. * @v dest_seg Destination segment
  104. * @v dest_off Destination offset
  105. */
  106. #define put_real( var, dest_seg, dest_off ) \
  107. copy_to_real ( (dest_seg), (dest_off), &(var), sizeof (var) )
  108. /**
  109. * Read a single variable from base memory
  110. *
  111. * @v var Variable to read
  112. * @v src_seg Source segment
  113. * @v src_off Source offset
  114. */
  115. #define get_real( var, src_seg, src_off ) \
  116. copy_from_real ( &(var), (src_seg), (src_off), sizeof (var) )
  117. /*
  118. * REAL_CODE ( asm_code_str )
  119. *
  120. * This can be used in inline assembly to create a fragment of code
  121. * that will execute in real mode. For example: to write a character
  122. * to the BIOS console using INT 10, you would do something like:
  123. *
  124. * __asm__ __volatile__ ( REAL_CODE ( "int $0x16" )
  125. * : "=a" ( character ) : "a" ( 0x0000 ) );
  126. *
  127. */
  128. #endif /* REALMODE_H */