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 } 434