bios_detect_memory.S 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #include "common.h"
  2. BEGIN
  3. CLEAR
  4. STAGE2
  5. mov $output, %di
  6. call do_e820
  7. /* Debug aid. */
  8. PRINT_WORD_HEX <%bp>
  9. PRINT_NEWLINE
  10. mov %bp, %ax
  11. mov $0, %dx
  12. /* Each entry is 24 bytes wide. */
  13. mov $24, %cx
  14. mul %cx
  15. PRINT_BYTES $output, <%ax>
  16. hlt
  17. /*
  18. This was copy pasted from:
  19. http://wiki.osdev.org/Detecting_Memory_%28x86%29#Getting_an_E820_Memory_Map
  20. use the INT 0x15, eax= 0xE820 BIOS function to get a memory map
  21. inputs: es:di -> destination buffer for 24 byte entries
  22. outputs: bp = entry count, trashes all registers except esi
  23. */
  24. do_e820:
  25. xorl %ebx,%ebx # ebx must be 0 to start
  26. xorw %bp,%bp # keep an entry count in bp
  27. movl $0x0534D4150,%edx # Place "SMAP" into edx
  28. movl $0xe820,%eax
  29. movl $1, %es:20(%di)
  30. movl $24,%ecx # ask for 24 bytes
  31. int $0x15
  32. jc do_e820.failed # carry set on first call means "unsupported function"
  33. movl $0x0534D4150,%edx # Some BIOSes apparently trash this register?
  34. cmpl %edx,%eax # on success, eax must have been reset to "SMAP"
  35. jne do_e820.failed
  36. testl %ebx,%ebx # ebx = 0 implies list is only 1 entry long (worthless)
  37. je do_e820.failed
  38. jmp do_e820.jmpin
  39. do_e820.e820lp:
  40. movl $0xe820,%eax # eax, ecx get trashed on every int 0x15 call
  41. movl $1, %es:20(%di)
  42. movl $24,%ecx # ask for 24 bytes again
  43. int $0x15
  44. jc do_e820.e820f # carry set means "end of list already reached"
  45. movl $0x0534D4150,%edx # repair potentially trashed register
  46. do_e820.jmpin:
  47. jcxz do_e820.skipent # skip any 0 length entries
  48. cmpb $20,%cl # got a 24 byte ACPI 3.X response?
  49. jbe do_e820.notext
  50. testb $1, %es:29(%di)
  51. je do_e820.skipent
  52. do_e820.notext:
  53. mov %ecx, %es:8(%di)
  54. or %ecx, %es:12(%di)
  55. jz do_e820.skipent # if length uint64_t is 0, skip entry
  56. incw %bp # got a good entry: ++count, move to next storage spot
  57. addw $24,%di
  58. do_e820.skipent:
  59. testl %ebx,%ebx # if ebx resets to 0, list is complete
  60. jne do_e820.e820lp
  61. do_e820.e820f:
  62. #movw %bp,mmap_ent # store the entry count
  63. clc # there is "jc" on end of list to this point, so the carry must be cleared
  64. ret
  65. do_e820.failed:
  66. stc # "function unsupported" error exit
  67. ret
  68. output: