123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- /*
- * segments.c
- *
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <segments.h>
- static gdt_descriptor_t gdt_table[GDT_MAX_ENTRIES];
- static dword_t gdt_entry_count = 0;
- static word_t system_code_sel, system_data_sel, user_code_sel, user_data_sel, tss_sel;
- static tss_entry_t tss;
- extern void init_cpu_gdt(gdt_descriptor_t *table, dword_t size, word_t code_selector, word_t data_selector, word_t tss_selector);
- dword_t get_kernel_esp(void)
- {
- return tss.esp0;
- }
- void set_kernel_esp(dword_t esp)
- {
- tss.esp0 = esp;
- }
- word_t get_kernel_code_selector(void)
- {
- return system_code_sel;
- }
- word_t get_kernel_data_selector(void)
- {
- return system_data_sel;
- }
- word_t get_user_code_selector(void)
- {
- return user_code_sel;
- }
- word_t get_user_data_selector(void)
- {
- return user_data_sel;
- }
- 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)
- {
- word_t selector;
- bool_t granularity = FALSE;
- if (gdt_entry_count == GDT_MAX_ENTRIES) return 0;
- if (priv_level > 3) return 0;
- if (limit > 0xFFFFF)
- {
- limit >>= 12;
- granularity = TRUE;
- }
- gdt_table[gdt_entry_count].base = base & 0x00FFFFFF;
- gdt_table[gdt_entry_count].base_high = base >> 24;
- gdt_table[gdt_entry_count].limit = limit & 0xFFFF;
- gdt_table[gdt_entry_count].limit_high = limit >> 16;
- gdt_table[gdt_entry_count].present = TRUE;
- gdt_table[gdt_entry_count].accessed = FALSE;
- gdt_table[gdt_entry_count].executable = executable ? TRUE : FALSE;
- gdt_table[gdt_entry_count].readwrite = readwrite ? TRUE : FALSE;
- gdt_table[gdt_entry_count].dirconf = dirconf ? TRUE : FALSE;
- gdt_table[gdt_entry_count].rpl = priv_level;
- gdt_table[gdt_entry_count].size = large ? TRUE : FALSE;
- gdt_table[gdt_entry_count].granularity = granularity;
- gdt_table[gdt_entry_count].standard = 1;
- gdt_table[gdt_entry_count].always_zero = 0;
- selector = (gdt_entry_count << 3) | priv_level;
- gdt_entry_count++;
- return selector;
- }
- word_t gdt_create_tss(tss_entry_t *base, dword_t limit)
- {
- word_t selector;
- if (gdt_entry_count == GDT_MAX_ENTRIES) return 0;
- if (limit < sizeof(tss_entry_t)) return 0;
- gdt_table[gdt_entry_count].base = (dword_t)base & 0x00FFFFFF;
- gdt_table[gdt_entry_count].base_high = (dword_t)base >> 24;
- gdt_table[gdt_entry_count].limit = limit & 0xFFFF;
- gdt_table[gdt_entry_count].limit_high = limit >> 16;
- gdt_table[gdt_entry_count].present = TRUE;
- gdt_table[gdt_entry_count].accessed = TRUE;
- gdt_table[gdt_entry_count].executable = TRUE;
- gdt_table[gdt_entry_count].readwrite = FALSE;
- gdt_table[gdt_entry_count].dirconf = FALSE;
- gdt_table[gdt_entry_count].rpl = 0;
- gdt_table[gdt_entry_count].size = TRUE;
- gdt_table[gdt_entry_count].granularity = FALSE;
- gdt_table[gdt_entry_count].standard = 0;
- gdt_table[gdt_entry_count].always_zero = 0;
- selector = gdt_entry_count << 3;
- gdt_entry_count++;
- return selector;
- }
- void segments_init(void)
- {
- gdt_entry_count = 0;
- memset(gdt_table, 0, sizeof(gdt_table));
- gdt_create_segment(0, 0, FALSE, 0, FALSE, FALSE, FALSE);
- system_code_sel = gdt_create_segment(0x00000000, 0xFFFFFFFF, TRUE, 0, TRUE, FALSE, TRUE);
- system_data_sel = gdt_create_segment(0x00000000, 0xFFFFFFFF, FALSE, 0, TRUE, FALSE, TRUE);
- user_code_sel = gdt_create_segment(0x00000000, 0xFFFFFFFF, TRUE, 3, TRUE, FALSE, TRUE);
- user_data_sel = gdt_create_segment(0x00000000, 0xFFFFFFFF, FALSE, 3, TRUE, FALSE, TRUE);
- tss_sel = gdt_create_tss(&tss, sizeof(tss));
- memset(&tss, 0, sizeof(tss));
- tss.ss0 = system_data_sel;
- tss.iopb = sizeof(tss_entry_t);
- init_cpu_gdt(gdt_table, sizeof(gdt_table), system_code_sel, system_data_sel, tss_sel);
- }
|