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