+++ /dev/null
-/** @file\r
- Pre-Create a 4G page table (2M pages).\r
- It's used in DUET x64 build needed to enter LongMode.\r
-\r
- Create 4G page table (2M pages)\r
-\r
- Linear Address\r
- 63 48 47 39 38 30 29 21 20 0\r
- +--------+-------+---------------+-----------+-----------------------------+\r
- PML4 Directory-Ptr Directory Offset\r
-\r
- Paging-Structures :=\r
- PML4\r
- (\r
- Directory-Ptr Directory {512}\r
- ) {4}\r
-\r
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include "VirtualMemory.h"\r
-#include "EfiUtilityMsgs.h"\r
-#include "ParseInf.h"\r
-\r
-#define EFI_PAGE_BASE_OFFSET_IN_LDR 0x70000\r
-#define EFI_PAGE_BASE_ADDRESS (EFI_PAGE_BASE_OFFSET_IN_LDR + 0x20000)\r
-\r
-UINT32 gPageTableBaseAddress = EFI_PAGE_BASE_ADDRESS;\r
-UINT32 gPageTableOffsetInFile = EFI_PAGE_BASE_OFFSET_IN_LDR;\r
-\r
-#define EFI_MAX_ENTRY_NUM 512\r
-\r
-#define EFI_PML4_ENTRY_NUM 1\r
-#define EFI_PDPTE_ENTRY_NUM 4\r
-#define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM\r
-\r
-#define EFI_PML4_PAGE_NUM 1\r
-#define EFI_PDPTE_PAGE_NUM EFI_PML4_ENTRY_NUM\r
-#define EFI_PDE_PAGE_NUM (EFI_PML4_ENTRY_NUM * EFI_PDPTE_ENTRY_NUM)\r
-\r
-#define EFI_PAGE_NUMBER (EFI_PML4_PAGE_NUM + EFI_PDPTE_PAGE_NUM + EFI_PDE_PAGE_NUM)\r
-\r
-#define EFI_SIZE_OF_PAGE 0x1000\r
-#define EFI_PAGE_SIZE_2M 0x200000\r
-\r
-#define CONVERT_BIN_PAGE_ADDRESS(a) ((UINT8 *) a - PageTable + gPageTableBaseAddress)\r
-\r
-//\r
-// Utility Name\r
-//\r
-#define UTILITY_NAME "GenPage"\r
-\r
-//\r
-// Utility version information\r
-//\r
-#define UTILITY_MAJOR_VERSION 0\r
-#define UTILITY_MINOR_VERSION 2\r
-\r
-void\r
-Version (\r
- void\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Displays the standard utility information to SDTOUT\r
-\r
-Arguments:\r
-\r
- None\r
-\r
-Returns:\r
-\r
- None\r
-\r
---*/\r
-{\r
- printf ("%s Version %d.%d %s\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
-}\r
-\r
-VOID\r
-Usage (\r
- void\r
- )\r
-{\r
- printf ("Usage: GenPage.exe [options] EfiLoaderImageName \n\n\\r
-Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.\n\n\\r
- Utility to generate the EfiLoader image containing a page table.\n\n\\r
-optional arguments:\n\\r
- -h, --help Show this help message and exit\n\\r
- --version Show program's version number and exit\n\\r
- -d [DEBUG], --debug [DEBUG]\n\\r
- Output DEBUG statements, where DEBUG_LEVEL is 0 (min)\n\\r
- - 9 (max)\n\\r
- -v, --verbose Print informational statements\n\\r
- -q, --quiet Returns the exit code, error messages will be\n\\r
- displayed\n\\r
- -s, --silent Returns only the exit code; informational and error\n\\r
- messages are not displayed\n\\r
- -o OUTPUT_FILENAME, --output OUTPUT_FILENAME\n\\r
- Output file contain both the non-page table part and\n\\r
- the page table\n\\r
- -b BASE_ADDRESS, --baseaddr BASE_ADDRESS\n\\r
- The page table location\n\\r
- -f OFFSET, --offset OFFSET\n\\r
- The position that the page table will appear in the\n\\r
- output file\n\\r
- --sfo Reserved for future use\n");\r
-\r
-}\r
-\r
-void *\r
-CreateIdentityMappingPageTables (\r
- void\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- To create 4G PAE 2M pagetable\r
-\r
-Return:\r
- void * - buffer containing created pagetable\r
-\r
---*/\r
-{\r
- UINT64 PageAddress;\r
- UINT8 *PageTable;\r
- UINT8 *PageTablePtr;\r
- int PML4Index;\r
- int PDPTEIndex;\r
- int PDEIndex;\r
- X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry;\r
- X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry;\r
- X64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB;\r
-\r
- PageTable = (void *)malloc (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE);\r
- if (PageTable == NULL) {\r
- Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
- return NULL;\r
- }\r
- memset (PageTable, 0, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE));\r
- PageTablePtr = PageTable;\r
-\r
- PageAddress = 0;\r
-\r
- //\r
- // Page Table structure 3 level 2MB.\r
- //\r
- // Page-Map-Level-4-Table : bits 47-39\r
- // Page-Directory-Pointer-Table : bits 38-30\r
- //\r
- // Page Table 2MB : Page-Directory(2M) : bits 29-21\r
- //\r
- //\r
-\r
- PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;\r
-\r
- for (PML4Index = 0; PML4Index < EFI_PML4_ENTRY_NUM; PML4Index++, PageMapLevel4Entry++) {\r
- //\r
- // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry\r
- //\r
- PageTablePtr += EFI_SIZE_OF_PAGE;\r
- PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;\r
-\r
- //\r
- // Make a Page-Map-Level-4-Table Entry\r
- //\r
- PageMapLevel4Entry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry));\r
- PageMapLevel4Entry->Bits.ReadWrite = 1;\r
- PageMapLevel4Entry->Bits.Present = 1;\r
-\r
- for (PDPTEIndex = 0; PDPTEIndex < EFI_PDPTE_ENTRY_NUM; PDPTEIndex++, PageDirectoryPointerEntry++) {\r
- //\r
- // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry\r
- //\r
- PageTablePtr += EFI_SIZE_OF_PAGE;\r
- PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)PageTablePtr;\r
-\r
- //\r
- // Make a Page-Directory-Pointer-Table Entry\r
- //\r
- PageDirectoryPointerEntry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB));\r
- PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
- PageDirectoryPointerEntry->Bits.Present = 1;\r
-\r
- for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry2MB++) {\r
- //\r
- // Make a Page-Directory Entry\r
- //\r
- PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress;\r
- PageDirectoryEntry2MB->Bits.ReadWrite = 1;\r
- PageDirectoryEntry2MB->Bits.Present = 1;\r
- PageDirectoryEntry2MB->Bits.MustBe1 = 1;\r
-\r
- PageAddress += EFI_PAGE_SIZE_2M;\r
- }\r
- }\r
- }\r
-\r
- return PageTable;\r
-}\r
-\r
-INT32\r
-GenBinPage (\r
- void *BaseMemory,\r
- char *NoPageFileName,\r
- char *PageFileName\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Write the buffer containing page table to file at a specified offset.\r
- Here the offset is defined as EFI_PAGE_BASE_OFFSET_IN_LDR.\r
-\r
-Arguments:\r
- BaseMemory - buffer containing page table\r
- NoPageFileName - file to write page table\r
- PageFileName - file save to after writing\r
-\r
-return:\r
- 0 : successful\r
- -1 : failed\r
-\r
---*/\r
-{\r
- FILE *PageFile;\r
- FILE *NoPageFile;\r
- UINT8 Data;\r
- unsigned long FileSize;\r
-\r
- //\r
- // Open files\r
- //\r
- PageFile = fopen (LongFilePath (PageFileName), "w+b");\r
- if (PageFile == NULL) {\r
- Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Output File %s open failure", PageFileName);\r
- return -1;\r
- }\r
-\r
- NoPageFile = fopen (LongFilePath (NoPageFileName), "r+b");\r
- if (NoPageFile == NULL) {\r
- Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Input File %s open failure", NoPageFileName);\r
- fclose (PageFile);\r
- return -1;\r
- }\r
-\r
- //\r
- // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR\r
- //\r
- fseek (NoPageFile, 0, SEEK_END);\r
- FileSize = ftell (NoPageFile);\r
- fseek (NoPageFile, 0, SEEK_SET);\r
- if (FileSize > gPageTableOffsetInFile) {\r
- Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Input file size (0x%lx) exceeds the Page Table Offset (0x%x)", FileSize, (unsigned) gPageTableOffsetInFile);\r
- fclose (PageFile);\r
- fclose (NoPageFile);\r
- return -1;\r
- }\r
-\r
- //\r
- // Write data\r
- //\r
- while (fread (&Data, sizeof(UINT8), 1, NoPageFile)) {\r
- fwrite (&Data, sizeof(UINT8), 1, PageFile);\r
- }\r
-\r
- //\r
- // Write PageTable\r
- //\r
- fseek (PageFile, gPageTableOffsetInFile, SEEK_SET);\r
- fwrite (BaseMemory, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE), 1, PageFile);\r
-\r
- //\r
- // Close files\r
- //\r
- fclose (PageFile);\r
- fclose (NoPageFile);\r
-\r
- return 0;\r
-}\r
-\r
-int\r
-main (\r
- int argc,\r
- char **argv\r
- )\r
-{\r
- VOID *BaseMemory;\r
- INTN result;\r
- CHAR8 *OutputFile = NULL;\r
- CHAR8 *InputFile = NULL;\r
- EFI_STATUS Status;\r
- UINT64 TempValue;\r
-\r
- SetUtilityName("GenPage");\r
-\r
- if (argc == 1) {\r
- Usage();\r
- return STATUS_ERROR;\r
- }\r
-\r
- argc --;\r
- argv ++;\r
-\r
- if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
- Usage();\r
- return 0;\r
- }\r
-\r
- if (stricmp (argv[0], "--version") == 0) {\r
- Version();\r
- return 0;\r
- }\r
-\r
- while (argc > 0) {\r
- if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {\r
- if (argv[1] == NULL || argv[1][0] == '-') {\r
- Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option");\r
- return STATUS_ERROR;\r
- }\r
- OutputFile = argv[1];\r
- argc -= 2;\r
- argv += 2;\r
- continue;\r
- }\r
-\r
- if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--baseaddr") == 0)) {\r
- if (argv[1] == NULL || argv[1][0] == '-') {\r
- Error (NULL, 0, 1003, "Invalid option value", "Base address is missing for -b option");\r
- return STATUS_ERROR;\r
- }\r
- Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue);\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 1003, "Invalid option value", "Base address is not valid intergrator");\r
- return STATUS_ERROR;\r
- }\r
- gPageTableBaseAddress = (UINT32) TempValue;\r
- argc -= 2;\r
- argv += 2;\r
- continue;\r
- }\r
-\r
- if ((stricmp (argv[0], "-f") == 0) || (stricmp (argv[0], "--offset") == 0)) {\r
- if (argv[1] == NULL || argv[1][0] == '-') {\r
- Error (NULL, 0, 1003, "Invalid option value", "Offset is missing for -f option");\r
- return STATUS_ERROR;\r
- }\r
- Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue);\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 1003, "Invalid option value", "Offset is not valid intergrator");\r
- return STATUS_ERROR;\r
- }\r
- gPageTableOffsetInFile = (UINT32) TempValue;\r
- argc -= 2;\r
- argv += 2;\r
- continue;\r
- }\r
-\r
- if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
- argc --;\r
- argv ++;\r
- continue;\r
- }\r
-\r
- if ((stricmp (argv[0], "-v") ==0) || (stricmp (argv[0], "--verbose") == 0)) {\r
- argc --;\r
- argv ++;\r
- continue;\r
- }\r
-\r
- if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
- if (argv[1] == NULL || argv[1][0] == '-') {\r
- Error (NULL, 0, 1003, "Invalid option value", "Debug Level is not specified.");\r
- return STATUS_ERROR;\r
- }\r
- Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue);\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 1003, "Invalid option value", "Debug Level is not valid intergrator.");\r
- return STATUS_ERROR;\r
- }\r
- if (TempValue > 9) {\r
- Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) TempValue);\r
- return STATUS_ERROR;\r
- }\r
- argc -= 2;\r
- argv += 2;\r
- continue;\r
- }\r
-\r
- if (argv[0][0] == '-') {\r
- Error (NULL, 0, 1000, "Unknown option", argv[0]);\r
- return STATUS_ERROR;\r
- }\r
-\r
- //\r
- // Don't recognize the parameter.\r
- //\r
- InputFile = argv[0];\r
- argc--;\r
- argv++;\r
- }\r
-\r
- if (InputFile == NULL) {\r
- Error (NULL, 0, 1003, "Invalid option value", "Input file is not specified");\r
- return STATUS_ERROR;\r
- }\r
-\r
- //\r
- // Create X64 page table\r
- //\r
- BaseMemory = CreateIdentityMappingPageTables ();\r
- if (BaseMemory == NULL) {\r
- Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
- return STATUS_ERROR;\r
- }\r
-\r
- //\r
- // Add page table to binary file\r
- //\r
- result = GenBinPage (BaseMemory, InputFile, OutputFile);\r
- if (result < 0) {\r
- free (BaseMemory);\r
- return STATUS_ERROR;\r
- }\r
-\r
- free (BaseMemory);\r
- return 0;\r
-}\r
-\r