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