藏拙於巧、用晦而明、寓清於濁、以屈為伸
這個 api 用來取得記憶體配置資訊, 雖然有關的 api 只有 GetMemoryMap(), 但因為記憶體不同的分類而顯得複雜。除了需要知道這些記憶體的分類的開頭位址和大小, 也要知道他們可以被如何利用。
而 GetMemoryMap() 本身也不是很容易使用的函式。
EFI_BOOT_SERVICES.GetMemoryMap() Prototype
Summary Returns the current memory map.
typedef EFI_STATUS (EFIAPI *EFI_GET_MEMORY_MAP)
(
IN OUT UINTN *MemoryMapSize,
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
OUT UINTN *MapKey,
OUT UINTN *DescriptorSize,
OUT UINT32 *DescriptorVersion
);
uefi runtime service 可以在進入 os 之後繼續提供服務, 所以需要知道 runtime service 的記憶體位址, 在進入 os 之後, map 出來讓 os 繼續使用。
如果需要在 os 中呼叫 runtime service, 參考以下 uefi spec 2.7.pdf 節錄的要點 (沒有完全列出)
2.3.4 x64 Platforms
For an operating system to use any UEFI runtime services, it must:
Preserve all memory in the memory map marked as runtime code and runtime data
Call the runtime service functions, with the following conditions:
In long mode, in 64-bit mode
Paging enabled
All selectors set to be flat with virtual = physical address. If the UEFI OS loader or OS
used SetVirtualAddressMap() to relocate the runtime services in a virtual address space, then this condition does not have to be met. See description of SetVirtualAddressMap() for details of memory map after this function has been called.
Direction flag in EFLAGs clear
...
EFI_GET_MEMORY_MAP 的用法需要自己傳入夠大的 MemoryMap, 而不是該函式自己配好傳回來, 問題是我怎麼知道我要 alloc 多大的記憶體才夠用, 這是第一個難用的地方。
第一次呼叫 EFI_GET_MEMORY_MAP, 如果給的 MemoryMap 空間太小, 會得到 EFI_BUFFER_TOO_SMALL 錯誤, 並會得知所需要的空間大小 (透過 MemoryMapSize 傳回), 所以可以用 AllocatePool() 重新配置一個大小, 再次呼叫 EFI_GET_MEMORY_MAP。
第二個難點是計算有幾個 EFI_MEMORY_DESCRIPTOR, (MemoryMapSize/DescriptorSize) 就是所有的 EFI_MEMORY_DESCRIPTOR, 一一的把這些 EFI_GET_MEMORY_MAP 印出來, 就可以找到所有的 memory map。
另外的難點是要搞清楚這些記憶體是幹什麼用的, 並不是只知道開始位址, 大小就可以了。
uefi shell memmap 指令可以列出 memmap, 可以用來對照自己抓出來的記憶體範圍有無正確。
typedef struct
{
UINT32 Type;
EFI_PHYSICAL_ADDRESS PhysicalStart;
EFI_VIRTUAL_ADDRESS VirtualStart;
UINT64 NumberOfPages;
UINT64 Attribute;
} EFI_MEMORY_DESCRIPTOR
page 大小是 4k
NumberOfPages: Number of 4 KiB pages in the memory region. NumberOfPages must not be 0, and must not be any value that would represent a memory page with a start address, either physical or virtual, above 0xfffffffffffff000
有這 2 個屬性:
UINT32 Type;
UINT64 Attribute;
Type
typedef enum
{
EfiReservedMemoryType,
EfiLoaderCode,
EfiLoaderData,
EfiBootServicesCode,
EfiBootServicesData,
EfiRuntimeServicesCode,
EfiRuntimeServicesData,
EfiConventionalMemory,
EfiUnusableMemory,
EfiACPIReclaimMemory,
EfiACPIMemoryNVS,
EfiMemoryMappedIO,
EfiMemoryMappedIOPortSpace,
EfiPalCode,
EfiPersistentMemory,
EfiMaxMemoryType
} EFI_MEMORY_TYPE
ExitBootServices() 之後, EfiBootServicesCode, EfiBootServicesData 就不是給 boot service 用的, 可以拿來自由運用。
Attribute 有一個 EFI_MEMORY_RUNTIME
EFI_MEMORY_RUNTIME Runtime memory attribute: The memory region needs to be given a virtual mapping by the operating system when SetVirtualAddressMap() is called (described in Section 8.4)
以下提供一個範例程式:
get_memmap.c
1 // http://www.lab-z.com/51gfxuefi1/
2 // http://f.osdev.org/viewtopic.php?f=1&t=25587&start=0
3
4 // the code is reference: http://forum.osdev.org/viewtopic.php?f=1&t=26796
5
6 #include "efi.h"
7 #include "efi_api.h"
8
9 #define MEMMAP_SIZE 400
10
11 //struct efi_mem_desc mem_desc_pool[MEMMAP_SIZE];
12 unsigned char mem_desc_pool[MEMMAP_SIZE*sizeof(struct efi_mem_desc)];
13 struct efi_mem_desc *mem_desc;
14 efi_uintn_t key, desc_size, size;
15 u32 ver;
16 typedef int (*PrintFp)(char *str);
17
18 PrintFp print;
19
20 struct efi_system_table *g_sys_table;
21
22 char* itoa(int n, char* str, int radix)
23 {
24 char digit[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
25 char* p=str;
26 char* head=str;
27
28 // if(!p || radix < 2 || radix > 36)
29 // return p;
30 if (n==0)
31 {
32 *p++='0';
33 *p=0;
34 return str;
35 }
36 #if 0
37 if (radix == 10 && n < 0)
38 {
39 *p++='-';
40 n= -n;
41 }
42 #endif
43 while(n)
44 {
45 *p++=digit[n%radix];
46 n/=radix;
47 }
48 *p=0;
49 #if 1
50 for (--p; head < p ; ++head, --p)
51 {
52 char temp=*head;
53 *head=*p;
54 *p=temp;
55 }
56 #endif
57 return str;
58 }
59
60 // output to com1 for debug
61 int print_char(char ch)
62 {
63 asm (
64 "push %%rdx\n"
65 "push %%rax\n"
66 "mov $0x3f8,%%rdx\n"
67 "out %%al,(%%dx)\n"
68 "pop %%rax\n"
69 "pop %%rdx\n\t"
70 :
71 :"a"(ch)
72 );
73 return 0;
74 }
75
76 int print_str(char *str)
77 {
78 char *s = str;
79 while(*s)
80 {
81 print_char(*s);
82 ++s;
83 }
84 return 0;
85 }
86
87
88 // ref: http://wiki.osdev.org/Inline_Assembly/Examples#OUTx
89 void outb(u16 port, u8 val)
90 {
91 asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) );
92 /* There's an outb %al, $imm8 encoding, for compile-time constant port numbers that fit in 8b. (N constraint).
93 * Wider immediate constants would be truncated at assemble-time (e.g. "i" constraint).
94 * The outb %al, %dx encoding is the only option for all other cases.
95 * %1 expands to %dx because port is a uint16_t. %w1 could be used if we had the port number a wider C type */
96 }
97
98
99 static inline u8 inb(u16 port)
100 {
101 u8 ret;
102 asm volatile ( "inb %1, %0"
103 : "=a"(ret)
104 : "Nd"(port) );
105 return ret;
106 }
107
108 static efi_guid_t gEfiSimpleFileSystemProtocolGuid = EFI_GUID(0x964E5B22, 0x6459, 0x11D2, 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B);
109 #define PORT 0x3f8
110
111 // ref: http://wiki.osdev.org/Serial_Ports#Baud_Rate
112 void init_serial()
113 {
114 outb(PORT + 1, 0x00); // Disable all interrupts
115 outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
116 outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
117 outb(PORT + 1, 0x00); // (hi byte)
118 outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
119 outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
120 //outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
121 outb(PORT + 4, 0x03); // RTS/DSR set
122 }
123
124 void uefi_print_char(char c)
125 {
126 char str[4] = {0};
127 str[0] = c;
128 g_sys_table->con_out->output_string(g_sys_table->con_out, str);
129 }
130
131 void uefi_print(const char *str)
132 {
133 char *s = str;
134 while(*s)
135 {
136 uefi_print_char(*s);
137 ++s;
138 }
139 return 0;
140 }
141
142 int print_memory_type(u32 memory_type)
143 {
144 if (0 <= memory_type && memory_type <= sizeof(memory_type_str)/sizeof(const char*))
145 {
146 print(memory_type_str[memory_type]);
147 print("\r\n");
148 return 0;
149 }
150 else
151 {
152 print("not found\r\n");
153 return -1;
154 }
155 }
156
157 const char * mystr="abc123";
158 const char * mystr_array[]={"mnq", "12345678"};
159
160 efi_status_t EFIAPI efi_main(efi_handle_t image, struct efi_system_table *sys_table)
161 {
162 efi_uintn_t mode_num;
163 efi_status_t status;
164 mem_desc = mem_desc_pool;
165 //static struct efi_mem_desc desc[200];
166
167 efi_status_t ret;
168
169 g_sys_table = sys_table;
170 sys_table->con_out->output_string(sys_table->con_out, L"\r\nBBB\n\r");
171
172 print_str("\r\naaa\r\n");
173 uefi_print("\r\nuefi print\r\n");
174 uefi_print(mystr);
175
176 print = uefi_print;
177 print("\r\n");
178 print_str(mystr_array[0]);
179 print("\r\n");
180 print_str(mystr_array[1]);
181 print("\r\n");
182
183
184
185 print("\r\n");
186 print(memory_type_str[0]);
187 print("\r\n");
188 print(memory_type_str[1]);
189 print("\r\n");
190 print(memory_type_str[2]);
191 print("\r\n");
192
193 //init_serial();
194
195 print("test get memory map\r\n");
196
197 /* Get the memory map so we can switch off EFI */
198 //size = 0;
199 size = sizeof(mem_desc_pool);
200 void *buf = NULL;
201 char str[20];
202
203 itoa(sizeof(struct efi_mem_desc), str, 10);
204 print_str("\r\nsizeof (struct efi_mem_desc): ");
205 print_str(str);
206 print_str("\r\n");
207
208 itoa(size, str, 10);
209 print_str("\r\nsize: ");
210 print_str(str);
211 print_str("\r\n");
212
213 //while(1)
214 for (int i=0 ; i < 2 ; ++i)
215 {
216 ret = sys_table->boottime->get_memory_map(&size, mem_desc, &key, &desc_size, &ver);
217 if (ret != EFI_SUCCESS)
218 {
219 //break;
220 if (ret == EFI_BUFFER_TOO_SMALL)
221 {
222 // use allocate_pool()
223 size += 1024;
224 print_str("\r\nxx EFI_BUFFER_TOO_SMALL\r\n");
225 //ret = sys_table->boottime->allocate_pool(EfiBootServicesData, size, &buf);
226 itoa(size, str, 10);
227 print_str("size: \r\n");
228 print_str(str);
229 print_str("\r\n");
230 }
231 else
232 {
233 sys_table->con_out->output_string(sys_table->con_out, L"\r\nget_memory_map fail, the error is not EFI_BUFFER_TOO_SMALL\n\r");
234 //break;
235 }
236 }
237 else
238 {
239 itoa(size, str, 10);
240 print("size: \r\n");
241 print(str);
242 print("\r\n");
243
244 itoa(desc_size, str, 10);
245 print("desc_size: \r\n");
246 print(str);
247 print("\r\n");
248
249 itoa(ver, str, 10);
250 print("ver: \r\n");
251 print(str);
252 print("\r\n");
253
254 print("\r\nget_memory_map ok\r\n");
255 break;
256 }
257 }
258 print("abc\r\n");
259 #if 1
260 for (int i=0 ; i < (size/desc_size) ; ++i)
261 {
262 struct efi_mem_desc *md = (struct efi_mem_desc *)(mem_desc_pool + (desc_size * i));
263 itoa(i, str, 10);
264 print(str);
265 print("\r\n");
266
267 print_memory_type(md->type);
268 itoa(md->type, str, 10);
269 print("type: ");
270 print(str);
271 print("\r\n");
272
273 itoa(md->physical_start, str, 16);
274 print("physical_start: ");
275 print(str);
276 print("\r\n");
277
278 itoa(md->virtual_start, str, 16);
279 print("virtual_start: ");
280 print(str);
281 print("\r\n");
282
283 print("physical end: ");
284 u64 end = md->physical_start + (md->num_pages * 4096) - 1;
285 itoa(end, str, 16);
286 print(str);
287 print("\r\n");
288
289 itoa(md->num_pages, str, 16);
290 print("num_pages: ");
291 print(str);
292 print("\r\n");
293
294 itoa(md->attribute, str, 16);
295 print("attribute: ");
296 print(str);
297 print("\r\n");
298 }
299 #endif
300 return 0;
348 }
這個資訊需要傳給 os kernel, 這樣 os kernel 才會知道記憶體的分佈範圍。
list 1. qemu uefi shell memmap command
1 Type Start End # Pages Attributes
2 BS_Code 0000000000000000-0000000000000FFF 0000000000000001 000000000000000F
3 Available 0000000000001000-000000000009FFFF 000000000000009F 000000000000000F
4 Available 0000000000100000-00000000007FFFFF 0000000000000700 000000000000000F
5 ACPI_NVS 0000000000800000-0000000000807FFF 0000000000000008 000000000000000F
6 Available 0000000000808000-000000000080FFFF 0000000000000008 000000000000000F
7 ACPI_NVS 0000000000810000-00000000008FFFFF 00000000000000F0 000000000000000F
8 BS_Data 0000000000900000-00000000013FFFFF 0000000000000B00 000000000000000F
9 Available 0000000001400000-0000000003F35FFF 0000000000002B36 000000000000000F
10 BS_Data 0000000003F36000-0000000003F55FFF 0000000000000020 000000000000000F
11 Available 0000000003F56000-0000000006602FFF 00000000000026AD 000000000000000F
12 LoaderCode 0000000006603000-00000000066D8FFF 00000000000000D6 000000000000000F
13 Available 00000000066D9000-0000000006727FFF 000000000000004F 000000000000000F
14 BS_Data 0000000006728000-0000000006745FFF 000000000000001E 000000000000000F
15 Available 0000000006746000-0000000006763FFF 000000000000001E 000000000000000F
16 BS_Data 0000000006764000-0000000006770FFF 000000000000000D 000000000000000F
17 Available 0000000006771000-0000000006773FFF 0000000000000003 000000000000000F
18 BS_Data 0000000006774000-000000000679AFFF 0000000000000027 000000000000000F
19 Available 000000000679B000-000000000679BFFF 0000000000000001 000000000000000F
20 BS_Data 000000000679C000-00000000068A6FFF 000000000000010B 000000000000000F
21 ACPI_NVS 00000000068A7000-00000000068B4FFF 000000000000000E 000000000000000F
22 Reserved 00000000068B5000-00000000068CCFFF 0000000000000018 000000000000000F
23 RT_Data 00000000068CD000-00000000068CDFFF 0000000000000001 800000000000000F
24 BS_Code 00000000068CE000-00000000069EDFFF 0000000000000120 000000000000000F
25 RT_Data 00000000069EE000-0000000006AB4FFF 00000000000000C7 800000000000000F
26 RT_Code 0000000006AB5000-0000000006B1AFFF 0000000000000066 800000000000000F
27 BS_Data 0000000006B1B000-0000000007A1AFFF 0000000000000F00 000000000000000F
28 BS_Code 0000000007A1B000-0000000007B9AFFF 0000000000000180 000000000000000F
29 RT_Code 0000000007B9B000-0000000007BCAFFF 0000000000000030 800000000000000F
30 RT_Data 0000000007BCB000-0000000007BEEFFF 0000000000000024 800000000000000F
31 Reserved 0000000007BEF000-0000000007BF2FFF 0000000000000004 000000000000000F
32 ACPI_Recl 0000000007BF3000-0000000007BFAFFF 0000000000000008 000000000000000F
33 ACPI_NVS 0000000007BFB000-0000000007BFEFFF 0000000000000004 000000000000000F
34 BS_Data 0000000007BFF000-0000000007DFFFFF 0000000000000201 000000000000000F
35 Available 0000000007E00000-0000000007EF3FFF 00000000000000F4 000000000000000F
36 BS_Data 0000000007EF4000-0000000007F13FFF 0000000000000020 000000000000000F
37 BS_Code 0000000007F14000-0000000007F38FFF 0000000000000025 000000000000000F
38 BS_Data 0000000007F39000-0000000007F41FFF 0000000000000009 000000000000000F
39 BS_Code 0000000007F42000-0000000007F57FFF 0000000000000016 000000000000000F
40 RT_Data 0000000007F58000-0000000007F77FFF 0000000000000020 800000000000000F
41 ACPI_NVS 0000000007F78000-0000000007FFFFFF 0000000000000088 000000000000000F
42
43 Reserved : 28 Pages (114,688 Bytes)
44 LoaderCode: 214 Pages (876,544 Bytes)
45 LoaderData: 0 Pages (0 Bytes)
46 BS_Code : 732 Pages (2,998,272 Bytes)
47 BS_Data : 7,591 Pages (31,092,736 Bytes)
48 RT_Code : 150 Pages (614,400 Bytes)
49 RT_Data : 268 Pages (1,097,728 Bytes)
50 ACPI_Recl : 8 Pages (32,768 Bytes)
51 ACPI_NVS : 402 Pages (1,646,592 Bytes)
52 MMIO : 0 Pages (0 Bytes)
53 MMIO_Port : 0 Pages (0 Bytes)
54 PalCode : 0 Pages (0 Bytes)
55 Available : 23,279 Pages (95,350,784 Bytes)
56 Persistent: 0 Pages (0 Bytes)
57 --------------
58 Total Memory: 127 MB (133,709,824 Bytes)
list 2. my_getmap
1 get_memory_map ok
2 abc
3 0
4 EFI_BOOT_SERVICES_CODE
5 type: 3
6 physical_start: 0
7 virtual_start: 0
8 physical end: FFF
9 num_pages: 1
10 attribute: F
11 1
12 EFI_CONVENTIONAL_MEMORY
13 type: 7
14 physical_start: 1000
15 virtual_start: 0
16 physical end: 9FFFF
17 num_pages: 9F
18 attribute: F
19 2
20 EFI_CONVENTIONAL_MEMORY
21 type: 7
22 physical_start: 100000
23 virtual_start: 0
24 physical end: 7FFFFF
25 num_pages: 700
26 attribute: F
27 3
28 EFI_ACPI_MEMORY_NVS
29 type: 10
30 physical_start: 800000
31 virtual_start: 0
32 physical end: 807FFF
33 num_pages: 8
34 attribute: F
35 4
36 EFI_CONVENTIONAL_MEMORY
37 type: 7
38 physical_start: 808000
39 virtual_start: 0
40 physical end: 80FFFF
41 num_pages: 8
42 attribute: F
43 5
44 EFI_ACPI_MEMORY_NVS
45 type: 10
46 physical_start: 810000
47 virtual_start: 0
48 physical end: 8FFFFF
49 num_pages: F0
50 attribute: F
51 6
52 EFI_BOOT_SERVICES_DATA
53 type: 4
54 physical_start: 900000
55 virtual_start: 0
56 physical end: 13FFFFF
57 num_pages: B00
58 attribute: F
59 7
60 EFI_CONVENTIONAL_MEMORY
61 type: 7
62 physical_start: 1400000
63 virtual_start: 0
64 physical end: 3F35FFF
65 num_pages: 2B36
66 attribute: F
67 8
68 EFI_BOOT_SERVICES_DATA
69 type: 4
70 physical_start: 3F36000
71 virtual_start: 0
72 physical end: 3F55FFF
73 num_pages: 20
74 attribute: F
75 9
76 EFI_CONVENTIONAL_MEMORY
77 type: 7
78 physical_start: 3F56000
79 virtual_start: 0
80 physical end: 6602FFF
81 num_pages: 26AD
82 attribute: F
83 10
84 EFI_LOADER_CODE
85 type: 1
86 physical_start: 6603000
87 virtual_start: 0
88 physical end: 66D8FFF
89 num_pages: D6
90 attribute: F
91 11
92 EFI_CONVENTIONAL_MEMORY
93 type: 7
94 physical_start: 66D9000
95 virtual_start: 0
96 physical end: 6727FFF
97 num_pages: 4F
98 attribute: F
99 12
100 EFI_BOOT_SERVICES_DATA
101 type: 4
102 physical_start: 6728000
103 virtual_start: 0
104 physical end: 6745FFF
105 num_pages: 1E
106 attribute: F
107 13
108 EFI_CONVENTIONAL_MEMORY
109 type: 7
110 physical_start: 6746000
111 virtual_start: 0
112 physical end: 674FFFF
113 num_pages: A
114 attribute: F
115 14
116 EFI_LOADER_CODE
117 type: 1
118 physical_start: 6750000
119 virtual_start: 0
120 physical end: 675CFFF
121 num_pages: D
122 attribute: F
123 15
124 EFI_CONVENTIONAL_MEMORY
125 type: 7
126 physical_start: 675D000
127 virtual_start: 0
128 physical end: 6763FFF
129 num_pages: 7
130 attribute: F
131 16
132 EFI_BOOT_SERVICES_DATA
133 type: 4
134 physical_start: 6764000
135 virtual_start: 0
136 physical end: 6770FFF
137 num_pages: D
138 attribute: F
139 17
140 EFI_CONVENTIONAL_MEMORY
141 type: 7
142 physical_start: 6771000
143 virtual_start: 0
144 physical end: 6773FFF
145 num_pages: 3
146 attribute: F
147 18
148 EFI_BOOT_SERVICES_DATA
149 type: 4
150 physical_start: 6774000
151 virtual_start: 0
152 physical end: 68A6FFF
153 num_pages: 133
154 attribute: F
155 19
156 EFI_ACPI_MEMORY_NVS
157 type: 10
158 physical_start: 68A7000
159 virtual_start: 0
160 physical end: 68B4FFF
161 num_pages: E
162 attribute: F
163 20
164 EFI_RESERVED_MEMORY_TYPE
165 type: 0
166 physical_start: 68B5000
167 virtual_start: 0
168 physical end: 68CCFFF
169 num_pages: 18
170 attribute: F
171 21
172 EFI_RUNTIME_SERVICES_DATA
173 type: 6
174 physical_start: 68CD000
175 virtual_start: 0
176 physical end: 68CDFFF
177 num_pages: 1
178 attribute: F
179 22
180 EFI_BOOT_SERVICES_CODE
181 type: 3
182 physical_start: 68CE000
183 virtual_start: 0
184 physical end: 69EDFFF
185 num_pages: 120
186 attribute: F
187 23
188 EFI_RUNTIME_SERVICES_DATA
189 type: 6
190 physical_start: 69EE000
191 virtual_start: 0
192 physical end: 6AB4FFF
193 num_pages: C7
194 attribute: F
195 24
196 EFI_RUNTIME_SERVICES_CODE
197 type: 5
198 physical_start: 6AB5000
199 virtual_start: 0
200 physical end: 6B1AFFF
201 num_pages: 66
202 attribute: F
203 25
204 EFI_BOOT_SERVICES_DATA
205 type: 4
206 physical_start: 6B1B000
207 virtual_start: 0
208 physical end: 7A1AFFF
209 num_pages: F00
210 attribute: F
211 26
212 EFI_BOOT_SERVICES_CODE
213 type: 3
214 physical_start: 7A1B000
215 virtual_start: 0
216 physical end: 7B9AFFF
217 num_pages: 180
218 attribute: F
219 27
220 EFI_RUNTIME_SERVICES_CODE
221 type: 5
222 physical_start: 7B9B000
223 virtual_start: 0
224 physical end: 7BCAFFF
225 num_pages: 30
226 attribute: F
227 28
228 EFI_RUNTIME_SERVICES_DATA
229 type: 6
230 physical_start: 7BCB000
231 virtual_start: 0
232 physical end: 7BEEFFF
233 num_pages: 24
234 attribute: F
235 29
236 EFI_RESERVED_MEMORY_TYPE
237 type: 0
238 physical_start: 7BEF000
239 virtual_start: 0
240 physical end: 7BF2FFF
241 num_pages: 4
242 attribute: F
243 30
244 EFI_ACPI_RECLAIM_MEMORY
245 type: 9
246 physical_start: 7BF3000
247 virtual_start: 0
248 physical end: 7BFAFFF
249 num_pages: 8
250 attribute: F
251 31
252 EFI_ACPI_MEMORY_NVS
253 type: 10
254 physical_start: 7BFB000
255 virtual_start: 0
256 physical end: 7BFEFFF
257 num_pages: 4
258 attribute: F
259 32
260 EFI_BOOT_SERVICES_DATA
261 type: 4
262 physical_start: 7BFF000
263 virtual_start: 0
264 physical end: 7DFFFFF
265 num_pages: 201
266 attribute: F
267 33
268 EFI_CONVENTIONAL_MEMORY
269 type: 7
270 physical_start: 7E00000
271 virtual_start: 0
272 physical end: 7EF3FFF
273 num_pages: F4
274 attribute: F
275 34
276 EFI_BOOT_SERVICES_DATA
277 type: 4
278 physical_start: 7EF4000
279 virtual_start: 0
280 physical end: 7F13FFF
281 num_pages: 20
282 attribute: F
283 35
284 EFI_BOOT_SERVICES_CODE
285 type: 3
286 physical_start: 7F14000
287 virtual_start: 0
288 physical end: 7F38FFF
289 num_pages: 25
290 attribute: F
291 36
292 EFI_BOOT_SERVICES_DATA
293 type: 4
294 physical_start: 7F39000
295 virtual_start: 0
296 physical end: 7F41FFF
297 num_pages: 9
298 attribute: F
299 37
300 EFI_BOOT_SERVICES_CODE
301 type: 3
302 physical_start: 7F42000
303 virtual_start: 0
304 physical end: 7F57FFF
305 num_pages: 16
306 attribute: F
307 38
308 EFI_RUNTIME_SERVICES_DATA
309 type: 6
310 physical_start: 7F58000
311 virtual_start: 0
312 physical end: 7F77FFF
313 num_pages: 20
314 attribute: F
315 39
316 EFI_ACPI_MEMORY_NVS
317 type: 10
318 physical_start: 7F78000
319 virtual_start: 0
320 physical end: 7FFFFFF
321 num_pages: 88
322 attribute: F
list 1 是 uefi shell memmap 指令列出的, list 2 是 get_memmap.c 程式的輸出, 我用以下指令將 ouput 存檔。
qemu-system-x86_64 -drive if=ide,file=fat:rw:hda-contents,index=0,media=disk -bios OVMF.fd -net none -serial file:com1_file
要確認是不是有抓到正確的 memory map, 可以對照 memmap 的結果, 除了 virtual_start 是 0 之外, 開始位址, 結束位置, memory type, attribute 都是對的。總共有 40 塊 EFI_MEMORY_DESCRIPTOR。
ref:
ACPI之 系统地址映射接口
Step to UEFI Shell (5)----获得Shell下内存分配状况
A Tour beyond BIOS Memory Map Design in UEFI BIOS
Get EFI/UEFI Memory Map (有討論什麼是 Multiboot)
Boot Services vs Runtime Services
kernel 如何调用uefi的runtime service
UEFI Test Tools For Linux Developers
學到許多,感激不盡
回覆刪除