From 30fdf1140b8d1ce93f3821d986fa165552023440 Mon Sep 17 00:00:00 2001 From: lgao4 Date: Fri, 17 Jul 2009 09:10:31 +0000 Subject: Check In tool source code based on Build tool project revision r1655. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8964 6f19259b-4bc3-4df7-8a09-765794883524 --- BaseTools/Source/C/GenPage/GNUmakefile | 10 + BaseTools/Source/C/GenPage/GenPage.c | 424 +++++++++++++++++++++++++++++ BaseTools/Source/C/GenPage/Makefile | 10 + BaseTools/Source/C/GenPage/VirtualMemory.h | 127 +++++++++ 4 files changed, 571 insertions(+) create mode 100644 BaseTools/Source/C/GenPage/GNUmakefile create mode 100644 BaseTools/Source/C/GenPage/GenPage.c create mode 100644 BaseTools/Source/C/GenPage/Makefile create mode 100644 BaseTools/Source/C/GenPage/VirtualMemory.h (limited to 'BaseTools/Source/C/GenPage') diff --git a/BaseTools/Source/C/GenPage/GNUmakefile b/BaseTools/Source/C/GenPage/GNUmakefile new file mode 100644 index 0000000000..a828168cd0 --- /dev/null +++ b/BaseTools/Source/C/GenPage/GNUmakefile @@ -0,0 +1,10 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = GenPage + +LIBS = -lCommon + +OBJECTS = GenPage.o + +include $(MAKEROOT)/Makefiles/app.makefile diff --git a/BaseTools/Source/C/GenPage/GenPage.c b/BaseTools/Source/C/GenPage/GenPage.c new file mode 100644 index 0000000000..99fbc1e472 --- /dev/null +++ b/BaseTools/Source/C/GenPage/GenPage.c @@ -0,0 +1,424 @@ +/** @file + +Copyright 2006 - 2008, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + GenPage.c + +Abstract: + Pre-Create a 4G page table (2M pages). + It's used in DUET x64 build needed to enter LongMode. + + Create 4G page table (2M pages) + + Linear Address + 63 48 47 39 38 30 29 21 20 0 + +--------+-------+---------------+-----------+-----------------------------+ + PML4 Directory-Ptr Directory Offset + + Paging-Structures := + PML4 + ( + Directory-Ptr Directory {512} + ) {4} +**/ + +#include +#include +#include +#include "VirtualMemory.h" +#include "EfiUtilityMsgs.h" + +#define EFI_PAGE_BASE_OFFSET_IN_LDR 0x70000 +#define EFI_PAGE_BASE_ADDRESS (EFI_PAGE_BASE_OFFSET_IN_LDR + 0x20000) + +UINT32 gPageTableBaseAddress = EFI_PAGE_BASE_ADDRESS; +UINT32 gPageTableOffsetInFile = EFI_PAGE_BASE_OFFSET_IN_LDR; + +#define EFI_MAX_ENTRY_NUM 512 + +#define EFI_PML4_ENTRY_NUM 1 +#define EFI_PDPTE_ENTRY_NUM 4 +#define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM + +#define EFI_PML4_PAGE_NUM 1 +#define EFI_PDPTE_PAGE_NUM EFI_PML4_ENTRY_NUM +#define EFI_PDE_PAGE_NUM (EFI_PML4_ENTRY_NUM * EFI_PDPTE_ENTRY_NUM) + +#define EFI_PAGE_NUMBER (EFI_PML4_PAGE_NUM + EFI_PDPTE_PAGE_NUM + EFI_PDE_PAGE_NUM) + +#define EFI_SIZE_OF_PAGE 0x1000 +#define EFI_PAGE_SIZE_2M 0x200000 + +#define CONVERT_BIN_PAGE_ADDRESS(a) ((UINT8 *) a - PageTable + gPageTableBaseAddress) + +// +// Utility Name +// +#define UTILITY_NAME "GenBootSector" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +void +Version ( + void + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ("%s v%d.%d -Utility to generate the EfiLoader image containing page table.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); + printf ("Copyright (c) 2008 - 2009 Intel Corporation. All rights reserved.\n"); +} + +VOID +Usage ( + void + ) +{ + Version(); + printf ("\nUsage: \n\ + GenPage\n\ + -o, --output Filename containing page table\n\ + [-b, --baseaddr baseaddress of page table]\n\ + [-f, --offset offset in the file that page table will reside]\n\ + [-v, --verbose]\n\ + [--version]\n\ + [-q, --quiet disable all messages except fatal errors]\n\ + [-d, --debug[#]\n\ + [-h, --help]\n\ + EfiLoaderImageName\n"); + +} + +void * +CreateIdentityMappingPageTables ( + void + ) +/*++ + +Routine Description: + To create 4G PAE 2M pagetable + +Return: + void * - buffer containing created pagetable + +--*/ +{ + UINT64 PageAddress; + UINT8 *PageTable; + UINT8 *PageTablePtr; + int PML4Index; + int PDPTEIndex; + int PDEIndex; + X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry; + X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry; + X64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB; + + PageTable = (void *)malloc (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE); + memset (PageTable, 0, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE)); + PageTablePtr = PageTable; + + PageAddress = 0; + + // + // Page Table structure 3 level 2MB. + // + // Page-Map-Level-4-Table : bits 47-39 + // Page-Directory-Pointer-Table : bits 38-30 + // + // Page Table 2MB : Page-Directory(2M) : bits 29-21 + // + // + + PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr; + + for (PML4Index = 0; PML4Index < EFI_PML4_ENTRY_NUM; PML4Index++, PageMapLevel4Entry++) { + // + // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry + // + PageTablePtr += EFI_SIZE_OF_PAGE; + PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr; + + // + // Make a Page-Map-Level-4-Table Entry + // + PageMapLevel4Entry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry)); + PageMapLevel4Entry->Bits.ReadWrite = 1; + PageMapLevel4Entry->Bits.Present = 1; + + for (PDPTEIndex = 0; PDPTEIndex < EFI_PDPTE_ENTRY_NUM; PDPTEIndex++, PageDirectoryPointerEntry++) { + // + // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry + // + PageTablePtr += EFI_SIZE_OF_PAGE; + PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)PageTablePtr; + + // + // Make a Page-Directory-Pointer-Table Entry + // + PageDirectoryPointerEntry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB)); + PageDirectoryPointerEntry->Bits.ReadWrite = 1; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry2MB++) { + // + // Make a Page-Directory Entry + // + PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress; + PageDirectoryEntry2MB->Bits.ReadWrite = 1; + PageDirectoryEntry2MB->Bits.Present = 1; + PageDirectoryEntry2MB->Bits.MustBe1 = 1; + + PageAddress += EFI_PAGE_SIZE_2M; + } + } + } + + return PageTable; +} + +INT32 +GenBinPage ( + void *BaseMemory, + char *NoPageFileName, + char *PageFileName + ) +/*++ + +Routine Description: + Write the buffer containing page table to file at a specified offset. + Here the offset is defined as EFI_PAGE_BASE_OFFSET_IN_LDR. + +Arguments: + BaseMemory - buffer containing page table + NoPageFileName - file to write page table + PageFileName - file save to after writing + +return: + 0 : successful + -1 : failed + +--*/ +{ + FILE *PageFile; + FILE *NoPageFile; + UINT8 Data; + unsigned long FileSize; + + // + // Open files + // + PageFile = fopen (PageFileName, "w+b"); + if (PageFile == NULL) { + Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Output File %s open failure", PageFileName); + return -1; + } + + NoPageFile = fopen (NoPageFileName, "r+b"); + if (NoPageFile == NULL) { + Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Input File %s open failure", NoPageFileName); + fclose (PageFile); + return -1; + } + + // + // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR + // + fseek (NoPageFile, 0, SEEK_END); + FileSize = ftell (NoPageFile); + fseek (NoPageFile, 0, SEEK_SET); + if (FileSize > gPageTableOffsetInFile) { + Error (NoPageFileName, 0, 0x4002, "Invalid parameter option", "Input file size (0x%x) exceeds the Page Table Offset (0x%x)", FileSize, gPageTableOffsetInFile); + fclose (PageFile); + fclose (NoPageFile); + return -1; + } + + // + // Write data + // + while (fread (&Data, sizeof(UINT8), 1, NoPageFile)) { + fwrite (&Data, sizeof(UINT8), 1, PageFile); + } + + // + // Write PageTable + // + fseek (PageFile, gPageTableOffsetInFile, SEEK_SET); + fwrite (BaseMemory, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE), 1, PageFile); + + // + // Close files + // + fclose (PageFile); + fclose (NoPageFile); + + return 0; +} + +int +main ( + int argc, + char **argv + ) +{ + VOID *BaseMemory; + INTN result; + CHAR8 *OutputFile = NULL; + CHAR8 *InputFile = NULL; + EFI_STATUS Status; + UINT64 TempValue; + + SetUtilityName("GenPage"); + + if (argc == 1) { + Usage(); + return STATUS_ERROR; + } + + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Usage(); + return 0; + } + + if (stricmp (argv[0], "--version") == 0) { + Version(); + return 0; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option"); + return STATUS_ERROR; + } + OutputFile = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--baseaddr") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Base address is missing for -b option"); + return STATUS_ERROR; + } + Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "Base address is not valid intergrator"); + return STATUS_ERROR; + } + gPageTableBaseAddress = (UINT32) TempValue; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-f") == 0) || (stricmp (argv[0], "--offset") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Offset is missing for -f option"); + return STATUS_ERROR; + } + Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "Offset is not valid intergrator"); + return STATUS_ERROR; + } + gPageTableOffsetInFile = (UINT32) TempValue; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-v") ==0) || (stricmp (argv[0], "--verbose") == 0)) { + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level is not specified."); + return STATUS_ERROR; + } + Status = AsciiStringToUint64 (argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level is not valid intergrator."); + return STATUS_ERROR; + } + if (TempValue > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", TempValue); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if (argv[0][0] == '-') { + Error (NULL, 0, 1000, "Unknown option", argv[0]); + return STATUS_ERROR; + } + + // + // Don't recognize the paramter. + // + InputFile = argv[0]; + argc--; + argv++; + } + + if (InputFile == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Input file is not specified"); + return STATUS_ERROR; + } + + // + // Create X64 page table + // + BaseMemory = CreateIdentityMappingPageTables (); + + // + // Add page table to binary file + // + result = GenBinPage (BaseMemory, InputFile, OutputFile); + if (result < 0) { + return STATUS_ERROR; + } + + return 0; +} + diff --git a/BaseTools/Source/C/GenPage/Makefile b/BaseTools/Source/C/GenPage/Makefile new file mode 100644 index 0000000000..5faf037f44 --- /dev/null +++ b/BaseTools/Source/C/GenPage/Makefile @@ -0,0 +1,10 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenPage + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenPage.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/BaseTools/Source/C/GenPage/VirtualMemory.h b/BaseTools/Source/C/GenPage/VirtualMemory.h new file mode 100644 index 0000000000..b4baec86b2 --- /dev/null +++ b/BaseTools/Source/C/GenPage/VirtualMemory.h @@ -0,0 +1,127 @@ +/** @file + +Copyright 2006 - 2008, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + VirtualMemory.h + +Abstract: + + x64 Long Mode Virtual Memory Management Definitions + + References: + 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming +**/ + +#ifndef _VIRTUAL_MEMORY_H_ +#define _VIRTUAL_MEMORY_H_ + +#include "CommonLib.h" + +#pragma pack(1) + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:2; // Must Be Zero + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K; + +// +// Page-Directory Offset 4K +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:1; // Must Be Zero + UINT64 Reserved2:1; // Reserved + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} X64_PAGE_DIRECTORY_ENTRY_4K; + +// +// Page Table Entry 4K +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 PAT:1; // 0 = Ignore Page Attribute Table + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} X64_PAGE_TABLE_ENTRY_4K; + + +// +// Page Table Entry 2MB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} X64_PAGE_TABLE_ENTRY_2M; + +#pragma pack() + +#endif -- cgit v1.2.3