Fixed possible memory corruption in commands exec and netexec; fixed command netcp...
[ZeXOS.git] / kernel / arch / x86_64 / gdt.c
blobc967348e3b406ae24b9beb4ce1901a1710685dcb
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <system.h>
21 #include <arch/io.h>
22 #include <string.h>
24 /* Defines a GDT entry */
25 struct gdt_entry
27 unsigned short limit_low;
28 unsigned short base_low;
29 unsigned char base_middle;
30 unsigned char access;
31 unsigned char granularity;
32 unsigned char base_high;
33 } __attribute__((packed));
35 struct gdt_ptr
37 unsigned short limit;
38 unsigned int base;
39 } __attribute__((packed));
41 /* Our GDT, with 3 entries, and finally our special GDT pointer */
42 struct gdt_entry gdt[3];
43 struct gdt_ptr gp;
45 /* This is in start.asm. We use this to properly reload
46 * the new segment registers */
47 extern void gdt_flush ();
49 /* Setup a descriptor in the Global Descriptor Table */
50 void gdt_set_gate (int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran)
52 /* Setup the descriptor base address */
53 gdt[num].base_low = (base & 0xFFFF);
54 gdt[num].base_middle = (base >> 16) & 0xFF;
55 gdt[num].base_high = (base >> 24) & 0xFF;
57 /* Setup the descriptor limits */
58 gdt[num].limit_low = (limit & 0xFFFF);
59 gdt[num].granularity = ((limit >> 16) & 0x0F);
61 /* Finally, set up the granularity and access flags */
62 gdt[num].granularity |= (gran & 0xF0);
63 gdt[num].access = access;
66 /* Should be called by main. This will setup the special GDT
67 * pointer, set up the first 3 entries in our GDT, and then
68 * finally call gdt_flush() in our assembler file in order
69 * to tell the processor where the new GDT is and update the
70 * new segment registers */
71 unsigned int gdt_install ()
73 /* Setup the GDT pointer and limit */
74 gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
75 gp.base = &gdt;
77 /* Our NULL descriptor */
78 gdt_set_gate(0, 0, 0, 0, 0);
80 /* The second entry is our Code Segment. The base address
81 * is 0, the limit is 4GBytes, it uses 4KByte granularity,
82 * uses 32-bit opcodes, and is a Code Segment descriptor.
83 * Please check the table above in the tutorial in order
84 * to see exactly what each value means */
85 gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
87 /* The third entry is our Data Segment. It's EXACTLY the
88 * same as our code segment, but the descriptor type in
89 * this entry's access byte says it's a Data Segment */
90 gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
92 /* Flush out the old GDT and install the new changes! */
93 gdt_flush();
95 return 1;