3 Copyright 2006 - 2007, 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}
35 #include "VirtualMemory.h"
38 memset (void *, char, long);
43 #define EFI_PAGE_BASE_OFFSET_IN_LDR 0x70000
44 #define EFI_PAGE_BASE_ADDRESS (EFI_PAGE_BASE_OFFSET_IN_LDR + 0x20000)
46 unsigned int gPageTableBaseAddress
= EFI_PAGE_BASE_ADDRESS
;
47 unsigned int gPageTableOffsetInFile
= EFI_PAGE_BASE_OFFSET_IN_LDR
;
49 #define EFI_MAX_ENTRY_NUM 512
51 #define EFI_PML4_ENTRY_NUM 1
52 #define EFI_PDPTE_ENTRY_NUM 4
53 #define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM
55 #define EFI_PML4_PAGE_NUM 1
56 #define EFI_PDPTE_PAGE_NUM EFI_PML4_ENTRY_NUM
57 #define EFI_PDE_PAGE_NUM (EFI_PML4_ENTRY_NUM * EFI_PDPTE_ENTRY_NUM)
59 #define EFI_PAGE_NUMBER (EFI_PML4_PAGE_NUM + EFI_PDPTE_PAGE_NUM + EFI_PDE_PAGE_NUM)
61 #define EFI_SIZE_OF_PAGE 0x1000
62 #define EFI_PAGE_SIZE_2M 0x200000
64 #define CONVERT_BIN_PAGE_ADDRESS(a) ((UINT8 *) a - PageTable + gPageTableBaseAddress)
68 CreateIdentityMappingPageTables (
74 To create 4G PAE 2M pagetable
77 void * - buffer containing created pagetable
87 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*PageMapLevel4Entry
;
88 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*PageDirectoryPointerEntry
;
89 X64_PAGE_TABLE_ENTRY_2M
*PageDirectoryEntry2MB
;
91 PageTable
= (void *)malloc (EFI_PAGE_NUMBER
* EFI_SIZE_OF_PAGE
);
92 memset (PageTable
, 0, (EFI_PAGE_NUMBER
* EFI_SIZE_OF_PAGE
));
93 PageTablePtr
= PageTable
;
98 // Page Table structure 3 level 2MB.
100 // Page-Map-Level-4-Table : bits 47-39
101 // Page-Directory-Pointer-Table : bits 38-30
103 // Page Table 2MB : Page-Directory(2M) : bits 29-21
107 PageMapLevel4Entry
= (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*)PageTablePtr
;
109 for (PML4Index
= 0; PML4Index
< EFI_PML4_ENTRY_NUM
; PML4Index
++, PageMapLevel4Entry
++) {
111 // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry
113 PageTablePtr
+= EFI_SIZE_OF_PAGE
;
114 PageDirectoryPointerEntry
= (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*)PageTablePtr
;
117 // Make a Page-Map-Level-4-Table Entry
119 PageMapLevel4Entry
->Uint64
= (UINT64
)(UINT32
)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry
));
120 PageMapLevel4Entry
->Bits
.ReadWrite
= 1;
121 PageMapLevel4Entry
->Bits
.Present
= 1;
123 for (PDPTEIndex
= 0; PDPTEIndex
< EFI_PDPTE_ENTRY_NUM
; PDPTEIndex
++, PageDirectoryPointerEntry
++) {
125 // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry
127 PageTablePtr
+= EFI_SIZE_OF_PAGE
;
128 PageDirectoryEntry2MB
= (X64_PAGE_TABLE_ENTRY_2M
*)PageTablePtr
;
131 // Make a Page-Directory-Pointer-Table Entry
133 PageDirectoryPointerEntry
->Uint64
= (UINT64
)(UINT32
)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB
));
134 PageDirectoryPointerEntry
->Bits
.ReadWrite
= 1;
135 PageDirectoryPointerEntry
->Bits
.Present
= 1;
137 for (PDEIndex
= 0; PDEIndex
< EFI_PDE_ENTRY_NUM
; PDEIndex
++, PageDirectoryEntry2MB
++) {
139 // Make a Page-Directory Entry
141 PageDirectoryEntry2MB
->Uint64
= (UINT64
)PageAddress
;
142 PageDirectoryEntry2MB
->Bits
.ReadWrite
= 1;
143 PageDirectoryEntry2MB
->Bits
.Present
= 1;
144 PageDirectoryEntry2MB
->Bits
.MustBe1
= 1;
146 PageAddress
+= EFI_PAGE_SIZE_2M
;
157 char *NoPageFileName
,
163 Write the buffer containing page table to file at a specified offset.
164 Here the offset is defined as EFI_PAGE_BASE_OFFSET_IN_LDR.
167 BaseMemory - buffer containing page table
168 NoPageFileName - file to write page table
169 PageFileName - file save to after writing
180 unsigned long FileSize
;
185 PageFile
= fopen (PageFileName
, "w+b");
186 if (PageFile
== NULL
) {
187 fprintf (stderr
, "GenBinPage: Could not open file %s\n", PageFileName
);
191 NoPageFile
= fopen (NoPageFileName
, "r+b");
192 if (NoPageFile
== NULL
) {
193 fprintf (stderr
, "GenBinPage: Could not open file %s\n", NoPageFileName
);
199 // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR
201 fseek (NoPageFile
, 0, SEEK_END
);
202 FileSize
= ftell (NoPageFile
);
203 fseek (NoPageFile
, 0, SEEK_SET
);
204 if (FileSize
> gPageTableOffsetInFile
) {
205 fprintf (stderr
, "GenBinPage: file size too large - 0x%x\n", FileSize
);
214 while (fread (&Data
, sizeof(UINT8
), 1, NoPageFile
)) {
215 fwrite (&Data
, sizeof(UINT8
), 1, PageFile
);
221 fseek (PageFile
, gPageTableOffsetInFile
, SEEK_SET
);
222 fwrite (BaseMemory
, (EFI_PAGE_NUMBER
* EFI_SIZE_OF_PAGE
), 1, PageFile
);
245 if ((argc
!= 3) && (argc
!= 5)) {
246 printf ("Usage: GenPage.exe NoPageFile PageFile [<PageTableBaseAddrss> <PageTableOffsetInFile>]\n");
251 // Get PageTable parameter, if have
254 gPageTableBaseAddress
= xtoi (argv
[3]);
255 gPageTableOffsetInFile
= xtoi (argv
[4]);
259 // Create X64 page table
261 BaseMemory
= CreateIdentityMappingPageTables ();
264 // Add page table to binary file
266 result
= GenBinPage (BaseMemory
, argv
[1], argv
[2]);
282 Convert hex string to uint
300 m
= (unsigned int) -1 >> 4;
302 // skip preceeding white space
304 while (*str
&& *str
== ' ') {
308 // skip preceeding zeros
310 while (*str
&& *str
== '0') {
314 // skip preceeding white space
316 if (*str
&& (*str
== 'x' || *str
== 'X')) {
320 // convert hex digits
325 if (c
>= 'a' && c
<= 'f') {
329 if ((c
>= '0' && c
<= '9') || (c
>= 'A' && c
<= 'F')) {
331 return (unsigned int) -1;
334 u
= u
<< 4 | c
- (c
>= 'A' ? 'A' - 10 : '0');