Add Key variable in PlatformFfsClass in PlatformClass.py file.
[people/mcb30/basetools.git] / Source / C / GenPage / genpage.c
1 /*++ \r
2 \r
3 Copyright 2006 - 2007, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13   GenPage.c\r
14   \r
15 Abstract:\r
16   Pre-Create a 4G page table (2M pages).\r
17   It's used in DUET x64 build needed to enter LongMode.\r
18  \r
19   Create 4G page table (2M pages)\r
20  \r
21                               Linear Address\r
22     63    48 47   39 38           30 29       21 20                          0\r
23    +--------+-------+---------------+-----------+-----------------------------+\r
24                PML4   Directory-Ptr   Directory                 Offset\r
25 \r
26    Paging-Structures :=\r
27                         PML4\r
28                         (\r
29                           Directory-Ptr Directory {512}\r
30                         ) {4}\r
31 --*/\r
32 \r
33 #include <stdio.h>\r
34 #include <stdlib.h>\r
35 #include "VirtualMemory.h"\r
36 #include "EfiUtilityMsgs.h"\r
37 \r
38 void\r
39 memset (void *, char, long);\r
40 \r
41 unsigned int\r
42 xtoi (char  *);\r
43 \r
44 #define EFI_PAGE_BASE_OFFSET_IN_LDR 0x70000\r
45 #define EFI_PAGE_BASE_ADDRESS       (EFI_PAGE_BASE_OFFSET_IN_LDR + 0x20000)\r
46 \r
47 unsigned int gPageTableBaseAddress  = EFI_PAGE_BASE_ADDRESS;\r
48 unsigned int gPageTableOffsetInFile = EFI_PAGE_BASE_OFFSET_IN_LDR;\r
49 \r
50 #define EFI_MAX_ENTRY_NUM     512\r
51 \r
52 #define EFI_PML4_ENTRY_NUM    1\r
53 #define EFI_PDPTE_ENTRY_NUM   4\r
54 #define EFI_PDE_ENTRY_NUM     EFI_MAX_ENTRY_NUM\r
55 \r
56 #define EFI_PML4_PAGE_NUM     1\r
57 #define EFI_PDPTE_PAGE_NUM    EFI_PML4_ENTRY_NUM\r
58 #define EFI_PDE_PAGE_NUM      (EFI_PML4_ENTRY_NUM * EFI_PDPTE_ENTRY_NUM)\r
59 \r
60 #define EFI_PAGE_NUMBER       (EFI_PML4_PAGE_NUM + EFI_PDPTE_PAGE_NUM + EFI_PDE_PAGE_NUM)\r
61 \r
62 #define EFI_SIZE_OF_PAGE      0x1000\r
63 #define EFI_PAGE_SIZE_2M      0x200000\r
64 \r
65 #define CONVERT_BIN_PAGE_ADDRESS(a)  ((UINT8 *) a - PageTable + gPageTableBaseAddress)\r
66 \r
67 //\r
68 // Utility Name\r
69 //\r
70 #define UTILITY_NAME  "GenBootSector"\r
71 \r
72 //\r
73 // Utility version information\r
74 //\r
75 #define UTILITY_MAJOR_VERSION 0\r
76 #define UTILITY_MINOR_VERSION 1\r
77 \r
78 void\r
79 Version (\r
80   void\r
81   )\r
82 /*++\r
83 \r
84 Routine Description:\r
85 \r
86   Displays the standard utility information to SDTOUT\r
87 \r
88 Arguments:\r
89 \r
90   None\r
91 \r
92 Returns:\r
93 \r
94   None\r
95 \r
96 --*/\r
97 {\r
98   printf ("%s v%d.%d -Utility to generate the EfiLoader image containing page table.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
99   printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");\r
100 }\r
101 \r
102 VOID\r
103 Usage (\r
104   void\r
105   )\r
106 {\r
107   Version();\r
108   printf ("\nUsage: \n\\r
109    GenPage\n\\r
110      -o, --output Filename containing page table\n\\r
111      [-b, --baseaddr baseaddress of page table]\n\\r
112      [-f, --offset offset in the file that page table will reside]\n\\r
113      [-v, --verbose]\n\\r
114      [--version]\n\\r
115      [-q, --quiet disable all messages except fatal errors]\n\\r
116      [-d, --debug[#]\n\\r
117      [-h, --help]\n\\r
118      EfiLoaderImageName\n");\r
119 \r
120 }\r
121 \r
122 void *\r
123 CreateIdentityMappingPageTables (\r
124   void\r
125   )\r
126 /*++\r
127 \r
128 Routine Description:\r
129   To create 4G PAE 2M pagetable\r
130 \r
131 Return:\r
132   void * - buffer containing created pagetable\r
133 \r
134 --*/\r
135 {\r
136   UINT64                                        PageAddress;\r
137   UINT8                                         *PageTable;\r
138   UINT8                                         *PageTablePtr;\r
139   int                                           PML4Index;\r
140   int                                           PDPTEIndex;\r
141   int                                           PDEIndex;\r
142   X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K     *PageMapLevel4Entry;\r
143   X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K     *PageDirectoryPointerEntry;\r
144   X64_PAGE_TABLE_ENTRY_2M                       *PageDirectoryEntry2MB;\r
145 \r
146   PageTable = (void *)malloc (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE);\r
147   memset (PageTable, 0, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE));\r
148   PageTablePtr = PageTable;\r
149 \r
150   PageAddress = 0;\r
151 \r
152   //\r
153   //  Page Table structure 3 level 2MB.\r
154   //\r
155   //                   Page-Map-Level-4-Table        : bits 47-39\r
156   //                   Page-Directory-Pointer-Table  : bits 38-30\r
157   //\r
158   //  Page Table 2MB : Page-Directory(2M)            : bits 29-21\r
159   //\r
160   //\r
161 \r
162   PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;\r
163 \r
164   for (PML4Index = 0; PML4Index < EFI_PML4_ENTRY_NUM; PML4Index++, PageMapLevel4Entry++) {\r
165     //\r
166     // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry\r
167     //  \r
168     PageTablePtr += EFI_SIZE_OF_PAGE;\r
169     PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;\r
170 \r
171     //\r
172     // Make a Page-Map-Level-4-Table Entry\r
173     //\r
174     PageMapLevel4Entry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry));\r
175     PageMapLevel4Entry->Bits.ReadWrite = 1;\r
176     PageMapLevel4Entry->Bits.Present = 1;\r
177 \r
178     for (PDPTEIndex = 0; PDPTEIndex < EFI_PDPTE_ENTRY_NUM; PDPTEIndex++, PageDirectoryPointerEntry++) {\r
179       //\r
180       // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry\r
181       //       \r
182       PageTablePtr += EFI_SIZE_OF_PAGE;\r
183       PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)PageTablePtr;\r
184 \r
185       //\r
186       // Make a Page-Directory-Pointer-Table Entry\r
187       //\r
188       PageDirectoryPointerEntry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB));\r
189       PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
190       PageDirectoryPointerEntry->Bits.Present = 1;\r
191 \r
192       for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry2MB++) {\r
193         //\r
194         // Make a Page-Directory Entry\r
195         //\r
196         PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress;\r
197         PageDirectoryEntry2MB->Bits.ReadWrite = 1;\r
198         PageDirectoryEntry2MB->Bits.Present = 1;\r
199         PageDirectoryEntry2MB->Bits.MustBe1 = 1;\r
200 \r
201         PageAddress += EFI_PAGE_SIZE_2M;\r
202       }\r
203     }\r
204   }\r
205 \r
206   return PageTable;\r
207 }\r
208 \r
209 int\r
210 GenBinPage (\r
211   void *BaseMemory,\r
212   char *NoPageFileName,\r
213   char *PageFileName\r
214   )\r
215 /*++\r
216 \r
217 Routine Description:\r
218   Write the buffer containing page table to file at a specified offset.\r
219   Here the offset is defined as EFI_PAGE_BASE_OFFSET_IN_LDR.\r
220 \r
221 Arguments:\r
222   BaseMemory     - buffer containing page table\r
223   NoPageFileName - file to write page table\r
224   PageFileName   - file save to after writing\r
225 \r
226 return:\r
227   0  : successful\r
228   -1 : failed\r
229 \r
230 --*/\r
231 {\r
232   FILE  *PageFile;\r
233   FILE  *NoPageFile;\r
234   UINT8 Data;\r
235   unsigned long FileSize;\r
236 \r
237   //\r
238   // Open files\r
239   //\r
240   PageFile = fopen (PageFileName, "w+b");\r
241   if (PageFile == NULL) {\r
242     fprintf (stderr, "GenBinPage: Could not open file %s\n", PageFileName);\r
243     return -1;\r
244   }\r
245 \r
246   NoPageFile = fopen (NoPageFileName, "r+b");\r
247   if (NoPageFile == NULL) {\r
248     fprintf (stderr, "GenBinPage: Could not open file %s\n", NoPageFileName);\r
249     fclose (PageFile);\r
250     return -1;\r
251   }\r
252 \r
253   //\r
254   // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR\r
255   //\r
256   fseek (NoPageFile, 0, SEEK_END);\r
257   FileSize = ftell (NoPageFile);\r
258   fseek (NoPageFile, 0, SEEK_SET);\r
259   if (FileSize > gPageTableOffsetInFile) {\r
260     fprintf (stderr, "GenBinPage: file size too large - 0x%x\n", FileSize);\r
261     fclose (PageFile);\r
262     fclose (NoPageFile);\r
263     return -1;\r
264   }\r
265 \r
266   //\r
267   // Write data\r
268   //\r
269   while (fread (&Data, sizeof(UINT8), 1, NoPageFile)) {\r
270     fwrite (&Data, sizeof(UINT8), 1, PageFile);\r
271   }\r
272 \r
273   //\r
274   // Write PageTable\r
275   //\r
276   fseek (PageFile, gPageTableOffsetInFile, SEEK_SET);\r
277   fwrite (BaseMemory, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE), 1, PageFile);\r
278 \r
279   //\r
280   // Close files\r
281   //\r
282   fclose (PageFile);\r
283   fclose (NoPageFile);\r
284 \r
285   return 0;\r
286 }\r
287 \r
288 int\r
289 main (\r
290   int argc,\r
291   char **argv\r
292   )\r
293 {\r
294   void *BaseMemory;\r
295   int  result;\r
296   char* OutputFile = NULL;\r
297   char* InputFile = NULL;\r
298 \r
299   if (argc == 1) {\r
300     Usage();\r
301     return -1;\r
302   }\r
303   \r
304   argc --;\r
305   argv ++;\r
306 \r
307   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
308     Usage();\r
309     return 0;    \r
310   }\r
311 \r
312   if (stricmp (argv[0], "--version") == 0) {\r
313     Version();\r
314     return 0;    \r
315   }\r
316 \r
317   while (argc > 0) {\r
318     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {\r
319       OutputFile = argv[1];\r
320       if (OutputFile == NULL) {\r
321         Error (NULL, 0, 0, "NO output file specified.", NULL);\r
322         return -1;\r
323       }\r
324       argc -= 2;\r
325       argv += 2;\r
326       continue; \r
327     }\r
328     \r
329     if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--baseaddr") == 0)) {\r
330       \r
331       if (argv[1] == NULL) {\r
332         Error (NULL, 0, 0, "NO base address specified.", NULL);\r
333         return STATUS_ERROR;\r
334       }\r
335       gPageTableBaseAddress  = xtoi (argv[1]);\r
336       argc -= 2;\r
337       argv += 2;\r
338       continue; \r
339     }\r
340     \r
341     if ((stricmp (argv[0], "-f") == 0) || (stricmp (argv[0], "--offset") == 0)) {\r
342       if (argv[1] == NULL) {\r
343         Error (NULL, 0, 0, "NO offset specified.", NULL);\r
344         return STATUS_ERROR;\r
345       }\r
346       gPageTableOffsetInFile  = xtoi (argv[1]);\r
347       argc -= 2;\r
348       argv += 2;\r
349       continue; \r
350     }\r
351 /*\r
352     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
353       QuietFlag = TRUE;\r
354       argc --;\r
355       argv ++;\r
356       continue; \r
357     }\r
358     \r
359     if ((strlen(argv[0]) >= 2 && argv[0][0] == '-' && (argv[0][1] == 'v' || argv[0][1] == 'V')) || (stricmp (argv[0], "--verbose") == 0)) {\r
360       VerboseLevel = 1;\r
361       if (strlen(argv[0]) > 2) {\r
362         Status = CountVerboseLevel (&argv[0][2], strlen(argv[0]) - 2, &VerboseLevel);\r
363         if (EFI_ERROR (Status)) {\r
364           Error (NULL, 0, 0, NULL, "%s is invaild paramter!", argv[0]);\r
365           return STATUS_ERROR;        \r
366         }\r
367       }\r
368       \r
369       argc --;\r
370       argv ++;\r
371       continue; \r
372     }\r
373     \r
374     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
375       Status = AsciiStringToUint64 (argv[1], FALSE, &DebugLevel);\r
376       if (EFI_ERROR (Status)) {\r
377         Error (NULL, 0, 0, "Input debug level is not one valid integrator.", NULL);\r
378         return STATUS_ERROR;        \r
379       }\r
380       argc -= 2;\r
381       argv += 2;\r
382       continue; \r
383     }*/\r
384     \r
385     //\r
386     // Don't recognize the paramter.\r
387     //\r
388     InputFile = argv[0];\r
389     argc--;\r
390     argv++;\r
391   }\r
392   \r
393   if (InputFile == NULL) {\r
394     Error (NULL, 0, 0, "NO Input file specified.", NULL);\r
395     return STATUS_ERROR;\r
396   }\r
397   \r
398   //\r
399   // Create X64 page table\r
400   //\r
401   BaseMemory = CreateIdentityMappingPageTables ();\r
402 \r
403   //\r
404   // Add page table to binary file\r
405   //\r
406   result = GenBinPage (BaseMemory, InputFile, OutputFile);\r
407   if (result < 0) {\r
408     return 1;\r
409   }\r
410 \r
411   return 0;\r
412 }\r
413 \r
414 unsigned int\r
415 xtoi (\r
416   char  *str\r
417   )\r
418 /*++\r
419 \r
420 Routine Description:\r
421 \r
422   Convert hex string to uint\r
423 \r
424 Arguments:\r
425 \r
426   Str  -  The string\r
427   \r
428 Returns:\r
429 \r
430 --*/\r
431 {\r
432   unsigned int u;\r
433   char         c;\r
434   unsigned int m;\r
435   \r
436   if (str == NULL) {\r
437     return 0;\r
438   }\r
439   \r
440   m = (unsigned int) -1 >> 4;\r
441   //\r
442   // skip preceeding white space\r
443   //\r
444   while (*str && *str == ' ') {\r
445     str += 1;\r
446   }\r
447   //\r
448   // skip preceeding zeros\r
449   //\r
450   while (*str && *str == '0') {\r
451     str += 1;\r
452   }\r
453   //\r
454   // skip preceeding white space\r
455   //\r
456   if (*str && (*str == 'x' || *str == 'X')) {\r
457     str += 1;\r
458   }\r
459   //\r
460   // convert hex digits\r
461   //\r
462   u = 0;\r
463   c = *(str++);\r
464   while (c) {\r
465     if (c >= 'a' && c <= 'f') {\r
466       c -= 'a' - 'A';\r
467     }\r
468 \r
469     if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {\r
470       if (u > m) {\r
471         return (unsigned int) -1;\r
472       }\r
473 \r
474       u = u << 4 | c - (c >= 'A' ? 'A' - 10 : '0');\r
475     } else {\r
476       break;\r
477     }\r
478 \r
479     c = *(str++);\r
480   }\r
481 \r
482   return u;\r
483 }\r
484 \r