From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4001:c0b::243; helo=mail-it0-x243.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-it0-x243.google.com (mail-it0-x243.google.com [IPv6:2607:f8b0:4001:c0b::243]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id D9EDC2234433C for ; Sat, 20 Jan 2018 03:05:52 -0800 (PST) Received: by mail-it0-x243.google.com with SMTP id x42so4937177ita.4 for ; Sat, 20 Jan 2018 03:11:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=49WDivxEbvurnYXH7d6P/KCXpyuVlpDh2ZyyZRUubsQ=; b=UEafGCogrLHw4UAtZq3sTfxFxGzfgIaYrDxen99xeYwmnbprE3WmZ1LWqKPc7FweNV 0fE+Zv3oBLiO3Z3VhXr+ZT7j9JIcXuQln7BaMH6ufxtKRazaDqQpMht7tazGjs+V1KqE jT/Kzo91iL3iZ70cH1OI/luasuxdUj2kVjkXo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=49WDivxEbvurnYXH7d6P/KCXpyuVlpDh2ZyyZRUubsQ=; b=kF//PHOofmlfEG1Wuq2IuGCjskf3ZhM7Q2lc1JZbMTIm9IXTvIlieV22wvGPfLFzlx MCn9QzsmCtrTjzKv83iSl7wI0BBCJRvHe8hXT/QklD3wm1ljcScoTmoNC0IwQcvzV7k4 Km7MvDtrWSy+32Al6GhtC4OcTrOhgWmHcDGQwWfxACDmImvB1igfK+3akBidA3x8P8sf fM2tAk3e7J6zo7DwtWAvQQnJ/+Vua70wzNMhu1OWLO54hruM3kxGN1zYIqBkYuK2A1l9 7juiOeewVzSgkKnBEcvDixlFonpgF+/27QOlFUKQLaDEMZaCQZ5435p9GskX7Sh4P01B TfVg== X-Gm-Message-State: AKwxyte+6FXGA1RbPrI5sIkYCvohI0+WvW25xdUaRd9+GLsArgElJAKA 0I1UR29Arw9iLQG7LFsPXd8NoWKTsTEYPkBEENAV1Muh X-Google-Smtp-Source: AH8x225gRuwGi7AF5S5NWp92K4xW+EsmWopDuGsNEHqECBXFeRcRcsvqVfGwJCgnvnJZqw19ewQvfglEuxJHTs5tUxM= X-Received: by 10.36.39.215 with SMTP id g206mr1211613ita.17.1516446675367; Sat, 20 Jan 2018 03:11:15 -0800 (PST) MIME-Version: 1.0 Received: by 10.107.112.13 with HTTP; Sat, 20 Jan 2018 03:11:14 -0800 (PST) In-Reply-To: <1516287703-35516-14-git-send-email-huangming23@huawei.com> References: <1516287703-35516-1-git-send-email-huangming23@huawei.com> <1516287703-35516-14-git-send-email-huangming23@huawei.com> From: Ard Biesheuvel Date: Sat, 20 Jan 2018 11:11:14 +0000 Message-ID: To: Ming Huang Cc: Leif Lindholm , linaro-uefi , "edk2-devel@lists.01.org" , Graeme Gregory , guoheyi@huawei.com, wanghuiqiang , huangming , Jason Zhang , Mengfanrong , waip23@126.com Subject: Re: [PATCH edk2-platforms v1 13/14] Hisilicon/Library: Add OsBootLib X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 20 Jan 2018 11:05:53 -0000 Content-Type: text/plain; charset="UTF-8" On 18 January 2018 at 15:01, Ming Huang wrote: > OsBootLib can create OS option after upgrade firmware. > Can you add a bit more explanation why you need this? > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Ming Huang > Signed-off-by: Heyi Guo > --- > Platform/Hisilicon/D03/D03.dsc | 1 + > Platform/Hisilicon/D05/D05.dsc | 1 + > Silicon/Hisilicon/Include/Library/OsBootLib.h | 47 ++ > Silicon/Hisilicon/Library/OsBootLib/OsBoot.h | 124 +++++ > Silicon/Hisilicon/Library/OsBootLib/OsBootLib.c | 217 +++++++++ > Silicon/Hisilicon/Library/OsBootLib/OsBootLib.inf | 59 +++ > Silicon/Hisilicon/Library/OsBootLib/OsBootLibMisc.c | 514 ++++++++++++++++++++ > Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c | 6 + > Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf | 1 + > 9 files changed, 970 insertions(+) > > diff --git a/Platform/Hisilicon/D03/D03.dsc b/Platform/Hisilicon/D03/D03.dsc > index 88c08dd..6f1164e 100644 > --- a/Platform/Hisilicon/D03/D03.dsc > +++ b/Platform/Hisilicon/D03/D03.dsc > @@ -47,6 +47,7 @@ > UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf > UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf > IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf > + OsBootLib|Silicon/Hisilicon/Library/OsBootLib/OsBootLib.inf > > > > diff --git a/Platform/Hisilicon/D05/D05.dsc b/Platform/Hisilicon/D05/D05.dsc > index 79890ef..52ffad5 100644 > --- a/Platform/Hisilicon/D05/D05.dsc > +++ b/Platform/Hisilicon/D05/D05.dsc > @@ -55,6 +55,7 @@ > FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf > BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf > SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf > + OsBootLib|Silicon/Hisilicon/Library/OsBootLib/OsBootLib.inf > > !if $(NETWORK_IP6_ENABLE) == TRUE > TcpIoLib|MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf > diff --git a/Silicon/Hisilicon/Include/Library/OsBootLib.h b/Silicon/Hisilicon/Include/Library/OsBootLib.h > new file mode 100644 > index 0000000..f5cbc4a > --- /dev/null > +++ b/Silicon/Hisilicon/Include/Library/OsBootLib.h > @@ -0,0 +1,47 @@ > +/** @file > +* > +* Copyright (c) 2017, Hisilicon Limited. All rights reserved. > +* Copyright (c) 2017, Linaro 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 > +* > +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +* > +**/ > + > +#ifndef _OS_BOOT_LIB_H_ > +#define _OS_BOOT_LIB_H_ > + > + > +/** > + Remove invalid OS boot options, and then add new ones. > + > +*/ > +EFI_STATUS > +AdjustOsBootOrder ( > + VOID > + ); > + > +/** > + Try to find UEFI OSs and create the boot options which haven't been listed in BootOrder. > + > +*/ > +EFI_STATUS > +CreateOsBootOptions ( > + VOID > + ); > + > +/** > + Remove UEFI OS boot options when it is disappeared in system. > + > +*/ > +EFI_STATUS > +RemoveInvalidOsBootOptions ( > + VOID > + ); > + > +#endif > diff --git a/Silicon/Hisilicon/Library/OsBootLib/OsBoot.h b/Silicon/Hisilicon/Library/OsBootLib/OsBoot.h > new file mode 100644 > index 0000000..1991471 > --- /dev/null > +++ b/Silicon/Hisilicon/Library/OsBootLib/OsBoot.h > @@ -0,0 +1,124 @@ > +/** @file > +* > +* Copyright (c) 2017, Hisilicon Limited. All rights reserved. > +* Copyright (c) 2017, Linaro 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 > +* > +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +* > +**/ > + > +#ifndef _OS_BOOT_H_ > +#define _OS_BOOT_H_ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > + > + > +typedef struct { > + CHAR16 *FilePathString; > + CHAR16 *Description; > + }UEFI_OS_BOOT_FILE; > + > +/** > + Check same boot option by device path. > + > +*/ > +BOOLEAN > +BeHaveSameBootOptionByDP ( > + EFI_DEVICE_PATH_PROTOCOL *DevicePath, > + CHAR16 *FileName > + ); > + > +/** > + Remove UEFI OS boot options when it is disappeared in system. > + > +*/ > +EFI_STATUS > +RemoveInvalidOsBootOptions ( > + VOID > + ); > + > + > +/** > + Check Os Boot Option if exist in current system. > + > +*/ > +BOOLEAN > +BeInvalidOsBootOption ( > + EFI_DEVICE_PATH_PROTOCOL *OptionDp > + ); > + > +/** > + Get the headers (dos, image, optional header) from an image > + > + @param Device SimpleFileSystem device handle > + @param FileName File name for the image > + @param DosHeader Pointer to dos header > + @param Hdr The buffer in which to return the PE32, PE32+, or TE header. > + > + @retval EFI_SUCCESS Successfully get the machine type. > + @retval EFI_NOT_FOUND The file is not found. > + @retval EFI_LOAD_ERROR File is not a valid image file. > + > +**/ > +EFI_STATUS > +EFIAPI > +OsBootGetImageHeader ( > + IN EFI_HANDLE Device, > + IN CHAR16 *FileName, > + OUT EFI_IMAGE_DOS_HEADER *DosHeader, > + OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr > + ); > + > +UINTN > +GetOptionPositionWithoutGpt ( > + VOID > + ); > + > +VOID > +PrintDevicePath ( > + CHAR16 *PreStr, > + EFI_DEVICE_PATH_PROTOCOL *Path > + ); > + > +VOID > +RemoveSuperfluousOption ( > + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions, > + UINT16 *OptionFlags, > + UINTN BootOptionCount > + ); > + > +BOOLEAN > +IsOptionAddedByOsBootLib ( > + UINT16 *OptionDescription > + ); > + > +#endif > diff --git a/Silicon/Hisilicon/Library/OsBootLib/OsBootLib.c b/Silicon/Hisilicon/Library/OsBootLib/OsBootLib.c > new file mode 100644 > index 0000000..29b6b62 > --- /dev/null > +++ b/Silicon/Hisilicon/Library/OsBootLib/OsBootLib.c > @@ -0,0 +1,217 @@ > +/** @file > +* > +* Copyright (c) 2017, Hisilicon Limited. All rights reserved. > +* Copyright (c) 2017, Linaro 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 > +* > +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +* > +**/ > + > +#include "OsBoot.h" > + > +UEFI_OS_BOOT_FILE mUefiOsBootFiles[] = { > + {EFI_REMOVABLE_MEDIA_FILE_NAME_AARCH64, L"Uefi Default Boot"}, > + {L"\\BOOT\\EFI\\EFI\\CENTOS\\grubaa64.efi", L"Uefi CENTOS Boot"}, > + {L"\\EFI\\centos\\grubaa64.efi", L"Uefi CentOS Grub Boot"}, > + {L"\\EFI\\debian\\grubaa64.efi", L"Uefi Debian Grub Boot"}, > + {L"\\EFI\\GRUB2\\GRUBAA64.EFI", L"Hisilicon Linux Boot"}, > + {L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", L"Uefi Windows Boot"}, > + {L"\\EFI\\redhat\\grub.efi", L"Uefi Redhat Boot"}, > + {L"\\EFI\\SuSE\\elilo.efi", L"Uefi SuSE Boot"}, > + {L"\\EFI\\ubuntu\\grubaa64.efi", L"Uefi Ubuntu Grub Boot"}, > + {L"\\EFI\\ubuntu\\shimx64.efi", L"Uefi Ubuntu Shimx64 Boot"}, > + {L"\\EFI\\ubuntu\\grubx64.efi", L"Uefi Ubuntu Grubx64 Boot"}, > + {L"\\EFI\\ubuntu\\shim.efi", L"Uefi Ubuntu Shim Boot"}, > + {L"\\EFI\\ubuntu\\grub.efi", L"Uefi Ubuntu Grub Boot"}, > + {L"\\EFI\\fedora\\shim.efi", L"Uefi Fedora Shim Boot"} > +}; > + > +BOOLEAN > +IsOptionAddedByOsBootLib ( > + UINT16 *OptionDescription > + ) > +{ > + UINTN Index; > + > + for (Index = 0; Index < (sizeof (mUefiOsBootFiles) / sizeof (UEFI_OS_BOOT_FILE)); Index++) { > + if (StrCmp (mUefiOsBootFiles[Index].Description, OptionDescription) == 0) { > + return TRUE; > + } > + } > + > + return FALSE; > +} > + > +/** > + Remove invalid OS boot options, and then add new ones. > + > +*/ > +EFI_STATUS > +AdjustOsBootOrder ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + > + Status = RemoveInvalidOsBootOptions (); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = CreateOsBootOptions (); > + return Status; > +} > + > + > +/** > + Remove UEFI OS boot options when it is disappeared in system. > + > +*/ > +EFI_STATUS > +RemoveInvalidOsBootOptions ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + UINT16 *OptionDelFlags; > + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; > + UINTN BootOptionCount; > + > + BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); > + OptionDelFlags = AllocateZeroPool (BootOptionCount * sizeof(UINT16)); > + if (OptionDelFlags == NULL) { > + goto exit; > + } > + > + for (Index = 0; Index < BootOptionCount; Index++) { > + if (OptionDelFlags[Index] == 0) { > + if (BeInvalidOsBootOption (BootOptions[Index].FilePath)) { > + Status = EfiBootManagerDeleteLoadOptionVariable (BootOptions[Index].OptionNumber, LoadOptionTypeBoot); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "DeleteLoadOptionVariable: %r\n", Status)); > + continue; > + } > + PrintDevicePath (L"Del Option,", BootOptions[Index].FilePath); > + } else { > + RemoveSuperfluousOption (&BootOptions[Index], OptionDelFlags, BootOptionCount - Index); > + } > + } > + } > + > + exit: > + if (OptionDelFlags != NULL) { > + FreePool (OptionDelFlags); > + } > + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); > + > + return EFI_SUCCESS; > +} > + > + > +/** > + Try to find UEFI OSs and create the boot options which haven't been listed in BootOrder. > + > +*/ > +EFI_STATUS > +CreateOsBootOptions ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE *FileSystemHandles; > + UINTN NumberFileSystemHandles; > + UINTN Index, Count; > + EFI_DEVICE_PATH_PROTOCOL *OsFileDP; > + EFI_BLOCK_IO_PROTOCOL *BlkIo; > + UINTN MaxFiles; > + EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData; > + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; > + EFI_IMAGE_DOS_HEADER DosHeader; > + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; > + > + // > + //Look for file system to find default Os boot load. > + // > + Status = gBS->LocateHandleBuffer ( > + ByProtocol, > + &gEfiSimpleFileSystemProtocolGuid, > + NULL, > + &NumberFileSystemHandles, > + &FileSystemHandles > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + MaxFiles = sizeof (mUefiOsBootFiles) / sizeof (UEFI_OS_BOOT_FILE); > + for (Index = 0; Index < NumberFileSystemHandles; Index++) { > + Status = gBS->HandleProtocol ( > + FileSystemHandles[Index], > + &gEfiBlockIoProtocolGuid, > + (VOID **) &BlkIo > + ); > + if (EFI_ERROR (Status)) { > + continue; > + } > + > + Hdr.Union = &HdrData; > + for (Count = 0; Count < MaxFiles; Count++) { > + // > + //Read Boot File Path to check validation. > + // > + Status = OsBootGetImageHeader ( > + FileSystemHandles[Index], > + mUefiOsBootFiles[Count].FilePathString, > + &DosHeader, > + Hdr > + ); > + if (!EFI_ERROR (Status) && > + EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) && > + Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { > + > + OsFileDP = NULL; > + OsFileDP = FileDevicePath (FileSystemHandles[Index], mUefiOsBootFiles[Count].FilePathString); > + PrintDevicePath (L"Exist", OsFileDP); > + if (!BeHaveSameBootOptionByDP (OsFileDP, mUefiOsBootFiles[Count].FilePathString)) { > + // > + // Create new BootOption if it is not present. > + // > + DEBUG ((DEBUG_INFO, "CreateOsBootOptions (), Make New Boot Option :%s.\n", mUefiOsBootFiles[Count].Description)); > + Status = EfiBootManagerInitializeLoadOption ( > + &NewOption, > + LoadOptionNumberUnassigned, > + LoadOptionTypeBoot, > + LOAD_OPTION_ACTIVE, > + mUefiOsBootFiles[Count].Description, > + OsFileDP, > + NULL, > + 0 > + ); > + ASSERT_EFI_ERROR (Status); > + Status = EfiBootManagerAddLoadOptionVariable (&NewOption, GetOptionPositionWithoutGpt ()); > + ASSERT_EFI_ERROR (Status); > + EfiBootManagerFreeLoadOption (&NewOption); > + } > + > + if(OsFileDP != NULL) { > + FreePool (OsFileDP); > + OsFileDP = NULL; > + } > + } > + } > + } > + > + if (NumberFileSystemHandles != 0) { > + FreePool (FileSystemHandles); > + } > + > + return EFI_SUCCESS; > +} > + > diff --git a/Silicon/Hisilicon/Library/OsBootLib/OsBootLib.inf b/Silicon/Hisilicon/Library/OsBootLib/OsBootLib.inf > new file mode 100644 > index 0000000..12e6d49 > --- /dev/null > +++ b/Silicon/Hisilicon/Library/OsBootLib/OsBootLib.inf > @@ -0,0 +1,59 @@ > +## @file > +# Manager Os Boot option. > +# Copyright (c) 2017, Hisilicon Limited. All rights reserved. > +# Copyright (c) 2017, Linaro Limited. All rights reserved. > +# > +# Copyright (c) 2008 - 2014, Intel Corporation. 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 > +# > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +# > +## > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = OsBootLib > + FILE_GUID = e406c654-ccde-4d32-8362-0aec01725139 > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = OsBootLib > + > +[Sources] > + OsBootLib.c > + OsBootLibMisc.c > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + Silicon/Hisilicon/HisiPkg.dec > + > +[LibraryClasses] > + BaseMemoryLib > + BaseLib > + DxeServicesLib > + DebugLib > + DxeServicesTableLib > + DevicePathLib > + MemoryAllocationLib > + PrintLib > + UefiRuntimeServicesTableLib > + UefiLib > + UefiBootServicesTableLib > + UefiBootManagerLib > + > +[Guids] > + gEfiGlobalVariableGuid > + gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## GUID > + > +[Protocols] > + gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES > + gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES > + gEfiFirmwareVolume2ProtocolGuid ## SOMETIMES_CONSUMES > + gEfiDevicePathProtocolGuid ## CONSUMES > + gEfiDevicePathToTextProtocolGuid > + > +[Pcd] > diff --git a/Silicon/Hisilicon/Library/OsBootLib/OsBootLibMisc.c b/Silicon/Hisilicon/Library/OsBootLib/OsBootLibMisc.c > new file mode 100644 > index 0000000..4e6d895 > --- /dev/null > +++ b/Silicon/Hisilicon/Library/OsBootLib/OsBootLibMisc.c > @@ -0,0 +1,514 @@ > +/** @file > +* > +* Copyright (c) 2017, Hisilicon Limited. All rights reserved. > +* Copyright (c) 2017, Linaro 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 > +* > +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +* > +**/ > + > +#include "OsBoot.h" > + > +extern UEFI_OS_BOOT_FILE mUefiOsBootFiles[]; > + > +/** > + Read file the headers of dos, image, optional header. > + > + @param Device SimpleFileSystem device handle > + @param FileSize File size > + @param DosHeader Pointer to dos header > + @param Hdr The buffer in which to return the PE32, PE32+, or TE header. > + > + @retval EFI_SUCCESS Successfully get the File. > + @retval EFI_LOAD_ERROR File is not a valid image file. > + > +**/ > +EFI_STATUS > +ReadDosHeader ( > + EFI_FILE_HANDLE ThisFile, > + UINT64 FileSize, > + EFI_IMAGE_DOS_HEADER *DosHeader, > + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION *Hdr > + ) > +{ > + EFI_STATUS Status; > + UINTN BufferSize; > + // > + // Read dos header > + // > + BufferSize = sizeof (EFI_IMAGE_DOS_HEADER); > + Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader); > + if (EFI_ERROR (Status) || > + BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) || > + FileSize <= DosHeader->e_lfanew || > + DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) { > + Status = EFI_LOAD_ERROR; > + DEBUG ((DEBUG_ERROR, "%a(%d):error!\n", __FUNCTION__,__LINE__)); > + goto ErrReadDos; > + } > + > + // > + // Move to PE signature > + // > + Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew); > + if (EFI_ERROR (Status)) { > + Status = EFI_LOAD_ERROR; > + DEBUG((DEBUG_ERROR, "%a(%d):error!\n", __FUNCTION__,__LINE__)); > + goto ErrReadDos; > + } > + > + // > + // Read and check PE signature > + // > + BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION); > + Status = ThisFile->Read (ThisFile, &BufferSize, (VOID*)(Hdr->Pe32)); > + if (EFI_ERROR (Status) || > + BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) || > + Hdr->Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) { > + Status = EFI_LOAD_ERROR; > + DEBUG((DEBUG_ERROR, "%a(%d):error!\n", __FUNCTION__,__LINE__)); > + goto ErrReadDos; > + } > + > +ErrReadDos: > + return Status; > +} > + > +/** > + Get the headers (dos, image, optional header) from an image > + > + @param Device SimpleFileSystem device handle > + @param FileName File name for the image > + @param DosHeader Pointer to dos header > + @param Hdr The buffer in which to return the PE32, PE32+, or TE header. > + > + @retval EFI_SUCCESS Successfully get the machine type. > + @retval EFI_NOT_FOUND The file is not found. > + @retval EFI_LOAD_ERROR File is not a valid image file. > + > +**/ > +EFI_STATUS > +EFIAPI > +OsBootGetImageHeader ( > + IN EFI_HANDLE Device, > + IN CHAR16 *FileName, > + OUT EFI_IMAGE_DOS_HEADER *DosHeader, > + OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr > + ) > +{ > + EFI_STATUS Status; > + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; > + EFI_FILE_HANDLE Root; > + EFI_FILE_HANDLE ThisFile; > + UINTN BufferSize; > + UINT64 FileSize; > + EFI_FILE_INFO *Info; > + BOOLEAN Condition = TRUE;//pclint > + > + Root = NULL; > + ThisFile = NULL; > + // > + // Handle the file system interface to the device > + // > + Status = gBS->HandleProtocol ( > + Device, > + &gEfiSimpleFileSystemProtocolGuid, > + (VOID *) &Volume > + ); > + if (EFI_ERROR (Status)) { > + DEBUG((DEBUG_ERROR, "%a(%d):error ret :%r !\n", __FUNCTION__,__LINE__,Status)); > + goto Done; > + } > + > + Status = Volume->OpenVolume ( > + Volume, > + &Root > + ); > + if (EFI_ERROR (Status)) { > + DEBUG((DEBUG_ERROR, "%a(%d):error ret :%r !\n", __FUNCTION__,__LINE__,Status)); > + Root = NULL; > + goto Done; > + } > + > + if (Root == NULL) { > + Status = EFI_LOAD_ERROR; > + DEBUG((DEBUG_ERROR, "%a(%d):error ret :%r !\n", __FUNCTION__,__LINE__,Status)); > + goto Done; > + } > + Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0); > + if (EFI_ERROR (Status)) { > + DEBUG((DEBUG_ERROR, "%a(%d):file not found ret :%r !\n", __FUNCTION__,__LINE__,Status)); > + goto Done; > + } > + > + if (ThisFile == NULL) { > + DEBUG((DEBUG_ERROR, "%a(%d):error ret :%r !\n", __FUNCTION__,__LINE__,Status)); > + Status = EFI_LOAD_ERROR; > + goto Done; > + } > + // > + // Get file size > + // > + BufferSize = SIZE_OF_EFI_FILE_INFO + 200; > + do { > + Info = NULL; > + Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info); > + if (EFI_ERROR (Status)) { > + goto Done; > + } > + Status = ThisFile->GetInfo ( > + ThisFile, > + &gEfiFileInfoGuid, > + &BufferSize, > + Info > + ); > + if (!EFI_ERROR (Status)) { > + break; > + } > + if (Status != EFI_BUFFER_TOO_SMALL) { > + FreePool (Info); > + goto Done; > + } > + FreePool (Info); > + } while (Condition); > + > + FileSize = Info->FileSize; > + FreePool (Info); > + > + Status = ReadDosHeader(ThisFile, FileSize, DosHeader, &Hdr); > + if (EFI_ERROR (Status)) { > + DEBUG((DEBUG_ERROR, "%a(%d):error ret :%r !\n", __FUNCTION__,__LINE__,Status)); > + goto Done; > + } > + // > + // Check PE32 or PE32+ magic > + // > + if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC && > + Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { > + Status = EFI_LOAD_ERROR; > + DEBUG((DEBUG_ERROR, "%a(%d):error ret :%r !\n", __FUNCTION__,__LINE__,Status)); > + goto Done; > + } > + > + Done: > + if (ThisFile != NULL) { > + ThisFile->Close (ThisFile); > + } > + if (Root != NULL) { > + Root->Close (Root); > + } > + return Status; > +} > + > + > +VOID > +PrintDevicePath ( > + CHAR16 *PreStr, > + EFI_DEVICE_PATH_PROTOCOL *Path > + ) > +{ > + CHAR16 *DevicePathTxt; > + EFI_STATUS Status; > + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathToTextProtocol; > + > + DevicePathTxt = NULL; > + Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); > + if (!EFI_ERROR (Status)) { > + DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (Path, FALSE, TRUE); > + DEBUG ((DEBUG_ERROR, "%s DevPath:[%s]\n", PreStr, DevicePathTxt)); > + } > + > + if (DevicePathTxt != NULL) { > + FreePool (DevicePathTxt); > + } > + > + return ; > +} > + > +CHAR16 * > +GetGptNodeText ( > + EFI_DEVICE_PATH_PROTOCOL *Path > + ) > +{ > + CHAR16 *NodeText; > + > + while (!IsDevicePathEnd (Path)) { > + NodeText = ConvertDeviceNodeToText (Path, TRUE, TRUE); > + if (StrStr (NodeText, L"GPT") != NULL) { > + return NodeText; > + } > + > + if (NodeText != NULL) { > + FreePool (NodeText); > + } > + > + Path = NextDevicePathNode (Path); > + } > + > + return NULL; > +} > + > +BOOLEAN > +IsPartitionGuidEqual ( > + EFI_DEVICE_PATH_PROTOCOL *OptionPath, > + EFI_DEVICE_PATH_PROTOCOL *FilePath > + ) > +{ > + CHAR16 *OptionGptText; > + CHAR16 *FileGptText; > + > + OptionGptText = GetGptNodeText (OptionPath); > + FileGptText = GetGptNodeText (FilePath); > + if ((OptionGptText != NULL) && (FileGptText != NULL) && (StrCmp (OptionGptText, FileGptText) == 0)) { > + return TRUE; > + } > + > + if (OptionGptText != NULL) { > + FreePool (OptionGptText); > + } > + if (FileGptText != NULL) { > + FreePool (FileGptText); > + } > + > + return FALSE; > +} > + > +/* If a partition exist a valid grub, OsBootLib will create a Option after bios firmware upgraded, > + * and then installing the same OS on the same partition will create anothor Option. the two Options > + * are superfluous, the Option added by OsBootLib should be remove. > + * > + * It's allowed of creating several Option in the same GPT by installing OS. > + */ > +VOID > +RemoveSuperfluousOption ( > + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions, > + UINT16 *OptionDelFlags, > + UINTN BootOptionCount > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + > + for (Index = 1; Index < BootOptionCount; Index++) { > + if (OptionDelFlags[Index] == 0) { > + if ((IsPartitionGuidEqual (BootOptions[0].FilePath, BootOptions[Index].FilePath)) && > + (IsOptionAddedByOsBootLib (BootOptions[Index].Description))) { > + OptionDelFlags[Index] = 1; > + > + Status = EfiBootManagerDeleteLoadOptionVariable (BootOptions[Index].OptionNumber, LoadOptionTypeBoot); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "DeleteLoadOptionVariable: %r\n", Status)); > + continue; > + } > + > + PrintDevicePath (L"Del Option(du),", BootOptions[Index].FilePath); > + } > + } > + } > + > + return; > +} > + > +UINTN > +GetOptionPositionWithoutGpt ( > + VOID > + ) > +{ > + UINTN Index; > + UINTN BootOptionCount; > + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; > + > + BootOptions = EfiBootManagerGetLoadOptions ( > + &BootOptionCount, LoadOptionTypeBoot > + ); > + for (Index = 0; Index < BootOptionCount; Index++) { > + if (GetGptNodeText (BootOptions[Index].FilePath) == NULL) { > + return Index; > + } > + } > + > + return 0; > +} > + > +CHAR16 * > +GetFileTextByDevicePath ( > + EFI_DEVICE_PATH_PROTOCOL *DevicePath > + ) > +{ > + CHAR16 *FileString; > + > + FileString = NULL; > + > + while (!IsDevicePathEnd (DevicePath)) { > + if (MEDIA_DEVICE_PATH == DevicePathType (DevicePath) && > + MEDIA_FILEPATH_DP == DevicePathSubType (DevicePath)) { > + FileString = ConvertDeviceNodeToText (DevicePath, TRUE, TRUE); > + break; > + } > + DevicePath = NextDevicePathNode (DevicePath); > + } > + > + return FileString; > +} > + > + > +/** > + Check same boot option by device path. > + > +*/ > +BOOLEAN > +BeHaveSameBootOptionByDP ( > + EFI_DEVICE_PATH_PROTOCOL *DevicePath, > + CHAR16 *FileName > + ) > +{ > + UINTN Index; > + UINTN ValidPathSize; > + BOOLEAN Found; > + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; > + UINTN BootOptionCount; > + > + if (NULL == DevicePath) { > + return FALSE; > + } > + > + BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); > + > + Found = FALSE; > + for (Index = 0; Index < BootOptionCount; Index++) { > + /* If a partition exist a valid Option, then the new Option should not be added. > + * After installation, some iso will create several valid grub file, like > + * \EFI\centos\shimaa64.efi, \EFI\BOOT\BOOTAA64.EFI. > + */ > + if(IsPartitionGuidEqual (BootOptions[Index].FilePath, DevicePath)) { > + DEBUG ((DEBUG_ERROR, "Get the same Option(GPT).\n")); > + Found = TRUE; > + break; > + } > + > + /* If DevicePath of new Option is matched in exist Option and file name of > + * new Option is EFI_REMOVABLE_MEDIA_FILE_NAME_AARCH64, then the new Option should be ignored. > + */ > + ValidPathSize = GetDevicePathSize (BootOptions[Index].FilePath) - END_DEVICE_PATH_LENGTH; > + if ((CompareMem (BootOptions[Index].FilePath, DevicePath, ValidPathSize) == 0) && > + (StrCmp (FileName, EFI_REMOVABLE_MEDIA_FILE_NAME_AARCH64) == 0)) > + { > + DEBUG ((DEBUG_ERROR, "Get the same Option.\n")); > + Found = TRUE; > + break; > + } > + } > + > + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); > + > + return Found; > +} > + > +/** > + Check Os Boot Option if exist in current system. > + > +*/ > +BOOLEAN > +BeInvalidOsBootOption ( > + EFI_DEVICE_PATH_PROTOCOL *OptionDp > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE *FileSystemHandles; > + UINTN NumberFileSystemHandles; > + UINTN Index; > + EFI_DEVICE_PATH_PROTOCOL *FileSystemDP; > + UINTN OptionDpSize; > + EFI_BLOCK_IO_PROTOCOL *BlkIo; > + EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData; > + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; > + EFI_IMAGE_DOS_HEADER DosHeader; > + BOOLEAN Invalid; > + EFI_DEVICE_PATH_PROTOCOL* DevicePathNode; > + CHAR16 *FileString; > + > + Invalid = TRUE; > + if (NULL == OptionDp) { > + return FALSE; > + } > + > + OptionDpSize = GetDevicePathSize (OptionDp); > + if (OptionDpSize == 0) { > + return FALSE; > + } > + > + // > + // Os BootOption should be File Device Path. > + // > + DevicePathNode = OptionDp; > + FileString = GetFileTextByDevicePath (DevicePathNode); > + if (FileString == NULL) { > + return FALSE; > + } > + > + // > + // File should be exsiting in system. > + // > + Status = gBS->LocateHandleBuffer ( > + ByProtocol, > + &gEfiSimpleFileSystemProtocolGuid, > + NULL, > + &NumberFileSystemHandles, > + &FileSystemHandles > + ); > + if (EFI_ERROR (Status)) { > + FreePool (FileString); > + return FALSE; > + } > + > + for (Index = 0; Index < NumberFileSystemHandles; Index++) { > + Status = gBS->HandleProtocol ( > + FileSystemHandles[Index], > + &gEfiBlockIoProtocolGuid, > + (VOID **) &BlkIo > + ); > + if (EFI_ERROR (Status)) { > + continue; > + } > + > + FileSystemDP = FileDevicePath (FileSystemHandles[Index], FileString); > + /* If Partition is existed and the grub file is existed, then the Option is valid. */ > + if ((CompareMem ((VOID *) OptionDp, (VOID *) FileSystemDP, OptionDpSize) == 0) || > + (IsPartitionGuidEqual (OptionDp, FileSystemDP))) { > + Hdr.Union = &HdrData; > + Status = OsBootGetImageHeader ( > + FileSystemHandles[Index], > + FileString, > + &DosHeader, > + Hdr > + ); > + if (!EFI_ERROR (Status) && > + EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Hdr.Pe32->FileHeader.Machine) && > + Hdr.Pe32->OptionalHeader.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { > + DEBUG ((DEBUG_ERROR, "BeValidOsBootOption (),Get Bootable file :%s.\n", FileString)); > + Invalid = FALSE; > + break; > + } > + } > + > + if (FileSystemDP != NULL) { > + FreePool (FileSystemDP); > + } > + } > + > + if (NumberFileSystemHandles != 0) { > + FreePool (FileSystemHandles); > + } > + if (FileString != NULL) { > + FreePool (FileString); > + } > + > + return Invalid; > +} > + > diff --git a/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c b/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c > index 845519f..1c6e8bf 100644 > --- a/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c > +++ b/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c > @@ -18,6 +18,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -576,6 +577,11 @@ PlatformBootManagerAfterConsole ( > PcdGetPtr (PcdShellFile), L"UEFI Shell", LOAD_OPTION_ACTIVE > ); > > + Status = AdjustOsBootOrder (); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a:%r\n", __FUNCTION__, Status)); > + } > + > HandleBmcBootType (); > } > > diff --git a/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf > index 7b151a9..a6d597d 100644 > --- a/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf > +++ b/Silicon/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf > @@ -49,6 +49,7 @@ > DevicePathLib > DxeServicesLib > MemoryAllocationLib > + OsBootLib > PcdLib > PrintLib > UefiBootManagerLib > -- > 1.9.1 >