Tizen 2.1 base
[sdk/emulator/qemu.git] / roms / seabios / src / memmap.c
1 // Support for building memory maps suitable for int 15 e820 calls.
2 //
3 // Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6
7 #include "memmap.h" // struct e820entry
8 #include "util.h" // dprintf.h
9 #include "biosvar.h" // SET_EBDA
10
11
12 /****************************************************************
13  * e820 memory map
14  ****************************************************************/
15
16 // Remove an entry from the e820_list.
17 static void
18 remove_e820(int i)
19 {
20     e820_count--;
21     memmove(&e820_list[i], &e820_list[i+1]
22             , sizeof(e820_list[0]) * (e820_count - i));
23 }
24
25 // Insert an entry in the e820_list at the given position.
26 static void
27 insert_e820(int i, u64 start, u64 size, u32 type)
28 {
29     if (e820_count >= CONFIG_MAX_E820) {
30         warn_noalloc();
31         return;
32     }
33
34     memmove(&e820_list[i+1], &e820_list[i]
35             , sizeof(e820_list[0]) * (e820_count - i));
36     e820_count++;
37     struct e820entry *e = &e820_list[i];
38     e->start = start;
39     e->size = size;
40     e->type = type;
41 }
42
43 // Show the current e820_list.
44 static void
45 dump_map(void)
46 {
47     dprintf(1, "e820 map has %d items:\n", e820_count);
48     int i;
49     for (i=0; i<e820_count; i++) {
50         struct e820entry *e = &e820_list[i];
51         u64 e_end = e->start + e->size;
52         dprintf(1, "  %d: %08x%08x - %08x%08x = %d\n", i
53                 , (u32)(e->start >> 32), (u32)e->start
54                 , (u32)(e_end >> 32), (u32)e_end
55                 , e->type);
56     }
57 }
58
59 // Add a new entry to the list.  This scans for overlaps and keeps the
60 // list sorted.
61 void
62 add_e820(u64 start, u64 size, u32 type)
63 {
64     dprintf(8, "Add to e820 map: %08x %08x %d\n", (u32)start, (u32)size, type);
65
66     if (! size)
67         // Huh?  Nothing to do.
68         return;
69
70     // Find position of new item (splitting existing item if needed).
71     u64 end = start + size;
72     int i;
73     for (i=0; i<e820_count; i++) {
74         struct e820entry *e = &e820_list[i];
75         u64 e_end = e->start + e->size;
76         if (start > e_end)
77             continue;
78         // Found position - check if an existing item needs to be split.
79         if (start > e->start) {
80             if (type == e->type) {
81                 // Same type - merge them.
82                 size += start - e->start;
83                 start = e->start;
84             } else {
85                 // Split existing item.
86                 e->size = start - e->start;
87                 i++;
88                 if (e_end > end)
89                     insert_e820(i, end, e_end - end, e->type);
90             }
91         }
92         break;
93     }
94     // Remove/adjust existing items that are overlapping.
95     while (i<e820_count) {
96         struct e820entry *e = &e820_list[i];
97         if (end < e->start)
98             // No overlap - done.
99             break;
100         u64 e_end = e->start + e->size;
101         if (end >= e_end) {
102             // Existing item completely overlapped - remove it.
103             remove_e820(i);
104             continue;
105         }
106         // Not completely overlapped - adjust its start.
107         e->start = end;
108         e->size = e_end - end;
109         if (type == e->type) {
110             // Same type - merge them.
111             size += e->size;
112             remove_e820(i);
113         }
114         break;
115     }
116     // Insert new item.
117     if (type != E820_HOLE)
118         insert_e820(i, start, size, type);
119     //dump_map();
120 }
121
122 // Prep for memmap stuff - init bios table locations.
123 void
124 memmap_setup(void)
125 {
126     e820_count = 0;
127 }
128
129 // Report on final memory locations.
130 void
131 memmap_finalize(void)
132 {
133     dump_map();
134 }