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