3 Copyright (c) 2006 - 2011, 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 1
82 Displays the standard utility information to SDTOUT
94 printf ("%s v%d.%d -Utility to generate the EfiLoader image containing page table.\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
95 printf ("Copyright (c) 2008 - 2011 Intel Corporation. All rights reserved.\n");
104 printf ("\nUsage: \n\
106 -o, --output Filename\n\
107 The file that contains both non-page table part and\n\
109 [-b, --baseaddr baseaddress]\n\
110 The page table location\n\
111 [-f, --offset offset]\n\
112 The position that the page table will appear in the\n\
114 [-v, --verbose] Turn on verbose output with informational messages\n\
116 [--version] Print version and copyright of this program and exit\n\
117 [-q, --quiet] Disable all messages except unrecoverable errors\n\
118 [-d, --debug[#]] Enable debug messages, at level #\n\
119 [-h, --help] Print copyright, version and usage of this program\n\
121 EfiLoaderImageName\n");
126 CreateIdentityMappingPageTables (
132 To create 4G PAE 2M pagetable
135 void * - buffer containing created pagetable
145 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*PageMapLevel4Entry
;
146 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*PageDirectoryPointerEntry
;
147 X64_PAGE_TABLE_ENTRY_2M
*PageDirectoryEntry2MB
;
149 PageTable
= (void *)malloc (EFI_PAGE_NUMBER
* EFI_SIZE_OF_PAGE
);
150 memset (PageTable
, 0, (EFI_PAGE_NUMBER
* EFI_SIZE_OF_PAGE
));
151 PageTablePtr
= PageTable
;
156 // Page Table structure 3 level 2MB.
158 // Page-Map-Level-4-Table : bits 47-39
159 // Page-Directory-Pointer-Table : bits 38-30
161 // Page Table 2MB : Page-Directory(2M) : bits 29-21
165 PageMapLevel4Entry
= (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*)PageTablePtr
;
167 for (PML4Index
= 0; PML4Index
< EFI_PML4_ENTRY_NUM
; PML4Index
++, PageMapLevel4Entry
++) {
169 // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry
171 PageTablePtr
+= EFI_SIZE_OF_PAGE
;
172 PageDirectoryPointerEntry
= (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*)PageTablePtr
;
175 // Make a Page-Map-Level-4-Table Entry
177 PageMapLevel4Entry
->Uint64
= (UINT64
)(UINT32
)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry
));
178 PageMapLevel4Entry
->Bits
.ReadWrite
= 1;
179 PageMapLevel4Entry
->Bits
.Present
= 1;
181 for (PDPTEIndex
= 0; PDPTEIndex
< EFI_PDPTE_ENTRY_NUM
; PDPTEIndex
++, PageDirectoryPointerEntry
++) {
183 // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry
185 PageTablePtr
+= EFI_SIZE_OF_PAGE
;
186 PageDirectoryEntry2MB
= (X64_PAGE_TABLE_ENTRY_2M
*)PageTablePtr
;
189 // Make a Page-Directory-Pointer-Table Entry
191 PageDirectoryPointerEntry
->Uint64
= (UINT64
)(UINT32
)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB
));
192 PageDirectoryPointerEntry
->Bits
.ReadWrite
= 1;
193 PageDirectoryPointerEntry
->Bits
.Present
= 1;
195 for (PDEIndex
= 0; PDEIndex
< EFI_PDE_ENTRY_NUM
; PDEIndex
++, PageDirectoryEntry2MB
++) {
197 // Make a Page-Directory Entry
199 PageDirectoryEntry2MB
->Uint64
= (UINT64
)PageAddress
;
200 PageDirectoryEntry2MB
->Bits
.ReadWrite
= 1;
201 PageDirectoryEntry2MB
->Bits
.Present
= 1;
202 PageDirectoryEntry2MB
->Bits
.MustBe1
= 1;
204 PageAddress
+= EFI_PAGE_SIZE_2M
;
215 char *NoPageFileName
,
221 Write the buffer containing page table to file at a specified offset.
222 Here the offset is defined as EFI_PAGE_BASE_OFFSET_IN_LDR.
225 BaseMemory - buffer containing page table
226 NoPageFileName - file to write page table
227 PageFileName - file save to after writing
238 unsigned long FileSize
;
243 PageFile
= fopen (PageFileName
, "w+b");
244 if (PageFile
== NULL
) {
245 Error (NoPageFileName
, 0, 0x4002, "Invalid parameter option", "Output File %s open failure", PageFileName
);
249 NoPageFile
= fopen (NoPageFileName
, "r+b");
250 if (NoPageFile
== NULL
) {
251 Error (NoPageFileName
, 0, 0x4002, "Invalid parameter option", "Input File %s open failure", NoPageFileName
);
257 // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR
259 fseek (NoPageFile
, 0, SEEK_END
);
260 FileSize
= ftell (NoPageFile
);
261 fseek (NoPageFile
, 0, SEEK_SET
);
262 if (FileSize
> gPageTableOffsetInFile
) {
263 Error (NoPageFileName
, 0, 0x4002, "Invalid parameter option", "Input file size (0x%lx) exceeds the Page Table Offset (0x%x)", FileSize
, (unsigned) gPageTableOffsetInFile
);
272 while (fread (&Data
, sizeof(UINT8
), 1, NoPageFile
)) {
273 fwrite (&Data
, sizeof(UINT8
), 1, PageFile
);
279 fseek (PageFile
, gPageTableOffsetInFile
, SEEK_SET
);
280 fwrite (BaseMemory
, (EFI_PAGE_NUMBER
* EFI_SIZE_OF_PAGE
), 1, PageFile
);
299 CHAR8
*OutputFile
= NULL
;
300 CHAR8
*InputFile
= NULL
;
304 SetUtilityName("GenPage");
314 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
319 if (stricmp (argv
[0], "--version") == 0) {
325 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--output") == 0)) {
326 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
327 Error (NULL
, 0, 1003, "Invalid option value", "Output file is missing for -o option");
330 OutputFile
= argv
[1];
336 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--baseaddr") == 0)) {
337 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
338 Error (NULL
, 0, 1003, "Invalid option value", "Base address is missing for -b option");
341 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &TempValue
);
342 if (EFI_ERROR (Status
)) {
343 Error (NULL
, 0, 1003, "Invalid option value", "Base address is not valid intergrator");
346 gPageTableBaseAddress
= (UINT32
) TempValue
;
352 if ((stricmp (argv
[0], "-f") == 0) || (stricmp (argv
[0], "--offset") == 0)) {
353 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
354 Error (NULL
, 0, 1003, "Invalid option value", "Offset is missing for -f option");
357 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &TempValue
);
358 if (EFI_ERROR (Status
)) {
359 Error (NULL
, 0, 1003, "Invalid option value", "Offset is not valid intergrator");
362 gPageTableOffsetInFile
= (UINT32
) TempValue
;
368 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
374 if ((stricmp (argv
[0], "-v") ==0) || (stricmp (argv
[0], "--verbose") == 0)) {
380 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
381 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
382 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level is not specified.");
385 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &TempValue
);
386 if (EFI_ERROR (Status
)) {
387 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level is not valid intergrator.");
391 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) TempValue
);
399 if (argv
[0][0] == '-') {
400 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
405 // Don't recognize the paramter.
412 if (InputFile
== NULL
) {
413 Error (NULL
, 0, 1003, "Invalid option value", "Input file is not specified");
418 // Create X64 page table
420 BaseMemory
= CreateIdentityMappingPageTables ();
423 // Add page table to binary file
425 result
= GenBinPage (BaseMemory
, InputFile
, OutputFile
);