3 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
4 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
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.
16 Pre-Create a 4G page table (2M pages).
17 It's used in DUET x64 build needed to enter LongMode.
19 Create 4G page table (2M pages)
22 63 48 47 39 38 30 29 21 20 0
23 +--------+-------+---------------+-----------+-----------------------------+
24 PML4 Directory-Ptr Directory Offset
29 Directory-Ptr Directory {512}
36 #include "VirtualMemory.h"
37 #include "EfiUtilityMsgs.h"
40 #define EFI_PAGE_BASE_OFFSET_IN_LDR 0x70000
41 #define EFI_PAGE_BASE_ADDRESS (EFI_PAGE_BASE_OFFSET_IN_LDR + 0x20000)
43 UINT32 gPageTableBaseAddress
= EFI_PAGE_BASE_ADDRESS
;
44 UINT32 gPageTableOffsetInFile
= EFI_PAGE_BASE_OFFSET_IN_LDR
;
46 #define EFI_MAX_ENTRY_NUM 512
48 #define EFI_PML4_ENTRY_NUM 1
49 #define EFI_PDPTE_ENTRY_NUM 4
50 #define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM
52 #define EFI_PML4_PAGE_NUM 1
53 #define EFI_PDPTE_PAGE_NUM EFI_PML4_ENTRY_NUM
54 #define EFI_PDE_PAGE_NUM (EFI_PML4_ENTRY_NUM * EFI_PDPTE_ENTRY_NUM)
56 #define EFI_PAGE_NUMBER (EFI_PML4_PAGE_NUM + EFI_PDPTE_PAGE_NUM + EFI_PDE_PAGE_NUM)
58 #define EFI_SIZE_OF_PAGE 0x1000
59 #define EFI_PAGE_SIZE_2M 0x200000
61 #define CONVERT_BIN_PAGE_ADDRESS(a) ((UINT8 *) a - PageTable + gPageTableBaseAddress)
66 #define UTILITY_NAME "GenPage"
69 // Utility version information
71 #define UTILITY_MAJOR_VERSION 0
72 #define UTILITY_MINOR_VERSION 2
82 Displays the standard utility information to SDTOUT
94 printf ("%s Version %d.%d %s\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
102 printf ("Usage: GenPage.exe [options] EfiLoaderImageName \n\n\
103 Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.\n\n\
104 Utility to generate the EfiLoader image containing a page table.\n\n\
105 optional arguments:\n\
106 -h, --help Show this help message and exit\n\
107 --version Show program's version number and exit\n\
108 -d [DEBUG], --debug [DEBUG]\n\
109 Output DEBUG statements, where DEBUG_LEVEL is 0 (min)\n\
111 -v, --verbose Print informational statements\n\
112 -q, --quiet Returns the exit code, error messages will be\n\
114 -s, --silent Returns only the exit code; informational and error\n\
115 messages are not displayed\n\
116 -o OUTPUT_FILENAME, --output OUTPUT_FILENAME\n\
117 Output file contain both the non-page table part and\n\
119 -b BASE_ADDRESS, --baseaddr BASE_ADDRESS\n\
120 The page table location\n\
121 -f OFFSET, --offset OFFSET\n\
122 The position that the page table will appear in the\n\
124 --sfo Reserved for future use\n");
129 CreateIdentityMappingPageTables (
135 To create 4G PAE 2M pagetable
138 void * - buffer containing created pagetable
148 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*PageMapLevel4Entry
;
149 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*PageDirectoryPointerEntry
;
150 X64_PAGE_TABLE_ENTRY_2M
*PageDirectoryEntry2MB
;
152 PageTable
= (void *)malloc (EFI_PAGE_NUMBER
* EFI_SIZE_OF_PAGE
);
153 memset (PageTable
, 0, (EFI_PAGE_NUMBER
* EFI_SIZE_OF_PAGE
));
154 PageTablePtr
= PageTable
;
159 // Page Table structure 3 level 2MB.
161 // Page-Map-Level-4-Table : bits 47-39
162 // Page-Directory-Pointer-Table : bits 38-30
164 // Page Table 2MB : Page-Directory(2M) : bits 29-21
168 PageMapLevel4Entry
= (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*)PageTablePtr
;
170 for (PML4Index
= 0; PML4Index
< EFI_PML4_ENTRY_NUM
; PML4Index
++, PageMapLevel4Entry
++) {
172 // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry
174 PageTablePtr
+= EFI_SIZE_OF_PAGE
;
175 PageDirectoryPointerEntry
= (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*)PageTablePtr
;
178 // Make a Page-Map-Level-4-Table Entry
180 PageMapLevel4Entry
->Uint64
= (UINT64
)(UINT32
)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry
));
181 PageMapLevel4Entry
->Bits
.ReadWrite
= 1;
182 PageMapLevel4Entry
->Bits
.Present
= 1;
184 for (PDPTEIndex
= 0; PDPTEIndex
< EFI_PDPTE_ENTRY_NUM
; PDPTEIndex
++, PageDirectoryPointerEntry
++) {
186 // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry
188 PageTablePtr
+= EFI_SIZE_OF_PAGE
;
189 PageDirectoryEntry2MB
= (X64_PAGE_TABLE_ENTRY_2M
*)PageTablePtr
;
192 // Make a Page-Directory-Pointer-Table Entry
194 PageDirectoryPointerEntry
->Uint64
= (UINT64
)(UINT32
)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB
));
195 PageDirectoryPointerEntry
->Bits
.ReadWrite
= 1;
196 PageDirectoryPointerEntry
->Bits
.Present
= 1;
198 for (PDEIndex
= 0; PDEIndex
< EFI_PDE_ENTRY_NUM
; PDEIndex
++, PageDirectoryEntry2MB
++) {
200 // Make a Page-Directory Entry
202 PageDirectoryEntry2MB
->Uint64
= (UINT64
)PageAddress
;
203 PageDirectoryEntry2MB
->Bits
.ReadWrite
= 1;
204 PageDirectoryEntry2MB
->Bits
.Present
= 1;
205 PageDirectoryEntry2MB
->Bits
.MustBe1
= 1;
207 PageAddress
+= EFI_PAGE_SIZE_2M
;
218 char *NoPageFileName
,
224 Write the buffer containing page table to file at a specified offset.
225 Here the offset is defined as EFI_PAGE_BASE_OFFSET_IN_LDR.
228 BaseMemory - buffer containing page table
229 NoPageFileName - file to write page table
230 PageFileName - file save to after writing
241 unsigned long FileSize
;
246 PageFile
= fopen (LongFilePath (PageFileName
), "w+b");
247 if (PageFile
== NULL
) {
248 Error (NoPageFileName
, 0, 0x4002, "Invalid parameter option", "Output File %s open failure", PageFileName
);
252 NoPageFile
= fopen (LongFilePath (NoPageFileName
), "r+b");
253 if (NoPageFile
== NULL
) {
254 Error (NoPageFileName
, 0, 0x4002, "Invalid parameter option", "Input File %s open failure", NoPageFileName
);
260 // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR
262 fseek (NoPageFile
, 0, SEEK_END
);
263 FileSize
= ftell (NoPageFile
);
264 fseek (NoPageFile
, 0, SEEK_SET
);
265 if (FileSize
> gPageTableOffsetInFile
) {
266 Error (NoPageFileName
, 0, 0x4002, "Invalid parameter option", "Input file size (0x%lx) exceeds the Page Table Offset (0x%x)", FileSize
, (unsigned) gPageTableOffsetInFile
);
275 while (fread (&Data
, sizeof(UINT8
), 1, NoPageFile
)) {
276 fwrite (&Data
, sizeof(UINT8
), 1, PageFile
);
282 fseek (PageFile
, gPageTableOffsetInFile
, SEEK_SET
);
283 fwrite (BaseMemory
, (EFI_PAGE_NUMBER
* EFI_SIZE_OF_PAGE
), 1, PageFile
);
302 CHAR8
*OutputFile
= NULL
;
303 CHAR8
*InputFile
= NULL
;
307 SetUtilityName("GenPage");
317 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
322 if (stricmp (argv
[0], "--version") == 0) {
328 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--output") == 0)) {
329 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
330 Error (NULL
, 0, 1003, "Invalid option value", "Output file is missing for -o option");
333 OutputFile
= argv
[1];
339 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--baseaddr") == 0)) {
340 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
341 Error (NULL
, 0, 1003, "Invalid option value", "Base address is missing for -b option");
344 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &TempValue
);
345 if (EFI_ERROR (Status
)) {
346 Error (NULL
, 0, 1003, "Invalid option value", "Base address is not valid intergrator");
349 gPageTableBaseAddress
= (UINT32
) TempValue
;
355 if ((stricmp (argv
[0], "-f") == 0) || (stricmp (argv
[0], "--offset") == 0)) {
356 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
357 Error (NULL
, 0, 1003, "Invalid option value", "Offset is missing for -f option");
360 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &TempValue
);
361 if (EFI_ERROR (Status
)) {
362 Error (NULL
, 0, 1003, "Invalid option value", "Offset is not valid intergrator");
365 gPageTableOffsetInFile
= (UINT32
) TempValue
;
371 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
377 if ((stricmp (argv
[0], "-v") ==0) || (stricmp (argv
[0], "--verbose") == 0)) {
383 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
384 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
385 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level is not specified.");
388 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &TempValue
);
389 if (EFI_ERROR (Status
)) {
390 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level is not valid intergrator.");
394 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) TempValue
);
402 if (argv
[0][0] == '-') {
403 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
408 // Don't recognize the paramter.
415 if (InputFile
== NULL
) {
416 Error (NULL
, 0, 1003, "Invalid option value", "Input file is not specified");
421 // Create X64 page table
423 BaseMemory
= CreateIdentityMappingPageTables ();
426 // Add page table to binary file
428 result
= GenBinPage (BaseMemory
, InputFile
, OutputFile
);