ceb4f076e2a6fcf6d9baabdba2247bdc01760381
[mirror_edk2.git] / ArmPlatformPkg / Library / PlatformIntelBdsLib / IntelBdsPlatform.c
1 /** @file
2
3 Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
4 Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "IntelBdsPlatform.h"
17
18 ///
19 /// Predefined platform default time out value
20 ///
21 UINT16 gPlatformBootTimeOutDefault;
22
23 EFI_STATUS
24 EFIAPI
25 PlatformIntelBdsConstructor (
26 IN EFI_HANDLE ImageHandle,
27 IN EFI_SYSTEM_TABLE *SystemTable
28 )
29 {
30 gPlatformBootTimeOutDefault = (UINT16)PcdGet16 (PcdPlatformBootTimeOut);
31 return EFI_SUCCESS;
32 }
33
34 /**
35 An empty function to pass error checking of CreateEventEx ().
36
37 @param Event Event whose notification function is being invoked.
38 @param Context Pointer to the notification function's context,
39 which is implementation-dependent.
40
41 **/
42 STATIC
43 VOID
44 EFIAPI
45 EmptyCallbackFunction (
46 IN EFI_EVENT Event,
47 IN VOID *Context
48 )
49 {
50 }
51
52 //
53 // BDS Platform Functions
54 //
55 /**
56 Platform Bds init. Include the platform firmware vendor, revision
57 and so crc check.
58
59 **/
60 VOID
61 EFIAPI
62 PlatformBdsInit (
63 VOID
64 )
65 {
66 EFI_EVENT EndOfDxeEvent;
67 EFI_STATUS Status;
68
69 //
70 // Signal EndOfDxe PI Event
71 //
72 Status = gBS->CreateEventEx (
73 EVT_NOTIFY_SIGNAL,
74 TPL_CALLBACK,
75 EmptyCallbackFunction,
76 NULL,
77 &gEfiEndOfDxeEventGroupGuid,
78 &EndOfDxeEvent
79 );
80 if (!EFI_ERROR (Status)) {
81 gBS->SignalEvent (EndOfDxeEvent);
82 gBS->CloseEvent (EndOfDxeEvent);
83 }
84 }
85
86 STATIC
87 EFI_STATUS
88 GetConsoleDevicePathFromVariable (
89 IN CHAR16* ConsoleVarName,
90 IN CHAR16* DefaultConsolePaths,
91 OUT EFI_DEVICE_PATH** DevicePaths
92 )
93 {
94 EFI_STATUS Status;
95 UINTN Size;
96 EFI_DEVICE_PATH_PROTOCOL* DevicePathInstances;
97 EFI_DEVICE_PATH_PROTOCOL* DevicePathInstance;
98 CHAR16* DevicePathStr;
99 CHAR16* NextDevicePathStr;
100 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;
101
102 Status = EFI_SUCCESS;
103 Size = 0;
104
105 DevicePathInstances = BdsLibGetVariableAndSize (ConsoleVarName, &gEfiGlobalVariableGuid, &Size);
106 if (DevicePathInstances == NULL) {
107 // In case no default console device path has been defined we assume a driver handles the console (eg: SimpleTextInOutSerial)
108 if ((DefaultConsolePaths == NULL) || (DefaultConsolePaths[0] == L'\0')) {
109 *DevicePaths = NULL;
110 return EFI_SUCCESS;
111 }
112
113 Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
114 ASSERT_EFI_ERROR(Status);
115
116 // Extract the Device Path instances from the multi-device path string
117 while ((DefaultConsolePaths != NULL) && (DefaultConsolePaths[0] != L'\0')) {
118 NextDevicePathStr = StrStr (DefaultConsolePaths, L";");
119 if (NextDevicePathStr == NULL) {
120 DevicePathStr = DefaultConsolePaths;
121 DefaultConsolePaths = NULL;
122 } else {
123 DevicePathStr = (CHAR16*)AllocateCopyPool ((NextDevicePathStr - DefaultConsolePaths + 1) * sizeof(CHAR16), DefaultConsolePaths);
124 *(DevicePathStr + (NextDevicePathStr - DefaultConsolePaths)) = L'\0';
125 DefaultConsolePaths = NextDevicePathStr;
126 if (DefaultConsolePaths[0] == L';') {
127 DefaultConsolePaths++;
128 }
129 }
130
131 DevicePathInstance = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (DevicePathStr);
132 ASSERT(DevicePathInstance != NULL);
133 DevicePathInstances = AppendDevicePathInstance (DevicePathInstances, DevicePathInstance);
134
135 if (NextDevicePathStr != NULL) {
136 FreePool (DevicePathStr);
137 }
138 FreePool (DevicePathInstance);
139 }
140
141 // Set the environment variable with this device path multi-instances
142 Size = GetDevicePathSize (DevicePathInstances);
143 if (Size > 0) {
144 gRT->SetVariable (
145 ConsoleVarName,
146 &gEfiGlobalVariableGuid,
147 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
148 Size,
149 DevicePathInstances
150 );
151 } else {
152 Status = EFI_INVALID_PARAMETER;
153 }
154 }
155
156 if (!EFI_ERROR(Status)) {
157 *DevicePaths = DevicePathInstances;
158 }
159 return Status;
160 }
161
162 STATIC
163 EFI_STATUS
164 InitializeConsolePipe (
165 IN EFI_DEVICE_PATH *ConsoleDevicePaths,
166 IN EFI_GUID *Protocol,
167 OUT EFI_HANDLE *Handle,
168 OUT VOID* *Interface
169 )
170 {
171 EFI_STATUS Status;
172 UINTN Size;
173 UINTN NoHandles;
174 EFI_HANDLE *Buffer;
175 EFI_DEVICE_PATH_PROTOCOL* DevicePath;
176
177 // Connect all the Device Path Consoles
178 while (ConsoleDevicePaths != NULL) {
179 DevicePath = GetNextDevicePathInstance (&ConsoleDevicePaths, &Size);
180
181 Status = BdsLibConnectDevicePath (DevicePath);
182 if (!EFI_ERROR (Status)) {
183 //
184 // If BdsLibConnectDevicePath () succeeded, *Handle must have a non-NULL
185 // value. So ASSERT that this is the case.
186 //
187 gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, Handle);
188 ASSERT (*Handle != NULL);
189 }
190 DEBUG_CODE_BEGIN();
191 if (EFI_ERROR(Status)) {
192 // We convert back to the text representation of the device Path
193 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathToTextProtocol;
194 CHAR16 *DevicePathTxt;
195
196 DevicePathToTextProtocol = NULL;
197 gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **) &DevicePathToTextProtocol);
198 if (DevicePathToTextProtocol != NULL) {
199 DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (DevicePath, TRUE, TRUE);
200
201 DEBUG((EFI_D_ERROR,"Fail to start the console with the Device Path '%s'. (Error '%r')\n", DevicePathTxt, Status));
202
203 FreePool (DevicePathTxt);
204 }
205 }
206 DEBUG_CODE_END();
207
208 // If the console splitter driver is not supported by the platform then use the first Device Path
209 // instance for the console interface.
210 if (!EFI_ERROR(Status) && (*Interface == NULL)) {
211 Status = gBS->HandleProtocol (*Handle, Protocol, Interface);
212 }
213 }
214
215 // No Device Path has been defined for this console interface. We take the first protocol implementation
216 if (*Interface == NULL) {
217 Status = gBS->LocateHandleBuffer (ByProtocol, Protocol, NULL, &NoHandles, &Buffer);
218 if (EFI_ERROR (Status)) {
219 BdsLibConnectAll ();
220 Status = gBS->LocateHandleBuffer (ByProtocol, Protocol, NULL, &NoHandles, &Buffer);
221 }
222
223 if (!EFI_ERROR(Status)) {
224 *Handle = Buffer[0];
225 Status = gBS->HandleProtocol (*Handle, Protocol, Interface);
226 ASSERT_EFI_ERROR (Status);
227 FreePool (Buffer);
228 }
229 } else {
230 Status = EFI_SUCCESS;
231 }
232
233 return Status;
234 }
235
236 /**
237 Connect the predefined platform default console device. Always try to find
238 and enable the vga device if have.
239
240 @param PlatformConsole Predefined platform default console device array.
241
242 @retval EFI_SUCCESS Success connect at least one ConIn and ConOut
243 device, there must have one ConOut device is
244 active vga device.
245 @return Return the status of BdsLibConnectAllDefaultConsoles ()
246
247 **/
248 EFI_STATUS
249 PlatformBdsConnectConsole (
250 VOID
251 )
252 {
253 EFI_STATUS Status;
254 EFI_DEVICE_PATH* ConOutDevicePaths;
255 EFI_DEVICE_PATH* ConInDevicePaths;
256 EFI_DEVICE_PATH* ConErrDevicePaths;
257
258 // By getting the Console Device Paths from the environment variables before initializing the console pipe, we
259 // create the 3 environment variables (ConIn, ConOut, ConErr) that allows to initialize all the console interface
260 // of newly installed console drivers
261 Status = GetConsoleDevicePathFromVariable (L"ConOut", (CHAR16*)PcdGetPtr(PcdDefaultConOutPaths), &ConOutDevicePaths);
262 ASSERT_EFI_ERROR (Status);
263 Status = GetConsoleDevicePathFromVariable (L"ConIn", (CHAR16*)PcdGetPtr(PcdDefaultConInPaths), &ConInDevicePaths);
264 ASSERT_EFI_ERROR (Status);
265 Status = GetConsoleDevicePathFromVariable (L"ErrOut", (CHAR16*)PcdGetPtr(PcdDefaultConOutPaths), &ConErrDevicePaths);
266 ASSERT_EFI_ERROR (Status);
267
268 // Initialize the Consoles
269 Status = InitializeConsolePipe (ConOutDevicePaths, &gEfiSimpleTextOutProtocolGuid, &gST->ConsoleOutHandle, (VOID **)&gST->ConOut);
270 ASSERT_EFI_ERROR (Status);
271 Status = InitializeConsolePipe (ConInDevicePaths, &gEfiSimpleTextInProtocolGuid, &gST->ConsoleInHandle, (VOID **)&gST->ConIn);
272 ASSERT_EFI_ERROR (Status);
273 Status = InitializeConsolePipe (ConErrDevicePaths, &gEfiSimpleTextOutProtocolGuid, &gST->StandardErrorHandle, (VOID **)&gST->StdErr);
274 if (EFI_ERROR(Status)) {
275 // In case of error, we reuse the console output for the error output
276 gST->StandardErrorHandle = gST->ConsoleOutHandle;
277 gST->StdErr = gST->ConOut;
278 }
279
280 return Status;
281 }
282
283 /**
284 Connect with predefined platform connect sequence,
285 the OEM/IBV can customize with their own connect sequence.
286 **/
287 VOID
288 PlatformBdsConnectSequence (
289 VOID
290 )
291 {
292 }
293
294 /**
295 Load the predefined driver option, OEM/IBV can customize this
296 to load their own drivers
297
298 @param BdsDriverLists - The header of the driver option link list.
299
300 **/
301 VOID
302 PlatformBdsGetDriverOption (
303 IN OUT LIST_ENTRY *BdsDriverLists
304 )
305 {
306 }
307
308 /**
309 Perform the platform diagnostic, such like test memory. OEM/IBV also
310 can customize this function to support specific platform diagnostic.
311
312 @param MemoryTestLevel The memory test intensive level
313 @param QuietBoot Indicate if need to enable the quiet boot
314 @param BaseMemoryTest A pointer to BdsMemoryTest()
315
316 **/
317 VOID
318 PlatformBdsDiagnostics (
319 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
320 IN BOOLEAN QuietBoot,
321 IN BASEM_MEMORY_TEST BaseMemoryTest
322 )
323 {
324 }
325
326 /**
327 The function will execute with as the platform policy, current policy
328 is driven by boot mode. IBV/OEM can customize this code for their specific
329 policy action.
330
331 @param DriverOptionList The header of the driver option link list
332 @param BootOptionList The header of the boot option link list
333 @param ProcessCapsules A pointer to ProcessCapsules()
334 @param BaseMemoryTest A pointer to BaseMemoryTest()
335
336 **/
337 VOID
338 EFIAPI
339 PlatformBdsPolicyBehavior (
340 IN LIST_ENTRY *DriverOptionList,
341 IN LIST_ENTRY *BootOptionList,
342 IN PROCESS_CAPSULES ProcessCapsules,
343 IN BASEM_MEMORY_TEST BaseMemoryTest
344 )
345 {
346 EFI_STATUS Status;
347
348 Status = PlatformBdsConnectConsole ();
349 ASSERT_EFI_ERROR (Status);
350
351 //
352 // Show the splash screen.
353 //
354 EnableQuietBoot (PcdGetPtr (PcdLogoFile));
355
356 //
357 // Connect _all_ devices, to pick up plug-in and removable devices
358 // TODO: do this more cleanly, permitting faster boot times when boot config
359 // is known
360 //
361 BdsLibConnectAll ();
362 }
363
364 /**
365 Hook point after a boot attempt succeeds. We don't expect a boot option to
366 return, so the UEFI 2.0 specification defines that you will default to an
367 interactive mode and stop processing the BootOrder list in this case. This
368 is also a platform implementation and can be customized by IBV/OEM.
369
370 @param Option Pointer to Boot Option that succeeded to boot.
371
372 **/
373 VOID
374 EFIAPI
375 PlatformBdsBootSuccess (
376 IN BDS_COMMON_OPTION *Option
377 )
378 {
379 }
380
381 /**
382 Hook point after a boot attempt fails.
383
384 @param Option Pointer to Boot Option that failed to boot.
385 @param Status Status returned from failed boot.
386 @param ExitData Exit data returned from failed boot.
387 @param ExitDataSize Exit data size returned from failed boot.
388
389 **/
390 VOID
391 EFIAPI
392 PlatformBdsBootFail (
393 IN BDS_COMMON_OPTION *Option,
394 IN EFI_STATUS Status,
395 IN CHAR16 *ExitData,
396 IN UINTN ExitDataSize
397 )
398 {
399 }
400
401 /**
402 This function locks platform flash that is not allowed to be updated during normal boot path.
403 The flash layout is platform specific.
404 **/
405 VOID
406 EFIAPI
407 PlatformBdsLockNonUpdatableFlash (
408 VOID
409 )
410 {
411 return;
412 }
413
414
415 /**
416 Lock the ConsoleIn device in system table. All key
417 presses will be ignored until the Password is typed in. The only way to
418 disable the password is to type it in to a ConIn device.
419
420 @param Password Password used to lock ConIn device.
421
422 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
423 @retval EFI_UNSUPPORTED Password not found
424
425 **/
426 EFI_STATUS
427 EFIAPI
428 LockKeyboards (
429 IN CHAR16 *Password
430 )
431 {
432 return EFI_UNSUPPORTED;
433 }