|
@@ -32,6 +32,45 @@ struct elf_state
|
32
|
32
|
|
33
|
33
|
static struct elf_state estate;
|
34
|
34
|
|
|
35
|
+static unsigned long find_segment(unsigned long size, unsigned long align)
|
|
36
|
+{
|
|
37
|
+ unsigned i;
|
|
38
|
+ /* Verify I have a power of 2 alignment */
|
|
39
|
+ if (align & (align - 1)) {
|
|
40
|
+ return ULONG_MAX;
|
|
41
|
+ }
|
|
42
|
+ for(i = 0; i < meminfo.map_count; i++) {
|
|
43
|
+ unsigned long r_start, r_end;
|
|
44
|
+ if (meminfo.map[i].type != E820_RAM)
|
|
45
|
+ continue;
|
|
46
|
+ if ((meminfo.map[i].addr + meminfo.map[i].size) > ULONG_MAX) {
|
|
47
|
+ continue;
|
|
48
|
+ }
|
|
49
|
+ r_start = meminfo.map[i].addr;
|
|
50
|
+ r_end = r_start + meminfo.map[i].size;
|
|
51
|
+ /* Don't allow the segment to overlap etherboot */
|
|
52
|
+ if ((r_end > virt_to_phys(_text)) && (r_start < virt_to_phys(_text))) {
|
|
53
|
+ r_end = virt_to_phys(_text);
|
|
54
|
+ }
|
|
55
|
+ if ((r_start > virt_to_phys(_text)) && (r_start < virt_to_phys(_end))) {
|
|
56
|
+ r_start = virt_to_phys(_end);
|
|
57
|
+ }
|
|
58
|
+ /* Don't allow the segment to overlap the heap */
|
|
59
|
+ if ((r_end > heap_ptr) && (r_start < heap_ptr)) {
|
|
60
|
+ r_end = heap_ptr;
|
|
61
|
+ }
|
|
62
|
+ if ((r_start > heap_ptr) && (r_start < heap_bot)) {
|
|
63
|
+ r_start = heap_ptr;
|
|
64
|
+ }
|
|
65
|
+ r_start = (r_start + align - 1) & ~(align - 1);
|
|
66
|
+ if ((r_end >= r_start) && ((r_end - r_start) >= size)) {
|
|
67
|
+ return r_start;
|
|
68
|
+ }
|
|
69
|
+ }
|
|
70
|
+ /* I did not find anything :( */
|
|
71
|
+ return ULONG_MAX;
|
|
72
|
+}
|
|
73
|
+
|
35
|
74
|
static void elf_boot(unsigned long machine, unsigned long entry)
|
36
|
75
|
{
|
37
|
76
|
int result;
|