|
|
1.1 root 1: /* Segmentation of the AMD64 architecture.
2: *
3: * 2003-07 by SONE Takeshi
4: */
5:
6: #include "config.h"
7: #include "kernel/kernel.h"
8: #include "libopenbios/sys_info.h"
9: #include "relocate.h"
10: #include "segment.h"
11:
12: #define printf printk
13: #ifdef CONFIG_DEBUG_BOOT
14: #define debug printk
15: #else
16: #define debug(x...)
17: #endif
18:
19: /* i386 lgdt argument */
20: struct gdtarg {
21: unsigned short limit;
22: unsigned int base;
23: } __attribute__((packed));
24:
25: /* How far the virtual address (used in C) is different from physical
26: * address. Since we start in flat mode, the initial value is zero. */
27: unsigned long virt_offset = 0;
28:
29: /* GDT, the global descriptor table */
30: struct segment_desc gdt[NUM_SEG] = {
31: /* 0x00: null segment */
32: {0, 0, 0, 0, 0, 0},
33: /* 0x08: flat code segment */
34: {0xffff, 0, 0, 0x9f, 0xcf, 0},
35: /* 0x10: flat data segment */
36: {0xffff, 0, 0, 0x93, 0xcf, 0},
37: /* 0x18: code segment for relocated execution */
38: {0xffff, 0, 0, 0x9f, 0xcf, 0},
39: /* 0x20: data segment for relocated execution */
40: {0xffff, 0, 0, 0x93, 0xcf, 0},
41: };
42:
43: extern char _start[], _end[];
44:
45: void relocate(struct sys_info *info)
46: {
47: int i;
48: unsigned long prog_addr;
49: unsigned long prog_size;
50: unsigned long addr, new_base;
51: unsigned long long segsize;
52: unsigned long new_offset;
53: unsigned d0, d1, d2;
54: struct gdtarg gdtarg;
55: #define ALIGNMENT 16
56:
57: prog_addr = virt_to_phys(&_start);
58: prog_size = virt_to_phys(&_end) - virt_to_phys(&_start);
59: debug("Current location: %#lx-%#lx\n", prog_addr, prog_addr+prog_size-1);
60:
61: new_base = 0;
62: for (i = 0; i < info->n_memranges; i++) {
63: if (info->memrange[i].base >= 1ULL<<32)
64: continue;
65: segsize = info->memrange[i].size;
66: if (info->memrange[i].base + segsize > 1ULL<<32)
67: segsize = (1ULL<<32) - info->memrange[i].base;
68: if (segsize < prog_size+ALIGNMENT)
69: continue;
70: addr = info->memrange[i].base + segsize - prog_size;
71: addr &= ~(ALIGNMENT-1);
72: if (addr >= prog_addr && addr < prog_addr + prog_size)
73: continue;
74: if (prog_addr >= addr && prog_addr < addr + prog_size)
75: continue;
76: if (addr > new_base)
77: new_base = addr;
78: }
79: if (new_base == 0) {
80: printf("Can't find address to relocate\n");
81: return;
82: }
83:
84: debug("Relocating to %#lx-%#lx... ",
85: new_base, new_base + prog_size - 1);
86:
87: /* New virtual address offset */
88: new_offset = new_base - (unsigned long) &_start;
89:
90: /* Tweak the GDT */
91: gdt[RELOC_CODE].base_0 = (unsigned short) new_offset;
92: gdt[RELOC_CODE].base_16 = (unsigned char) (new_offset>>16);
93: gdt[RELOC_CODE].base_24 = (unsigned char) (new_offset>>24);
94: gdt[RELOC_DATA].base_0 = (unsigned short) new_offset;
95: gdt[RELOC_DATA].base_16 = (unsigned char) (new_offset>>16);
96: gdt[RELOC_DATA].base_24 = (unsigned char) (new_offset>>24);
97:
98: /* Load new GDT and reload segments */
99: gdtarg.base = new_offset + (unsigned long) gdt;
100: gdtarg.limit = GDT_LIMIT;
101: __asm__ __volatile__ (
102: "rep; movsb\n\t" /* copy everything */
103: "lgdt %3\n\t"
104: "ljmp %4, $1f\n1:\t"
105: "movw %5, %%ds\n\t"
106: "movw %5, %%es\n\t"
107: "movw %5, %%fs\n\t"
108: "movw %5, %%gs\n\t"
109: "movw %5, %%ss\n"
110: : "=&S" (d0), "=&D" (d1), "=&c" (d2)
111: : "m" (gdtarg), "n" (RELOC_CS), "q" ((unsigned short) RELOC_DS),
112: "0" (&_start), "1" (new_base), "2" (prog_size));
113:
114: virt_offset = new_offset;
115: debug("ok\n");
116: }
117:
118: #if 0
119: /* Copy GDT to new location and reload it */
120: void move_gdt(unsigned long newgdt)
121: {
122: struct gdtarg gdtarg;
123:
124: debug("Moving GDT to %#lx...", newgdt);
125: memcpy(phys_to_virt(newgdt), gdt, sizeof gdt);
126: gdtarg.base = newgdt;
127: gdtarg.limit = GDT_LIMIT;
128: debug("reloading GDT...");
129: __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg));
130: debug("reloading CS for fun...");
131: __asm__ __volatile__ ("ljmp %0, $1f\n1:" : : "n" (RELOC_CS));
132: debug("ok\n");
133: }
134: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.