multiboot2.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /**
  2. * @file multiboot2.cpp
  3. * @brief multiboot2 解析实现
  4. * @author Zone.N ([email protected])
  5. * @version 1.0
  6. * @date 2021-09-18
  7. * @copyright MIT LICENSE
  8. * https://github.com/Simple-XX/SimpleKernel
  9. * @par change log:
  10. * <table>
  11. * <tr><th>Date<th>Author<th>Description
  12. * <tr><td>2021-09-18<td>digmouse233<td>迁移到 doxygen
  13. * </table>
  14. */
  15. #include "assert.h"
  16. #include "stdio.h"
  17. //#include "common.h"
  18. #include "multiboot2.h"
  19. #include "boot_info.h"
  20. //#include "resource.h"
  21. //#include "pmm.h"
  22. /// @todo 优化
  23. void MULTIBOOT2::multiboot2_iter(bool (*_fun)(const iter_data_t *, void *),
  24. void *_data) {
  25. uintptr_t addr = BOOT_INFO::boot_info_addr;
  26. // 下一字节开始为 tag 信息
  27. iter_data_t *tag = (iter_data_t *)(addr + 8);
  28. for (; tag->type != MULTIBOOT_TAG_TYPE_END;
  29. tag = (iter_data_t *)((uint8_t *)tag + COMMON::ALIGN(tag->size, 8))) {
  30. if (_fun(tag, _data) == true) {
  31. return;
  32. }
  33. }
  34. return;
  35. }
  36. bool MULTIBOOT2::multiboot2_init(void) {
  37. uintptr_t addr = BOOT_INFO::boot_info_addr;
  38. // 判断魔数是否正确
  39. assert(BOOT_INFO::multiboot2_magic == MULTIBOOT2_BOOTLOADER_MAGIC);
  40. assert((reinterpret_cast<uintptr_t>(addr) & 7) == 0);
  41. // addr+0 保存大小
  42. BOOT_INFO::boot_info_size = *(uint32_t *)addr;
  43. return true;
  44. }
  45. // 读取 grub2 传递的物理内存信息,保存到 e820map_t 结构体中
  46. // 一般而言是这样的
  47. // 地址(长度) 类型
  48. // 0x00(0x9F000) 0x1
  49. // 0x9F000(0x1000) 0x2
  50. // 0xE8000(0x18000) 0x2
  51. // 0x100000(0x7EF0000) 0x1
  52. // 0x7FF0000(0x10000) 0x3
  53. // 0xFFFC0000(0x40000) 0x2
  54. bool MULTIBOOT2::get_memory(const iter_data_t *_iter_data, void *_data) {
  55. if (_iter_data->type != MULTIBOOT2::MULTIBOOT_TAG_TYPE_MMAP) {
  56. return false;
  57. }
  58. resource_t *resource = (resource_t *)_data;
  59. resource->type = resource_t::MEM;
  60. resource->name = (char *)"available phy memory";
  61. resource->mem.addr = 0x0;
  62. resource->mem.len = 0;
  63. MULTIBOOT2::multiboot_mmap_entry_t *mmap =
  64. ((MULTIBOOT2::multiboot_tag_mmap_t *)_iter_data)->entries;
  65. for (; (uint8_t *)mmap < (uint8_t *)_iter_data + _iter_data->size;
  66. mmap = (MULTIBOOT2::multiboot_mmap_entry_t
  67. *)((uint8_t *)mmap +
  68. ((MULTIBOOT2::multiboot_tag_mmap_t *)_iter_data)
  69. ->entry_size)) {
  70. // 如果是可用内存或地址小于 1M
  71. // 这里将 0~1M 的空间全部算为可用,在 c++ 库可用后进行优化
  72. if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE ||
  73. mmap->addr < 1 * COMMON::MB) {
  74. // 长度+
  75. resource->mem.len += mmap->len;
  76. }
  77. }
  78. return true;
  79. }
  80. namespace BOOT_INFO {
  81. // 地址
  82. uintptr_t boot_info_addr;
  83. // 长度
  84. size_t boot_info_size;
  85. // 魔数
  86. uint32_t multiboot2_magic;
  87. bool init(void) {
  88. auto res = MULTIBOOT2::multiboot2_init();
  89. info("BOOT_INFO init.\n");
  90. return res;
  91. }
  92. resource_t get_memory(void) {
  93. resource_t resource;
  94. MULTIBOOT2::multiboot2_iter(MULTIBOOT2::get_memory, &resource);
  95. return resource;
  96. }
  97. };