OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
GenPage.c
Go to the documentation of this file.
1
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <stdarg.h>
33#include "VirtualMemory.h"
34
35#define EFI_PAGE_BASE_OFFSET_IN_LDR 0x70000
36#define EFI_PAGE_BASE_ADDRESS (EFI_PAGE_BASE_OFFSET_IN_LDR + 0x20000)
37
40
41#define EFI_MAX_ENTRY_NUM 512
42
43#define EFI_PML4_ENTRY_NUM 1
44#define EFI_PDPTE_ENTRY_NUM 4
45#define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM
46
47#define EFI_PML4_PAGE_NUM 1
48#define EFI_PDPTE_PAGE_NUM EFI_PML4_ENTRY_NUM
49#define EFI_PDE_PAGE_NUM (EFI_PML4_ENTRY_NUM * EFI_PDPTE_ENTRY_NUM)
50
51#define EFI_PAGE_NUMBER (EFI_PML4_PAGE_NUM + EFI_PDPTE_PAGE_NUM + EFI_PDE_PAGE_NUM)
52
53#define EFI_SIZE_OF_PAGE 0x1000
54#define EFI_PAGE_SIZE_2M 0x200000
55
56#define CONVERT_BIN_PAGE_ADDRESS(a) ((uint8_t *) a - PageTable + gPageTableBaseAddress)
57
58//
59// Utility Name
60//
61#define UTILITY_NAME "GenPage"
62
63//
64// Utility version information
65//
66#define UTILITY_MAJOR_VERSION 0
67#define UTILITY_MINOR_VERSION 2
68
69void
71 char *FileName,
72 uint32_t LineNumber,
73 uint32_t ErrorCode,
74 char *OffendingText,
75 char *MsgFmt,
76 ...
77 )
78{
79 va_list List;
80 va_start (List, MsgFmt);
81 vprintf (MsgFmt, List);
82 va_end (List);
83 puts("");
84}
85
86void
88 void
89 )
90/*++
91
92Routine Description:
93
94 Displays the standard utility information to SDTOUT
95
96Arguments:
97
98 None
99
100Returns:
101
102 None
103
104--*/
105{
106 printf ("%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
107}
108
109void
111 void
112 )
113{
114 printf ("Usage: GenPage.exe [options] EfiLoaderImageName \n\n\
115Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.\n\n\
116 Utility to generate the EfiLoader image containing a page table.\n\n\
117optional arguments:\n\
118 -h, --help Show this help message and exit\n\
119 --version Show program's version number and exit\n\
120 -d [DEBUG], --debug [DEBUG]\n\
121 Output DEBUG statements, where DEBUG_LEVEL is 0 (min)\n\
122 - 9 (max)\n\
123 -v, --verbose Print informational statements\n\
124 -q, --quiet Returns the exit code, error messages will be\n\
125 displayed\n\
126 -s, --silent Returns only the exit code; informational and error\n\
127 messages are not displayed\n\
128 -o OUTPUT_FILENAME, --output OUTPUT_FILENAME\n\
129 Output file contain both the non-page table part and\n\
130 the page table\n\
131 -b BASE_ADDRESS, --baseaddr BASE_ADDRESS\n\
132 The page table location\n\
133 -f OFFSET, --offset OFFSET\n\
134 The position that the page table will appear in the\n\
135 output file\n\
136 --sfo Reserved for future use\n");
137
138}
139
140void *
142 void
143 )
144/*++
145
146Routine Description:
147 To create 4G PAE 2M pagetable
148
149Return:
150 void * - buffer containing created pagetable
151
152--*/
153{
154 uint64_t PageAddress;
155 uint8_t *PageTable;
156 uint8_t *PageTablePtr;
157 int PML4Index;
158 int PDPTEIndex;
159 int PDEIndex;
161 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry;
162 X64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB;
163
164 PageTable = (void *)malloc (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE);
165 if (PageTable == NULL) {
166 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
167 return NULL;
168 }
169 memset (PageTable, 0, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE));
170 PageTablePtr = PageTable;
171
172 PageAddress = 0;
173
174 //
175 // Page Table structure 3 level 2MB.
176 //
177 // Page-Map-Level-4-Table : bits 47-39
178 // Page-Directory-Pointer-Table : bits 38-30
179 //
180 // Page Table 2MB : Page-Directory(2M) : bits 29-21
181 //
182 //
183
184 PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;
185
186 for (PML4Index = 0; PML4Index < EFI_PML4_ENTRY_NUM; PML4Index++, PageMapLevel4Entry++) {
187 //
188 // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry
189 //
190 PageTablePtr += EFI_SIZE_OF_PAGE;
191 PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;
192
193 //
194 // Make a Page-Map-Level-4-Table Entry
195 //
196 PageMapLevel4Entry->Uint64 = (uint64_t)(uint32_t)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry));
197 PageMapLevel4Entry->Bits.ReadWrite = 1;
198 PageMapLevel4Entry->Bits.Present = 1;
199
200 for (PDPTEIndex = 0; PDPTEIndex < EFI_PDPTE_ENTRY_NUM; PDPTEIndex++, PageDirectoryPointerEntry++) {
201 //
202 // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry
203 //
204 PageTablePtr += EFI_SIZE_OF_PAGE;
205 PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)PageTablePtr;
206
207 //
208 // Make a Page-Directory-Pointer-Table Entry
209 //
210 PageDirectoryPointerEntry->Uint64 = (uint64_t)(uint32_t)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB));
211 PageDirectoryPointerEntry->Bits.ReadWrite = 1;
212 PageDirectoryPointerEntry->Bits.Present = 1;
213
214 for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry2MB++) {
215 //
216 // Make a Page-Directory Entry
217 //
218 PageDirectoryEntry2MB->Uint64 = (uint64_t)PageAddress;
219 PageDirectoryEntry2MB->Bits.ReadWrite = 1;
220 PageDirectoryEntry2MB->Bits.Present = 1;
221 PageDirectoryEntry2MB->Bits.MustBe1 = 1;
222
223 PageAddress += EFI_PAGE_SIZE_2M;
224 }
225 }
226 }
227
228 return PageTable;
229}
230
233 void *BaseMemory,
234 char *NoPageFileName,
235 char *PageFileName
236 )
237/*++
238
239Routine Description:
240 Write the buffer containing page table to file at a specified offset.
241 Here the offset is defined as EFI_PAGE_BASE_OFFSET_IN_LDR.
242
243Arguments:
244 BaseMemory - buffer containing page table
245 NoPageFileName - file to write page table
246 PageFileName - file save to after writing
247
248return:
249 0 : successful
250 -1 : failed
251
252--*/
253{
254 FILE *PageFile;
255 FILE *NoPageFile;
256 uint8_t Data;
257 unsigned long FileSize;
258
259 //
260 // Open files
261 //
262 PageFile = fopen (PageFileName, "w+b");
263 if (PageFile == NULL) {
264 Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Output File %s open failure", PageFileName);
265 return -1;
266 }
267
268 NoPageFile = fopen (NoPageFileName, "r+b");
269 if (NoPageFile == NULL) {
270 Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Input File %s open failure", NoPageFileName);
271 fclose (PageFile);
272 return -1;
273 }
274
275 //
276 // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR
277 //
278 fseek (NoPageFile, 0, SEEK_END);
279 FileSize = ftell (NoPageFile);
280 fseek (NoPageFile, 0, SEEK_SET);
281 if (FileSize > gPageTableOffsetInFile) {
282 Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Input file size (0x%lx) exceeds the Page Table Offset (0x%x)", FileSize, (unsigned) gPageTableOffsetInFile);
283 fclose (PageFile);
284 fclose (NoPageFile);
285 return -1;
286 }
287
288 //
289 // Write data
290 //
291 while (fread (&Data, sizeof(uint8_t), 1, NoPageFile)) {
292 fwrite (&Data, sizeof(uint8_t), 1, PageFile);
293 }
294
295 //
296 // Write PageTable
297 //
298 fseek (PageFile, gPageTableOffsetInFile, SEEK_SET);
299 fwrite (BaseMemory, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE), 1, PageFile);
300
301 //
302 // Close files
303 //
304 fclose (PageFile);
305 fclose (NoPageFile);
306
307 return 0;
308}
309
310int
312 int argc,
313 char **argv
314 )
315{
316 void *BaseMemory;
317 int32_t result;
318 char *OutputFile = NULL;
319 char *InputFile = NULL;
320 uint64_t TempValue;
321
322 if (argc == 1) {
323 Usage();
324 return EXIT_FAILURE;
325 }
326
327 argc --;
328 argv ++;
329
330 if ((strcmp (argv[0], "-h") == 0) || (strcmp (argv[0], "--help") == 0)) {
331 Usage();
332 return 0;
333 }
334
335 if (strcmp (argv[0], "--version") == 0) {
336 Version();
337 return 0;
338 }
339
340 while (argc > 0) {
341 if ((strcmp (argv[0], "-o") == 0) || (strcmp (argv[0], "--output") == 0)) {
342 if (argv[1] == NULL || argv[1][0] == '-') {
343 Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option");
344 return EXIT_FAILURE;
345 }
346 OutputFile = argv[1];
347 argc -= 2;
348 argv += 2;
349 continue;
350 }
351
352 if ((strcmp (argv[0], "-b") == 0) || (strcmp (argv[0], "--baseaddr") == 0)) {
353 if (argv[1] == NULL || argv[1][0] == '-') {
354 Error (NULL, 0, 1003, "Invalid option value", "Base address is missing for -b option");
355 return EXIT_FAILURE;
356 }
357 TempValue = strtoull (argv[1], NULL, 0);
358 gPageTableBaseAddress = (uint32_t) TempValue;
359 argc -= 2;
360 argv += 2;
361 continue;
362 }
363
364 if ((strcmp (argv[0], "-f") == 0) || (strcmp (argv[0], "--offset") == 0)) {
365 if (argv[1] == NULL || argv[1][0] == '-') {
366 Error (NULL, 0, 1003, "Invalid option value", "Offset is missing for -f option");
367 return EXIT_FAILURE;
368 }
369 TempValue = strtoull (argv[1], NULL, 0);
370 gPageTableOffsetInFile = (uint32_t) TempValue;
371 argc -= 2;
372 argv += 2;
373 continue;
374 }
375
376 if ((strcmp (argv[0], "-q") == 0) || (strcmp (argv[0], "--quiet") == 0)) {
377 argc --;
378 argv ++;
379 continue;
380 }
381
382 if ((strcmp (argv[0], "-v") ==0) || (strcmp (argv[0], "--verbose") == 0)) {
383 argc --;
384 argv ++;
385 continue;
386 }
387
388 if ((strcmp (argv[0], "-d") == 0) || (strcmp (argv[0], "--debug") == 0)) {
389 if (argv[1] == NULL || argv[1][0] == '-') {
390 Error (NULL, 0, 1003, "Invalid option value", "Debug Level is not specified.");
391 return EXIT_FAILURE;
392 }
393 TempValue = strtoull (argv[1], NULL, 0);
394 if (TempValue > 9) {
395 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) TempValue);
396 return EXIT_FAILURE;
397 }
398 argc -= 2;
399 argv += 2;
400 continue;
401 }
402
403 if (argv[0][0] == '-') {
404 Error (NULL, 0, 1000, "Unknown option", argv[0]);
405 return EXIT_FAILURE;
406 }
407
408 //
409 // Don't recognize the parameter.
410 //
411 InputFile = argv[0];
412 argc--;
413 argv++;
414 }
415
416 if (InputFile == NULL) {
417 Error (NULL, 0, 1003, "Invalid option value", "Input file is not specified");
418 return EXIT_FAILURE;
419 }
420
421 //
422 // Create X64 page table
423 //
424 BaseMemory = CreateIdentityMappingPageTables ();
425 if (BaseMemory == NULL) {
426 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
427 return EXIT_FAILURE;
428 }
429
430 //
431 // Add page table to binary file
432 //
433 result = GenBinPage (BaseMemory, InputFile, OutputFile);
434 if (result < 0) {
435 free (BaseMemory);
436 return EXIT_FAILURE;
437 }
438
439 free (BaseMemory);
440 return 0;
441}
442
#define EFI_PML4_ENTRY_NUM
Definition GenPage.c:43
void * CreateIdentityMappingPageTables(void)
Definition GenPage.c:141
#define UTILITY_MAJOR_VERSION
Definition GenPage.c:66
#define EFI_SIZE_OF_PAGE
Definition GenPage.c:53
#define UTILITY_NAME
Definition GenPage.c:61
int32_t GenBinPage(void *BaseMemory, char *NoPageFileName, char *PageFileName)
Definition GenPage.c:232
uint32_t gPageTableOffsetInFile
Definition GenPage.c:39
void Usage(void)
Definition GenPage.c:110
#define EFI_PAGE_BASE_ADDRESS
Definition GenPage.c:36
#define EFI_PAGE_NUMBER
Definition GenPage.c:51
#define EFI_PDPTE_ENTRY_NUM
Definition GenPage.c:44
void Error(char *FileName, uint32_t LineNumber, uint32_t ErrorCode, char *OffendingText, char *MsgFmt,...)
Definition GenPage.c:70
#define EFI_PAGE_SIZE_2M
Definition GenPage.c:54
#define CONVERT_BIN_PAGE_ADDRESS(a)
Definition GenPage.c:56
#define EFI_PDE_ENTRY_NUM
Definition GenPage.c:45
uint32_t gPageTableBaseAddress
Definition GenPage.c:38
void Version(void)
Definition GenPage.c:87
#define UTILITY_MINOR_VERSION
Definition GenPage.c:67
#define EFI_PAGE_BASE_OFFSET_IN_LDR
Definition GenPage.c:35
#define va_end
Definition Ubsan.h:99
#define va_list
Definition Ubsan.h:97
#define vprintf(f, v)
Definition Ubsan.h:206
#define va_start
Definition Ubsan.h:98
#define uint32_t
Definition Ubsan.h:59
#define uint64_t
Definition Ubsan.h:60
int main()
Definition acdtinfo.c:181
#define memset(ptr, c, len)
UINT8 uint8_t
UINT32 uint32_t
UINT64 uint64_t
INT32 int32_t
Definition lzss.h:34
#define malloc(Size)
Definition lzss.h:49
#define free(Ptr)
Definition lzss.h:50
struct X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K::@131 Bits
struct X64_PAGE_TABLE_ENTRY_2M::@134 Bits