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