X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ArmPlatformPkg%2FBds%2FBds.c;h=1fab43976f29c0940be607acd85db3a776b99f40;hb=b51cffe12fbea45a1112bffea40a63efc7e79982;hp=11a76de90f139092d4ba046b34858c832b43e937;hpb=b34e4db38206407f13442b5f61cead6ce0d3c99c;p=mirror_edk2.git diff --git a/ArmPlatformPkg/Bds/Bds.c b/ArmPlatformPkg/Bds/Bds.c index 11a76de90f..1fab43976f 100644 --- a/ArmPlatformPkg/Bds/Bds.c +++ b/ArmPlatformPkg/Bds/Bds.c @@ -1,14 +1,14 @@ /** @file * -* Copyright (c) 2011-2012, ARM Limited. All rights reserved. -* -* This program and the accompanying materials -* are licensed and made available under the terms and conditions of the BSD License -* which accompanies this distribution. The full text of the license may be found at -* http://opensource.org/licenses/bsd-license.php +* Copyright (c) 2011-2015, ARM Limited. All rights reserved. * -* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. * **/ @@ -19,9 +19,9 @@ #include -#define EFI_SET_TIMER_TO_SECOND 10000000 +#include -EFI_HANDLE mImageHandle; +#define EFI_SET_TIMER_TO_SECOND 10000000 STATIC EFI_STATUS @@ -39,7 +39,7 @@ GetConsoleDevicePathFromVariable ( CHAR16* NextDevicePathStr; EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; - Status = GetEnvironmentVariable (ConsoleVarName, NULL, NULL, (VOID**)&DevicePathInstances); + Status = GetGlobalEnvironmentVariable (ConsoleVarName, NULL, NULL, (VOID**)&DevicePathInstances); if (EFI_ERROR(Status)) { // In case no default console device path has been defined we assume a driver handles the console (eg: SimpleTextInOutSerial) if ((DefaultConsolePaths == NULL) || (DefaultConsolePaths[0] == L'\0')) { @@ -124,7 +124,7 @@ InitializeConsolePipe ( EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; CHAR16* DevicePathTxt; EFI_STATUS Status; - + Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); if (!EFI_ERROR(Status)) { DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (DevicePath, TRUE, TRUE); @@ -155,8 +155,8 @@ InitializeConsolePipe ( *Handle = Buffer[0]; Status = gBS->HandleProtocol (*Handle, Protocol, Interface); ASSERT_EFI_ERROR(Status); + FreePool (Buffer); } - FreePool (Buffer); } else { Status = EFI_SUCCESS; } @@ -220,11 +220,16 @@ DefineDefaultBootEntries ( EFI_STATUS Status; EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol; EFI_DEVICE_PATH* BootDevicePath; + UINT8* OptionalData; + UINTN OptionalDataSize; ARM_BDS_LOADER_ARGUMENTS* BootArguments; ARM_BDS_LOADER_TYPE BootType; EFI_DEVICE_PATH* InitrdPath; - UINTN CmdLineSize; UINTN InitrdSize; + UINTN CmdLineSize; + UINTN CmdLineAsciiSize; + CHAR16* DefaultBootArgument; + CHAR8* AsciiDefaultBootArgument; // // If Boot Order does not exist then create a default entry @@ -253,7 +258,11 @@ DefineDefaultBootEntries ( ASSERT_EFI_ERROR(Status); DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (BootDevicePath, TRUE, TRUE); - ASSERT (StrCmp ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath), DevicePathTxt) == 0); + if (StrCmp ((CHAR16*)PcdGetPtr (PcdDefaultBootDevicePath), DevicePathTxt) != 0) { + DEBUG ((EFI_D_ERROR, "Device Path given: '%s' Device Path expected: '%s'\n", + (CHAR16*)PcdGetPtr (PcdDefaultBootDevicePath), DevicePathTxt)); + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + } FreePool (DevicePathTxt); DEBUG_CODE_END(); @@ -262,35 +271,85 @@ DefineDefaultBootEntries ( if (BootDevicePath != NULL) { BootType = (ARM_BDS_LOADER_TYPE)PcdGet32 (PcdDefaultBootType); + // We do not support NULL pointer + ASSERT (PcdGetPtr (PcdDefaultBootArgument) != NULL); + + // + // Logic to handle ASCII or Unicode default parameters + // + if (*(CHAR8*)PcdGetPtr (PcdDefaultBootArgument) == '\0') { + CmdLineSize = 0; + CmdLineAsciiSize = 0; + DefaultBootArgument = NULL; + AsciiDefaultBootArgument = NULL; + } else if (IsUnicodeString ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument))) { + // The command line is a Unicode string + DefaultBootArgument = (CHAR16*)PcdGetPtr (PcdDefaultBootArgument); + CmdLineSize = StrSize (DefaultBootArgument); + + // Initialize ASCII variables + CmdLineAsciiSize = CmdLineSize / 2; + AsciiDefaultBootArgument = AllocatePool (CmdLineAsciiSize); + if (AsciiDefaultBootArgument == NULL) { + return EFI_OUT_OF_RESOURCES; + } + UnicodeStrToAsciiStr ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument), AsciiDefaultBootArgument); + } else { + // The command line is a ASCII string + AsciiDefaultBootArgument = (CHAR8*)PcdGetPtr (PcdDefaultBootArgument); + CmdLineAsciiSize = AsciiStrSize (AsciiDefaultBootArgument); + + // Initialize ASCII variables + CmdLineSize = CmdLineAsciiSize * 2; + DefaultBootArgument = AllocatePool (CmdLineSize); + if (DefaultBootArgument == NULL) { + return EFI_OUT_OF_RESOURCES; + } + AsciiStrToUnicodeStr (AsciiDefaultBootArgument, DefaultBootArgument); + } + if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { - CmdLineSize = AsciiStrSize ((CHAR8*)PcdGetPtr(PcdDefaultBootArgument)); InitrdPath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultBootInitrdPath)); InitrdSize = GetDevicePathSize (InitrdPath); - BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize); - BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; + OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineAsciiSize + InitrdSize; + BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize); + if (BootArguments == NULL) { + return EFI_OUT_OF_RESOURCES; + } + BootArguments->LinuxArguments.CmdLineSize = CmdLineAsciiSize; BootArguments->LinuxArguments.InitrdSize = InitrdSize; - CopyMem ((VOID*)(BootArguments + 1), (CHAR8*)PcdGetPtr(PcdDefaultBootArgument), CmdLineSize); - CopyMem ((VOID*)((UINTN)(BootArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); + CopyMem ((VOID*)(BootArguments + 1), AsciiDefaultBootArgument, CmdLineAsciiSize); + CopyMem ((VOID*)((UINTN)(BootArguments + 1) + CmdLineAsciiSize), InitrdPath, InitrdSize); + + OptionalData = (UINT8*)BootArguments; } else { - BootArguments = NULL; + OptionalData = (UINT8*)DefaultBootArgument; + OptionalDataSize = CmdLineSize; } BootOptionCreate (LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT, (CHAR16*)PcdGetPtr(PcdDefaultBootDescription), BootDevicePath, BootType, - BootArguments, + OptionalData, + OptionalDataSize, &BdsLoadOption ); FreePool (BdsLoadOption); + + if (DefaultBootArgument == (CHAR16*)PcdGetPtr (PcdDefaultBootArgument)) { + FreePool (AsciiDefaultBootArgument); + } else if (DefaultBootArgument != NULL) { + FreePool (DefaultBootArgument); + } } else { Status = EFI_UNSUPPORTED; } } - return EFI_SUCCESS; + return Status; } EFI_STATUS @@ -312,8 +371,11 @@ StartDefaultBootOnTimeout ( Size = sizeof(UINT16); Timeout = (UINT16)PcdGet16 (PcdPlatformBootTimeOut); - TimeoutPtr = &Timeout; - GetEnvironmentVariable (L"Timeout", &Timeout, &Size, (VOID**)&TimeoutPtr); + Status = GetGlobalEnvironmentVariable (L"Timeout", &Timeout, &Size, (VOID**)&TimeoutPtr); + if (!EFI_ERROR (Status)) { + Timeout = *TimeoutPtr; + FreePool (TimeoutPtr); + } if (Timeout != 0xFFFF) { if (Timeout > 0) { @@ -335,7 +397,7 @@ StartDefaultBootOnTimeout ( } // Discard key in the buffer do { - Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); } while(!EFI_ERROR(Status)); gBS->CloseEvent (WaitList[0]); Print(L"\n\r"); @@ -344,14 +406,14 @@ StartDefaultBootOnTimeout ( // In case of Timeout we start the default boot selection if (Timeout == 0) { // Get the Boot Option Order from the environment variable (a default value should have been created) - GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder); + GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder); for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BootOrder[Index]); Status = BdsStartBootOption (BootVariableName); if(!EFI_ERROR(Status)){ - // Boot option returned successfully, hence don't need to start next boot option - break; + // Boot option returned successfully, hence don't need to start next boot option + break; } // In case of success, we should not return from this call. } @@ -362,19 +424,37 @@ StartDefaultBootOnTimeout ( } /** - This function uses policy data from the platform to determine what operating - system or system utility should be loaded and invoked. This function call - also optionally make the use of user input to determine the operating system - or system utility to be loaded and invoked. When the DXE Core has dispatched - all the drivers on the dispatch queue, this function is called. This - function will attempt to connect the boot devices required to load and invoke - the selected operating system or system utility. During this process, - additional firmware volumes may be discovered that may contain addition DXE - drivers that can be dispatched by the DXE Core. If a boot device cannot be - fully connected, this function calls the DXE Service Dispatch() to allow the - DXE drivers from any newly discovered firmware volumes to be dispatched. - Then the boot device connection can be attempted again. If the same boot - device connection operation fails twice in a row, then that boot device has + An empty function to pass error checking of CreateEventEx (). + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context, + which is implementation-dependent. + +**/ +VOID +EFIAPI +EmptyCallbackFunction ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + return; +} + +/** + This function uses policy data from the platform to determine what operating + system or system utility should be loaded and invoked. This function call + also optionally make the use of user input to determine the operating system + or system utility to be loaded and invoked. When the DXE Core has dispatched + all the drivers on the dispatch queue, this function is called. This + function will attempt to connect the boot devices required to load and invoke + the selected operating system or system utility. During this process, + additional firmware volumes may be discovered that may contain addition DXE + drivers that can be dispatched by the DXE Core. If a boot device cannot be + fully connected, this function calls the DXE Service Dispatch() to allow the + DXE drivers from any newly discovered firmware volumes to be dispatched. + Then the boot device connection can be attempted again. If the same boot + device connection operation fails twice in a row, then that boot device has failed, and should be skipped. This function should never return. @param This The EFI_BDS_ARCH_PROTOCOL instance. @@ -393,6 +473,22 @@ BdsEntry ( UINT16 *BootNext; UINTN BootNextSize; CHAR16 BootVariableName[9]; + EFI_EVENT EndOfDxeEvent; + + // + // Signal EndOfDxe PI Event + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + EmptyCallbackFunction, + NULL, + &gEfiEndOfDxeEventGroupGuid, + &EndOfDxeEvent + ); + if (!EFI_ERROR (Status)) { + gBS->SignalEvent (EndOfDxeEvent); + } PERF_END (NULL, "DXE", NULL, 0); @@ -406,9 +502,16 @@ BdsEntry ( UnicodeSPrint (gST->FirmwareVendor, Size, L"%a EFI %a %a", PcdGetPtr(PcdFirmwareVendor), __DATE__, __TIME__); } + // + // Fixup Table CRC after we updated Firmware Vendor + // + gST->Hdr.CRC32 = 0; + Status = gBS->CalculateCrc32 ((VOID*)gST, gST->Hdr.HeaderSize, &gST->Hdr.CRC32); + ASSERT_EFI_ERROR (Status); + // If BootNext environment variable is defined then we just load it ! BootNextSize = sizeof(UINT16); - Status = GetEnvironmentVariable (L"BootNext", NULL, &BootNextSize, (VOID**)&BootNext); + Status = GetGlobalEnvironmentVariable (L"BootNext", NULL, &BootNextSize, (VOID**)&BootNext); if (!EFI_ERROR(Status)) { ASSERT(BootNextSize == sizeof(UINT16)); @@ -448,6 +551,13 @@ BdsEntry ( // Now we need to setup the EFI System Table with information about the console devices. InitializeConsole (); + // + // Update the CRC32 in the EFI System Table header + // + gST->Hdr.CRC32 = 0; + Status = gBS->CalculateCrc32 ((VOID*)gST, gST->Hdr.HeaderSize, &gST->Hdr.CRC32); + ASSERT_EFI_ERROR (Status); + // Timer before initiating the default boot selection StartDefaultBootOnTimeout (); @@ -470,8 +580,6 @@ BdsInitialize ( { EFI_STATUS Status; - mImageHandle = ImageHandle; - Status = gBS->InstallMultipleProtocolInterfaces ( &ImageHandle, &gEfiBdsArchProtocolGuid, &gBdsProtocol,