segments.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * segments.c
  3. *
  4. * Copyright (C) 2013 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <segments.h>
  20. static gdt_descriptor_t gdt_table[GDT_MAX_ENTRIES];
  21. static dword_t gdt_entry_count = 0;
  22. static word_t system_code_sel, system_data_sel, user_code_sel, user_data_sel, tss_sel;
  23. static tss_entry_t tss;
  24. extern void init_cpu_gdt(gdt_descriptor_t *table, dword_t size, word_t code_selector, word_t data_selector, word_t tss_selector);
  25. dword_t get_kernel_esp(void)
  26. {
  27. return tss.esp0;
  28. }
  29. void set_kernel_esp(dword_t esp)
  30. {
  31. tss.esp0 = esp;
  32. }
  33. word_t get_kernel_code_selector(void)
  34. {
  35. return system_code_sel;
  36. }
  37. word_t get_kernel_data_selector(void)
  38. {
  39. return system_data_sel;
  40. }
  41. word_t get_user_code_selector(void)
  42. {
  43. return user_code_sel;
  44. }
  45. word_t get_user_data_selector(void)
  46. {
  47. return user_data_sel;
  48. }
  49. word_t gdt_create_segment(dword_t base, dword_t limit, bool_t executable, byte_t priv_level, bool_t readwrite, bool_t dirconf, bool_t large)
  50. {
  51. word_t selector;
  52. bool_t granularity = FALSE;
  53. if (gdt_entry_count == GDT_MAX_ENTRIES) return 0;
  54. if (priv_level > 3) return 0;
  55. if (limit > 0xFFFFF)
  56. {
  57. limit >>= 12;
  58. granularity = TRUE;
  59. }
  60. gdt_table[gdt_entry_count].base = base & 0x00FFFFFF;
  61. gdt_table[gdt_entry_count].base_high = base >> 24;
  62. gdt_table[gdt_entry_count].limit = limit & 0xFFFF;
  63. gdt_table[gdt_entry_count].limit_high = limit >> 16;
  64. gdt_table[gdt_entry_count].present = TRUE;
  65. gdt_table[gdt_entry_count].accessed = FALSE;
  66. gdt_table[gdt_entry_count].executable = executable ? TRUE : FALSE;
  67. gdt_table[gdt_entry_count].readwrite = readwrite ? TRUE : FALSE;
  68. gdt_table[gdt_entry_count].dirconf = dirconf ? TRUE : FALSE;
  69. gdt_table[gdt_entry_count].rpl = priv_level;
  70. gdt_table[gdt_entry_count].size = large ? TRUE : FALSE;
  71. gdt_table[gdt_entry_count].granularity = granularity;
  72. gdt_table[gdt_entry_count].standard = 1;
  73. gdt_table[gdt_entry_count].always_zero = 0;
  74. selector = (gdt_entry_count << 3) | priv_level;
  75. gdt_entry_count++;
  76. return selector;
  77. }
  78. word_t gdt_create_tss(tss_entry_t *base, dword_t limit)
  79. {
  80. word_t selector;
  81. if (gdt_entry_count == GDT_MAX_ENTRIES) return 0;
  82. if (limit < sizeof(tss_entry_t)) return 0;
  83. gdt_table[gdt_entry_count].base = (dword_t)base & 0x00FFFFFF;
  84. gdt_table[gdt_entry_count].base_high = (dword_t)base >> 24;
  85. gdt_table[gdt_entry_count].limit = limit & 0xFFFF;
  86. gdt_table[gdt_entry_count].limit_high = limit >> 16;
  87. gdt_table[gdt_entry_count].present = TRUE;
  88. gdt_table[gdt_entry_count].accessed = TRUE;
  89. gdt_table[gdt_entry_count].executable = TRUE;
  90. gdt_table[gdt_entry_count].readwrite = FALSE;
  91. gdt_table[gdt_entry_count].dirconf = FALSE;
  92. gdt_table[gdt_entry_count].rpl = 0;
  93. gdt_table[gdt_entry_count].size = TRUE;
  94. gdt_table[gdt_entry_count].granularity = FALSE;
  95. gdt_table[gdt_entry_count].standard = 0;
  96. gdt_table[gdt_entry_count].always_zero = 0;
  97. selector = gdt_entry_count << 3;
  98. gdt_entry_count++;
  99. return selector;
  100. }
  101. void segments_init(void)
  102. {
  103. gdt_entry_count = 0;
  104. memset(gdt_table, 0, sizeof(gdt_table));
  105. gdt_create_segment(0, 0, FALSE, 0, FALSE, FALSE, FALSE);
  106. system_code_sel = gdt_create_segment(0x00000000, 0xFFFFFFFF, TRUE, 0, TRUE, FALSE, TRUE);
  107. system_data_sel = gdt_create_segment(0x00000000, 0xFFFFFFFF, FALSE, 0, TRUE, FALSE, TRUE);
  108. user_code_sel = gdt_create_segment(0x00000000, 0xFFFFFFFF, TRUE, 3, TRUE, FALSE, TRUE);
  109. user_data_sel = gdt_create_segment(0x00000000, 0xFFFFFFFF, FALSE, 3, TRUE, FALSE, TRUE);
  110. tss_sel = gdt_create_tss(&tss, sizeof(tss));
  111. memset(&tss, 0, sizeof(tss));
  112. tss.ss0 = system_data_sel;
  113. tss.iopb = sizeof(tss_entry_t);
  114. init_cpu_gdt(gdt_table, sizeof(gdt_table), system_code_sel, system_data_sel, tss_sel);
  115. }