X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=Nt32Pkg%2FSec%2FSecMain.c;h=56753fd421da583b5975f7fefac0ad80cd8004c5;hb=4cda7726e5fd30aaf3e05c80207ae1b264bfa123;hp=ab66dfc52cb94aa393b25b2c863eeac8c4ffff43;hpb=e1001af1d40370ff40cece775aaf10a2f8a0414e;p=mirror_edk2.git diff --git a/Nt32Pkg/Sec/SecMain.c b/Nt32Pkg/Sec/SecMain.c index ab66dfc52c..56753fd421 100644 --- a/Nt32Pkg/Sec/SecMain.c +++ b/Nt32Pkg/Sec/SecMain.c @@ -1,4 +1,4 @@ -/*++ +/**@file Copyright (c) 2006, Intel Corporation All rights reserved. This program and the accompanying materials @@ -17,20 +17,16 @@ Abstract: WinNt emulator of SEC phase. It's really a Win32 application, but this is Ok since all the other modules for NT32 are NOT Win32 applications. - This program processes Windows environment variables and figures out - what the memory layout will be, how may FD's will be loaded and also - what the boot mode is. + This program gets NT32 PCD setting and figures out what the memory layout + will be, how may FD's will be loaded and also what the boot mode is. The SEC registers a set of services with the SEC core. gPrivateDispatchTable is a list of PPI's produced by the SEC that are availble for usage in PEI. - This code produces 128 K of temporary memory for the PEI stack by opening a - Windows file and mapping it directly to memory addresses. - - The system.cmd script is used to set windows environment variables that drive - the configuration opitons of the SEC. + This code produces 128 K of temporary memory for the PEI stack by directly + allocate memory space with ReadWrite and Execute attribute. ---*/ +**/ #include "SecMain.h" @@ -62,6 +58,7 @@ EFI_PEI_PROGRESS_CODE_PPI mSecStatusCodePpi = { SecPeiReport NT_FWH_PPI mSecFwhInformationPpi = { SecWinNtFdAddress }; +TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPpi = {SecTemporaryRamSupport}; EFI_PEI_PPI_DESCRIPTOR gPrivateDispatchTable[] = { { @@ -89,6 +86,11 @@ EFI_PEI_PPI_DESCRIPTOR gPrivateDispatchTable[] = { &gEfiPeiStatusCodePpiGuid, &mSecStatusCodePpi }, + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiTemporaryRamSupportPpiGuid, + &mSecTemporaryRamSupportPpi + }, { EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, &gNtFwhPpiGuid, @@ -99,19 +101,18 @@ EFI_PEI_PPI_DESCRIPTOR gPrivateDispatchTable[] = { // // Default information about where the FD is located. -// This array gets filled in with information from EFI_FIRMWARE_VOLUMES -// EFI_FIRMWARE_VOLUMES is a Windows environment variable set by system.cmd. +// This array gets filled in with information from PcdWinNtFirmwareVolume // The number of array elements is allocated base on parsing -// EFI_FIRMWARE_VOLUMES and the memory is never freed. +// PcdWinNtFirmwareVolume and the memory is never freed. // UINTN gFdInfoCount = 0; NT_FD_INFO *gFdInfo; // // Array that supports seperate memory rantes. -// The memory ranges are set in system.cmd via the EFI_MEMORY_SIZE variable. +// The memory ranges are set by PcdWinNtMemorySizeForSecMain. // The number of array elements is allocated base on parsing -// EFI_MEMORY_SIZE and the memory is never freed. +// PcdWinNtMemorySizeForSecMain value and the memory is never freed. // UINTN gSystemMemoryCount = 0; NT_SYSTEM_MEMORY *gSystemMemory; @@ -121,7 +122,12 @@ UINTN mPdbNameModHandleArraySize = 0; PDB_NAME_TO_MOD_HANDLE *mPdbNameModHandleArray = NULL; - +VOID +EFIAPI +SecSwitchStack ( + UINT32 TemporaryMemoryBase, + UINT32 PermenentMemoryBase + ); INTN EFIAPI @@ -152,16 +158,16 @@ Returns: UINTN Index; UINTN Index1; UINTN Index2; - UINTN PeiIndex; CHAR16 *FileName; CHAR16 *FileNamePtr; BOOLEAN Done; VOID *PeiCoreFile; CHAR16 *MemorySizeStr; CHAR16 *FirmwareVolumesStr; + UINTN *StackPointer; - MemorySizeStr = (CHAR16 *)L"64!64"; - FirmwareVolumesStr = (CHAR16 *)L"..\\Fv\\Fv_Recovery.fd"; + MemorySizeStr = (CHAR16 *) FixedPcdGetPtr (PcdWinNtMemorySizeForSecMain); + FirmwareVolumesStr = (CHAR16 *) FixedPcdGetPtr (PcdWinNtFirmwareVolume); printf ("\nEDK SEC Main NT Emulation Environment from www.TianoCore.org\n"); @@ -178,7 +184,7 @@ Returns: gSystemMemoryCount = CountSeperatorsInString (MemorySizeStr, '!') + 1; gSystemMemory = calloc (gSystemMemoryCount, sizeof (NT_SYSTEM_MEMORY)); if (gSystemMemory == NULL) { - printf ("ERROR : Can not allocate memory for %s. Exiting.\n", MemorySizeStr); + wprintf (L"ERROR : Can not allocate memory for %s. Exiting.\n", MemorySizeStr); exit (1); } // @@ -187,7 +193,7 @@ Returns: gFdInfoCount = CountSeperatorsInString (FirmwareVolumesStr, '!') + 1; gFdInfo = calloc (gFdInfoCount, sizeof (NT_FD_INFO)); if (gFdInfo == NULL) { - printf ("ERROR : Can not allocate memory for %s. Exiting.\n", FirmwareVolumesStr); + wprintf (L"ERROR : Can not allocate memory for %s. Exiting.\n", FirmwareVolumesStr); exit (1); } // @@ -196,25 +202,24 @@ Returns: printf (" BootMode 0x%02x\n", FixedPcdGet32 (PcdWinNtBootMode)); // - // Open up a 128K file to emulate temp memory for PEI. + // Allocate 128K memory to emulate temp memory for PEI. // on a real platform this would be SRAM, or using the cache as RAM. // Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping // - InitialStackMemory = 0; - InitialStackMemorySize = 0x20000; - Status = WinNtOpenFile ( - L"SecStack", - (UINT32) InitialStackMemorySize, - OPEN_ALWAYS, - &InitialStackMemory, - &InitialStackMemorySize - ); - if (EFI_ERROR (Status)) { - printf ("ERROR : Can not open SecStack Exiting\n"); + InitialStackMemorySize = STACK_SIZE; + InitialStackMemory = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAlloc (NULL, (SIZE_T) (InitialStackMemorySize), MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if (InitialStackMemory == 0) { + printf ("ERROR : Can not allocate enough space for SecStack\n"); exit (1); } - printf (" SEC passing in %d bytes of temp RAM to PEI\n", InitialStackMemorySize); + for (StackPointer = (UINTN*) (UINTN) InitialStackMemory; + StackPointer < (UINTN*) ((UINTN)InitialStackMemory + (SIZE_T) InitialStackMemorySize); + StackPointer ++) { + *StackPointer = 0x5AA55AA5; + } + + wprintf (L" SEC passing in %d bytes of temp RAM to PEI\n", InitialStackMemorySize); // // Open All the firmware volumes and remember the info in the gFdInfo global @@ -227,7 +232,7 @@ Returns: StrCpy (FileNamePtr, (CHAR16*)FirmwareVolumesStr); - for (Done = FALSE, Index = 0, PeiIndex = 0, PeiCoreFile = NULL; !Done; Index++) { + for (Done = FALSE, Index = 0, PeiCoreFile = NULL; !Done; Index++) { FileName = FileNamePtr; for (Index1 = 0; (FileNamePtr[Index1] != '!') && (FileNamePtr[Index1] != 0); Index1++) ; @@ -249,7 +254,7 @@ Returns: &gFdInfo[Index].Size ); if (EFI_ERROR (Status)) { - printf ("ERROR : Can not open Firmware Device File %S (%r). Exiting.\n", FileName, Status); + printf ("ERROR : Can not open Firmware Device File %S (0x%X). Exiting.\n", FileName, Status); exit (1); } @@ -269,7 +274,6 @@ Returns: // Status = SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) gFdInfo[Index].Address, &PeiCoreFile); if (!EFI_ERROR (Status)) { - PeiIndex = Index; printf (" contains SEC Core"); } } @@ -286,7 +290,6 @@ Returns: // Save the size of the memory and make a Unicode filename SystemMemory00, ... // gSystemMemory[Index].Size = _wtoi (MemorySizeStr) * 0x100000; - _snwprintf (gSystemMemory[Index].FileName, NT_SYSTEM_MEMORY_FILENAME_SIZE, L"SystemMemory%02d", Index); // // Find the next region @@ -471,7 +474,7 @@ Returns: // // Processes ASSERT () // - printf ("ASSERT %s(%d): %s\n", Filename, LineNumber, Description); + printf ("ASSERT %s(%d): %s\n", Filename, (int)LineNumber, Description); } else if (ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) { // @@ -484,6 +487,63 @@ Returns: return EFI_SUCCESS; } +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's + Reserved on other architectures. + +**/ +VOID +EFIAPI +PeiSwitchStacks ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *Context3, OPTIONAL + IN VOID *NewStack + ) +{ + BASE_LIBRARY_JUMP_BUFFER JumpBuffer; + + ASSERT (EntryPoint != NULL); + ASSERT (NewStack != NULL); + + // + // Stack should be aligned with CPU_STACK_ALIGNMENT + // + ASSERT (((UINTN)NewStack & (CPU_STACK_ALIGNMENT - 1)) == 0); + + JumpBuffer.Eip = (UINTN)EntryPoint; + JumpBuffer.Esp = (UINTN)NewStack - sizeof (VOID*); + JumpBuffer.Esp -= sizeof (Context1) + sizeof (Context2) + sizeof(Context3); + ((VOID**)JumpBuffer.Esp)[1] = Context1; + ((VOID**)JumpBuffer.Esp)[2] = Context2; + ((VOID**)JumpBuffer.Esp)[3] = Context3; + + LongJump (&JumpBuffer, (UINTN)-1); + + + // + // InternalSwitchStack () will never return + // + ASSERT (FALSE); +} VOID SecLoadFromCore ( @@ -509,24 +569,34 @@ Returns: --*/ { EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS TopOfMemory; VOID *TopOfStack; UINT64 PeiCoreSize; EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint; EFI_PHYSICAL_ADDRESS PeiImageAddress; - EFI_PEI_STARTUP_DESCRIPTOR *PeiStartup; + EFI_SEC_PEI_HAND_OFF *SecCoreData; + UINTN PeiStackSize; // // Compute Top Of Memory for Stack and PEI Core Allocations // - TopOfMemory = LargestRegion + LargestRegionSize; + PeiStackSize = (UINTN)RShiftU64((UINT64)STACK_SIZE,1); // - // Allocate 128KB for the Stack + // |-----------| <---- TemporaryRamBase + TemporaryRamSize + // | Heap | + // | | + // |-----------| <---- StackBase / PeiTemporaryMemoryBase + // | | + // | Stack | + // |-----------| <---- TemporaryRamBase + // + TopOfStack = (VOID *)(LargestRegion + PeiStackSize); + // - TopOfStack = (VOID *)((UINTN)TopOfMemory - sizeof (EFI_PEI_STARTUP_DESCRIPTOR) - CPU_STACK_ALIGNMENT); + // Reservet space for storing PeiCore's parament in stack. + // + TopOfStack = (VOID *)((UINTN)TopOfStack - sizeof (EFI_SEC_PEI_HAND_OFF) - CPU_STACK_ALIGNMENT); TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); - TopOfMemory = TopOfMemory - STACK_SIZE; // // Patch value in dispatch table values @@ -536,10 +606,16 @@ Returns: // // Bind this information into the SEC hand-off state // - PeiStartup = (EFI_PEI_STARTUP_DESCRIPTOR *) (UINTN) TopOfStack; - PeiStartup->DispatchTable = (EFI_PEI_PPI_DESCRIPTOR *) &gPrivateDispatchTable; - PeiStartup->SizeOfCacheAsRam = STACK_SIZE; - PeiStartup->BootFirmwareVolume = BootFirmwareVolumeBase; + SecCoreData = (EFI_SEC_PEI_HAND_OFF*)(UINTN) TopOfStack; + SecCoreData->DataSize = sizeof(EFI_SEC_PEI_HAND_OFF); + SecCoreData->BootFirmwareVolumeBase = (VOID*)BootFirmwareVolumeBase; + SecCoreData->BootFirmwareVolumeSize = FixedPcdGet32(PcdWinNtFirmwareFdSize); + SecCoreData->TemporaryRamBase = (VOID*)(UINTN)LargestRegion; + SecCoreData->TemporaryRamSize = STACK_SIZE; + SecCoreData->StackBase = SecCoreData->TemporaryRamBase; + SecCoreData->StackSize = PeiStackSize; + SecCoreData->PeiTemporaryRamBase = (VOID*) ((UINTN) SecCoreData->TemporaryRamBase + PeiStackSize); + SecCoreData->PeiTemporaryRamSize = STACK_SIZE - PeiStackSize; // // Load the PEI Core from a Firmware Volume @@ -553,12 +629,14 @@ Returns: if (EFI_ERROR (Status)) { return ; } + // // Transfer control to the PEI Core // - SwitchStack ( + PeiSwitchStacks ( (SWITCH_STACK_ENTRY_POINT) (UINTN) PeiCoreEntryPoint, - PeiStartup, + SecCoreData, + (VOID *) (UINTN) ((EFI_PEI_PPI_DESCRIPTOR *) &gPrivateDispatchTable), NULL, TopOfStack ); @@ -581,9 +659,9 @@ Routine Description: This service is called from Index == 0 until it returns EFI_UNSUPPORTED. It allows discontiguous memory regions to be supported by the emulator. It uses gSystemMemory[] and gSystemMemoryCount that were created by - parsing the Windows environment variable EFI_MEMORY_SIZE. - The size comes from the varaible and the address comes from the call to - WinNtOpenFile. + parsing PcdWinNtMemorySizeForSecMain value. + The size comes from the Pcd value and the address comes from the memory space + with ReadWrite and Execute attributes allocated by VirtualAlloc() API. Arguments: Index - Which memory region to use @@ -596,24 +674,22 @@ Returns: --*/ { - EFI_STATUS Status; - if (Index >= gSystemMemoryCount) { return EFI_UNSUPPORTED; } + + // + // Allocate enough memory space for emulator + // + gSystemMemory[Index].Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAlloc (NULL, (SIZE_T) (gSystemMemory[Index].Size), MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if (gSystemMemory[Index].Memory == 0) { + return EFI_OUT_OF_RESOURCES; + } + + *MemoryBase = gSystemMemory[Index].Memory; + *MemorySize = gSystemMemory[Index].Size; - *MemoryBase = 0; - Status = WinNtOpenFile ( - gSystemMemory[Index].FileName, - (UINT32) gSystemMemory[Index].Size, - OPEN_ALWAYS, - MemoryBase, - MemorySize - ); - - gSystemMemory[Index].Memory = *MemoryBase; - - return Status; + return EFI_SUCCESS; } VOID * @@ -679,9 +755,10 @@ Returns: return Status; } // - // Allocate space in NT (not emulator) memory. Extra space is for alignment + // Allocate space in NT (not emulator) memory with ReadWrite and Execute attribue. + // Extra space is for alignment // - ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) malloc ((UINTN) (ImageContext.ImageSize + (ImageContext.SectionAlignment * 2))); + ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAlloc (NULL, (SIZE_T) (ImageContext.ImageSize + (ImageContext.SectionAlignment * 2)), MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (ImageContext.ImageAddress == 0) { return EFI_OUT_OF_RESOURCES; } @@ -836,7 +913,7 @@ Returns: UINTN CountSeperatorsInString ( - IN const CHAR16 *String, + IN CONST CHAR16 *String, IN CHAR16 Seperator ) /*++ @@ -1151,3 +1228,44 @@ _ModuleEntryPoint ( { } +EFI_STATUS +EFIAPI +SecTemporaryRamSupport ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ) +{ + // + // Migrate the whole temporary memory to permenent memory. + // + CopyMem ( + (VOID*)(UINTN)PermanentMemoryBase, + (VOID*)(UINTN)TemporaryMemoryBase, + CopySize + ); + + // + // SecSwitchStack function must be invoked after the memory migration + // immediatly, also we need fixup the stack change caused by new call into + // permenent memory. + // + SecSwitchStack ( + (UINT32) TemporaryMemoryBase, + (UINT32) PermanentMemoryBase + ); + + // + // We need *not* fix the return address because currently, + // The PeiCore is excuted in flash. + // + + // + // Simulate to invalid CAR, terminate CAR + // + //ZeroMem ((VOID*)(UINTN)TemporaryMemoryBase, CopySize); + + return EFI_SUCCESS; +} +