]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Sample/Tools/Source/GenPage/genpage.c
1) Sync EdkCompatibilityPkg with EDK 1.04. The changes includes:
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / GenPage / genpage.c
1 /*++
2
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
8
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.
11
12 Module Name:
13 GenPage.c
14
15 Abstract:
16 Pre-Create a 4G page table (2M pages).
17 It's used in DUET x64 build needed to enter LongMode.
18
19 Create 4G page table (2M pages)
20
21 Linear Address
22 63 48 47 39 38 30 29 21 20 0
23 +--------+-------+---------------+-----------+-----------------------------+
24 PML4 Directory-Ptr Directory Offset
25
26 Paging-Structures :=
27 PML4
28 (
29 Directory-Ptr Directory {512}
30 ) {4}
31 --*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include "VirtualMemory.h"
36
37 void
38 memset (void *, char, long);
39
40 unsigned int
41 xtoi (char *);
42
43 #define EFI_PAGE_BASE_OFFSET_IN_LDR 0x70000
44 #define EFI_PAGE_BASE_ADDRESS (EFI_PAGE_BASE_OFFSET_IN_LDR + 0x20000)
45
46 unsigned int gPageTableBaseAddress = EFI_PAGE_BASE_ADDRESS;
47 unsigned int gPageTableOffsetInFile = EFI_PAGE_BASE_OFFSET_IN_LDR;
48
49 #define EFI_MAX_ENTRY_NUM 512
50
51 #define EFI_PML4_ENTRY_NUM 1
52 #define EFI_PDPTE_ENTRY_NUM 4
53 #define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM
54
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)
58
59 #define EFI_PAGE_NUMBER (EFI_PML4_PAGE_NUM + EFI_PDPTE_PAGE_NUM + EFI_PDE_PAGE_NUM)
60
61 #define EFI_SIZE_OF_PAGE 0x1000
62 #define EFI_PAGE_SIZE_2M 0x200000
63
64 #define CONVERT_BIN_PAGE_ADDRESS(a) ((UINT8 *) a - PageTable + gPageTableBaseAddress)
65
66
67 void *
68 CreateIdentityMappingPageTables (
69 void
70 )
71 /*++
72
73 Routine Description:
74 To create 4G PAE 2M pagetable
75
76 Return:
77 void * - buffer containing created pagetable
78
79 --*/
80 {
81 UINT64 PageAddress;
82 UINT8 *PageTable;
83 UINT8 *PageTablePtr;
84 int PML4Index;
85 int PDPTEIndex;
86 int PDEIndex;
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;
90
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;
94
95 PageAddress = 0;
96
97 //
98 // Page Table structure 3 level 2MB.
99 //
100 // Page-Map-Level-4-Table : bits 47-39
101 // Page-Directory-Pointer-Table : bits 38-30
102 //
103 // Page Table 2MB : Page-Directory(2M) : bits 29-21
104 //
105 //
106
107 PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;
108
109 for (PML4Index = 0; PML4Index < EFI_PML4_ENTRY_NUM; PML4Index++, PageMapLevel4Entry++) {
110 //
111 // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry
112 //
113 PageTablePtr += EFI_SIZE_OF_PAGE;
114 PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;
115
116 //
117 // Make a Page-Map-Level-4-Table Entry
118 //
119 PageMapLevel4Entry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry));
120 PageMapLevel4Entry->Bits.ReadWrite = 1;
121 PageMapLevel4Entry->Bits.Present = 1;
122
123 for (PDPTEIndex = 0; PDPTEIndex < EFI_PDPTE_ENTRY_NUM; PDPTEIndex++, PageDirectoryPointerEntry++) {
124 //
125 // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry
126 //
127 PageTablePtr += EFI_SIZE_OF_PAGE;
128 PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)PageTablePtr;
129
130 //
131 // Make a Page-Directory-Pointer-Table Entry
132 //
133 PageDirectoryPointerEntry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB));
134 PageDirectoryPointerEntry->Bits.ReadWrite = 1;
135 PageDirectoryPointerEntry->Bits.Present = 1;
136
137 for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry2MB++) {
138 //
139 // Make a Page-Directory Entry
140 //
141 PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress;
142 PageDirectoryEntry2MB->Bits.ReadWrite = 1;
143 PageDirectoryEntry2MB->Bits.Present = 1;
144 PageDirectoryEntry2MB->Bits.MustBe1 = 1;
145
146 PageAddress += EFI_PAGE_SIZE_2M;
147 }
148 }
149 }
150
151 return PageTable;
152 }
153
154 int
155 GenBinPage (
156 void *BaseMemory,
157 char *NoPageFileName,
158 char *PageFileName
159 )
160 /*++
161
162 Routine Description:
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.
165
166 Arguments:
167 BaseMemory - buffer containing page table
168 NoPageFileName - file to write page table
169 PageFileName - file save to after writing
170
171 return:
172 0 : successful
173 -1 : failed
174
175 --*/
176 {
177 FILE *PageFile;
178 FILE *NoPageFile;
179 UINT8 Data;
180 unsigned long FileSize;
181
182 //
183 // Open files
184 //
185 PageFile = fopen (PageFileName, "w+b");
186 if (PageFile == NULL) {
187 fprintf (stderr, "GenBinPage: Could not open file %s\n", PageFileName);
188 return -1;
189 }
190
191 NoPageFile = fopen (NoPageFileName, "r+b");
192 if (NoPageFile == NULL) {
193 fprintf (stderr, "GenBinPage: Could not open file %s\n", NoPageFileName);
194 fclose (PageFile);
195 return -1;
196 }
197
198 //
199 // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR
200 //
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);
206 fclose (PageFile);
207 fclose (NoPageFile);
208 return -1;
209 }
210
211 //
212 // Write data
213 //
214 while (fread (&Data, sizeof(UINT8), 1, NoPageFile)) {
215 fwrite (&Data, sizeof(UINT8), 1, PageFile);
216 }
217
218 //
219 // Write PageTable
220 //
221 fseek (PageFile, gPageTableOffsetInFile, SEEK_SET);
222 fwrite (BaseMemory, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE), 1, PageFile);
223
224 //
225 // Close files
226 //
227 fclose (PageFile);
228 fclose (NoPageFile);
229
230 return 0;
231 }
232
233 int
234 main (
235 int argc,
236 char **argv
237 )
238 {
239 void *BaseMemory;
240 int result;
241
242 //
243 // Check parameter
244 //
245 if ((argc != 3) && (argc != 5)) {
246 printf ("Usage: GenPage.exe NoPageFile PageFile [<PageTableBaseAddrss> <PageTableOffsetInFile>]\n");
247 return 1;
248 }
249
250 //
251 // Get PageTable parameter, if have
252 //
253 if (argc == 5) {
254 gPageTableBaseAddress = xtoi (argv[3]);
255 gPageTableOffsetInFile = xtoi (argv[4]);
256 }
257
258 //
259 // Create X64 page table
260 //
261 BaseMemory = CreateIdentityMappingPageTables ();
262
263 //
264 // Add page table to binary file
265 //
266 result = GenBinPage (BaseMemory, argv[1], argv[2]);
267 if (result < 0) {
268 return 1;
269 }
270
271 return 0;
272 }
273
274 unsigned int
275 xtoi (
276 char *str
277 )
278 /*++
279
280 Routine Description:
281
282 Convert hex string to uint
283
284 Arguments:
285
286 Str - The string
287
288 Returns:
289
290 --*/
291 {
292 unsigned int u;
293 char c;
294 unsigned int m;
295
296 if (str == NULL) {
297 return 0;
298 }
299
300 m = (unsigned int) -1 >> 4;
301 //
302 // skip preceeding white space
303 //
304 while (*str && *str == ' ') {
305 str += 1;
306 }
307 //
308 // skip preceeding zeros
309 //
310 while (*str && *str == '0') {
311 str += 1;
312 }
313 //
314 // skip preceeding white space
315 //
316 if (*str && (*str == 'x' || *str == 'X')) {
317 str += 1;
318 }
319 //
320 // convert hex digits
321 //
322 u = 0;
323 c = *(str++);
324 while (c) {
325 if (c >= 'a' && c <= 'f') {
326 c -= 'a' - 'A';
327 }
328
329 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
330 if (u > m) {
331 return (unsigned int) -1;
332 }
333
334 u = u << 4 | c - (c >= 'A' ? 'A' - 10 : '0');
335 } else {
336 break;
337 }
338
339 c = *(str++);
340 }
341
342 return u;
343 }
344