X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ArmPlatformPkg%2FBds%2FBootMenu.c;h=a304cc4ce916f39dbe060095d3f5cec06f12013d;hb=0c72676d371f8a2988f1fae958da696444e70672;hp=b96a1c3f923cc30a69e82974a0e44b526f7af839;hpb=019680b3dcde5e1c88034e0bf92ffce509f211be;p=mirror_edk2.git diff --git a/ArmPlatformPkg/Bds/BootMenu.c b/ArmPlatformPkg/Bds/BootMenu.c index b96a1c3f92..a304cc4ce9 100644 --- a/ArmPlatformPkg/Bds/BootMenu.c +++ b/ArmPlatformPkg/Bds/BootMenu.c @@ -1,6 +1,6 @@ /** @file * -* Copyright (c) 2011 - 2014, ARM Limited. All rights reserved. +* Copyright (c) 2011 - 2015, 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 @@ -16,8 +16,7 @@ #include -extern EFI_HANDLE mImageHandle; -extern BDS_LOAD_OPTION_SUPPORT *BdsLoadOptionSupportList; +#include /** Worker function that displays the list of boot options that is passed in. @@ -342,6 +341,9 @@ BootMenuAddBootOption ( if (InitrdPathNodes != NULL) { // Append the Device Path to the selected device path InitrdPath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes); + // Free the InitrdPathNodes created by Support->CreateDevicePathNode() + FreePool (InitrdPathNodes); + if (InitrdPath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto EXIT; @@ -541,6 +543,8 @@ BootMenuUpdateBootOption ( // Append the Device Path to the selected device path InitrdPath = AppendDevicePath (TempInitrdPath, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes); FreePool (TempInitrdPath); + // Free the InitrdPathNodes created by Support->CreateDevicePathNode() + FreePool (InitrdPathNodes); if (InitrdPath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto EXIT; @@ -556,7 +560,8 @@ BootMenuUpdateBootOption ( Print(L"Arguments to pass to the binary: "); if (CmdLineSize > 0) { - AsciiStrnCpy(CmdLine, (CONST CHAR8*)(LinuxArguments + 1), CmdLineSize); + AsciiStrnCpy (CmdLine, (CONST CHAR8*)(LinuxArguments + 1), sizeof (CmdLine)); + CmdLine[sizeof (CmdLine) - 1] = '\0'; } else { CmdLine[0] = '\0'; } @@ -582,10 +587,29 @@ BootMenuUpdateBootOption ( if (BootOption->OptionalDataSize > 0) { IsPrintable = IsPrintableString (BootOption->OptionalData, &IsUnicode); if (IsPrintable) { + // + // The size in bytes of the string, final zero included, should + // be equal to or at least lower than "BootOption->OptionalDataSize" + // and the "IsPrintableString()" has already tested that the length + // in number of characters is smaller than BOOT_DEVICE_OPTION_MAX, + // final '\0' included. We can thus copy the string for editing + // using "CopyMem()". Furthermore, note that in the case of an Unicode + // string "StrnCpy()" and "StrCpy()" can not be used to copy the + // string because the data pointed to by "BootOption->OptionalData" + // is not necessarily 2-byte aligned. + // if (IsUnicode) { - StrnCpy (UnicodeCmdLine, BootOption->OptionalData, BootOption->OptionalDataSize / 2); + CopyMem ( + UnicodeCmdLine, BootOption->OptionalData, + MIN (sizeof (UnicodeCmdLine), + BootOption->OptionalDataSize) + ); } else { - AsciiStrnCpy (CmdLine, BootOption->OptionalData, BootOption->OptionalDataSize); + CopyMem ( + CmdLine, BootOption->OptionalData, + MIN (sizeof (CmdLine), + BootOption->OptionalDataSize) + ); } } } else { @@ -692,6 +716,7 @@ BootMenuReorderBootOptions ( } SelectedEntry = &BootOptionEntry->Link; + SecondEntry = NULL; // Note down the previous entry in the list to be able to cancel changes PrevEntry = GetPreviousNode (BootOptionsList, SelectedEntry); @@ -740,7 +765,9 @@ BootMenuReorderBootOptions ( } while ((!Move) && (!Save) && (!Cancel)); if (Move) { - SwapListEntries (SelectedEntry, SecondEntry); + if ((SelectedEntry != NULL) && (SecondEntry != NULL)) { + SwapListEntries (SelectedEntry, SecondEntry); + } } else { if (Save) { Status = GetGlobalEnvironmentVariable ( @@ -803,52 +830,143 @@ UpdateFdtPath ( ) { EFI_STATUS Status; - UINTN FdtDevicePathSize; BDS_SUPPORTED_DEVICE *SupportedBootDevice; EFI_DEVICE_PATH_PROTOCOL *FdtDevicePathNodes; EFI_DEVICE_PATH_PROTOCOL *FdtDevicePath; + CHAR16 *FdtTextDevicePath; + EFI_PHYSICAL_ADDRESS FdtBlobBase; + UINTN FdtBlobSize; + UINTN NumPages; + EFI_PHYSICAL_ADDRESS FdtConfigurationTableBase; + + SupportedBootDevice = NULL; Status = SelectBootDevice (&SupportedBootDevice); - if (EFI_ERROR(Status)) { + if (EFI_ERROR (Status)) { Status = EFI_ABORTED; goto EXIT; } // Create the specific device path node Status = SupportedBootDevice->Support->CreateDevicePathNode (L"FDT blob", &FdtDevicePathNodes); - if (EFI_ERROR(Status)) { + if (EFI_ERROR (Status)) { Status = EFI_ABORTED; goto EXIT; } if (FdtDevicePathNodes != NULL) { - // Append the Device Path node to the select device path + Status = EFI_OUT_OF_RESOURCES; + FdtDevicePath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, FdtDevicePathNodes); - FdtDevicePathSize = GetDevicePathSize (FdtDevicePath); + FreePool (FdtDevicePathNodes); + if (FdtDevicePath == NULL) { + goto EXIT; + } + + FdtTextDevicePath = ConvertDevicePathToText (FdtDevicePath, TRUE, TRUE); + if (FdtTextDevicePath == NULL) { + goto EXIT; + } + Status = gRT->SetVariable ( (CHAR16*)L"Fdt", - &gArmGlobalVariableGuid, - EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, - FdtDevicePathSize, - FdtDevicePath + &gFdtVariableGuid, + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + StrSize (FdtTextDevicePath), + FdtTextDevicePath ); - ASSERT_EFI_ERROR(Status); + ASSERT_EFI_ERROR (Status); + FreePool (FdtTextDevicePath); } else { - gRT->SetVariable ( + Status = gRT->SetVariable ( (CHAR16*)L"Fdt", - &gArmGlobalVariableGuid, - EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + &gFdtVariableGuid, + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, 0, NULL ); - ASSERT_EFI_ERROR(Status); + ASSERT_EFI_ERROR (Status); + return Status; + } + + // + // Try to load FDT from the new EFI Device Path + // + + // + // Load the FDT given its device path. + // This operation may fail if the device path is not supported. + // + FdtBlobBase = 0; + NumPages = 0; + Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize); + FreePool (FdtDevicePath); + + if (EFI_ERROR (Status)) { + goto EXIT_LOAD_FDT; + } + + // Check the FDT header is valid. We only make this check in DEBUG mode in + // case the FDT header change on production device and this ASSERT() becomes + // not valid. + ASSERT (fdt_check_header ((VOID*)(UINTN)FdtBlobBase) == 0); + + // + // Ensure the Size of the Device Tree is smaller than the size of the read file + // + ASSERT ((UINTN)fdt_totalsize ((VOID*)(UINTN)FdtBlobBase) <= FdtBlobSize); + + // + // Store the FDT as Runtime Service Data to prevent the Kernel from + // overwritting its data. + // + NumPages = EFI_SIZE_TO_PAGES (FdtBlobSize); + Status = gBS->AllocatePages ( + AllocateAnyPages, EfiRuntimeServicesData, + NumPages, &FdtConfigurationTableBase + ); + if (EFI_ERROR (Status)) { + goto EXIT_LOAD_FDT; + } + gBS->CopyMem ( + (VOID*)(UINTN)FdtConfigurationTableBase, + (VOID*)(UINTN)FdtBlobBase, + FdtBlobSize + ); + + // + // Install the FDT into the Configuration Table + // + Status = gBS->InstallConfigurationTable ( + &gFdtTableGuid, + (VOID*)(UINTN)FdtConfigurationTableBase + ); + if (EFI_ERROR (Status)) { + gBS->FreePages (FdtConfigurationTableBase, NumPages); + } + +EXIT_LOAD_FDT: + if (EFI_ERROR (Status)) { + Print (L"\nWarning: Did not manage to install the new device tree. Try to restart the platform.\n"); + } + + if (FdtBlobBase != 0) { + gBS->FreePages (FdtBlobBase, NumPages); } EXIT: if (Status == EFI_ABORTED) { - Print(L"\n"); + Print (L"\n"); } - FreePool(SupportedBootDevice); + + if (SupportedBootDevice != NULL) { + FreePool (SupportedBootDevice); + } + return Status; } @@ -951,17 +1069,27 @@ BootShell ( IN LIST_ENTRY *BootOptionsList ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_DEVICE_PATH* EfiShellDevicePath; - // Start EFI Shell - Status = BdsLoadApplication (mImageHandle, L"Shell", 0, NULL); + // Find the EFI Shell + Status = LocateEfiApplicationInFvByName (L"Shell", &EfiShellDevicePath); if (Status == EFI_NOT_FOUND) { Print (L"Error: EFI Application not found.\n"); - } else if (EFI_ERROR(Status)) { - Print (L"Error: Status Code: 0x%X\n",(UINT32)Status); - } + return Status; + } else if (EFI_ERROR (Status)) { + Print (L"Error: Status Code: 0x%X\n", (UINT32)Status); + return Status; + } else { + // Need to connect every drivers to ensure no dependencies are missing for the application + Status = BdsConnectAllDrivers (); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n")); + return Status; + } - return Status; + return BdsStartEfiApplication (gImageHandle, EfiShellDevicePath, 0, NULL); + } } struct BOOT_MAIN_ENTRY {