2019年4月26日 星期五

uefi os loader (3) - get memory map

藏拙於巧、用晦而明、寓清於濁、以屈為伸
這個 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:
  1. ACPI之 系统地址映射接口
  2. Step to UEFI Shell (5)----获得Shell下内存分配状况
  3. A Tour beyond BIOS Memory Map Design in UEFI BIOS
  4. Get EFI/UEFI Memory Map(有討論什麼是 Multiboot)
  5. Boot Services vs Runtime Services
  6. kernel 如何调用uefi的runtime service
  7. UEFI Test Tools For Linux Developers

1 則留言:

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。