Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


imported SEABIOS source tree
[palacios.git] / bios / 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 static const char *
44 e820_type_name(u32 type)
45 {
46         switch (type) {
47         case E820_RAM:      return "RAM";
48         case E820_RESERVED: return "RESERVED";
49         case E820_ACPI:     return "ACPI";
50         case E820_NVS:      return "NVS";
51         case E820_UNUSABLE: return "UNUSABLE";
52         case E820_HOLE:     return "HOLE";
53         default:            return "UNKNOWN";
54         }
55 }
56
57 // Show the current e820_list.
58 static void
59 dump_map(void)
60 {
61     dprintf(1, "e820 map has %d items:\n", e820_count);
62     int i;
63     for (i=0; i<e820_count; i++) {
64         struct e820entry *e = &e820_list[i];
65         u64 e_end = e->start + e->size;
66         dprintf(1, "  %d: %08x%08x - %08x%08x = %d %s\n", i
67                 , (u32)(e->start >> 32), (u32)e->start
68                 , (u32)(e_end >> 32), (u32)e_end
69                 , e->type, e820_type_name(e->type));
70     }
71 }
72
73 // Add a new entry to the list.  This scans for overlaps and keeps the
74 // list sorted.
75 void
76 add_e820(u64 start, u64 size, u32 type)
77 {
78     dprintf(8, "Add to e820 map: %08x %08x %d\n", (u32)start, (u32)size, type);
79
80     if (! size)
81         // Huh?  Nothing to do.
82         return;
83
84     // Find position of new item (splitting existing item if needed).
85     u64 end = start + size;
86     int i;
87     for (i=0; i<e820_count; i++) {
88         struct e820entry *e = &e820_list[i];
89         u64 e_end = e->start + e->size;
90         if (start > e_end)
91             continue;
92         // Found position - check if an existing item needs to be split.
93         if (start > e->start) {
94             if (type == e->type) {
95                 // Same type - merge them.
96                 size += start - e->start;
97                 start = e->start;
98             } else {
99                 // Split existing item.
100                 e->size = start - e->start;
101                 i++;
102                 if (e_end > end)
103                     insert_e820(i, end, e_end - end, e->type);
104             }
105         }
106         break;
107     }
108     // Remove/adjust existing items that are overlapping.
109     while (i<e820_count) {
110         struct e820entry *e = &e820_list[i];
111         if (end < e->start)
112             // No overlap - done.
113             break;
114         u64 e_end = e->start + e->size;
115         if (end >= e_end) {
116             // Existing item completely overlapped - remove it.
117             remove_e820(i);
118             continue;
119         }
120         // Not completely overlapped - adjust its start.
121         e->start = end;
122         e->size = e_end - end;
123         if (type == e->type) {
124             // Same type - merge them.
125             size += e->size;
126             remove_e820(i);
127         }
128         break;
129     }
130     // Insert new item.
131     if (type != E820_HOLE)
132         insert_e820(i, start, size, type);
133     //dump_map();
134 }
135
136 // Report on final memory locations.
137 void
138 memmap_finalize(void)
139 {
140     dump_map();
141 }