]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Sample/Tools/Source/GenPage/genpage.c
1) Sync EdkCompatibilityPkg with EDK 1.04. The changes includes:
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / GenPage / genpage.c
CommitLineData
3eb9473e 1/*++ \r
2\r
3Copyright 2006 - 2007, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13 GenPage.c\r
14 \r
15Abstract:\r
16 Pre-Create a 4G page table (2M pages).\r
17 It's used in DUET x64 build needed to enter LongMode.\r
18 \r
19 Create 4G page table (2M pages)\r
20 \r
21 Linear Address\r
22 63 48 47 39 38 30 29 21 20 0\r
23 +--------+-------+---------------+-----------+-----------------------------+\r
24 PML4 Directory-Ptr Directory Offset\r
25\r
26 Paging-Structures :=\r
27 PML4\r
28 (\r
29 Directory-Ptr Directory {512}\r
30 ) {4}\r
31--*/\r
32\r
33#include <stdio.h>\r
34#include <stdlib.h>\r
35#include "VirtualMemory.h"\r
36\r
37void\r
38memset (void *, char, long);\r
39\r
40unsigned int\r
41xtoi (char *);\r
42\r
43#define EFI_PAGE_BASE_OFFSET_IN_LDR 0x70000\r
44#define EFI_PAGE_BASE_ADDRESS (EFI_PAGE_BASE_OFFSET_IN_LDR + 0x20000)\r
45\r
46unsigned int gPageTableBaseAddress = EFI_PAGE_BASE_ADDRESS;\r
47unsigned int gPageTableOffsetInFile = EFI_PAGE_BASE_OFFSET_IN_LDR;\r
48\r
49#define EFI_MAX_ENTRY_NUM 512\r
50\r
51#define EFI_PML4_ENTRY_NUM 1\r
52#define EFI_PDPTE_ENTRY_NUM 4\r
53#define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM\r
54\r
55#define EFI_PML4_PAGE_NUM 1\r
56#define EFI_PDPTE_PAGE_NUM EFI_PML4_ENTRY_NUM\r
57#define EFI_PDE_PAGE_NUM (EFI_PML4_ENTRY_NUM * EFI_PDPTE_ENTRY_NUM)\r
58\r
59#define EFI_PAGE_NUMBER (EFI_PML4_PAGE_NUM + EFI_PDPTE_PAGE_NUM + EFI_PDE_PAGE_NUM)\r
60\r
61#define EFI_SIZE_OF_PAGE 0x1000\r
62#define EFI_PAGE_SIZE_2M 0x200000\r
63\r
64#define CONVERT_BIN_PAGE_ADDRESS(a) ((UINT8 *) a - PageTable + gPageTableBaseAddress)\r
65\r
66\r
67void *\r
68CreateIdentityMappingPageTables (\r
69 void\r
70 )\r
71/*++\r
72\r
73Routine Description:\r
74 To create 4G PAE 2M pagetable\r
75\r
76Return:\r
77 void * - buffer containing created pagetable\r
78\r
79--*/\r
80{\r
81 UINT64 PageAddress;\r
82 UINT8 *PageTable;\r
83 UINT8 *PageTablePtr;\r
84 int PML4Index;\r
85 int PDPTEIndex;\r
86 int PDEIndex;\r
87 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry;\r
88 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry;\r
89 X64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB;\r
90\r
91 PageTable = (void *)malloc (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE);\r
92 memset (PageTable, 0, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE));\r
93 PageTablePtr = PageTable;\r
94\r
95 PageAddress = 0;\r
96\r
97 //\r
98 // Page Table structure 3 level 2MB.\r
99 //\r
100 // Page-Map-Level-4-Table : bits 47-39\r
101 // Page-Directory-Pointer-Table : bits 38-30\r
102 //\r
103 // Page Table 2MB : Page-Directory(2M) : bits 29-21\r
104 //\r
105 //\r
106\r
107 PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;\r
108\r
109 for (PML4Index = 0; PML4Index < EFI_PML4_ENTRY_NUM; PML4Index++, PageMapLevel4Entry++) {\r
110 //\r
111 // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry\r
112 // \r
113 PageTablePtr += EFI_SIZE_OF_PAGE;\r
114 PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;\r
115\r
116 //\r
117 // Make a Page-Map-Level-4-Table Entry\r
118 //\r
119 PageMapLevel4Entry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry));\r
120 PageMapLevel4Entry->Bits.ReadWrite = 1;\r
121 PageMapLevel4Entry->Bits.Present = 1;\r
122\r
123 for (PDPTEIndex = 0; PDPTEIndex < EFI_PDPTE_ENTRY_NUM; PDPTEIndex++, PageDirectoryPointerEntry++) {\r
124 //\r
125 // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry\r
126 // \r
127 PageTablePtr += EFI_SIZE_OF_PAGE;\r
128 PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)PageTablePtr;\r
129\r
130 //\r
131 // Make a Page-Directory-Pointer-Table Entry\r
132 //\r
133 PageDirectoryPointerEntry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB));\r
134 PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
135 PageDirectoryPointerEntry->Bits.Present = 1;\r
136\r
137 for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry2MB++) {\r
138 //\r
139 // Make a Page-Directory Entry\r
140 //\r
141 PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress;\r
142 PageDirectoryEntry2MB->Bits.ReadWrite = 1;\r
143 PageDirectoryEntry2MB->Bits.Present = 1;\r
144 PageDirectoryEntry2MB->Bits.MustBe1 = 1;\r
145\r
146 PageAddress += EFI_PAGE_SIZE_2M;\r
147 }\r
148 }\r
149 }\r
150\r
151 return PageTable;\r
152}\r
153\r
154int\r
155GenBinPage (\r
156 void *BaseMemory,\r
157 char *NoPageFileName,\r
158 char *PageFileName\r
159 )\r
160/*++\r
161\r
162Routine Description:\r
163 Write the buffer containing page table to file at a specified offset.\r
164 Here the offset is defined as EFI_PAGE_BASE_OFFSET_IN_LDR.\r
165\r
166Arguments:\r
167 BaseMemory - buffer containing page table\r
168 NoPageFileName - file to write page table\r
169 PageFileName - file save to after writing\r
170\r
171return:\r
172 0 : successful\r
173 -1 : failed\r
174\r
175--*/\r
176{\r
177 FILE *PageFile;\r
178 FILE *NoPageFile;\r
179 UINT8 Data;\r
180 unsigned long FileSize;\r
181\r
182 //\r
183 // Open files\r
184 //\r
185 PageFile = fopen (PageFileName, "w+b");\r
186 if (PageFile == NULL) {\r
187 fprintf (stderr, "GenBinPage: Could not open file %s\n", PageFileName);\r
188 return -1;\r
189 }\r
190\r
191 NoPageFile = fopen (NoPageFileName, "r+b");\r
192 if (NoPageFile == NULL) {\r
193 fprintf (stderr, "GenBinPage: Could not open file %s\n", NoPageFileName);\r
194 fclose (PageFile);\r
195 return -1;\r
196 }\r
197\r
198 //\r
199 // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR\r
200 //\r
201 fseek (NoPageFile, 0, SEEK_END);\r
202 FileSize = ftell (NoPageFile);\r
203 fseek (NoPageFile, 0, SEEK_SET);\r
204 if (FileSize > gPageTableOffsetInFile) {\r
205 fprintf (stderr, "GenBinPage: file size too large - 0x%x\n", FileSize);\r
206 fclose (PageFile);\r
207 fclose (NoPageFile);\r
208 return -1;\r
209 }\r
210\r
211 //\r
212 // Write data\r
213 //\r
214 while (fread (&Data, sizeof(UINT8), 1, NoPageFile)) {\r
215 fwrite (&Data, sizeof(UINT8), 1, PageFile);\r
216 }\r
217\r
218 //\r
219 // Write PageTable\r
220 //\r
221 fseek (PageFile, gPageTableOffsetInFile, SEEK_SET);\r
222 fwrite (BaseMemory, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE), 1, PageFile);\r
223\r
224 //\r
225 // Close files\r
226 //\r
227 fclose (PageFile);\r
228 fclose (NoPageFile);\r
229\r
230 return 0;\r
231}\r
232\r
233int\r
234main (\r
235 int argc,\r
236 char **argv\r
237 )\r
238{\r
239 void *BaseMemory;\r
240 int result;\r
241\r
242 //\r
243 // Check parameter\r
244 //\r
245 if ((argc != 3) && (argc != 5)) {\r
246 printf ("Usage: GenPage.exe NoPageFile PageFile [<PageTableBaseAddrss> <PageTableOffsetInFile>]\n");\r
247 return 1;\r
248 }\r
249\r
250 //\r
251 // Get PageTable parameter, if have\r
252 //\r
253 if (argc == 5) {\r
254 gPageTableBaseAddress = xtoi (argv[3]);\r
255 gPageTableOffsetInFile = xtoi (argv[4]);\r
256 }\r
257\r
258 //\r
259 // Create X64 page table\r
260 //\r
261 BaseMemory = CreateIdentityMappingPageTables ();\r
262\r
263 //\r
264 // Add page table to binary file\r
265 //\r
266 result = GenBinPage (BaseMemory, argv[1], argv[2]);\r
267 if (result < 0) {\r
268 return 1;\r
269 }\r
270\r
271 return 0;\r
272}\r
273\r
274unsigned int\r
275xtoi (\r
276 char *str\r
277 )\r
278/*++\r
279\r
280Routine Description:\r
281\r
282 Convert hex string to uint\r
283\r
284Arguments:\r
285\r
286 Str - The string\r
287 \r
288Returns:\r
289\r
290--*/\r
291{\r
292 unsigned int u;\r
293 char c;\r
294 unsigned int m;\r
295 \r
296 if (str == NULL) {\r
297 return 0;\r
298 }\r
299 \r
300 m = (unsigned int) -1 >> 4;\r
301 //\r
302 // skip preceeding white space\r
303 //\r
304 while (*str && *str == ' ') {\r
305 str += 1;\r
306 }\r
307 //\r
308 // skip preceeding zeros\r
309 //\r
310 while (*str && *str == '0') {\r
311 str += 1;\r
312 }\r
313 //\r
314 // skip preceeding white space\r
315 //\r
316 if (*str && (*str == 'x' || *str == 'X')) {\r
317 str += 1;\r
318 }\r
319 //\r
320 // convert hex digits\r
321 //\r
322 u = 0;\r
323 c = *(str++);\r
324 while (c) {\r
325 if (c >= 'a' && c <= 'f') {\r
326 c -= 'a' - 'A';\r
327 }\r
328\r
329 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {\r
330 if (u > m) {\r
331 return (unsigned int) -1;\r
332 }\r
333\r
334 u = u << 4 | c - (c >= 'A' ? 'A' - 10 : '0');\r
335 } else {\r
336 break;\r
337 }\r
338\r
339 c = *(str++);\r
340 }\r
341\r
342 return u;\r
343}\r
344\r