bios_detect_memory.S 2.6 KB

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