On 18 January 2018 at 15:01, Ming Huang <heyi....@linaro.org> 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 <huangmin...@huawei.com>
> Signed-off-by: Heyi Guo <heyi....@linaro.org>
> ---
>  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 <PiDxe.h>
> +#include <PlatformArch.h>
> +#include <Uefi.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/GlobalVariable.h>
> +#include <IndustryStandard/PeImage.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/OsBootLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiBootManagerLib.h>
> +
> +#include <Protocol/BlockIo.h>
> +#include <Protocol/DevicePath.h>
> +#include <Protocol/DevicePathFromText.h>
> +#include <Protocol/DevicePathToText.h>
> +#include <Protocol/FirmwareVolume2.h>
> +#include <Protocol/SimpleFileSystem.h>
> +
> +
> +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.<BR>
> +#  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 <IndustryStandard/Pci22.h>
>  #include <Library/BmcConfigBootLib.h>
>  #include <Library/DevicePathLib.h>
> +#include <Library/OsBootLib.h>
>  #include <Library/PcdLib.h>
>  #include <Library/UefiBootManagerLib.h>
>  #include <Library/UefiLib.h>
> @@ -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
>
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to