]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenPage/GenPage.c
Sync BaseTool trunk (version r2599) into EDKII BaseTools.
[mirror_edk2.git] / BaseTools / Source / C / GenPage / GenPage.c
CommitLineData
30fdf114
LG
1/** @file\r
2\r
4afd3d04 3Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
40d841f6 4This program and the accompanying materials \r
30fdf114
LG
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 <string.h>\r
36#include "VirtualMemory.h"\r
37#include "EfiUtilityMsgs.h"\r
fd171542 38#include "ParseInf.h"\r
30fdf114
LG
39\r
40#define EFI_PAGE_BASE_OFFSET_IN_LDR 0x70000\r
41#define EFI_PAGE_BASE_ADDRESS (EFI_PAGE_BASE_OFFSET_IN_LDR + 0x20000)\r
42\r
43UINT32 gPageTableBaseAddress = EFI_PAGE_BASE_ADDRESS;\r
44UINT32 gPageTableOffsetInFile = EFI_PAGE_BASE_OFFSET_IN_LDR;\r
45\r
46#define EFI_MAX_ENTRY_NUM 512\r
47\r
48#define EFI_PML4_ENTRY_NUM 1\r
49#define EFI_PDPTE_ENTRY_NUM 4\r
50#define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM\r
51\r
52#define EFI_PML4_PAGE_NUM 1\r
53#define EFI_PDPTE_PAGE_NUM EFI_PML4_ENTRY_NUM\r
54#define EFI_PDE_PAGE_NUM (EFI_PML4_ENTRY_NUM * EFI_PDPTE_ENTRY_NUM)\r
55\r
56#define EFI_PAGE_NUMBER (EFI_PML4_PAGE_NUM + EFI_PDPTE_PAGE_NUM + EFI_PDE_PAGE_NUM)\r
57\r
58#define EFI_SIZE_OF_PAGE 0x1000\r
59#define EFI_PAGE_SIZE_2M 0x200000\r
60\r
61#define CONVERT_BIN_PAGE_ADDRESS(a) ((UINT8 *) a - PageTable + gPageTableBaseAddress)\r
62\r
63//\r
64// Utility Name\r
65//\r
4234283c 66#define UTILITY_NAME "GenPage"\r
30fdf114
LG
67\r
68//\r
69// Utility version information\r
70//\r
71#define UTILITY_MAJOR_VERSION 0\r
72#define UTILITY_MINOR_VERSION 1\r
73\r
74void\r
75Version (\r
76 void\r
77 )\r
78/*++\r
79\r
80Routine Description:\r
81\r
82 Displays the standard utility information to SDTOUT\r
83\r
84Arguments:\r
85\r
86 None\r
87\r
88Returns:\r
89\r
90 None\r
91\r
92--*/\r
93{\r
4afd3d04 94 printf ("%s Version %d.%d Build %s\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
30fdf114
LG
95}\r
96\r
97VOID\r
98Usage (\r
99 void\r
100 )\r
101{\r
4afd3d04
LG
102 printf ("Usage: GenPage.exe [options] EfiLoaderImageName \n\n\\r
103Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.\n\n\\r
104 Utility to generate the EfiLoader image containing a page table.\n\n\\r
105optional arguments:\n\\r
106 -h, --help Show this help message and exit\n\\r
107 --version Show program's version number and exit\n\\r
108 -d [DEBUG], --debug [DEBUG]\n\\r
109 Output DEBUG statements, where DEBUG_LEVEL is 0 (min)\n\\r
110 - 9 (max)\n\\r
111 -v, --verbose Print informational statements\n\\r
112 -q, --quiet Returns the exit code, error messages will be\n\\r
113 displayed\n\\r
114 -s, --silent Returns only the exit code; informational and error\n\\r
115 messages are not displayed\n\\r
116 -o OUTPUT_FILENAME, --output OUTPUT_FILENAME\n\\r
117 Output file contain both the non-page table part and\n\\r
118 the page table\n\\r
119 -b BASE_ADDRESS, --baseaddr BASE_ADDRESS\n\\r
4234283c 120 The page table location\n\\r
4afd3d04 121 -f OFFSET, --offset OFFSET\n\\r
4234283c
LG
122 The position that the page table will appear in the\n\\r
123 output file\n\\r
4afd3d04 124 --sfo Reserved for future use\n");\r
30fdf114
LG
125\r
126}\r
127\r
128void *\r
129CreateIdentityMappingPageTables (\r
130 void\r
131 )\r
132/*++\r
133\r
134Routine Description:\r
135 To create 4G PAE 2M pagetable\r
136\r
137Return:\r
138 void * - buffer containing created pagetable\r
139\r
140--*/\r
141{\r
142 UINT64 PageAddress;\r
143 UINT8 *PageTable;\r
144 UINT8 *PageTablePtr;\r
145 int PML4Index;\r
146 int PDPTEIndex;\r
147 int PDEIndex;\r
148 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry;\r
149 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry;\r
150 X64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB;\r
151\r
152 PageTable = (void *)malloc (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE);\r
153 memset (PageTable, 0, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE));\r
154 PageTablePtr = PageTable;\r
155\r
156 PageAddress = 0;\r
157\r
158 //\r
159 // Page Table structure 3 level 2MB.\r
160 //\r
161 // Page-Map-Level-4-Table : bits 47-39\r
162 // Page-Directory-Pointer-Table : bits 38-30\r
163 //\r
164 // Page Table 2MB : Page-Directory(2M) : bits 29-21\r
165 //\r
166 //\r
167\r
168 PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;\r
169\r
170 for (PML4Index = 0; PML4Index < EFI_PML4_ENTRY_NUM; PML4Index++, PageMapLevel4Entry++) {\r
171 //\r
172 // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry\r
173 // \r
174 PageTablePtr += EFI_SIZE_OF_PAGE;\r
175 PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;\r
176\r
177 //\r
178 // Make a Page-Map-Level-4-Table Entry\r
179 //\r
180 PageMapLevel4Entry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry));\r
181 PageMapLevel4Entry->Bits.ReadWrite = 1;\r
182 PageMapLevel4Entry->Bits.Present = 1;\r
183\r
184 for (PDPTEIndex = 0; PDPTEIndex < EFI_PDPTE_ENTRY_NUM; PDPTEIndex++, PageDirectoryPointerEntry++) {\r
185 //\r
186 // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry\r
187 // \r
188 PageTablePtr += EFI_SIZE_OF_PAGE;\r
189 PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)PageTablePtr;\r
190\r
191 //\r
192 // Make a Page-Directory-Pointer-Table Entry\r
193 //\r
194 PageDirectoryPointerEntry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB));\r
195 PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
196 PageDirectoryPointerEntry->Bits.Present = 1;\r
197\r
198 for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry2MB++) {\r
199 //\r
200 // Make a Page-Directory Entry\r
201 //\r
202 PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress;\r
203 PageDirectoryEntry2MB->Bits.ReadWrite = 1;\r
204 PageDirectoryEntry2MB->Bits.Present = 1;\r
205 PageDirectoryEntry2MB->Bits.MustBe1 = 1;\r
206\r
207 PageAddress += EFI_PAGE_SIZE_2M;\r
208 }\r
209 }\r
210 }\r
211\r
212 return PageTable;\r
213}\r
214\r
215INT32\r
216GenBinPage (\r
217 void *BaseMemory,\r
218 char *NoPageFileName,\r
219 char *PageFileName\r
220 )\r
221/*++\r
222\r
223Routine Description:\r
224 Write the buffer containing page table to file at a specified offset.\r
225 Here the offset is defined as EFI_PAGE_BASE_OFFSET_IN_LDR.\r
226\r
227Arguments:\r
228 BaseMemory - buffer containing page table\r
229 NoPageFileName - file to write page table\r
230 PageFileName - file save to after writing\r
231\r
232return:\r
233 0 : successful\r
234 -1 : failed\r
235\r
236--*/\r
237{\r
238 FILE *PageFile;\r
239 FILE *NoPageFile;\r
240 UINT8 Data;\r
241 unsigned long FileSize;\r
242\r
243 //\r
244 // Open files\r
245 //\r
246 PageFile = fopen (PageFileName, "w+b");\r
247 if (PageFile == NULL) {\r
248 Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Output File %s open failure", PageFileName);\r
249 return -1;\r
250 }\r
251\r
252 NoPageFile = fopen (NoPageFileName, "r+b");\r
253 if (NoPageFile == NULL) {\r
254 Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Input File %s open failure", NoPageFileName);\r
255 fclose (PageFile);\r
256 return -1;\r
257 }\r
258\r
259 //\r
260 // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR\r
261 //\r
262 fseek (NoPageFile, 0, SEEK_END);\r
263 FileSize = ftell (NoPageFile);\r
264 fseek (NoPageFile, 0, SEEK_SET);\r
265 if (FileSize > gPageTableOffsetInFile) {\r
fd171542 266 Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Input file size (0x%lx) exceeds the Page Table Offset (0x%x)", FileSize, (unsigned) gPageTableOffsetInFile);\r
30fdf114
LG
267 fclose (PageFile);\r
268 fclose (NoPageFile);\r
269 return -1;\r
270 }\r
271\r
272 //\r
273 // Write data\r
274 //\r
275 while (fread (&Data, sizeof(UINT8), 1, NoPageFile)) {\r
276 fwrite (&Data, sizeof(UINT8), 1, PageFile);\r
277 }\r
278\r
279 //\r
280 // Write PageTable\r
281 //\r
282 fseek (PageFile, gPageTableOffsetInFile, SEEK_SET);\r
283 fwrite (BaseMemory, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE), 1, PageFile);\r
284\r
285 //\r
286 // Close files\r
287 //\r
288 fclose (PageFile);\r
289 fclose (NoPageFile);\r
290\r
291 return 0;\r
292}\r
293\r
294int\r
295main (\r
296 int argc,\r
297 char **argv\r
298 )\r
299{\r
300 VOID *BaseMemory;\r
301 INTN result;\r
302 CHAR8 *OutputFile = NULL;\r
303 CHAR8 *InputFile = NULL;\r
304 EFI_STATUS Status;\r
305 UINT64 TempValue;\r
306\r
307 SetUtilityName("GenPage");\r
308\r
309 if (argc == 1) {\r
310 Usage();\r
311 return STATUS_ERROR;\r
312 }\r
313 \r
314 argc --;\r
315 argv ++;\r
316\r
317 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
318 Usage();\r
319 return 0; \r
320 }\r
321\r
322 if (stricmp (argv[0], "--version") == 0) {\r
323 Version();\r
324 return 0; \r
325 }\r
326 \r
327 while (argc > 0) {\r
328 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {\r
329 if (argv[1] == NULL || argv[1][0] == '-') {\r
330 Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option");\r
331 return STATUS_ERROR;\r
332 }\r
333 OutputFile = argv[1];\r
334 argc -= 2;\r
335 argv += 2;\r
336 continue; \r
337 }\r
338 \r
339 if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--baseaddr") == 0)) {\r
340 if (argv[1] == NULL || argv[1][0] == '-') {\r
341 Error (NULL, 0, 1003, "Invalid option value", "Base address is missing for -b option");\r
342 return STATUS_ERROR;\r
343 }\r
344 Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue);\r
345 if (EFI_ERROR (Status)) {\r
346 Error (NULL, 0, 1003, "Invalid option value", "Base address is not valid intergrator");\r
347 return STATUS_ERROR;\r
348 }\r
349 gPageTableBaseAddress = (UINT32) TempValue;\r
350 argc -= 2;\r
351 argv += 2;\r
352 continue; \r
353 }\r
354 \r
355 if ((stricmp (argv[0], "-f") == 0) || (stricmp (argv[0], "--offset") == 0)) {\r
356 if (argv[1] == NULL || argv[1][0] == '-') {\r
357 Error (NULL, 0, 1003, "Invalid option value", "Offset is missing for -f option");\r
358 return STATUS_ERROR;\r
359 }\r
360 Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue);\r
361 if (EFI_ERROR (Status)) {\r
362 Error (NULL, 0, 1003, "Invalid option value", "Offset is not valid intergrator");\r
363 return STATUS_ERROR;\r
364 }\r
365 gPageTableOffsetInFile = (UINT32) TempValue;\r
366 argc -= 2;\r
367 argv += 2;\r
368 continue; \r
369 }\r
370\r
371 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
372 argc --;\r
373 argv ++;\r
374 continue; \r
375 }\r
376 \r
377 if ((stricmp (argv[0], "-v") ==0) || (stricmp (argv[0], "--verbose") == 0)) {\r
378 argc --;\r
379 argv ++;\r
380 continue; \r
381 }\r
382 \r
383 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
384 if (argv[1] == NULL || argv[1][0] == '-') {\r
385 Error (NULL, 0, 1003, "Invalid option value", "Debug Level is not specified.");\r
386 return STATUS_ERROR;\r
387 }\r
388 Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue);\r
389 if (EFI_ERROR (Status)) {\r
390 Error (NULL, 0, 1003, "Invalid option value", "Debug Level is not valid intergrator.");\r
391 return STATUS_ERROR;\r
392 }\r
393 if (TempValue > 9) {\r
fd171542 394 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) TempValue);\r
30fdf114
LG
395 return STATUS_ERROR;\r
396 }\r
397 argc -= 2;\r
398 argv += 2;\r
399 continue; \r
400 }\r
401\r
402 if (argv[0][0] == '-') {\r
403 Error (NULL, 0, 1000, "Unknown option", argv[0]);\r
404 return STATUS_ERROR;\r
405 }\r
406 \r
407 //\r
408 // Don't recognize the paramter.\r
409 //\r
410 InputFile = argv[0];\r
411 argc--;\r
412 argv++;\r
413 }\r
414 \r
415 if (InputFile == NULL) {\r
416 Error (NULL, 0, 1003, "Invalid option value", "Input file is not specified");\r
417 return STATUS_ERROR;\r
418 }\r
419 \r
420 //\r
421 // Create X64 page table\r
422 //\r
423 BaseMemory = CreateIdentityMappingPageTables ();\r
424\r
425 //\r
426 // Add page table to binary file\r
427 //\r
428 result = GenBinPage (BaseMemory, InputFile, OutputFile);\r
429 if (result < 0) {\r
430 return STATUS_ERROR;\r
431 }\r
432\r
433 return 0;\r
434}\r
435\r