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