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.

basemem.c 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. #ifdef PCBIOS
  2. #include "etherboot.h"
  3. #include "realmode.h" /* for real_mode_stack */
  4. /* Routines to allocate base memory in a BIOS-compatible way, by
  5. * updating the Free Base Memory Size counter at 40:13h.
  6. *
  7. * Michael Brown <mbrown@fensystems.co.uk> (mcb30)
  8. * $Id$
  9. */
  10. #define fbms ( ( uint16_t * ) phys_to_virt ( 0x413 ) )
  11. #define BASE_MEMORY_MAX ( 640 )
  12. #define FREE_BLOCK_MAGIC ( ('!'<<0) + ('F'<<8) + ('R'<<16) + ('E'<<24) )
  13. #define FREE_BASE_MEMORY ( (uint32_t) ( *fbms << 10 ) )
  14. /* Prototypes */
  15. void * _allot_base_memory ( size_t size );
  16. void _forget_base_memory ( void *ptr, size_t size );
  17. typedef struct free_base_memory_block {
  18. uint32_t magic;
  19. uint16_t size_kb;
  20. } free_base_memory_block_t;
  21. /* Return amount of free base memory in bytes
  22. */
  23. uint32_t get_free_base_memory ( void ) {
  24. return FREE_BASE_MEMORY;
  25. }
  26. /* Start of our image in base memory.
  27. */
  28. #define __text16_nocompress __attribute__ ((section (".text16.nocompress")))
  29. uint32_t image_basemem __text16_nocompress = 0;
  30. uint32_t image_basemem_size __text16_nocompress = 0;
  31. /* Allot/free the real-mode stack
  32. */
  33. void allot_real_mode_stack ( void )
  34. {
  35. void *new_real_mode_stack;
  36. if ( lock_real_mode_stack )
  37. return;
  38. /* This is evil hack.
  39. * Until we have a real_mode stack use 0x7c00.
  40. * Except for 0 - 0x600 membory below 0x7c00 is hardly every used.
  41. * This stack should never be used unless the stack allocation fails,
  42. * or if someone has placed a print statement in a dangerous location.
  43. */
  44. if (!real_mode_stack) {
  45. real_mode_stack = 0x7c00;
  46. }
  47. new_real_mode_stack = _allot_base_memory ( real_mode_stack_size );
  48. if ( ! new_real_mode_stack ) {
  49. printf ( "FATAL: No real-mode stack\n" );
  50. while ( 1 ) {};
  51. }
  52. real_mode_stack = virt_to_phys ( new_real_mode_stack );
  53. get_memsizes();
  54. }
  55. void forget_real_mode_stack ( void )
  56. {
  57. if ( lock_real_mode_stack )
  58. return;
  59. if ( real_mode_stack) {
  60. _forget_base_memory ( phys_to_virt(real_mode_stack),
  61. real_mode_stack_size );
  62. /* get_memsizes() uses the real_mode stack we just freed
  63. * for it's BIOS calls.
  64. */
  65. get_memsizes();
  66. real_mode_stack = 0;
  67. }
  68. }
  69. /* Allocate N bytes of base memory. Amount allocated will be rounded
  70. * up to the nearest kB, since that's the granularity of the BIOS FBMS
  71. * counter. Returns NULL if memory cannot be allocated.
  72. */
  73. static void * _allot_base_memory ( size_t size )
  74. {
  75. uint16_t size_kb = ( size + 1023 ) >> 10;
  76. void *ptr = NULL;
  77. #ifdef DEBUG_BASEMEM
  78. printf ( "Trying to allocate %d kB of base memory from %d kB free\n",
  79. size_kb, *fbms );
  80. #endif
  81. /* Free up any unused memory before we start */
  82. free_unused_base_memory();
  83. /* Check available base memory */
  84. if ( size_kb > *fbms ) { return NULL; }
  85. /* Reduce available base memory */
  86. *fbms -= size_kb;
  87. /* Calculate address of memory allocated */
  88. ptr = phys_to_virt ( FREE_BASE_MEMORY );
  89. /* Zero out memory. We do this so that allocation of
  90. * already-used space will show up in the form of a crash as
  91. * soon as possible.
  92. *
  93. * Update: there's another reason for doing this. If we don't
  94. * zero the contents, then they could still retain our "free
  95. * block" markers and be liable to being freed whenever a
  96. * base-memory allocation routine is next called.
  97. */
  98. memset ( ptr, 0, size_kb << 10 );
  99. #ifdef DEBUG_BASEMEM
  100. printf ( "Allocated %d kB at [%x,%x)\n", size_kb,
  101. virt_to_phys ( ptr ),
  102. virt_to_phys ( ptr ) + size_kb * 1024 );
  103. #endif
  104. return ptr;
  105. }
  106. void * allot_base_memory ( size_t size )
  107. {
  108. void *ptr;
  109. /* Free real-mode stack, allocate memory, reallocate real-mode
  110. * stack.
  111. */
  112. forget_real_mode_stack();
  113. ptr = _allot_base_memory ( size );
  114. get_memsizes();
  115. return ptr;
  116. }
  117. /* Free base memory allocated by allot_base_memory. The BIOS provides
  118. * nothing better than a LIFO mechanism for freeing memory (i.e. it
  119. * just has the single "total free memory" counter), but we improve
  120. * upon this slightly; as long as you free all the allotted blocks, it
  121. * doesn't matter what order you free them in. (This will only work
  122. * for blocks that are freed via forget_base_memory()).
  123. *
  124. * Yes, it's annoying that you have to remember the size of the blocks
  125. * you've allotted. However, since our granularity of allocation is
  126. * 1K, the alternative is to risk wasting the occasional kB of base
  127. * memory, which is a Bad Thing. Really, you should be using as
  128. * little base memory as possible, so consider the awkwardness of the
  129. * API to be a feature! :-)
  130. */
  131. static void _forget_base_memory ( void *ptr, size_t size )
  132. {
  133. uint16_t remainder = virt_to_phys(ptr) & 1023;
  134. uint16_t size_kb = ( size + remainder + 1023 ) >> 10;
  135. free_base_memory_block_t *free_block =
  136. ( free_base_memory_block_t * ) ( ptr - remainder );
  137. if ( ( ptr == NULL ) || ( size == 0 ) ) {
  138. return;
  139. }
  140. #ifdef DEBUG_BASEMEM
  141. printf ( "Trying to free %d bytes base memory at 0x%x\n",
  142. size, virt_to_phys ( ptr ) );
  143. if ( remainder > 0 ) {
  144. printf ( "WARNING: destructively expanding free block "
  145. "downwards to 0x%x\n",
  146. virt_to_phys ( ptr - remainder ) );
  147. }
  148. #endif
  149. /* Mark every kilobyte within this block as free. This is
  150. * overkill for normal purposes, but helps when something has
  151. * allocated base memory with a granularity finer than the
  152. * BIOS granularity of 1kB. PXE ROMs tend to do this when
  153. * they allocate their own memory. This method allows us to
  154. * free their blocks (admittedly in a rather dangerous,
  155. * tread-on-anything-either-side sort of way, but there's no
  156. * other way to do it).
  157. *
  158. * Since we're marking every kB as free, there's actually no
  159. * need for recording the size of the blocks. However, we
  160. * keep this in so that debug messages are friendlier. It
  161. * probably adds around 8 bytes to the overall code size.
  162. */
  163. while ( size_kb > 0 ) {
  164. /* Mark this block as unused */
  165. free_block->magic = FREE_BLOCK_MAGIC;
  166. free_block->size_kb = size_kb;
  167. /* Move up by 1 kB */
  168. free_block = (void *)(((char *)free_block) + (1 << 10));
  169. size_kb--;
  170. }
  171. /* Free up unused base memory */
  172. free_unused_base_memory();
  173. }
  174. void forget_base_memory ( void *ptr, size_t size )
  175. {
  176. /* Free memory, free real-mode stack, re-allocate real-mode
  177. * stack. Do this so that we don't end up wasting a huge
  178. * block of memory trapped behind the real-mode stack.
  179. */
  180. _forget_base_memory ( ptr, size );
  181. forget_real_mode_stack();
  182. get_memsizes();
  183. }
  184. /* Do the actual freeing of memory. This is split out from
  185. * forget_base_memory() so that it may be called separately. It
  186. * should be called whenever base memory is deallocated by an external
  187. * entity (if we can detect that it has done so) so that we get the
  188. * chance to free up our own blocks.
  189. */
  190. static void free_unused_base_memory ( void ) {
  191. free_base_memory_block_t *free_block = NULL;
  192. /* Try to release memory back to the BIOS. Free all
  193. * consecutive blocks marked as free.
  194. */
  195. while ( 1 ) {
  196. /* Calculate address of next potential free block */
  197. free_block = ( free_base_memory_block_t * )
  198. phys_to_virt ( FREE_BASE_MEMORY );
  199. /* Stop processing if we're all the way up to 640K or
  200. * if this is not a free block
  201. */
  202. if ( ( *fbms == BASE_MEMORY_MAX ) ||
  203. ( free_block->magic != FREE_BLOCK_MAGIC ) ) {
  204. break;
  205. }
  206. /* Return memory to BIOS */
  207. *fbms += free_block->size_kb;
  208. #ifdef DEBUG_BASEMEM
  209. printf ( "Freed %d kB base memory, %d kB now free\n",
  210. free_block->size_kb, *fbms );
  211. #endif
  212. /* Zero out freed block. We do this in case
  213. * the block contained any structures that
  214. * might be located by scanning through
  215. * memory.
  216. */
  217. memset ( free_block, 0, free_block->size_kb << 10 );
  218. }
  219. }
  220. /* Free base memory used by the prefix. Called once at start of
  221. * Etherboot by arch_main().
  222. */
  223. void forget_prefix_base_memory ( void )
  224. {
  225. /* runtime_start_kb is _text rounded down to a physical kB boundary */
  226. uint32_t runtime_start_kb = virt_to_phys(_text) & ~0x3ff;
  227. /* prefix_size_kb is the prefix size excluding any portion
  228. * that overlaps into the first kB used by the runtime image
  229. */
  230. uint32_t prefix_size_kb = runtime_start_kb - image_basemem;
  231. #ifdef DEBUG_BASEMEM
  232. printf ( "Attempting to free base memory used by prefix\n" );
  233. #endif
  234. /* If the decompressor is in allocated base memory
  235. * *and* the Etherboot text is in base
  236. * memory, then free the decompressor.
  237. */
  238. if ( ( image_basemem >= FREE_BASE_MEMORY ) &&
  239. ( runtime_start_kb >= FREE_BASE_MEMORY ) &&
  240. ( runtime_start_kb <= ( BASE_MEMORY_MAX << 10 ) ) )
  241. {
  242. forget_base_memory ( phys_to_virt ( image_basemem ),
  243. prefix_size_kb );
  244. /* Update image_basemem and image_basemem_size to
  245. * indicate that our allocation now starts with _text
  246. */
  247. image_basemem = runtime_start_kb;
  248. image_basemem_size -= prefix_size_kb;
  249. }
  250. }
  251. /* Free base memory used by the runtime image. Called after
  252. * relocation by arch_relocated_from().
  253. */
  254. void forget_runtime_base_memory ( unsigned long old_addr )
  255. {
  256. /* text_start_kb is old _text rounded down to a physical KB boundary */
  257. uint32_t old_text_start_kb = old_addr & ~0x3ff;
  258. #ifdef DEBUG_BASEMEM
  259. printf ( "Attempting to free base memory used by runtime image\n" );
  260. #endif
  261. if ( ( image_basemem >= FREE_BASE_MEMORY ) &&
  262. ( image_basemem == old_text_start_kb ) )
  263. {
  264. forget_base_memory ( phys_to_virt ( image_basemem ),
  265. image_basemem_size );
  266. /* Update image_basemem to show no longer in use */
  267. image_basemem = 0;
  268. image_basemem_size = 0;
  269. }
  270. }
  271. #endif /* PCBIOS */