Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / arch / i386 / core / relocate.c
1 #include <ipxe/io.h>
2 #include <registers.h>
3
4 /*
5  * Originally by Eric Biederman
6  *
7  * Heavily modified by Michael Brown 
8  *
9  */
10
11 FILE_LICENCE ( GPL2_OR_LATER );
12
13 /*
14  * The linker passes in the symbol _max_align, which is the alignment
15  * that we must preserve, in bytes.
16  *
17  */
18 extern char _max_align[];
19 #define max_align ( ( unsigned int ) _max_align )
20
21 /* Linker symbols */
22 extern char _textdata[];
23 extern char _etextdata[];
24
25 /* within 1MB of 4GB is too close. 
26  * MAX_ADDR is the maximum address we can easily do DMA to.
27  *
28  * Not sure where this constraint comes from, but kept it from Eric's
29  * old code - mcb30
30  */
31 #define MAX_ADDR (0xfff00000UL)
32
33 /**
34  * Relocate iPXE
35  *
36  * @v ebp               Maximum address to use for relocation
37  * @ret esi             Current physical address
38  * @ret edi             New physical address
39  * @ret ecx             Length to copy
40  *
41  * This finds a suitable location for iPXE near the top of 32-bit
42  * address space, and returns the physical address of the new location
43  * to the prefix in %edi.
44  */
45 __asmcall void relocate ( struct i386_all_regs *ix86 ) {
46         struct memory_map memmap;
47         unsigned long start, end, size, padded_size, max;
48         unsigned long new_start, new_end;
49         unsigned i;
50
51         /* Get memory map and current location */
52         get_memmap ( &memmap );
53         start = virt_to_phys ( _textdata );
54         end = virt_to_phys ( _etextdata );
55         size = ( end - start );
56         padded_size = ( size + max_align - 1 );
57
58         DBG ( "Relocate: currently at [%lx,%lx)\n"
59               "...need %lx bytes for %d-byte alignment\n",
60               start, end, padded_size, max_align );
61
62         /* Determine maximum usable address */
63         max = MAX_ADDR;
64         if ( ix86->regs.ebp < max ) {
65                 max = ix86->regs.ebp;
66                 DBG ( "Limiting relocation to [0,%lx)\n", max );
67         }
68
69         /* Walk through the memory map and find the highest address
70          * below 4GB that iPXE will fit into.
71          */
72         new_end = end;
73         for ( i = 0 ; i < memmap.count ; i++ ) {
74                 struct memory_region *region = &memmap.regions[i];
75                 unsigned long r_start, r_end;
76
77                 DBG ( "Considering [%llx,%llx)\n", region->start, region->end);
78                 
79                 /* Truncate block to maximum address.  This will be
80                  * less than 4GB, which means that we can get away
81                  * with using just 32-bit arithmetic after this stage.
82                  */
83                 if ( region->start > max ) {
84                         DBG ( "...starts after max=%lx\n", max );
85                         continue;
86                 }
87                 r_start = region->start;
88                 if ( region->end > max ) {
89                         DBG ( "...end truncated to max=%lx\n", max );
90                         r_end = max;
91                 } else {
92                         r_end = region->end;
93                 }
94                 DBG ( "...usable portion is [%lx,%lx)\n", r_start, r_end );
95
96                 /* If we have rounded down r_end below r_ start, skip
97                  * this block.
98                  */
99                 if ( r_end < r_start ) {
100                         DBG ( "...truncated to negative size\n" );
101                         continue;
102                 }
103
104                 /* Check that there is enough space to fit in iPXE */
105                 if ( ( r_end - r_start ) < size ) {
106                         DBG ( "...too small (need %lx bytes)\n", size );
107                         continue;
108                 }
109
110                 /* If the start address of the iPXE we would
111                  * place in this block is higher than the end address
112                  * of the current highest block, use this block.
113                  *
114                  * Note that this avoids overlaps with the current
115                  * iPXE, as well as choosing the highest of all viable
116                  * blocks.
117                  */
118                 if ( ( r_end - size ) > new_end ) {
119                         new_end = r_end;
120                         DBG ( "...new best block found.\n" );
121                 }
122         }
123
124         /* Calculate new location of iPXE, and align it to the
125          * required alignemnt.
126          */
127         new_start = new_end - padded_size;
128         new_start += ( start - new_start ) & ( max_align - 1 );
129         new_end = new_start + size;
130
131         DBG ( "Relocating from [%lx,%lx) to [%lx,%lx)\n",
132               start, end, new_start, new_end );
133         
134         /* Let prefix know what to copy */
135         ix86->regs.esi = start;
136         ix86->regs.edi = new_start;
137         ix86->regs.ecx = size;
138 }