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.6KB

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