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