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.

e820mangler.S 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /*
  2. * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. .text
  19. .arch i386
  20. .section ".text16", "ax", @progbits
  21. .section ".data16", "aw", @progbits
  22. .section ".text16.data", "aw", @progbits
  23. .code16
  24. #define SMAP 0x534d4150
  25. /****************************************************************************
  26. * Check for overlap
  27. *
  28. * Parameters:
  29. * %edx:%eax Region start
  30. * %ecx:%ebx Region end
  31. * %si Pointer to hidden region descriptor
  32. * Returns:
  33. * CF set Region overlaps
  34. * CF clear No overlap
  35. ****************************************************************************
  36. */
  37. .section ".text16"
  38. check_overlap:
  39. /* If start >= hidden_end, there is no overlap. */
  40. testl %edx, %edx
  41. jnz no_overlap
  42. cmpl 4(%si), %eax
  43. jae no_overlap
  44. /* If end <= hidden_start, there is no overlap; equivalently,
  45. * if end > hidden_start, there is overlap.
  46. */
  47. testl %ecx, %ecx
  48. jnz overlap
  49. cmpl 0(%si), %ebx
  50. ja overlap
  51. no_overlap:
  52. clc
  53. ret
  54. overlap:
  55. stc
  56. ret
  57. .size check_overlap, . - check_overlap
  58. /****************************************************************************
  59. * Check for overflow/underflow
  60. *
  61. * Parameters:
  62. * %edx:%eax Region start
  63. * %ecx:%ebx Region end
  64. * Returns:
  65. * CF set start < end
  66. * CF clear start >= end
  67. ****************************************************************************
  68. */
  69. .section ".text16"
  70. check_overflow:
  71. pushl %ecx
  72. pushl %ebx
  73. subl %eax, %ebx
  74. sbbl %edx, %ecx
  75. popl %ebx
  76. popl %ecx
  77. ret
  78. .size check_overflow, . - check_overflow
  79. /****************************************************************************
  80. * Truncate towards start of region
  81. *
  82. * Parameters:
  83. * %edx:%eax Region start
  84. * %ecx:%ebx Region end
  85. * %si Pointer to hidden region descriptor
  86. * Returns:
  87. * %edx:%eax Modified region start
  88. * %ecx:%ebx Modified region end
  89. * CF set Region was truncated
  90. * CF clear Region was not truncated
  91. ****************************************************************************
  92. */
  93. .section ".text16"
  94. truncate_to_start:
  95. /* If overlaps, set region end = hidden region start */
  96. call check_overlap
  97. jnc 99f
  98. movl 0(%si), %ebx
  99. xorl %ecx, %ecx
  100. /* If region end < region start, set region end = region start */
  101. call check_overflow
  102. jnc 1f
  103. movl %eax, %ebx
  104. movl %edx, %ecx
  105. 1: stc
  106. 99: ret
  107. .size truncate_to_start, . - truncate_to_start
  108. /****************************************************************************
  109. * Truncate towards end of region
  110. *
  111. * Parameters:
  112. * %edx:%eax Region start
  113. * %ecx:%ebx Region end
  114. * %si Pointer to hidden region descriptor
  115. * Returns:
  116. * %edx:%eax Modified region start
  117. * %ecx:%ebx Modified region end
  118. * CF set Region was truncated
  119. * CF clear Region was not truncated
  120. ****************************************************************************
  121. */
  122. .section ".text16"
  123. truncate_to_end:
  124. /* If overlaps, set region start = hidden region end */
  125. call check_overlap
  126. jnc 99f
  127. movl 4(%si), %eax
  128. xorl %edx, %edx
  129. /* If region start > region end, set region start = region end */
  130. call check_overflow
  131. jnc 1f
  132. movl %ebx, %eax
  133. movl %ecx, %edx
  134. 1: stc
  135. 99: ret
  136. .size truncate_to_end, . - truncate_to_end
  137. /****************************************************************************
  138. * Truncate region
  139. *
  140. * Parameters:
  141. * %edx:%eax Region start
  142. * %ecx:%ebx Region length (*not* region end)
  143. * %bp truncate_to_start or truncate_to_end
  144. * Returns:
  145. * %edx:%eax Modified region start
  146. * %ecx:%ebx Modified region length
  147. * CF set Region was truncated
  148. * CF clear Region was not truncated
  149. ****************************************************************************
  150. */
  151. .section ".text16"
  152. truncate:
  153. pushw %si
  154. pushfw
  155. /* Convert (start,len) to (start,end) */
  156. addl %eax, %ebx
  157. adcl %edx, %ecx
  158. /* Hide all hidden regions, truncating as directed */
  159. movw $hidden_regions, %si
  160. 1: call *%bp
  161. jnc 2f
  162. popfw /* If CF was set, set stored CF in flags word on stack */
  163. stc
  164. pushfw
  165. 2: addw $8, %si
  166. cmpl $0, 0(%si)
  167. jne 1b
  168. /* Convert modified (start,end) back to (start,len) */
  169. subl %eax, %ebx
  170. sbbl %edx, %ecx
  171. popfw
  172. popw %si
  173. ret
  174. .size truncate, . - truncate
  175. /****************************************************************************
  176. * Patch "memory above 1MB" figure
  177. *
  178. * Parameters:
  179. * %ax Memory above 1MB, in 1kB blocks
  180. * Returns:
  181. * %ax Modified memory above 1M in 1kB blocks
  182. * CF set Region was truncated
  183. * CF clear Region was not truncated
  184. ****************************************************************************
  185. */
  186. .section ".text16"
  187. patch_1m:
  188. pushal
  189. /* Convert to (start,len) format and call truncate */
  190. movw $truncate_to_start, %bp
  191. xorl %ecx, %ecx
  192. movzwl %ax, %ebx
  193. shll $10, %ebx
  194. xorl %edx, %edx
  195. movl $0x100000, %eax
  196. call truncate
  197. /* Convert back to "memory above 1MB" format and return via %ax */
  198. pushfw
  199. shrl $10, %ebx
  200. popfw
  201. movw %sp, %bp
  202. movw %bx, 28(%bp)
  203. popal
  204. ret
  205. .size patch_1m, . - patch_1m
  206. /****************************************************************************
  207. * Patch "memory above 16MB" figure
  208. *
  209. * Parameters:
  210. * %bx Memory above 16MB, in 64kB blocks
  211. * Returns:
  212. * %bx Modified memory above 16M in 64kB blocks
  213. * CF set Region was truncated
  214. * CF clear Region was not truncated
  215. ****************************************************************************
  216. */
  217. .section ".text16"
  218. patch_16m:
  219. pushal
  220. /* Convert to (start,len) format and call truncate */
  221. movw $truncate_to_start, %bp
  222. xorl %ecx, %ecx
  223. shll $16, %ebx
  224. xorl %edx, %edx
  225. movl $0x1000000, %eax
  226. call truncate
  227. /* Convert back to "memory above 16MB" format and return via %bx */
  228. pushfw
  229. shrl $16, %ebx
  230. popfw
  231. movw %sp, %bp
  232. movw %bx, 16(%bp)
  233. popal
  234. ret
  235. .size patch_16m, . - patch_16m
  236. /****************************************************************************
  237. * Patch "memory between 1MB and 16MB" and "memory above 16MB" figures
  238. *
  239. * Parameters:
  240. * %ax Memory between 1MB and 16MB, in 1kB blocks
  241. * %bx Memory above 16MB, in 64kB blocks
  242. * Returns:
  243. * %ax Modified memory between 1MB and 16MB, in 1kB blocks
  244. * %bx Modified memory above 16MB, in 64kB blocks
  245. * CF set Region was truncated
  246. * CF clear Region was not truncated
  247. ****************************************************************************
  248. */
  249. .section ".text16"
  250. patch_1m_16m:
  251. call patch_1m
  252. jc 1f
  253. call patch_16m
  254. ret
  255. 1: /* 1m region was truncated; kill the 16m region */
  256. xorw %bx, %bx
  257. ret
  258. .size patch_1m_16m, . - patch_1m_16m
  259. /****************************************************************************
  260. * Patch E820 memory map entry
  261. *
  262. * Parameters:
  263. * %es:di Pointer to E820 memory map descriptor
  264. * %bp truncate_to_start or truncate_to_end
  265. * Returns:
  266. * %es:di Pointer to now-modified E820 memory map descriptor
  267. * CF set Region was truncated
  268. * CF clear Region was not truncated
  269. ****************************************************************************
  270. */
  271. .section ".text16"
  272. patch_e820:
  273. pushal
  274. movl %es:0(%di), %eax
  275. movl %es:4(%di), %edx
  276. movl %es:8(%di), %ebx
  277. movl %es:12(%di), %ecx
  278. call truncate
  279. movl %eax, %es:0(%di)
  280. movl %edx, %es:4(%di)
  281. movl %ebx, %es:8(%di)
  282. movl %ecx, %es:12(%di)
  283. popal
  284. ret
  285. .size patch_e820, . - patch_e820
  286. /****************************************************************************
  287. * Split E820 memory map entry if necessary
  288. *
  289. * Parameters:
  290. * As for INT 15,e820
  291. * Returns:
  292. * As for INT 15,e820
  293. *
  294. * Calls the underlying INT 15,e820 and returns a modified memory map.
  295. * Regions will be split around any hidden regions.
  296. ****************************************************************************
  297. */
  298. .section ".text16"
  299. split_e820:
  300. pushw %si
  301. pushw %bp
  302. /* Caller's %bx => %si, real %ebx to %ebx, call previous handler */
  303. pushfw
  304. movw %bx, %si
  305. testl %ebx, %ebx
  306. jnz 1f
  307. movl %ebx, %cs:real_ebx
  308. 1: movl %cs:real_ebx, %ebx
  309. lcall *%cs:int15_vector
  310. pushfw
  311. /* Edit result */
  312. pushw %ds
  313. pushw %cs:rm_ds
  314. popw %ds
  315. movw $truncate_to_start, %bp
  316. incw %si
  317. jns 2f
  318. movw $truncate_to_end, %bp
  319. 2: call patch_e820
  320. jnc 3f
  321. xorw $0x8000, %si
  322. 3: testw %si, %si
  323. js 4f
  324. movl %ebx, %cs:real_ebx
  325. testl %ebx, %ebx
  326. jz 5f
  327. 4: movw %si, %bx
  328. 5: popw %ds
  329. /* Restore flags returned by previous handler and return */
  330. popfw
  331. popw %bp
  332. popw %si
  333. ret
  334. .size split_e820, . - split_e820
  335. .section ".text16.data"
  336. real_ebx:
  337. .long 0
  338. .size real_ebx, . - real_ebx
  339. /****************************************************************************
  340. * INT 15,e820 handler
  341. ****************************************************************************
  342. */
  343. .section ".text16"
  344. int15_e820:
  345. pushl %eax
  346. pushl %ecx
  347. pushl %edx
  348. call split_e820
  349. pushfw
  350. /* Skip empty region checking if we've reached the end of the
  351. * map or hit an error, to avoid a potential endless loop.
  352. */
  353. jc 1f
  354. testl %ebx, %ebx
  355. jz 1f
  356. /* Check for an empty region */
  357. pushl %eax
  358. movl %es:8(%di), %eax
  359. orl %es:12(%di), %eax
  360. popl %eax
  361. jnz 1f
  362. /* Strip empty regions out of the returned map */
  363. popfw
  364. popl %edx
  365. popl %ecx
  366. popl %eax
  367. jmp int15_e820
  368. /* Restore flags from original INT 15,e820 call and return */
  369. 1: popfw
  370. addr32 leal 12(%esp), %esp /* avoid changing flags */
  371. lret $2
  372. .size int15_e820, . - int15_e820
  373. /****************************************************************************
  374. * INT 15,e801 handler
  375. ****************************************************************************
  376. */
  377. .section ".text16"
  378. int15_e801:
  379. /* Call previous handler */
  380. pushfw
  381. lcall *%cs:int15_vector
  382. pushfw
  383. /* Edit result */
  384. pushw %ds
  385. pushw %cs:rm_ds
  386. popw %ds
  387. call patch_1m_16m
  388. xchgw %ax, %cx
  389. xchgw %bx, %dx
  390. call patch_1m_16m
  391. xchgw %ax, %cx
  392. xchgw %bx, %dx
  393. popw %ds
  394. /* Restore flags returned by previous handler and return */
  395. popfw
  396. lret $2
  397. .size int15_e801, . - int15_e801
  398. /****************************************************************************
  399. * INT 15,88 handler
  400. ****************************************************************************
  401. */
  402. .section ".text16"
  403. int15_88:
  404. /* Call previous handler */
  405. pushfw
  406. lcall *%cs:int15_vector
  407. pushfw
  408. /* Edit result */
  409. pushw %ds
  410. pushw %cs:rm_ds
  411. popw %ds
  412. call patch_1m
  413. popw %ds
  414. /* Restore flags returned by previous handler and return */
  415. popfw
  416. lret $2
  417. .size int15_88, . - int15_88
  418. /****************************************************************************
  419. * INT 15 handler
  420. ****************************************************************************
  421. */
  422. .section ".text16"
  423. .globl int15
  424. int15:
  425. /* See if we want to intercept this call */
  426. pushfw
  427. cmpw $0xe820, %ax
  428. jne 1f
  429. cmpl $SMAP, %edx
  430. jne 1f
  431. popfw
  432. jmp int15_e820
  433. 1: cmpw $0xe801, %ax
  434. jne 2f
  435. popfw
  436. jmp int15_e801
  437. 2: cmpb $0x88, %ah
  438. jne 3f
  439. popfw
  440. jmp int15_88
  441. 3: popfw
  442. ljmp *%cs:int15_vector
  443. .size int15, . - int15
  444. .section ".text16.data"
  445. .globl int15_vector
  446. int15_vector:
  447. .long 0
  448. .size int15_vector, . - int15_vector