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
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"
39 #define EFI_PAGE_BASE_OFFSET_IN_LDR 0x70000
40 #define EFI_PAGE_BASE_ADDRESS (EFI_PAGE_BASE_OFFSET_IN_LDR + 0x20000)
42 UINT32 gPageTableBaseAddress
= EFI_PAGE_BASE_ADDRESS
;
43 UINT32 gPageTableOffsetInFile
= EFI_PAGE_BASE_OFFSET_IN_LDR
;
45 #define EFI_MAX_ENTRY_NUM 512
47 #define EFI_PML4_ENTRY_NUM 1
48 #define EFI_PDPTE_ENTRY_NUM 4
49 #define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM
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)
55 #define EFI_PAGE_NUMBER (EFI_PML4_PAGE_NUM + EFI_PDPTE_PAGE_NUM + EFI_PDE_PAGE_NUM)
57 #define EFI_SIZE_OF_PAGE 0x1000
58 #define EFI_PAGE_SIZE_2M 0x200000
60 #define CONVERT_BIN_PAGE_ADDRESS(a) ((UINT8 *) a - PageTable + gPageTableBaseAddress)
65 #define UTILITY_NAME "GenBootSector"
68 // Utility version information
70 #define UTILITY_MAJOR_VERSION 0
71 #define UTILITY_MINOR_VERSION 1
81 Displays the standard utility information to SDTOUT
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");
103 printf ("\nUsage: \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\
110 [-q, --quiet disable all messages except fatal errors]\n\
113 EfiLoaderImageName\n");
118 CreateIdentityMappingPageTables (
124 To create 4G PAE 2M pagetable
127 void * - buffer containing created pagetable
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
;
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
;
148 // Page Table structure 3 level 2MB.
150 // Page-Map-Level-4-Table : bits 47-39
151 // Page-Directory-Pointer-Table : bits 38-30
153 // Page Table 2MB : Page-Directory(2M) : bits 29-21
157 PageMapLevel4Entry
= (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*)PageTablePtr
;
159 for (PML4Index
= 0; PML4Index
< EFI_PML4_ENTRY_NUM
; PML4Index
++, PageMapLevel4Entry
++) {
161 // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry
163 PageTablePtr
+= EFI_SIZE_OF_PAGE
;
164 PageDirectoryPointerEntry
= (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*)PageTablePtr
;
167 // Make a Page-Map-Level-4-Table Entry
169 PageMapLevel4Entry
->Uint64
= (UINT64
)(UINT32
)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry
));
170 PageMapLevel4Entry
->Bits
.ReadWrite
= 1;
171 PageMapLevel4Entry
->Bits
.Present
= 1;
173 for (PDPTEIndex
= 0; PDPTEIndex
< EFI_PDPTE_ENTRY_NUM
; PDPTEIndex
++, PageDirectoryPointerEntry
++) {
175 // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry
177 PageTablePtr
+= EFI_SIZE_OF_PAGE
;
178 PageDirectoryEntry2MB
= (X64_PAGE_TABLE_ENTRY_2M
*)PageTablePtr
;
181 // Make a Page-Directory-Pointer-Table Entry
183 PageDirectoryPointerEntry
->Uint64
= (UINT64
)(UINT32
)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB
));
184 PageDirectoryPointerEntry
->Bits
.ReadWrite
= 1;
185 PageDirectoryPointerEntry
->Bits
.Present
= 1;
187 for (PDEIndex
= 0; PDEIndex
< EFI_PDE_ENTRY_NUM
; PDEIndex
++, PageDirectoryEntry2MB
++) {
189 // Make a Page-Directory Entry
191 PageDirectoryEntry2MB
->Uint64
= (UINT64
)PageAddress
;
192 PageDirectoryEntry2MB
->Bits
.ReadWrite
= 1;
193 PageDirectoryEntry2MB
->Bits
.Present
= 1;
194 PageDirectoryEntry2MB
->Bits
.MustBe1
= 1;
196 PageAddress
+= EFI_PAGE_SIZE_2M
;
207 char *NoPageFileName
,
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.
217 BaseMemory - buffer containing page table
218 NoPageFileName - file to write page table
219 PageFileName - file save to after writing
230 unsigned long FileSize
;
235 PageFile
= fopen (PageFileName
, "w+b");
236 if (PageFile
== NULL
) {
237 Error (NoPageFileName
, 0, 0x4002, "Invalid parameter option", "Output File %s open failure", PageFileName
);
241 NoPageFile
= fopen (NoPageFileName
, "r+b");
242 if (NoPageFile
== NULL
) {
243 Error (NoPageFileName
, 0, 0x4002, "Invalid parameter option", "Input File %s open failure", NoPageFileName
);
249 // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR
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
);
264 while (fread (&Data
, sizeof(UINT8
), 1, NoPageFile
)) {
265 fwrite (&Data
, sizeof(UINT8
), 1, PageFile
);
271 fseek (PageFile
, gPageTableOffsetInFile
, SEEK_SET
);
272 fwrite (BaseMemory
, (EFI_PAGE_NUMBER
* EFI_SIZE_OF_PAGE
), 1, PageFile
);
291 CHAR8
*OutputFile
= NULL
;
292 CHAR8
*InputFile
= NULL
;
296 SetUtilityName("GenPage");
306 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
311 if (stricmp (argv
[0], "--version") == 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");
322 OutputFile
= argv
[1];
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");
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");
338 gPageTableBaseAddress
= (UINT32
) TempValue
;
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");
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");
354 gPageTableOffsetInFile
= (UINT32
) TempValue
;
360 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
366 if ((stricmp (argv
[0], "-v") ==0) || (stricmp (argv
[0], "--verbose") == 0)) {
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.");
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.");
383 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", TempValue
);
391 if (argv
[0][0] == '-') {
392 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
397 // Don't recognize the paramter.
404 if (InputFile
== NULL
) {
405 Error (NULL
, 0, 1003, "Invalid option value", "Input file is not specified");
410 // Create X64 page table
412 BaseMemory
= CreateIdentityMappingPageTables ();
415 // Add page table to binary file
417 result
= GenBinPage (BaseMemory
, InputFile
, OutputFile
);