1b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/** @file
2b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyThis is the code for Boot Script Executer module.
3b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
4b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyThis driver is dispatched by Dxe core and the driver will reload itself to ACPI NVS memory
5b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneyin the entry point. The functionality is to interpret and restore the S3 boot script
6b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
7b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyCopyright (c) 2013-2015 Intel Corporation.
8b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
9b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyThis program and the accompanying materials
10b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneyare licensed and made available under the terms and conditions of the BSD License
11b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneywhich accompanies this distribution.  The full text of the license may be found at
12b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneyhttp://opensource.org/licenses/bsd-license.php
13b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
14b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
17b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney**/
18b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
19b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#include "ScriptExecute.h"
20b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
21b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#pragma pack(1)
22b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneytypedef union {
23b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  struct {
24b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    UINT32  LimitLow    : 16;
25b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    UINT32  BaseLow     : 16;
26b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    UINT32  BaseMid     : 8;
27b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    UINT32  Type        : 4;
28b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    UINT32  System      : 1;
29b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    UINT32  Dpl         : 2;
30b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    UINT32  Present     : 1;
31b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    UINT32  LimitHigh   : 4;
32b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    UINT32  Software    : 1;
33b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    UINT32  Reserved    : 1;
34b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    UINT32  DefaultSize : 1;
35b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    UINT32  Granularity : 1;
36b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    UINT32  BaseHigh    : 8;
37b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  } Bits;
38b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT64  Uint64;
39b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney} IA32_GDT;
40b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
41b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#pragma pack()
42b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
43b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_GUID              mBootScriptExecutorImageGuid = {
44b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  0x9a8d3433, 0x9fe8, 0x42b6, {0x87, 0xb, 0x1e, 0x31, 0xc8, 0x4e, 0xbe, 0x3b}
45b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney};
46b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
47b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney//
48b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney// Global Descriptor Table (GDT)
49b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney//
50b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyGLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = {
51b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* selector { Global Segment Descriptor                              } */
52b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x00 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},
53b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x08 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},
54b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x10 */  {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  0, 1,  1,  0}},
55b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x18 */  {{0xFFFF, 0,  0,  0x3,  1,  0,  1,  0xF,  0,  0, 1,  1,  0}},
56b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x20 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},
57b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x28 */  {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  0, 0,  1,  0}},
58b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x30 */  {{0xFFFF, 0,  0,  0x3,  1,  0,  1,  0xF,  0,  0, 0,  1,  0}},
59b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x38 */  {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  1, 0,  1,  0}},
60b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/* 0x40 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},
61b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney};
62b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
63b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney//
64b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney// IA32 Gdt register
65b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney//
66b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyGLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR mGdt = {
67b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  sizeof (mGdtEntries) - 1,
68b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  (UINTN) mGdtEntries
69b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  };
70b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
71b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/**
72b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Entry function of Boot script exector. This function will be executed in
73b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  S3 boot path.
74b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  This function should not return, because it is invoked by switch stack.
75b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
76b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  @param  AcpiS3Context    a pointer to a structure of ACPI_S3_CONTEXT
77b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  @param  PeiS3ResumeState a pointer to a structure of PEI_S3_RESUME_STATE
78b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
79b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  @retval EFI_INVALID_PARAMETER - OS waking vector not found
80b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  @retval EFI_UNSUPPORTED - something wrong when we resume to OS
81b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney**/
82b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
83b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI
84b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyS3BootScriptExecutorEntryFunction (
85b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN ACPI_S3_CONTEXT       *AcpiS3Context,
86b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN PEI_S3_RESUME_STATE   *PeiS3ResumeState
87b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
88b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
89b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS                                    Status;
90b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
91b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
92b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Disable interrupt of Debug timer, since new IDT table cannot handle it.
93b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
94b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  SaveAndSetDebugTimerInterrupt (FALSE);
95b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
96b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
97b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Restore IDT for debug
98b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
99b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  SetIdtEntry (AcpiS3Context);
100b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
101b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
102b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Initialize Debug Agent to support source level debug in S3 path.
103b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
104b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  InitializeDebugAgent (DEBUG_AGENT_INIT_S3, NULL, NULL);
105b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
106b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
107b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Because not install BootScriptExecute PPI(used just in this module), So just pass NULL
108b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // for that parameter.
109b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
110b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = S3BootScriptExecute ();
111b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
112b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  AsmWbinvd ();
113b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
114b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
115b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // We need turn back to S3Resume - install boot script done ppi and report status code on S3resume.
116b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
117b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (PeiS3ResumeState != 0) {
118b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
119b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // Need report status back to S3ResumePeim.
120b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // If boot script execution is failed, S3ResumePeim wil report the error status code.
121b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
122b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    PeiS3ResumeState->ReturnStatus = (UINT64)(UINTN)Status;
123b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
124b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // IA32 S3 Resume
125b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
126b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    DEBUG ((EFI_D_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));
127b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)PlatformTransferControl16;
128b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
129b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    SwitchStack (
130b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiS3ResumeState->ReturnEntryPoint,
131b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      (VOID *)(UINTN)AcpiS3Context,
132b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      (VOID *)(UINTN)PeiS3ResumeState,
133b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      (VOID *)(UINTN)PeiS3ResumeState->ReturnStackPointer
134b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      );
135b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
136b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
137b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // Never run to here
138b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
139b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    CpuDeadLoop();
140b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_UNSUPPORTED;
141b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
142b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
143b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
144b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Never run to here
145b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
146b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  CpuDeadLoop();
147b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return EFI_UNSUPPORTED;
148b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
149b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/**
150b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Entrypoint of Boot script exector driver, this function will be executed in
151b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  normal boot phase and invoked by DXE dispatch.
152b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
153b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
154b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  @param[in] SystemTable    A pointer to the EFI System Table.
155b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
156b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  @retval EFI_SUCCESS       The entry point is executed successfully.
157b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  @retval other             Some error occurs when executing this entry point.
158b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney**/
159b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
160b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI
161b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyBootScriptExecutorEntryPoint (
162b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_HANDLE           ImageHandle,
163b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_SYSTEM_TABLE     *SystemTable
164b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
165b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
166b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT8                                         *Buffer;
167b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN                                         BufferSize;
168b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN                                         Pages;
169b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_PHYSICAL_ADDRESS                          FfsBuffer;
170b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  PE_COFF_LOADER_IMAGE_CONTEXT                  ImageContext;
171b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  BOOT_SCRIPT_EXECUTOR_VARIABLE                 *EfiBootScriptExecutorVariable;
172b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_PHYSICAL_ADDRESS                          BootScriptExecutorBuffer;
173b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS                                    Status;
174b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VOID                                          *DevicePath;
175b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_HANDLE                                    NewImageHandle;
176b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
177b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
178b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry
179b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // point is loaded by DXE code which is the first time loaded. or else, it is already
180b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // be reloaded be itself.This is a work-around
181b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
182b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);
183b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (EFI_ERROR (Status)) {
184b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
185b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
186b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // This is the first-time loaded by DXE core. reload itself to NVS mem
187b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
188b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
189b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // A workarouond: Here we install a dummy handle
190b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
191b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      NewImageHandle = NULL;
192b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = gBS->InstallProtocolInterface (
193b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  &NewImageHandle,
194b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  &gEfiCallerIdGuid,
195b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  EFI_NATIVE_INTERFACE,
196b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  NULL
197b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                  );
198b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
199b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = GetSectionFromAnyFv  (
200b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 &gEfiCallerIdGuid,
201b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 EFI_SECTION_PE32,
202b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 0,
203b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 (VOID **) &Buffer,
204b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 &BufferSize
205b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 );
206b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ImageContext.Handle    = Buffer;
207b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
208b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
209b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // Get information about the image being loaded
210b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
211b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = PeCoffLoaderGetImageInfo (&ImageContext);
212b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (EFI_ERROR (Status)) {
213b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        return Status;
214b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
215b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Pages = EFI_SIZE_TO_PAGES(BufferSize + ImageContext.SectionAlignment);
216b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      FfsBuffer = 0xFFFFFFFF;
217b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = gBS->AllocatePages (
218b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    AllocateMaxAddress,
219b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    EfiACPIMemoryNVS,
220b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    Pages,
221b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    &FfsBuffer
222b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    );
223b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (EFI_ERROR (Status)) {
224b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        return EFI_OUT_OF_RESOURCES;
225b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
226b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
227b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
228b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // Align buffer on section boundry
229b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
230b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
231b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
232b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
233b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // Load the image to our new buffer
234b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
235b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = PeCoffLoaderLoadImage (&ImageContext);
236b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (EFI_ERROR (Status)) {
237b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        gBS->FreePages (FfsBuffer, Pages);
238b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        return Status;
239b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
240b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
241b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
242b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // Relocate the image in our new buffer
243b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
244b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = PeCoffLoaderRelocateImage (&ImageContext);
245b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
246b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (EFI_ERROR (Status)) {
247b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        PeCoffLoaderUnloadImage (&ImageContext);
248b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        gBS->FreePages (FfsBuffer, Pages);
249b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        return Status;
250b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
251b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
252b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // Flush the instruction cache so the image data is written before we execute it
253b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
254b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
255b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);
256b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (EFI_ERROR (Status)) {
257b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        gBS->FreePages (FfsBuffer, Pages);
258b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        return Status;
259b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
260b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
261b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // Additional step for BootScript integrity
262b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // Save BootScriptExecutor image
263b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
264b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = SaveLockBox (
265b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 &mBootScriptExecutorImageGuid,
266b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 (VOID *)(UINTN)ImageContext.ImageAddress,
267b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 (UINTN)ImageContext.ImageSize
268b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 );
269b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ASSERT_EFI_ERROR (Status);
270b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
271b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = SetLockBoxAttributes (&mBootScriptExecutorImageGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
272b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ASSERT_EFI_ERROR (Status);
273b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
274b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    } else {
275b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
276b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // the entry point is invoked after reloading. following code only run in  ACPI NVS
277b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
278b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      BufferSize = sizeof (BOOT_SCRIPT_EXECUTOR_VARIABLE);
279b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
280b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      BootScriptExecutorBuffer = 0xFFFFFFFF;
281b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Pages = EFI_SIZE_TO_PAGES(BufferSize);
282b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = gBS->AllocatePages (
283b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      AllocateMaxAddress,
284b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      EfiACPIMemoryNVS,
285b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      Pages,
286b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      &BootScriptExecutorBuffer
287b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      );
288b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      if (EFI_ERROR (Status)) {
289b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney        return EFI_OUT_OF_RESOURCES;
290b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      }
291b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
292b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *)(UINTN)BootScriptExecutorBuffer;
293b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = (UINTN) S3BootScriptExecutorEntryFunction ;
294b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
295b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = SaveLockBox (
296b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 &gEfiBootScriptExecutorVariableGuid,
297b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 &BootScriptExecutorBuffer,
298b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 sizeof(BootScriptExecutorBuffer)
299b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 );
300b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ASSERT_EFI_ERROR (Status);
301b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
302b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
303b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // Additional step for BootScript integrity
304b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      // Save BootScriptExecutor context
305b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      //
306b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = SaveLockBox (
307b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 &gEfiBootScriptExecutorContextGuid,
308b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 EfiBootScriptExecutorVariable,
309b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 sizeof(*EfiBootScriptExecutorVariable)
310b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                 );
311b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ASSERT_EFI_ERROR (Status);
312b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
313b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = SetLockBoxAttributes (&gEfiBootScriptExecutorContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
314b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ASSERT_EFI_ERROR (Status);
315b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
316b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
317b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
318b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    return EFI_SUCCESS;
319b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
320b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
321b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/**
322b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Platform specific mechanism to transfer control to 16bit OS waking vector
323b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
324b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  @param[in] AcpiWakingVector    The 16bit OS waking vector
325b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  @param[in] AcpiLowMemoryBase   A buffer under 1M which could be used during the transfer
326b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
327b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney**/
328b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyVOID
329b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyPlatformTransferControl16 (
330b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINT32       AcpiWakingVector,
331b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN UINT32       AcpiLowMemoryBase
332b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
333b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
334b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT32      NewValue;
335b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT64      BaseAddress;
336b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINT64      SmramLength;
337b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN       Index;
338b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
339b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  DEBUG (( EFI_D_INFO, "PlatformTransferControl - Entry\r\n"));
340b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
341b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
342b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Need to make sure the GDT is loaded with values that support long mode and real mode.
343b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
344b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  AsmWriteGdtr (&mGdt);
345b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
346b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
347b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Disable eSram block (this will also clear/zero eSRAM)
348b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // We only use eSRAM in the PEI phase. Disable now that we are resuming the OS
349b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
350b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  NewValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK);
351b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  NewValue |= BLOCK_DISABLE_PG;
352b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_ESRAMPGCTRL_BLOCK, NewValue);
353b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
354b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
355b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Update HMBOUND to top of DDR3 memory and LOCK
356b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // We disabled eSRAM so now we move HMBOUND down to top of DDR3
357b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
358b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  QNCGetTSEGMemoryRange (&BaseAddress, &SmramLength);
359b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  NewValue = (UINT32)(BaseAddress + SmramLength);
360b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  DEBUG ((EFI_D_INFO,"Locking HMBOUND at: = 0x%8x\n",NewValue));
361b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HMBOUND_REG, (NewValue | HMBOUND_LOCK));
362b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
363b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
364b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Lock all IMR regions now that HMBOUND is locked
365b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
366b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  for (Index = (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL); Index <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXL); Index += 4) {
367b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    NewValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, Index);
368b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    NewValue |= IMR_LOCK;
369b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, Index, NewValue);
370b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
371b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
372b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
373b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Call ASM routine to switch to real mode and jump to 16bit OS waking vector
374b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
375b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  AsmTransferControl(AcpiWakingVector, 0);
376b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
377b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
378b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Never run to here
379b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
380b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  CpuDeadLoop();
381b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
382b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
383b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
384b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
385b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
386