]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/Sec/SecMain.c
ShellBinPkg: Added Aarch64 Shell binaries
[mirror_edk2.git] / Nt32Pkg / Sec / SecMain.c
CommitLineData
6ae81428 1/**@file\r
2e19fd0f 2\r
3bbe68a3 3Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
8f2a5f80 4This program and the accompanying materials\r
2e19fd0f 5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 SecMain.c\r
15\r
16Abstract:\r
17 WinNt emulator of SEC phase. It's really a Win32 application, but this is\r
18 Ok since all the other modules for NT32 are NOT Win32 applications.\r
19\r
952261d5
LG
20 This program gets NT32 PCD setting and figures out what the memory layout \r
21 will be, how may FD's will be loaded and also what the boot mode is.\r
2e19fd0f 22\r
23 The SEC registers a set of services with the SEC core. gPrivateDispatchTable\r
24 is a list of PPI's produced by the SEC that are availble for usage in PEI.\r
25\r
952261d5
LG
26 This code produces 128 K of temporary memory for the PEI stack by directly\r
27 allocate memory space with ReadWrite and Execute attribute.\r
2e19fd0f 28\r
6ae81428 29**/\r
2e19fd0f 30\r
31#include "SecMain.h"\r
d0dc913e 32\r
24e12917
RN
33#ifndef SE_TIME_ZONE_NAME\r
34#define SE_TIME_ZONE_NAME TEXT("SeTimeZonePrivilege")\r
35#endif\r
2e19fd0f 36\r
37NT_PEI_LOAD_FILE_PPI mSecNtLoadFilePpi = { SecWinNtPeiLoadFile };\r
38\r
39PEI_NT_AUTOSCAN_PPI mSecNtAutoScanPpi = { SecWinNtPeiAutoScan };\r
40\r
41PEI_NT_THUNK_PPI mSecWinNtThunkPpi = { SecWinNtWinNtThunkAddress };\r
42\r
43EFI_PEI_PROGRESS_CODE_PPI mSecStatusCodePpi = { SecPeiReportStatusCode };\r
44\r
45NT_FWH_PPI mSecFwhInformationPpi = { SecWinNtFdAddress };\r
46\r
d0a3ead2 47EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPpi = {SecTemporaryRamSupport};\r
2e19fd0f 48\r
49EFI_PEI_PPI_DESCRIPTOR gPrivateDispatchTable[] = {\r
2e19fd0f 50 {\r
51 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
52 &gNtPeiLoadFilePpiGuid,\r
53 &mSecNtLoadFilePpi\r
54 },\r
55 {\r
56 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
57 &gPeiNtAutoScanPpiGuid,\r
58 &mSecNtAutoScanPpi\r
59 },\r
60 {\r
61 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
62 &gPeiNtThunkPpiGuid,\r
63 &mSecWinNtThunkPpi\r
64 },\r
65 {\r
66 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
67 &gEfiPeiStatusCodePpiGuid,\r
68 &mSecStatusCodePpi\r
69 },\r
58dcdada 70 {\r
71 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
72 &gEfiTemporaryRamSupportPpiGuid,\r
73 &mSecTemporaryRamSupportPpi\r
74 },\r
2e19fd0f 75 {\r
76 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
77 &gNtFwhPpiGuid,\r
78 &mSecFwhInformationPpi\r
79 }\r
80};\r
81\r
82\r
83//\r
84// Default information about where the FD is located.\r
952261d5 85// This array gets filled in with information from PcdWinNtFirmwareVolume\r
2e19fd0f 86// The number of array elements is allocated base on parsing\r
952261d5 87// PcdWinNtFirmwareVolume and the memory is never freed.\r
2e19fd0f 88//\r
89UINTN gFdInfoCount = 0;\r
90NT_FD_INFO *gFdInfo;\r
91\r
92//\r
93// Array that supports seperate memory rantes.\r
952261d5 94// The memory ranges are set by PcdWinNtMemorySizeForSecMain.\r
2e19fd0f 95// The number of array elements is allocated base on parsing\r
952261d5 96// PcdWinNtMemorySizeForSecMain value and the memory is never freed.\r
2e19fd0f 97//\r
98UINTN gSystemMemoryCount = 0;\r
99NT_SYSTEM_MEMORY *gSystemMemory;\r
100\r
58dcdada 101VOID\r
102EFIAPI\r
103SecSwitchStack (\r
104 UINT32 TemporaryMemoryBase,\r
105 UINT32 PermenentMemoryBase\r
106 );\r
ffdd18bb 107EFI_STATUS\r
108SecNt32PeCoffRelocateImage (\r
109 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
110 );\r
1f53f7bb 111\r
112VOID\r
113SecPrint (\r
114 CHAR8 *Format,\r
115 ...\r
116 )\r
117{\r
118 va_list Marker;\r
119 UINTN CharCount;\r
120 CHAR8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];\r
121\r
122 va_start (Marker, Format);\r
123 \r
1f53f7bb 124 _vsnprintf (Buffer, sizeof (Buffer), Format, Marker);\r
125\r
3bbe68a3 126 va_end (Marker);\r
127\r
1f53f7bb 128 CharCount = strlen (Buffer);\r
129 WriteFile (\r
130 GetStdHandle (STD_OUTPUT_HANDLE), \r
131 Buffer,\r
132 CharCount,\r
133 (LPDWORD)&CharCount,\r
134 NULL\r
135 );\r
136}\r
137\r
2e19fd0f 138INTN\r
139EFIAPI\r
140main (\r
141 IN INTN Argc,\r
142 IN CHAR8 **Argv,\r
143 IN CHAR8 **Envp\r
144 )\r
145/*++\r
146\r
147Routine Description:\r
148 Main entry point to SEC for WinNt. This is a Windows program\r
149\r
150Arguments:\r
151 Argc - Number of command line arguments\r
152 Argv - Array of command line argument strings\r
153 Envp - Array of environmemt variable strings\r
154\r
155Returns:\r
156 0 - Normal exit\r
157 1 - Abnormal exit\r
158\r
159--*/\r
160{\r
161 EFI_STATUS Status;\r
24e12917
RN
162 HANDLE Token;\r
163 TOKEN_PRIVILEGES TokenPrivileges;\r
2e19fd0f 164 EFI_PHYSICAL_ADDRESS InitialStackMemory;\r
165 UINT64 InitialStackMemorySize;\r
166 UINTN Index;\r
167 UINTN Index1;\r
168 UINTN Index2;\r
2e19fd0f 169 CHAR16 *FileName;\r
170 CHAR16 *FileNamePtr;\r
171 BOOLEAN Done;\r
172 VOID *PeiCoreFile;\r
173 CHAR16 *MemorySizeStr;\r
174 CHAR16 *FirmwareVolumesStr;\r
85e43be1 175 UINTN *StackPointer;\r
706e7534 176\r
24e12917
RN
177 //\r
178 // Enable the privilege so that RTC driver can successfully run SetTime()\r
179 //\r
180 OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &Token);\r
181 if (LookupPrivilegeValue(NULL, SE_TIME_ZONE_NAME, &TokenPrivileges.Privileges[0].Luid)) {\r
182 TokenPrivileges.PrivilegeCount = 1;\r
183 TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\r
184 AdjustTokenPrivileges(Token, FALSE, &TokenPrivileges, 0, (PTOKEN_PRIVILEGES) NULL, 0);\r
185 }\r
186\r
f7c58a94 187 MemorySizeStr = (CHAR16 *) PcdGetPtr (PcdWinNtMemorySizeForSecMain);\r
188 FirmwareVolumesStr = (CHAR16 *) PcdGetPtr (PcdWinNtFirmwareVolume);\r
2e19fd0f 189\r
1f53f7bb 190 SecPrint ("\nEDK II SEC Main NT Emulation Environment from www.TianoCore.org\n");\r
2e19fd0f 191\r
192 //\r
193 // Make some Windows calls to Set the process to the highest priority in the\r
194 // idle class. We need this to have good performance.\r
195 //\r
196 SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS);\r
197 SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);\r
198\r
199 //\r
200 // Allocate space for gSystemMemory Array\r
201 //\r
202 gSystemMemoryCount = CountSeperatorsInString (MemorySizeStr, '!') + 1;\r
203 gSystemMemory = calloc (gSystemMemoryCount, sizeof (NT_SYSTEM_MEMORY));\r
204 if (gSystemMemory == NULL) {\r
1f53f7bb 205 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", MemorySizeStr);\r
2e19fd0f 206 exit (1);\r
207 }\r
208 //\r
209 // Allocate space for gSystemMemory Array\r
210 //\r
211 gFdInfoCount = CountSeperatorsInString (FirmwareVolumesStr, '!') + 1;\r
212 gFdInfo = calloc (gFdInfoCount, sizeof (NT_FD_INFO));\r
213 if (gFdInfo == NULL) {\r
1f53f7bb 214 SecPrint ("ERROR : Can not allocate memory for %S. Exiting.\n", FirmwareVolumesStr);\r
2e19fd0f 215 exit (1);\r
216 }\r
217 //\r
218 // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION)\r
219 //\r
f7c58a94 220 SecPrint (" BootMode 0x%02x\n", PcdGet32 (PcdWinNtBootMode));\r
2e19fd0f 221\r
222 //\r
952261d5 223 // Allocate 128K memory to emulate temp memory for PEI.\r
2e19fd0f 224 // on a real platform this would be SRAM, or using the cache as RAM.\r
225 // Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping\r
226 //\r
952261d5
LG
227 InitialStackMemorySize = STACK_SIZE;\r
228 InitialStackMemory = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAlloc (NULL, (SIZE_T) (InitialStackMemorySize), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
229 if (InitialStackMemory == 0) {\r
1f53f7bb 230 SecPrint ("ERROR : Can not allocate enough space for SecStack\n");\r
2e19fd0f 231 exit (1);\r
232 }\r
233\r
85e43be1 234 for (StackPointer = (UINTN*) (UINTN) InitialStackMemory;\r
235 StackPointer < (UINTN*) ((UINTN)InitialStackMemory + (SIZE_T) InitialStackMemorySize);\r
236 StackPointer ++) {\r
237 *StackPointer = 0x5AA55AA5;\r
238 }\r
239 \r
1f53f7bb 240 SecPrint (" SEC passing in %d bytes of temp RAM to PEI\n", InitialStackMemorySize);\r
2e19fd0f 241\r
242 //\r
243 // Open All the firmware volumes and remember the info in the gFdInfo global\r
244 //\r
245 FileNamePtr = (CHAR16 *)malloc (StrLen ((CHAR16 *)FirmwareVolumesStr) * sizeof(CHAR16));\r
246 if (FileNamePtr == NULL) {\r
1f53f7bb 247 SecPrint ("ERROR : Can not allocate memory for firmware volume string\n");\r
2e19fd0f 248 exit (1);\r
249 }\r
250\r
251 StrCpy (FileNamePtr, (CHAR16*)FirmwareVolumesStr);\r
252\r
0b94e319 253 for (Done = FALSE, Index = 0, PeiCoreFile = NULL; !Done; Index++) {\r
2e19fd0f 254 FileName = FileNamePtr;\r
255 for (Index1 = 0; (FileNamePtr[Index1] != '!') && (FileNamePtr[Index1] != 0); Index1++)\r
256 ;\r
257 if (FileNamePtr[Index1] == 0) {\r
258 Done = TRUE;\r
259 } else {\r
260 FileNamePtr[Index1] = '\0';\r
261 FileNamePtr = FileNamePtr + Index1 + 1;\r
262 }\r
263\r
264 //\r
265 // Open the FD and remmeber where it got mapped into our processes address space\r
266 //\r
267 Status = WinNtOpenFile (\r
268 FileName,\r
269 0,\r
270 OPEN_EXISTING,\r
271 &gFdInfo[Index].Address,\r
272 &gFdInfo[Index].Size\r
273 );\r
274 if (EFI_ERROR (Status)) {\r
1f53f7bb 275 SecPrint ("ERROR : Can not open Firmware Device File %S (0x%X). Exiting.\n", FileName, Status);\r
2e19fd0f 276 exit (1);\r
277 }\r
278\r
1f53f7bb 279 SecPrint (" FD loaded from");\r
2e19fd0f 280 //\r
281 // printf can't print filenames directly as the \ gets interperted as an\r
282 // escape character.\r
283 //\r
284 for (Index2 = 0; FileName[Index2] != '\0'; Index2++) {\r
1f53f7bb 285 SecPrint ("%c", FileName[Index2]);\r
2e19fd0f 286 }\r
287\r
288 if (PeiCoreFile == NULL) {\r
289 //\r
290 // Assume the beginning of the FD is an FV and look for the PEI Core.\r
291 // Load the first one we find.\r
292 //\r
293 Status = SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) gFdInfo[Index].Address, &PeiCoreFile);\r
294 if (!EFI_ERROR (Status)) {\r
1f53f7bb 295 SecPrint (" contains SEC Core");\r
2e19fd0f 296 }\r
297 }\r
298\r
1f53f7bb 299 SecPrint ("\n");\r
2e19fd0f 300 }\r
301 //\r
302 // Calculate memory regions and store the information in the gSystemMemory\r
303 // global for later use. The autosizing code will use this data to\r
304 // map this memory into the SEC process memory space.\r
305 //\r
306 for (Index = 0, Done = FALSE; !Done; Index++) {\r
307 //\r
308 // Save the size of the memory and make a Unicode filename SystemMemory00, ...\r
309 //\r
310 gSystemMemory[Index].Size = _wtoi (MemorySizeStr) * 0x100000;\r
2e19fd0f 311\r
312 //\r
313 // Find the next region\r
314 //\r
315 for (Index1 = 0; MemorySizeStr[Index1] != '!' && MemorySizeStr[Index1] != 0; Index1++)\r
316 ;\r
317 if (MemorySizeStr[Index1] == 0) {\r
318 Done = TRUE;\r
319 }\r
320\r
321 MemorySizeStr = MemorySizeStr + Index1 + 1;\r
322 }\r
323\r
1f53f7bb 324 SecPrint ("\n");\r
2e19fd0f 325\r
326 //\r
327 // Hand off to PEI Core\r
328 //\r
329 SecLoadFromCore ((UINTN) InitialStackMemory, (UINTN) InitialStackMemorySize, (UINTN) gFdInfo[0].Address, PeiCoreFile);\r
330\r
331 //\r
332 // If we get here, then the PEI Core returned. This is an error as PEI should\r
333 // always hand off to DXE.\r
334 //\r
1f53f7bb 335 SecPrint ("ERROR : PEI Core returned\n");\r
2e19fd0f 336 exit (1);\r
337}\r
338\r
339EFI_STATUS\r
340WinNtOpenFile (\r
341 IN CHAR16 *FileName,\r
342 IN UINT32 MapSize,\r
343 IN DWORD CreationDisposition,\r
344 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,\r
345 OUT UINT64 *Length\r
346 )\r
347/*++\r
348\r
349Routine Description:\r
350 Opens and memory maps a file using WinNt services. If BaseAddress is non zero\r
351 the process will try and allocate the memory starting at BaseAddress.\r
352\r
353Arguments:\r
354 FileName - The name of the file to open and map\r
355 MapSize - The amount of the file to map in bytes\r
356 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for\r
357 memory emulation, and exiting files for firmware volume emulation\r
358 BaseAddress - The base address of the mapped file in the user address space.\r
359 If passed in as NULL the a new memory region is used.\r
360 If passed in as non NULL the request memory region is used for\r
361 the mapping of the file into the process space.\r
362 Length - The size of the mapped region in bytes\r
363\r
364Returns:\r
365 EFI_SUCCESS - The file was opened and mapped.\r
366 EFI_NOT_FOUND - FileName was not found in the current directory\r
367 EFI_DEVICE_ERROR - An error occured attempting to map the opened file\r
368\r
369--*/\r
370{\r
371 HANDLE NtFileHandle;\r
372 HANDLE NtMapHandle;\r
373 VOID *VirtualAddress;\r
374 UINTN FileSize;\r
375\r
376 //\r
377 // Use Win API to open/create a file\r
378 //\r
379 NtFileHandle = CreateFile (\r
380 FileName,\r
75e55c54 381 GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,\r
2e19fd0f 382 FILE_SHARE_READ,\r
383 NULL,\r
384 CreationDisposition,\r
385 FILE_ATTRIBUTE_NORMAL,\r
386 NULL\r
387 );\r
388 if (NtFileHandle == INVALID_HANDLE_VALUE) {\r
389 return EFI_NOT_FOUND;\r
390 }\r
391 //\r
392 // Map the open file into a memory range\r
393 //\r
394 NtMapHandle = CreateFileMapping (\r
395 NtFileHandle,\r
396 NULL,\r
75e55c54 397 PAGE_EXECUTE_READWRITE,\r
2e19fd0f 398 0,\r
399 MapSize,\r
400 NULL\r
401 );\r
402 if (NtMapHandle == NULL) {\r
403 return EFI_DEVICE_ERROR;\r
404 }\r
405 //\r
406 // Get the virtual address (address in the emulator) of the mapped file\r
407 //\r
408 VirtualAddress = MapViewOfFileEx (\r
409 NtMapHandle,\r
75e55c54 410 FILE_MAP_EXECUTE | FILE_MAP_ALL_ACCESS,\r
2e19fd0f 411 0,\r
412 0,\r
413 MapSize,\r
414 (LPVOID) (UINTN) *BaseAddress\r
415 );\r
416 if (VirtualAddress == NULL) {\r
417 return EFI_DEVICE_ERROR;\r
418 }\r
419\r
420 if (MapSize == 0) {\r
421 //\r
422 // Seek to the end of the file to figure out the true file size.\r
423 //\r
424 FileSize = SetFilePointer (\r
425 NtFileHandle,\r
426 0,\r
427 NULL,\r
428 FILE_END\r
429 );\r
430 if (FileSize == -1) {\r
431 return EFI_DEVICE_ERROR;\r
432 }\r
433\r
434 *Length = (UINT64) FileSize;\r
435 } else {\r
436 *Length = (UINT64) MapSize;\r
437 }\r
438\r
439 *BaseAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAddress;\r
440\r
441 return EFI_SUCCESS;\r
442}\r
443\r
2e19fd0f 444\r
d0dc913e 445#define BYTES_PER_RECORD 512\r
2e19fd0f 446\r
447EFI_STATUS\r
448EFIAPI\r
449SecPeiReportStatusCode (\r
e1001af1 450 IN CONST EFI_PEI_SERVICES **PeiServices,\r
2e19fd0f 451 IN EFI_STATUS_CODE_TYPE CodeType,\r
452 IN EFI_STATUS_CODE_VALUE Value,\r
453 IN UINT32 Instance,\r
e1001af1 454 IN CONST EFI_GUID *CallerId,\r
455 IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL\r
2e19fd0f 456 )\r
457/*++\r
458\r
459Routine Description:\r
460\r
461 This routine produces the ReportStatusCode PEI service. It's passed\r
462 up to the PEI Core via a PPI. T\r
463\r
464 This code currently uses the NT clib printf. This does not work the same way\r
465 as the EFI Print (), as %t, %g, %s as Unicode are not supported.\r
466\r
467Arguments:\r
468 (see EFI_PEI_REPORT_STATUS_CODE)\r
469\r
470Returns:\r
471 EFI_SUCCESS - Always return success\r
472\r
473--*/\r
474// TODO: PeiServices - add argument and description to function comment\r
475// TODO: CodeType - add argument and description to function comment\r
476// TODO: Value - add argument and description to function comment\r
477// TODO: Instance - add argument and description to function comment\r
478// TODO: CallerId - add argument and description to function comment\r
479// TODO: Data - add argument and description to function comment\r
480{\r
481 CHAR8 *Format;\r
a776476a 482 BASE_LIST Marker;\r
2e19fd0f 483 CHAR8 PrintBuffer[BYTES_PER_RECORD * 2];\r
484 CHAR8 *Filename;\r
485 CHAR8 *Description;\r
486 UINT32 LineNumber;\r
d0dc913e 487 UINT32 ErrorLevel;\r
2e19fd0f 488\r
d0dc913e
A
489\r
490 if (Data == NULL) {\r
491 } else if (ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {\r
2e19fd0f 492 //\r
d0dc913e 493 // Processes ASSERT ()\r
2e19fd0f 494 //\r
1f53f7bb 495 SecPrint ("ASSERT %s(%d): %s\n", Filename, (int)LineNumber, Description);\r
2e19fd0f 496\r
d0dc913e
A
497 } else if (ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {\r
498 //\r
499 // Process DEBUG () macro \r
500 //\r
a776476a 501 AsciiBSPrint (PrintBuffer, BYTES_PER_RECORD, Format, Marker);\r
1f53f7bb 502 SecPrint (PrintBuffer);\r
2e19fd0f 503 }\r
504\r
505 return EFI_SUCCESS;\r
506}\r
507\r
5aae0aa7 508/**\r
509 Transfers control to a function starting with a new stack.\r
510\r
511 Transfers control to the function specified by EntryPoint using the new stack\r
512 specified by NewStack and passing in the parameters specified by Context1 and\r
513 Context2. Context1 and Context2 are optional and may be NULL. The function\r
514 EntryPoint must never return.\r
515\r
516 If EntryPoint is NULL, then ASSERT().\r
517 If NewStack is NULL, then ASSERT().\r
518\r
519 @param EntryPoint A pointer to function to call with the new stack.\r
520 @param Context1 A pointer to the context to pass into the EntryPoint\r
521 function.\r
522 @param Context2 A pointer to the context to pass into the EntryPoint\r
523 function.\r
524 @param NewStack A pointer to the new stack to use for the EntryPoint\r
525 function.\r
526 @param NewBsp A pointer to the new BSP for the EntryPoint on IPF. It's\r
527 Reserved on other architectures.\r
528\r
529**/\r
530VOID\r
531EFIAPI\r
532PeiSwitchStacks (\r
533 IN SWITCH_STACK_ENTRY_POINT EntryPoint,\r
534 IN VOID *Context1, OPTIONAL\r
535 IN VOID *Context2, OPTIONAL\r
536 IN VOID *Context3, OPTIONAL\r
537 IN VOID *NewStack\r
538 )\r
539{\r
540 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;\r
541 \r
542 ASSERT (EntryPoint != NULL);\r
543 ASSERT (NewStack != NULL);\r
544\r
545 //\r
546 // Stack should be aligned with CPU_STACK_ALIGNMENT\r
547 //\r
548 ASSERT (((UINTN)NewStack & (CPU_STACK_ALIGNMENT - 1)) == 0);\r
549\r
550 JumpBuffer.Eip = (UINTN)EntryPoint;\r
551 JumpBuffer.Esp = (UINTN)NewStack - sizeof (VOID*);\r
552 JumpBuffer.Esp -= sizeof (Context1) + sizeof (Context2) + sizeof(Context3);\r
553 ((VOID**)JumpBuffer.Esp)[1] = Context1;\r
554 ((VOID**)JumpBuffer.Esp)[2] = Context2;\r
555 ((VOID**)JumpBuffer.Esp)[3] = Context3;\r
556\r
557 LongJump (&JumpBuffer, (UINTN)-1);\r
558 \r
559\r
560 //\r
561 // InternalSwitchStack () will never return\r
562 //\r
563 ASSERT (FALSE); \r
564}\r
2e19fd0f 565\r
566VOID\r
567SecLoadFromCore (\r
568 IN UINTN LargestRegion,\r
569 IN UINTN LargestRegionSize,\r
570 IN UINTN BootFirmwareVolumeBase,\r
571 IN VOID *PeiCorePe32File\r
572 )\r
573/*++\r
574\r
575Routine Description:\r
576 This is the service to load the PEI Core from the Firmware Volume\r
577\r
578Arguments:\r
579 LargestRegion - Memory to use for PEI.\r
580 LargestRegionSize - Size of Memory to use for PEI\r
581 BootFirmwareVolumeBase - Start of the Boot FV\r
582 PeiCorePe32File - PEI Core PE32\r
583\r
584Returns:\r
585 Success means control is transfered and thus we should never return\r
586\r
587--*/\r
588{\r
589 EFI_STATUS Status;\r
2e19fd0f 590 VOID *TopOfStack;\r
591 UINT64 PeiCoreSize;\r
592 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint;\r
593 EFI_PHYSICAL_ADDRESS PeiImageAddress;\r
5aae0aa7 594 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
58dcdada 595 UINTN PeiStackSize;\r
2e19fd0f 596\r
597 //\r
598 // Compute Top Of Memory for Stack and PEI Core Allocations\r
599 //\r
58dcdada 600 PeiStackSize = (UINTN)RShiftU64((UINT64)STACK_SIZE,1);\r
2e19fd0f 601\r
602 //\r
58dcdada 603 // |-----------| <---- TemporaryRamBase + TemporaryRamSize\r
604 // | Heap |\r
605 // | |\r
606 // |-----------| <---- StackBase / PeiTemporaryMemoryBase\r
607 // | |\r
608 // | Stack |\r
609 // |-----------| <---- TemporaryRamBase\r
610 // \r
611 TopOfStack = (VOID *)(LargestRegion + PeiStackSize);\r
58dcdada 612\r
2e19fd0f 613 //\r
58dcdada 614 // Reservet space for storing PeiCore's parament in stack.\r
615 // \r
616 TopOfStack = (VOID *)((UINTN)TopOfStack - sizeof (EFI_SEC_PEI_HAND_OFF) - CPU_STACK_ALIGNMENT);\r
2e19fd0f 617 TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
2e19fd0f 618\r
2e19fd0f 619 //\r
620 // Bind this information into the SEC hand-off state\r
621 //\r
5aae0aa7 622 SecCoreData = (EFI_SEC_PEI_HAND_OFF*)(UINTN) TopOfStack;\r
623 SecCoreData->DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);\r
624 SecCoreData->BootFirmwareVolumeBase = (VOID*)BootFirmwareVolumeBase;\r
f7c58a94 625 SecCoreData->BootFirmwareVolumeSize = PcdGet32(PcdWinNtFirmwareFdSize);\r
58dcdada 626 SecCoreData->TemporaryRamBase = (VOID*)(UINTN)LargestRegion; \r
5aae0aa7 627 SecCoreData->TemporaryRamSize = STACK_SIZE;\r
ff33b87d 628 SecCoreData->StackBase = SecCoreData->TemporaryRamBase;\r
58dcdada 629 SecCoreData->StackSize = PeiStackSize;\r
ff33b87d 630 SecCoreData->PeiTemporaryRamBase = (VOID*) ((UINTN) SecCoreData->TemporaryRamBase + PeiStackSize);\r
58dcdada 631 SecCoreData->PeiTemporaryRamSize = STACK_SIZE - PeiStackSize;\r
2e19fd0f 632\r
633 //\r
634 // Load the PEI Core from a Firmware Volume\r
635 //\r
636 Status = SecWinNtPeiLoadFile (\r
637 PeiCorePe32File,\r
638 &PeiImageAddress,\r
639 &PeiCoreSize,\r
640 &PeiCoreEntryPoint\r
641 );\r
642 if (EFI_ERROR (Status)) {\r
643 return ;\r
644 }\r
5aae0aa7 645 \r
2e19fd0f 646 //\r
647 // Transfer control to the PEI Core\r
648 //\r
5aae0aa7 649 PeiSwitchStacks (\r
2e19fd0f 650 (SWITCH_STACK_ENTRY_POINT) (UINTN) PeiCoreEntryPoint,\r
5aae0aa7 651 SecCoreData,\r
652 (VOID *) (UINTN) ((EFI_PEI_PPI_DESCRIPTOR *) &gPrivateDispatchTable),\r
2e19fd0f 653 NULL,\r
654 TopOfStack\r
655 );\r
656 //\r
657 // If we get here, then the PEI Core returned. This is an error\r
658 //\r
659 return ;\r
660}\r
661\r
662EFI_STATUS\r
663EFIAPI\r
664SecWinNtPeiAutoScan (\r
665 IN UINTN Index,\r
666 OUT EFI_PHYSICAL_ADDRESS *MemoryBase,\r
667 OUT UINT64 *MemorySize\r
668 )\r
669/*++\r
670\r
671Routine Description:\r
672 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.\r
673 It allows discontiguous memory regions to be supported by the emulator.\r
674 It uses gSystemMemory[] and gSystemMemoryCount that were created by\r
952261d5
LG
675 parsing PcdWinNtMemorySizeForSecMain value.\r
676 The size comes from the Pcd value and the address comes from the memory space \r
677 with ReadWrite and Execute attributes allocated by VirtualAlloc() API.\r
2e19fd0f 678\r
679Arguments:\r
680 Index - Which memory region to use\r
681 MemoryBase - Return Base address of memory region\r
682 MemorySize - Return size in bytes of the memory region\r
683\r
684Returns:\r
685 EFI_SUCCESS - If memory region was mapped\r
686 EFI_UNSUPPORTED - If Index is not supported\r
687\r
688--*/\r
689{\r
2e19fd0f 690 if (Index >= gSystemMemoryCount) {\r
691 return EFI_UNSUPPORTED;\r
692 }\r
952261d5
LG
693 \r
694 //\r
695 // Allocate enough memory space for emulator \r
696 //\r
697 gSystemMemory[Index].Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAlloc (NULL, (SIZE_T) (gSystemMemory[Index].Size), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
698 if (gSystemMemory[Index].Memory == 0) {\r
699 return EFI_OUT_OF_RESOURCES;\r
700 }\r
701 \r
702 *MemoryBase = gSystemMemory[Index].Memory;\r
703 *MemorySize = gSystemMemory[Index].Size;\r
2e19fd0f 704\r
952261d5 705 return EFI_SUCCESS;\r
2e19fd0f 706}\r
707\r
708VOID *\r
709EFIAPI\r
710SecWinNtWinNtThunkAddress (\r
711 VOID\r
712 )\r
713/*++\r
714\r
715Routine Description:\r
716 Since the SEC is the only Windows program in stack it must export\r
717 an interface to do Win API calls. That's what the WinNtThunk address\r
718 is for. gWinNt is initailized in WinNtThunk.c.\r
719\r
720Arguments:\r
721 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);\r
722 InterfaceBase - Address of the gWinNt global\r
723\r
724Returns:\r
725 EFI_SUCCESS - Data returned\r
726\r
727--*/\r
728{\r
729 return gWinNt;\r
730}\r
731\r
732\r
733EFI_STATUS\r
734EFIAPI\r
735SecWinNtPeiLoadFile (\r
736 IN VOID *Pe32Data,\r
737 IN EFI_PHYSICAL_ADDRESS *ImageAddress,\r
738 IN UINT64 *ImageSize,\r
739 IN EFI_PHYSICAL_ADDRESS *EntryPoint\r
740 )\r
741/*++\r
742\r
743Routine Description:\r
744 Loads and relocates a PE/COFF image into memory.\r
745\r
746Arguments:\r
747 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated\r
748 ImageAddress - The base address of the relocated PE/COFF image\r
749 ImageSize - The size of the relocated PE/COFF image\r
750 EntryPoint - The entry point of the relocated PE/COFF image\r
751\r
752Returns:\r
753 EFI_SUCCESS - The file was loaded and relocated\r
754 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file\r
755\r
756--*/\r
757{\r
758 EFI_STATUS Status;\r
759 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
760\r
761 ZeroMem (&ImageContext, sizeof (ImageContext));\r
762 ImageContext.Handle = Pe32Data;\r
763\r
764 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) SecImageRead;\r
765\r
ffdd18bb 766 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
2e19fd0f 767 if (EFI_ERROR (Status)) {\r
768 return Status;\r
769 }\r
770 //\r
952261d5
LG
771 // Allocate space in NT (not emulator) memory with ReadWrite and Execute attribue. \r
772 // Extra space is for alignment\r
2e19fd0f 773 //\r
952261d5 774 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAlloc (NULL, (SIZE_T) (ImageContext.ImageSize + (ImageContext.SectionAlignment * 2)), MEM_COMMIT, PAGE_EXECUTE_READWRITE);\r
2e19fd0f 775 if (ImageContext.ImageAddress == 0) {\r
776 return EFI_OUT_OF_RESOURCES;\r
777 }\r
778 //\r
779 // Align buffer on section boundry\r
780 //\r
0d10bfc8 781 ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
2e19fd0f 782 ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);\r
783\r
ffdd18bb 784 Status = PeCoffLoaderLoadImage (&ImageContext);\r
2e19fd0f 785 if (EFI_ERROR (Status)) {\r
786 return Status;\r
787 }\r
788\r
ffdd18bb 789 Status = SecNt32PeCoffRelocateImage (&ImageContext);\r
2e19fd0f 790 if (EFI_ERROR (Status)) {\r
791 return Status;\r
792 }\r
793\r
794 //\r
795 // BugBug: Flush Instruction Cache Here when CPU Lib is ready\r
796 //\r
797\r
798 *ImageAddress = ImageContext.ImageAddress;\r
799 *ImageSize = ImageContext.ImageSize;\r
800 *EntryPoint = ImageContext.EntryPoint;\r
801\r
802 return EFI_SUCCESS;\r
803}\r
804\r
805EFI_STATUS\r
806EFIAPI\r
807SecWinNtFdAddress (\r
808 IN UINTN Index,\r
809 IN OUT EFI_PHYSICAL_ADDRESS *FdBase,\r
810 IN OUT UINT64 *FdSize\r
811 )\r
812/*++\r
813\r
814Routine Description:\r
815 Return the FD Size and base address. Since the FD is loaded from a\r
816 file into Windows memory only the SEC will know it's address.\r
817\r
818Arguments:\r
819 Index - Which FD, starts at zero.\r
820 FdSize - Size of the FD in bytes\r
821 FdBase - Start address of the FD. Assume it points to an FV Header\r
822\r
823Returns:\r
824 EFI_SUCCESS - Return the Base address and size of the FV\r
825 EFI_UNSUPPORTED - Index does nto map to an FD in the system\r
826\r
827--*/\r
828{\r
829 if (Index >= gFdInfoCount) {\r
830 return EFI_UNSUPPORTED;\r
831 }\r
832\r
833 *FdBase = gFdInfo[Index].Address;\r
834 *FdSize = gFdInfo[Index].Size;\r
835\r
836 if (*FdBase == 0 && *FdSize == 0) {\r
837 return EFI_UNSUPPORTED;\r
838 }\r
839\r
840 return EFI_SUCCESS;\r
841}\r
842\r
843EFI_STATUS\r
844EFIAPI\r
845SecImageRead (\r
846 IN VOID *FileHandle,\r
847 IN UINTN FileOffset,\r
848 IN OUT UINTN *ReadSize,\r
849 OUT VOID *Buffer\r
850 )\r
851/*++\r
852\r
853Routine Description:\r
854 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
855\r
856Arguments:\r
857 FileHandle - The handle to the PE/COFF file\r
858 FileOffset - The offset, in bytes, into the file to read\r
859 ReadSize - The number of bytes to read from the file starting at FileOffset\r
860 Buffer - A pointer to the buffer to read the data into.\r
861\r
862Returns:\r
863 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
864\r
865--*/\r
866{\r
867 CHAR8 *Destination8;\r
868 CHAR8 *Source8;\r
869 UINTN Length;\r
870\r
871 Destination8 = Buffer;\r
872 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
873 Length = *ReadSize;\r
874 while (Length--) {\r
875 *(Destination8++) = *(Source8++);\r
876 }\r
877\r
878 return EFI_SUCCESS;\r
879}\r
880\r
881CHAR16 *\r
882AsciiToUnicode (\r
883 IN CHAR8 *Ascii,\r
884 IN UINTN *StrLen OPTIONAL\r
885 )\r
886/*++\r
887\r
888Routine Description:\r
889 Convert the passed in Ascii string to Unicode.\r
890 Optionally return the length of the strings.\r
891\r
892Arguments:\r
893 Ascii - Ascii string to convert\r
894 StrLen - Length of string\r
895\r
896Returns:\r
897 Pointer to malloc'ed Unicode version of Ascii\r
898\r
899--*/\r
900{\r
901 UINTN Index;\r
902 CHAR16 *Unicode;\r
903\r
904 //\r
905 // Allocate a buffer for unicode string\r
906 //\r
907 for (Index = 0; Ascii[Index] != '\0'; Index++)\r
908 ;\r
909 Unicode = malloc ((Index + 1) * sizeof (CHAR16));\r
910 if (Unicode == NULL) {\r
911 return NULL;\r
912 }\r
913\r
914 for (Index = 0; Ascii[Index] != '\0'; Index++) {\r
915 Unicode[Index] = (CHAR16) Ascii[Index];\r
916 }\r
917\r
918 Unicode[Index] = '\0';\r
919\r
920 if (StrLen != NULL) {\r
921 *StrLen = Index;\r
922 }\r
923\r
924 return Unicode;\r
925}\r
926\r
927UINTN\r
928CountSeperatorsInString (\r
03c19e06 929 IN CONST CHAR16 *String,\r
2e19fd0f 930 IN CHAR16 Seperator\r
931 )\r
932/*++\r
933\r
934Routine Description:\r
935 Count the number of seperators in String\r
936\r
937Arguments:\r
938 String - String to process\r
939 Seperator - Item to count\r
940\r
941Returns:\r
942 Number of Seperator in String\r
943\r
944--*/\r
945{\r
946 UINTN Count;\r
947\r
948 for (Count = 0; *String != '\0'; String++) {\r
949 if (*String == Seperator) {\r
950 Count++;\r
951 }\r
952 }\r
953\r
954 return Count;\r
955}\r
956\r
957\r
958EFI_STATUS\r
2e19fd0f 959SecNt32PeCoffRelocateImage (\r
2e19fd0f 960 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
961 )\r
962{\r
963 EFI_STATUS Status;\r
964 VOID *DllEntryPoint;\r
965 CHAR16 *DllFileName;\r
966 HMODULE Library;\r
967 UINTN Index;\r
968\r
969\r
970 Status = PeCoffLoaderRelocateImage (ImageContext);\r
971 if (EFI_ERROR (Status)) {\r
972 //\r
973 // We could not relocated the image in memory properly\r
974 //\r
975 return Status;\r
976 }\r
977\r
978 //\r
979 // If we load our own PE COFF images the Windows debugger can not source\r
980 // level debug our code. If a valid PDB pointer exists usw it to load\r
981 // the *.dll file as a library using Windows* APIs. This allows \r
982 // source level debug. The image is still loaded and reloaced\r
983 // in the Framework memory space like on a real system (by the code above),\r
984 // but the entry point points into the DLL loaded by the code bellow. \r
985 //\r
986\r
987 DllEntryPoint = NULL;\r
988\r
989 //\r
990 // Load the DLL if it's not an EBC image.\r
991 //\r
992 if ((ImageContext->PdbPointer != NULL) &&\r
993 (ImageContext->Machine != EFI_IMAGE_MACHINE_EBC)) {\r
994 //\r
995 // Convert filename from ASCII to Unicode\r
996 //\r
997 DllFileName = AsciiToUnicode (ImageContext->PdbPointer, &Index);\r
998\r
999 //\r
1000 // Check that we have a valid filename\r
1001 //\r
1002 if (Index < 5 || DllFileName[Index - 4] != '.') {\r
1003 free (DllFileName);\r
1004\r
1005 //\r
1006 // Never return an error if PeCoffLoaderRelocateImage() succeeded.\r
1007 // The image will run, but we just can't source level debug. If we\r
1008 // return an error the image will not run.\r
1009 //\r
1010 return EFI_SUCCESS;\r
1011 }\r
1012 //\r
1013 // Replace .PDB with .DLL on the filename\r
1014 //\r
1015 DllFileName[Index - 3] = 'D';\r
1016 DllFileName[Index - 2] = 'L';\r
1017 DllFileName[Index - 1] = 'L';\r
1018\r
1019 //\r
1020 // Load the .DLL file into the user process's address space for source \r
1021 // level debug\r
1022 //\r
1023 Library = LoadLibraryEx (DllFileName, NULL, DONT_RESOLVE_DLL_REFERENCES);\r
1024 if (Library != NULL) {\r
1025 //\r
1026 // InitializeDriver is the entry point we put in all our EFI DLL's. The\r
1027 // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() supresses the \r
1028 // normal DLL entry point of DllMain, and prevents other modules that are\r
1029 // referenced in side the DllFileName from being loaded. There is no error \r
1030 // checking as the we can point to the PE32 image loaded by Tiano. This \r
1031 // step is only needed for source level debuging\r
1032 //\r
1033 DllEntryPoint = (VOID *) (UINTN) GetProcAddress (Library, "InitializeDriver");\r
1034\r
1035 }\r
1036\r
1037 if ((Library != NULL) && (DllEntryPoint != NULL)) {\r
2e19fd0f 1038 ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) DllEntryPoint;\r
1f53f7bb 1039 SecPrint ("LoadLibraryEx (%S,\n NULL, DONT_RESOLVE_DLL_REFERENCES)\n", DllFileName);\r
2e19fd0f 1040 } else {\r
1f53f7bb 1041 SecPrint ("WARNING: No source level debug %S. \n", DllFileName);\r
2e19fd0f 1042 }\r
1043\r
1044 free (DllFileName);\r
1045 }\r
1046\r
1047 //\r
1048 // Never return an error if PeCoffLoaderRelocateImage() succeeded.\r
1049 // The image will run, but we just can't source level debug. If we\r
1050 // return an error the image will not run.\r
1051 //\r
1052 return EFI_SUCCESS;\r
1053}\r
1054\r
1055\r
2e19fd0f 1056\r
2e19fd0f 1057\r
1058VOID\r
1059_ModuleEntryPoint (\r
1060 VOID\r
1061 )\r
1062{\r
1063}\r
1064\r
58dcdada 1065EFI_STATUS\r
1066EFIAPI\r
1067SecTemporaryRamSupport (\r
1068 IN CONST EFI_PEI_SERVICES **PeiServices,\r
1069 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
1070 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
1071 IN UINTN CopySize\r
1072 )\r
1073{\r
1074 //\r
1075 // Migrate the whole temporary memory to permenent memory.\r
1076 // \r
1077 CopyMem (\r
1078 (VOID*)(UINTN)PermanentMemoryBase, \r
1079 (VOID*)(UINTN)TemporaryMemoryBase, \r
1080 CopySize\r
1081 );\r
1082\r
1083 //\r
1084 // SecSwitchStack function must be invoked after the memory migration\r
1085 // immediatly, also we need fixup the stack change caused by new call into \r
1086 // permenent memory.\r
1087 // \r
1088 SecSwitchStack (\r
1089 (UINT32) TemporaryMemoryBase,\r
1090 (UINT32) PermanentMemoryBase\r
1091 );\r
1092\r
1093 //\r
1094 // We need *not* fix the return address because currently, \r
1095 // The PeiCore is excuted in flash.\r
1096 //\r
1097\r
1098 //\r
84a7fd1e 1099 // Simulate to invalid temporary memory, terminate temporary memory\r
58dcdada 1100 // \r
1101 //ZeroMem ((VOID*)(UINTN)TemporaryMemoryBase, CopySize);\r
1102 \r
1103 return EFI_SUCCESS;\r
1104}\r
1105\r