Nt32Pkg: Platform BDS should test the untested memory
[mirror_edk2.git] / Nt32Pkg / Library / PlatformBootManagerLib / PlatformBootManager.c
CommitLineData
123e9f62
RN
1/** @file\r
2 This file include all platform action which can be customized\r
3 by IBV/OEM.\r
4\r
5Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "PlatformBootManager.h"\r
17\r
18\r
19EFI_GUID mUefiShellFileGuid = { 0x7C04A583, 0x9E3E, 0x4f1c, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 };\r
20\r
8f227c2f
RN
21/**\r
22 Perform the memory test base on the memory test intensive level,\r
23 and update the memory resource.\r
24\r
25 @param Level The memory test intensive level.\r
26\r
27 @retval EFI_STATUS Success test all the system memory and update\r
28 the memory resource\r
29\r
30**/\r
31EFI_STATUS\r
32PlatformBootManagerMemoryTest (\r
33 IN EXTENDMEM_COVERAGE_LEVEL Level\r
34 )\r
35{\r
36 EFI_STATUS Status;\r
37 BOOLEAN RequireSoftECCInit;\r
38 EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;\r
39 UINT64 TestedMemorySize;\r
40 UINT64 TotalMemorySize;\r
41 UINTN TestPercent;\r
42 UINT64 PreviousValue;\r
43 BOOLEAN ErrorOut;\r
44 UINT32 TempData;\r
45\r
46 TestedMemorySize = 0;\r
47 TotalMemorySize = 0;\r
48 PreviousValue = 0;\r
49\r
50 RequireSoftECCInit = FALSE;\r
51\r
52 Status = gBS->LocateProtocol (\r
53 &gEfiGenericMemTestProtocolGuid,\r
54 NULL,\r
55 (VOID **) &GenMemoryTest\r
56 );\r
57 if (EFI_ERROR (Status)) {\r
58 return EFI_SUCCESS;\r
59 }\r
60\r
61 Status = GenMemoryTest->MemoryTestInit (\r
62 GenMemoryTest,\r
63 Level,\r
64 &RequireSoftECCInit\r
65 );\r
66 if (Status == EFI_NO_MEDIA) {\r
67 //\r
68 // The PEI codes also have the relevant memory test code to check the memory,\r
69 // it can select to test some range of the memory or all of them. If PEI code\r
70 // checks all the memory, this BDS memory test will has no not-test memory to\r
71 // do the test, and then the status of EFI_NO_MEDIA will be returned by\r
72 // "MemoryTestInit". So it does not need to test memory again, just return.\r
73 //\r
74 return EFI_SUCCESS;\r
75 }\r
76\r
77 do {\r
78 Status = GenMemoryTest->PerformMemoryTest (\r
79 GenMemoryTest,\r
80 &TestedMemorySize,\r
81 &TotalMemorySize,\r
82 &ErrorOut,\r
83 FALSE\r
84 );\r
85 if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {\r
86 Print (L"System encounters memory errors!");\r
87 CpuDeadLoop ();\r
88 }\r
89 \r
90 TempData = (UINT32) DivU64x32 (TotalMemorySize, 16);\r
91 TestPercent = (UINTN) DivU64x32 (\r
92 DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),\r
93 TempData\r
94 );\r
95 if (TestPercent != PreviousValue) {\r
96 Print (L"Perform memory test: %d/100", TestPercent);\r
97 PreviousValue = TestPercent;\r
98 }\r
99 } while (Status != EFI_NOT_FOUND);\r
100\r
101 Status = GenMemoryTest->Finished (GenMemoryTest);\r
102\r
103 Print (L"\r%dM bytes of system memory tested OK\n", (UINT32) DivU64x32 (TotalMemorySize, 1024 * 1024));\r
104 return EFI_SUCCESS;\r
105}\r
106\r
107\r
123e9f62
RN
108/**\r
109 Return the index of the load option in the load option array.\r
110\r
111 The function consider two load options are equal when the \r
112 OptionType, Attributes, Description, FilePath and OptionalData are equal.\r
113\r
114 @param Key Pointer to the load option to be found.\r
115 @param Array Pointer to the array of load options to be found.\r
116 @param Count Number of entries in the Array.\r
117\r
118 @retval -1 Key wasn't found in the Array.\r
119 @retval 0 ~ Count-1 The index of the Key in the Array.\r
120**/\r
121INTN\r
122PlatformFindLoadOption (\r
123 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,\r
124 IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,\r
125 IN UINTN Count\r
126 )\r
127{\r
128 UINTN Index;\r
129\r
130 for (Index = 0; Index < Count; Index++) {\r
131 if ((Key->OptionType == Array[Index].OptionType) &&\r
132 (Key->Attributes == Array[Index].Attributes) &&\r
133 (StrCmp (Key->Description, Array[Index].Description) == 0) &&\r
134 (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&\r
135 (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&\r
136 (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {\r
137 return (INTN) Index;\r
138 }\r
139 }\r
140\r
141 return -1;\r
142}\r
143\r
144VOID\r
145PlatformRegisterFvBootOption (\r
146 EFI_GUID *FileGuid,\r
147 CHAR16 *Description,\r
148 UINT32 Attributes\r
149 )\r
150{\r
151 EFI_STATUS Status;\r
152 UINTN OptionIndex;\r
153 EFI_BOOT_MANAGER_LOAD_OPTION NewOption;\r
154 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
155 UINTN BootOptionCount;\r
156 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;\r
157 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
158 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
159\r
160 Status = gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);\r
161 ASSERT_EFI_ERROR (Status);\r
162\r
163 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);\r
164 DevicePath = AppendDevicePathNode (\r
165 DevicePathFromHandle (LoadedImage->DeviceHandle),\r
166 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
167 );\r
168\r
169 Status = EfiBootManagerInitializeLoadOption (\r
170 &NewOption,\r
171 LoadOptionNumberUnassigned,\r
172 LoadOptionTypeBoot,\r
173 Attributes,\r
174 Description,\r
175 DevicePath,\r
176 NULL,\r
177 0\r
178 );\r
179 if (!EFI_ERROR (Status)) {\r
180 BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
181\r
182 OptionIndex = PlatformFindLoadOption (&NewOption, BootOptions, BootOptionCount);\r
183\r
184 if (OptionIndex == -1) {\r
185 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN) -1);\r
186 ASSERT_EFI_ERROR (Status);\r
187 }\r
188 EfiBootManagerFreeLoadOption (&NewOption);\r
189 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
190 }\r
191}\r
192\r
193/**\r
194 Do the platform specific action before the console is connected.\r
195\r
196 Such as:\r
197 Update console variable;\r
198 Register new Driver#### or Boot####;\r
199 Signal ReadyToLock event.\r
200**/\r
201VOID\r
202EFIAPI\r
203PlatformBootManagerBeforeConsole (\r
204 VOID\r
205 )\r
206{\r
207 UINTN Index;\r
208 EFI_STATUS Status;\r
209 WIN_NT_SYSTEM_CONFIGURATION *Configuration;\r
210 EFI_INPUT_KEY Enter;\r
211 EFI_INPUT_KEY F2;\r
212 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
213\r
214 GetVariable2 (L"Setup", &gEfiWinNtSystemConfigGuid, (VOID **) &Configuration, NULL);\r
215 if (Configuration != NULL) {\r
216 //\r
217 // SetupVariable is corrupt\r
218 //\r
219 Configuration->ConOutRow = PcdGet32 (PcdConOutColumn);\r
220 Configuration->ConOutColumn = PcdGet32 (PcdConOutRow);\r
221\r
222 Status = gRT->SetVariable (\r
223 L"Setup",\r
224 &gEfiWinNtSystemConfigGuid,\r
225 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
226 sizeof (WIN_NT_SYSTEM_CONFIGURATION),\r
227 Configuration\r
228 );\r
229 if (EFI_ERROR (Status)) {\r
230 DEBUG ((EFI_D_ERROR, "Failed to save Setup Variable to non-volatile storage, Status = %r\n", Status));\r
231 }\r
232 FreePool (Configuration);\r
233 }\r
234\r
235 //\r
236 // Update the ocnsole variables.\r
237 //\r
238 for (Index = 0; gPlatformConsole[Index].DevicePath != NULL; Index++) {\r
239 if ((gPlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {\r
240 EfiBootManagerUpdateConsoleVariable (ConIn, gPlatformConsole[Index].DevicePath, NULL);\r
241 }\r
242\r
243 if ((gPlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r
244 EfiBootManagerUpdateConsoleVariable (ConOut, gPlatformConsole[Index].DevicePath, NULL);\r
245 }\r
246\r
247 if ((gPlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r
248 EfiBootManagerUpdateConsoleVariable (ErrOut, gPlatformConsole[Index].DevicePath, NULL);\r
249 }\r
250 }\r
251\r
252 //\r
253 // Register ENTER as CONTINUE key\r
254 //\r
255 Enter.ScanCode = SCAN_NULL;\r
256 Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
257 EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);\r
258 //\r
259 // Map F2 to Boot Manager Menu\r
260 //\r
261 F2.ScanCode = SCAN_F2;\r
262 F2.UnicodeChar = CHAR_NULL;\r
263 EfiBootManagerGetBootManagerMenu (&BootOption);\r
264 EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL);\r
265 //\r
266 // Register UEFI Shell\r
267 //\r
268 PlatformRegisterFvBootOption (&mUefiShellFileGuid, L"UEFI Shell", LOAD_OPTION_ACTIVE);\r
269}\r
270\r
271/**\r
272 Do the platform specific action after the console is connected.\r
273\r
274 Such as:\r
275 Dynamically switch output mode;\r
276 Signal console ready platform customized event;\r
277 Run diagnostics like memory testing;\r
278 Connect certain devices;\r
279 Dispatch aditional option roms.\r
280**/\r
281VOID\r
282EFIAPI\r
283PlatformBootManagerAfterConsole (\r
284 VOID\r
285 )\r
286{\r
8f227c2f 287 PlatformBootManagerMemoryTest (QUICK);\r
99eda885
ED
288 EfiBootManagerConnectAll ();\r
289 EfiBootManagerRefreshAllBootOption ();\r
123e9f62
RN
290 Print (\r
291 L"\n"\r
292 L"F2 to enter Boot Manager Menu.\n"\r
293 L"Enter to boot directly.\n"\r
294 L"\n"\r
295 );\r
296}\r
297\r
298/**\r
299 This function is called each second during the boot manager waits the timeout.\r
300\r
301 @param TimeoutRemain The remaining timeout.\r
302**/\r
303VOID\r
304EFIAPI\r
305PlatformBootManagerWaitCallback (\r
306 UINT16 TimeoutRemain\r
307 )\r
308{\r
309 Print (L"\r%-2d seconds remained...", TimeoutRemain);\r
310}\r