kernel.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include <stdint.h>
  2. #include <stddef.h>
  3. #include "stivale2.h"
  4. #include "defining.h"
  5. typedef uint8_t u8;
  6. typedef uint16_t u16;
  7. typedef uint32_t u32;
  8. typedef uint64_t u64;
  9. const u8 idt_ist = 0 >> 3;
  10. // We need to tell the stivale bootloader where we want our stack to be.
  11. // We are going to allocate our stack as an uninitialised array in .bss.
  12. static uint8_t stack[4096];
  13. // stivale2 uses a linked list of tags for both communicating TO the
  14. // bootloader, or receiving info FROM it. More information about these tags
  15. // is found in the stivale2 specification.
  16. // stivale2 offers a runtime terminal service which can be ditched at any
  17. // time, but it provides an easy way to print out to graphical terminal,
  18. // especially during early boot.
  19. static struct stivale2_header_tag_terminal terminal_hdr_tag = {
  20. // All tags need to begin with an identifier and a pointer to the next tag.
  21. .tag = {
  22. // Identification constant defined in stivale2.h and the specification.
  23. .identifier = STIVALE2_HEADER_TAG_TERMINAL_ID,
  24. // If next is 0, it marks the end of the linked list of header tags.
  25. .next = 0
  26. },
  27. // The terminal header tag possesses a flags field, leave it as 0 for now
  28. // as it is unused.
  29. .flags = 0
  30. };
  31. // We are now going to define a framebuffer header tag, which is mandatory when
  32. // using the stivale2 terminal.
  33. // This tag tells the bootloader that we want a graphical framebuffer instead
  34. // of a CGA-compatible text mode. Omitting this tag will make the bootloader
  35. // default to text mode, if available.
  36. static struct stivale2_header_tag_framebuffer framebuffer_hdr_tag = {
  37. // Same as above.
  38. .tag = {
  39. .identifier = STIVALE2_HEADER_TAG_FRAMEBUFFER_ID,
  40. // Instead of 0, we now point to the previous header tag. The order in
  41. // which header tags are linked does not matter.
  42. .next = (uint64_t)&terminal_hdr_tag
  43. },
  44. // We set all the framebuffer specifics to 0 as we want the bootloader
  45. // to pick the best it can.
  46. .framebuffer_width = 0,
  47. .framebuffer_height = 0,
  48. .framebuffer_bpp = 0
  49. };
  50. // The stivale2 specification says we need to define a "header structure".
  51. // This structure needs to reside in the .stivale2hdr ELF section in order
  52. // for the bootloader to find it. We use this __attribute__ directive to
  53. // tell the compiler to put the following structure in said section.
  54. __attribute__((section(".stivale2hdr"), used))
  55. static struct stivale2_header stivale_hdr = {
  56. // The entry_point member is used to specify an alternative entry
  57. // point that the bootloader should jump to instead of the executable's
  58. // ELF entry point. We do not care about that so we leave it zeroed.
  59. .entry_point = 0,
  60. // Let's tell the bootloader where our stack is.
  61. // We need to add the sizeof(stack) since in x86(_64) the stack grows
  62. // downwards.
  63. .stack = (uintptr_t)stack + sizeof(stack),
  64. // No flags are currently defined as per spec and should be left to 0.
  65. .flags = 0,
  66. // This header structure is the root of the linked list of header tags and
  67. // points to the first one in the linked list.
  68. .tags = (uintptr_t)&framebuffer_hdr_tag
  69. };
  70. // We will now write a helper function which will allow us to scan for tags
  71. // that we want FROM the bootloader (structure tags).
  72. void *stivale2_get_tag(struct stivale2_struct *stivale2_struct, uint64_t id) {
  73. struct stivale2_tag *current_tag = (void *)stivale2_struct->tags;
  74. for (;;) {
  75. // If the tag pointer is NULL (end of linked list), we did not find
  76. // the tag. Return NULL to signal this.
  77. if (current_tag == NULL) {
  78. return NULL;
  79. }
  80. // Check whether the identifier matches. If it does, return a pointer
  81. // to the matching tag.
  82. if (current_tag->identifier == id) {
  83. return current_tag;
  84. }
  85. // Get a pointer to the next tag in the linked list and repeat.
  86. current_tag = (void *)current_tag->next;
  87. }
  88. }
  89. // The following will be our kernel's entry point.
  90. // Let's get the terminal structure tag from the bootloader.
  91. void (*write)(const char *string, size_t length);
  92. // The following will be our kernel's entry point.
  93. void _start(struct stivale2_struct *stivale2_struct) {
  94. // Let's get the terminal structure tag from the bootloader.
  95. struct stivale2_struct_tag_memmap *mmap = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_MEMMAP_ID);
  96. uint64_t length = 0;
  97. for (int i = 0; i < mmap->entries; i++) {
  98. struct stivale2_mmap_entry *m = &mmap->memmap[i];
  99. if (m->type == STIVALE2_MMAP_USABLE) length += m->length;
  100. }
  101. length /= (1024 * 1024);
  102. struct stivale2_struct_tag_terminal *term_str_tag;
  103. term_str_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_TERMINAL_ID);
  104. // Check if the tag was actually found.
  105. if (term_str_tag == NULL) {
  106. // It wasn't found, just hang...
  107. for (;;) {
  108. asm ("hlt");
  109. }
  110. }
  111. if (mmap == NULL){
  112. for (;;) {
  113. asm ("hlt");
  114. }
  115. }
  116. void *term_write_ptr = (void *)term_str_tag->term_write;
  117. write = term_write_ptr;
  118. write("Welcome to YerbaOS\n", 19);
  119. write("Memory map:\n ", 14);
  120. print(mmap); // Memory map
  121. write("\nHuman readable memory map:\n", 27);
  122. print(length); // Formated memory map into GB aka human readable memory output
  123. gdt_load();
  124. idt_init(); //defined in defining.h
  125. for (;;) {
  126. asm ("hlt");
  127. }
  128. }