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"
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 "GenBootSector"
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 - 2009 Intel Corporation. All rights reserved.\n");
104 printf ("\nUsage: \n\
106 -o, --output Filename containing page table\n\
107 [-b, --baseaddr baseaddress of page table]\n\
108 [-f, --offset offset in the file that page table will reside]\n\
111 [-q, --quiet disable all messages except fatal errors]\n\
114 EfiLoaderImageName\n");
119 CreateIdentityMappingPageTables (
125 To create 4G PAE 2M pagetable
128 void * - buffer containing created pagetable
138 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*PageMapLevel4Entry
;
139 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*PageDirectoryPointerEntry
;
140 X64_PAGE_TABLE_ENTRY_2M
*PageDirectoryEntry2MB
;
142 PageTable
= (void *)malloc (EFI_PAGE_NUMBER
* EFI_SIZE_OF_PAGE
);
143 memset (PageTable
, 0, (EFI_PAGE_NUMBER
* EFI_SIZE_OF_PAGE
));
144 PageTablePtr
= PageTable
;
149 // Page Table structure 3 level 2MB.
151 // Page-Map-Level-4-Table : bits 47-39
152 // Page-Directory-Pointer-Table : bits 38-30
154 // Page Table 2MB : Page-Directory(2M) : bits 29-21
158 PageMapLevel4Entry
= (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*)PageTablePtr
;
160 for (PML4Index
= 0; PML4Index
< EFI_PML4_ENTRY_NUM
; PML4Index
++, PageMapLevel4Entry
++) {
162 // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry
164 PageTablePtr
+= EFI_SIZE_OF_PAGE
;
165 PageDirectoryPointerEntry
= (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*)PageTablePtr
;
168 // Make a Page-Map-Level-4-Table Entry
170 PageMapLevel4Entry
->Uint64
= (UINT64
)(UINT32
)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry
));
171 PageMapLevel4Entry
->Bits
.ReadWrite
= 1;
172 PageMapLevel4Entry
->Bits
.Present
= 1;
174 for (PDPTEIndex
= 0; PDPTEIndex
< EFI_PDPTE_ENTRY_NUM
; PDPTEIndex
++, PageDirectoryPointerEntry
++) {
176 // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry
178 PageTablePtr
+= EFI_SIZE_OF_PAGE
;
179 PageDirectoryEntry2MB
= (X64_PAGE_TABLE_ENTRY_2M
*)PageTablePtr
;
182 // Make a Page-Directory-Pointer-Table Entry
184 PageDirectoryPointerEntry
->Uint64
= (UINT64
)(UINT32
)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB
));
185 PageDirectoryPointerEntry
->Bits
.ReadWrite
= 1;
186 PageDirectoryPointerEntry
->Bits
.Present
= 1;
188 for (PDEIndex
= 0; PDEIndex
< EFI_PDE_ENTRY_NUM
; PDEIndex
++, PageDirectoryEntry2MB
++) {
190 // Make a Page-Directory Entry
192 PageDirectoryEntry2MB
->Uint64
= (UINT64
)PageAddress
;
193 PageDirectoryEntry2MB
->Bits
.ReadWrite
= 1;
194 PageDirectoryEntry2MB
->Bits
.Present
= 1;
195 PageDirectoryEntry2MB
->Bits
.MustBe1
= 1;
197 PageAddress
+= EFI_PAGE_SIZE_2M
;
208 char *NoPageFileName
,
214 Write the buffer containing page table to file at a specified offset.
215 Here the offset is defined as EFI_PAGE_BASE_OFFSET_IN_LDR.
218 BaseMemory - buffer containing page table
219 NoPageFileName - file to write page table
220 PageFileName - file save to after writing
231 unsigned long FileSize
;
236 PageFile
= fopen (PageFileName
, "w+b");
237 if (PageFile
== NULL
) {
238 Error (NoPageFileName
, 0, 0x4002, "Invalid parameter option", "Output File %s open failure", PageFileName
);
242 NoPageFile
= fopen (NoPageFileName
, "r+b");
243 if (NoPageFile
== NULL
) {
244 Error (NoPageFileName
, 0, 0x4002, "Invalid parameter option", "Input File %s open failure", NoPageFileName
);
250 // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR
252 fseek (NoPageFile
, 0, SEEK_END
);
253 FileSize
= ftell (NoPageFile
);
254 fseek (NoPageFile
, 0, SEEK_SET
);
255 if (FileSize
> gPageTableOffsetInFile
) {
256 Error (NoPageFileName
, 0, 0x4002, "Invalid parameter option", "Input file size (0x%lx) exceeds the Page Table Offset (0x%x)", FileSize
, (unsigned) gPageTableOffsetInFile
);
265 while (fread (&Data
, sizeof(UINT8
), 1, NoPageFile
)) {
266 fwrite (&Data
, sizeof(UINT8
), 1, PageFile
);
272 fseek (PageFile
, gPageTableOffsetInFile
, SEEK_SET
);
273 fwrite (BaseMemory
, (EFI_PAGE_NUMBER
* EFI_SIZE_OF_PAGE
), 1, PageFile
);
292 CHAR8
*OutputFile
= NULL
;
293 CHAR8
*InputFile
= NULL
;
297 SetUtilityName("GenPage");
307 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
312 if (stricmp (argv
[0], "--version") == 0) {
318 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--output") == 0)) {
319 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
320 Error (NULL
, 0, 1003, "Invalid option value", "Output file is missing for -o option");
323 OutputFile
= argv
[1];
329 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--baseaddr") == 0)) {
330 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
331 Error (NULL
, 0, 1003, "Invalid option value", "Base address is missing for -b option");
334 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &TempValue
);
335 if (EFI_ERROR (Status
)) {
336 Error (NULL
, 0, 1003, "Invalid option value", "Base address is not valid intergrator");
339 gPageTableBaseAddress
= (UINT32
) TempValue
;
345 if ((stricmp (argv
[0], "-f") == 0) || (stricmp (argv
[0], "--offset") == 0)) {
346 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
347 Error (NULL
, 0, 1003, "Invalid option value", "Offset is missing for -f option");
350 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &TempValue
);
351 if (EFI_ERROR (Status
)) {
352 Error (NULL
, 0, 1003, "Invalid option value", "Offset is not valid intergrator");
355 gPageTableOffsetInFile
= (UINT32
) TempValue
;
361 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
367 if ((stricmp (argv
[0], "-v") ==0) || (stricmp (argv
[0], "--verbose") == 0)) {
373 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
374 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
375 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level is not specified.");
378 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &TempValue
);
379 if (EFI_ERROR (Status
)) {
380 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level is not valid intergrator.");
384 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) TempValue
);
392 if (argv
[0][0] == '-') {
393 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
398 // Don't recognize the paramter.
405 if (InputFile
== NULL
) {
406 Error (NULL
, 0, 1003, "Invalid option value", "Input file is not specified");
411 // Create X64 page table
413 BaseMemory
= CreateIdentityMappingPageTables ();
416 // Add page table to binary file
418 result
= GenBinPage (BaseMemory
, InputFile
, OutputFile
);