Browse Source

Update relocate() to work with get_memmap().

Change semantics; relocate() now just finds a suitable location; it
doesn't actually perform the relocation itself.  Code in libprefix does
the copy in flat real mode.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
1966945a5d
1 changed files with 44 additions and 66 deletions
  1. 44
    66
      src/arch/i386/core/relocate.c

+ 44
- 66
src/arch/i386/core/relocate.c View File

1
-#include <virtaddr.h>
1
+#include <io.h>
2
 #include <registers.h>
2
 #include <registers.h>
3
-#include <memsizes.h>
3
+#include <memmap.h>
4
 
4
 
5
 /*
5
 /*
6
  * Originally by Eric Biederman
6
  * Originally by Eric Biederman
35
  * @v ix86		x86 register dump from prefix
35
  * @v ix86		x86 register dump from prefix
36
  * @ret ix86		x86 registers to return to prefix
36
  * @ret ix86		x86 registers to return to prefix
37
  *
37
  *
38
- * This copies Etherboot to a suitable location near the top of 32-bit
38
+ * This finds a suitable location for Etherboot near the top of 32-bit
39
  * address space, and returns the physical address of the new location
39
  * address space, and returns the physical address of the new location
40
  * to the prefix in %edi.
40
  * to the prefix in %edi.
41
  */
41
  */
42
 void relocate ( struct i386_all_regs *ix86 ) {
42
 void relocate ( struct i386_all_regs *ix86 ) {
43
-	unsigned long addr, eaddr, size;
43
+	struct memory_map memmap;
44
+	unsigned long start, end, size, padded_size;
45
+	unsigned long new_start, new_end;
44
 	unsigned i;
46
 	unsigned i;
45
 
47
 
48
+	/* Get memory map and current location */
49
+	get_memmap ( &memmap );
50
+	start = virt_to_phys ( _text );
51
+	end = virt_to_phys ( _end );
52
+	size = ( end - start );
53
+	padded_size = ( size + max_align - 1 );
54
+
55
+	DBG ( "Relocate: currently at [%lx,%lx)\n"
56
+	      "...need %lx bytes for %d-byte alignment\n",
57
+	      start, end, padded_size, max_align );
58
+
46
 	/* Walk through the memory map and find the highest address
59
 	/* Walk through the memory map and find the highest address
47
 	 * below 4GB that etherboot will fit into.  Ensure etherboot
60
 	 * below 4GB that etherboot will fit into.  Ensure etherboot
48
 	 * lies entirely within a range with A20=0.  This means that
61
 	 * lies entirely within a range with A20=0.  This means that
50
 	 * etherboot code is still visible and we have a chance to
63
 	 * etherboot code is still visible and we have a chance to
51
 	 * diagnose the problem.
64
 	 * diagnose the problem.
52
 	 */
65
 	 */
53
-
54
-	/* First find the size of etherboot, including enough space to
55
-	 * pad it to the required alignment
56
-	 */
57
-	size = _end - _text + max_align - 1;
58
-
59
-	/* Current end address of Etherboot.  If the current etherboot
60
-	 * is beyond MAX_ADDR pretend it is at the lowest possible
61
-	 * address.
62
-	 */
63
-	eaddr = virt_to_phys(_end);
64
-	if ( eaddr > MAX_ADDR ) {
65
-		eaddr = 0;
66
-	}
67
-
68
-	DBG ( "Relocate: currently at [%x,%x)\n"
69
-	      "...need %x bytes for %d-byte alignment\n",
70
-	      virt_to_phys ( _text ), eaddr, size, max_align );
71
-
72
-	for ( i = 0; i < meminfo.map_count; i++ ) {
66
+	new_end = end;
67
+	for ( i = 0 ; i < memmap.count ; i++ ) {
68
+		struct memory_region *region = &memmap.regions[i];
73
 		unsigned long r_start, r_end;
69
 		unsigned long r_start, r_end;
74
 
70
 
75
-		DBG ( "Considering [%x%x,%x%x)\n",
76
-		      ( unsigned long ) ( meminfo.map[i].addr >> 32 ),
77
-		      ( unsigned long ) meminfo.map[i].addr,
78
-		      ( unsigned long )
79
-		       ( ( meminfo.map[i].addr + meminfo.map[i].size ) >> 32 ),
80
-		      ( unsigned long )
81
-		       ( meminfo.map[i].addr + meminfo.map[i].size ) );
71
+		DBG ( "Considering [%llx,%llx)\n", region->start, region->end);
82
 		
72
 		
83
-		/* Check block is usable memory */
84
-		if (meminfo.map[i].type != E820_RAM) {
85
-			DBG ( "...not RAM\n" );
86
-			continue;
87
-		}
88
-
89
 		/* Truncate block to MAX_ADDR.  This will be less than
73
 		/* Truncate block to MAX_ADDR.  This will be less than
90
 		 * 4GB, which means that we can get away with using
74
 		 * 4GB, which means that we can get away with using
91
 		 * just 32-bit arithmetic after this stage.
75
 		 * just 32-bit arithmetic after this stage.
92
 		 */
76
 		 */
93
-		if ( meminfo.map[i].addr > MAX_ADDR ) {
94
-			DBG ( "...starts after MAX_ADDR=%x\n", MAX_ADDR );
77
+		if ( region->start > MAX_ADDR ) {
78
+			DBG ( "...starts after MAX_ADDR=%lx\n", MAX_ADDR );
95
 			continue;
79
 			continue;
96
 		}
80
 		}
97
-		r_start = meminfo.map[i].addr;
98
-		if ( meminfo.map[i].addr + meminfo.map[i].size > MAX_ADDR ) {
81
+		r_start = region->start;
82
+		if ( region->end > MAX_ADDR ) {
83
+			DBG ( "...end truncated to MAX_ADDR=%lx\n", MAX_ADDR );
99
 			r_end = MAX_ADDR;
84
 			r_end = MAX_ADDR;
100
-			DBG ( "...end truncated to MAX_ADDR=%x\n", MAX_ADDR );
101
 		} else {
85
 		} else {
102
-			r_end = meminfo.map[i].addr + meminfo.map[i].size;
86
+			r_end = region->end;
103
 		}
87
 		}
104
-
88
+		
105
 		/* Shrink the range down to use only even megabytes
89
 		/* Shrink the range down to use only even megabytes
106
 		 * (i.e. A20=0).
90
 		 * (i.e. A20=0).
107
 		 */
91
 		 */
111
 			 * the top of the next even megabyte.
95
 			 * the top of the next even megabyte.
112
 			 */
96
 			 */
113
 			r_end = ( r_end - 1 ) & ~0xfffff;
97
 			r_end = ( r_end - 1 ) & ~0xfffff;
114
-			DBG ( "...end truncated to %x "
98
+			DBG ( "...end truncated to %lx "
115
 			      "(avoid ending in odd megabyte)\n",
99
 			      "(avoid ending in odd megabyte)\n",
116
 			      r_end );
100
 			      r_end );
117
 		} else if ( ( r_end - size ) & 0x100000 ) {
101
 		} else if ( ( r_end - size ) & 0x100000 ) {
126
 			 */
110
 			 */
127
 			if ( r_end > 0x100000 ) {
111
 			if ( r_end > 0x100000 ) {
128
 				r_end = ( r_end - 0x100000 ) & ~0xfffff;
112
 				r_end = ( r_end - 0x100000 ) & ~0xfffff;
129
-				DBG ( "...end truncated to %x "
113
+				DBG ( "...end truncated to %lx "
130
 				      "(avoid starting in odd megabyte)\n",
114
 				      "(avoid starting in odd megabyte)\n",
131
 				      r_end );
115
 				      r_end );
132
 			}
116
 			}
133
 		}
117
 		}
134
 
118
 
135
-		DBG ( "...usable portion is [%x,%x)\n", r_start, r_end );
119
+		DBG ( "...usable portion is [%lx,%lx)\n", r_start, r_end );
136
 
120
 
137
 		/* If we have rounded down r_end below r_ start, skip
121
 		/* If we have rounded down r_end below r_ start, skip
138
 		 * this block.
122
 		 * this block.
143
 		}
127
 		}
144
 
128
 
145
 		/* Check that there is enough space to fit in Etherboot */
129
 		/* Check that there is enough space to fit in Etherboot */
146
-		if ( r_end - r_start < size ) {
147
-			DBG ( "...too small (need %x bytes)\n", size );
130
+		if ( ( r_end - r_start ) < size ) {
131
+			DBG ( "...too small (need %lx bytes)\n", size );
148
 			continue;
132
 			continue;
149
 		}
133
 		}
150
 
134
 
156
 		 * Etherboot, as well as choosing the highest of all
140
 		 * Etherboot, as well as choosing the highest of all
157
 		 * viable blocks.
141
 		 * viable blocks.
158
 		 */
142
 		 */
159
-		if ( r_end - size > eaddr ) {
160
-			eaddr = r_end;
143
+		if ( ( r_end - size ) > new_end ) {
144
+			new_end = r_end;
161
 			DBG ( "...new best block found.\n" );
145
 			DBG ( "...new best block found.\n" );
162
 		}
146
 		}
163
 	}
147
 	}
164
 
148
 
165
-	DBG ( "New location will be in [%x,%x)\n", eaddr - size, eaddr );
166
-
167
 	/* Calculate new location of Etherboot, and align it to the
149
 	/* Calculate new location of Etherboot, and align it to the
168
 	 * required alignemnt.
150
 	 * required alignemnt.
169
 	 */
151
 	 */
170
-	addr = eaddr - size;
171
-	addr += ( virt_to_phys ( _text ) - addr ) & ( max_align - 1 );
172
-	DBG ( "After alignment, new location is [%x,%x)\n",
173
-	      addr, addr + _end - _text );
152
+	new_start = new_end - padded_size;
153
+	new_start += ( start - new_start ) & ( max_align - 1 );
154
+	new_end = new_start + size;
174
 
155
 
175
-	if ( addr != virt_to_phys ( _text ) ) {
176
-		DBG ( "Relocating _text from: [%lx,%lx) to [%lx,%lx)\n",
177
-		      virt_to_phys ( _text ), virt_to_phys ( _end ),
178
-		      addr, addr + _end - _text );
179
-
180
-		memcpy ( phys_to_virt ( addr ), _text, _end - _text );
181
-	}
156
+	DBG ( "Relocating from [%lx,%lx) to [%lx,%lx)\n",
157
+	      start, end, new_start, new_end );
182
 	
158
 	
183
-	/* Let prefix know where the new copy is */
184
-	ix86->regs.edi = addr;
159
+	/* Let prefix know what to copy */
160
+	ix86->regs.esi = start;
161
+	ix86->regs.edi = new_start;
162
+	ix86->regs.ecx = size;
185
 }
163
 }

Loading…
Cancel
Save