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,6 +1,6 @@
1
-#include <virtaddr.h>
1
+#include <io.h>
2 2
 #include <registers.h>
3
-#include <memsizes.h>
3
+#include <memmap.h>
4 4
 
5 5
 /*
6 6
  * Originally by Eric Biederman
@@ -35,14 +35,27 @@ extern char _end[];
35 35
  * @v ix86		x86 register dump from prefix
36 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 39
  * address space, and returns the physical address of the new location
40 40
  * to the prefix in %edi.
41 41
  */
42 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 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 59
 	/* Walk through the memory map and find the highest address
47 60
 	 * below 4GB that etherboot will fit into.  Ensure etherboot
48 61
 	 * lies entirely within a range with A20=0.  This means that
@@ -50,58 +63,29 @@ void relocate ( struct i386_all_regs *ix86 ) {
50 63
 	 * etherboot code is still visible and we have a chance to
51 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 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 73
 		/* Truncate block to MAX_ADDR.  This will be less than
90 74
 		 * 4GB, which means that we can get away with using
91 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 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 84
 			r_end = MAX_ADDR;
100
-			DBG ( "...end truncated to MAX_ADDR=%x\n", MAX_ADDR );
101 85
 		} else {
102
-			r_end = meminfo.map[i].addr + meminfo.map[i].size;
86
+			r_end = region->end;
103 87
 		}
104
-
88
+		
105 89
 		/* Shrink the range down to use only even megabytes
106 90
 		 * (i.e. A20=0).
107 91
 		 */
@@ -111,7 +95,7 @@ void relocate ( struct i386_all_regs *ix86 ) {
111 95
 			 * the top of the next even megabyte.
112 96
 			 */
113 97
 			r_end = ( r_end - 1 ) & ~0xfffff;
114
-			DBG ( "...end truncated to %x "
98
+			DBG ( "...end truncated to %lx "
115 99
 			      "(avoid ending in odd megabyte)\n",
116 100
 			      r_end );
117 101
 		} else if ( ( r_end - size ) & 0x100000 ) {
@@ -126,13 +110,13 @@ void relocate ( struct i386_all_regs *ix86 ) {
126 110
 			 */
127 111
 			if ( r_end > 0x100000 ) {
128 112
 				r_end = ( r_end - 0x100000 ) & ~0xfffff;
129
-				DBG ( "...end truncated to %x "
113
+				DBG ( "...end truncated to %lx "
130 114
 				      "(avoid starting in odd megabyte)\n",
131 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 121
 		/* If we have rounded down r_end below r_ start, skip
138 122
 		 * this block.
@@ -143,8 +127,8 @@ void relocate ( struct i386_all_regs *ix86 ) {
143 127
 		}
144 128
 
145 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 132
 			continue;
149 133
 		}
150 134
 
@@ -156,30 +140,24 @@ void relocate ( struct i386_all_regs *ix86 ) {
156 140
 		 * Etherboot, as well as choosing the highest of all
157 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 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 149
 	/* Calculate new location of Etherboot, and align it to the
168 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