From: Ming Huang <heyi.guo@linaro.org>
To: leif.lindholm@linaro.org, linaro-uefi@lists.linaro.org,
edk2-devel@lists.01.org, graeme.gregory@linaro.org
Cc: ard.biesheuvel@linaro.org, guoheyi@huawei.com,
wanghuiqiang@huawei.com, huangming23@huawei.com,
zhangjinsong2@huawei.com, mengfanrong@huawei.com, waip23@126.com,
Heyi Guo <heyi.guo@linaro.org>
Subject: [PATCH edk2-platforms v1 13/14] Hisilicon/Library: Add OsBootLib
Date: Thu, 18 Jan 2018 23:01:42 +0800 [thread overview]
Message-ID: <1516287703-35516-14-git-send-email-huangming23@huawei.com> (raw)
In-Reply-To: <1516287703-35516-1-git-send-email-huangming23@huawei.com>
OsBootLib can create OS option after upgrade firmware.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ming Huang <huangming23@huawei.com>
Signed-off-by: Heyi Guo <heyi.guo@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
next prev parent reply other threads:[~2018-01-18 14:57 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-18 15:01 [PATCH edk2-platforms v1 00/14] Improve D0x platforms and bug fix Ming Huang
2018-01-18 15:01 ` [PATCH edk2-platforms v1 01/14] Hisilicon/D05: Add PPTT support Ming Huang
2018-01-20 10:16 ` Ard Biesheuvel
2018-01-22 9:16 ` Huangming (Mark)
2018-01-23 6:00 ` Huangming (Mark)
2018-01-22 13:53 ` Leif Lindholm
2018-01-22 14:15 ` Leif Lindholm
2018-01-24 13:49 ` graeme.gregory
2018-01-23 21:29 ` Jeremy Linton
2018-01-24 7:57 ` Huangming (Mark)
2018-01-25 5:56 ` Huangming (Mark)
2018-01-25 15:27 ` Jeremy Linton
2018-01-18 15:01 ` [PATCH edk2-platforms v1 02/14] Hisilicon D03/D05:Switch to Generic BDS driver Ming Huang
2018-01-20 10:27 ` Ard Biesheuvel
2018-01-22 18:38 ` Leif Lindholm
2018-01-23 6:03 ` Huangming (Mark)
2018-01-18 15:01 ` [PATCH edk2-platforms v1 03/14] Hisilicon D03/D05: Optimize the feature of BMC set boot option Ming Huang
2018-01-20 10:41 ` Ard Biesheuvel
2018-01-23 8:28 ` Huangming (Mark)
2018-01-23 10:28 ` Leif Lindholm
2018-01-23 10:51 ` Huangming (Mark)
2018-01-18 15:01 ` [PATCH edk2-platforms v1 04/14] Hisilicon D03/D05: Add capsule upgrade support Ming Huang
2018-01-20 10:50 ` Ard Biesheuvel
2018-01-23 8:53 ` Huangming (Mark)
2018-01-23 9:33 ` Ard Biesheuvel
2018-01-24 11:10 ` Huangming (Mark)
2018-01-24 11:21 ` Ard Biesheuvel
2018-01-25 0:53 ` Huangming (Mark)
2018-01-23 14:06 ` Leif Lindholm
2018-01-18 15:01 ` [PATCH edk2-platforms v1 05/14] Hisilicon D03/D05: Open SasPlatform source code Ming Huang
2018-01-20 10:57 ` Ard Biesheuvel
2018-01-23 11:01 ` Huangming (Mark)
2018-01-23 14:04 ` Leif Lindholm
2018-01-18 15:01 ` [PATCH edk2-platforms v1 06/14] Hisilicon D03/D05: Open SnpPlatform " Ming Huang
2018-01-20 11:00 ` Ard Biesheuvel
2018-01-23 11:01 ` Huangming (Mark)
2018-01-23 14:07 ` Leif Lindholm
2018-01-24 12:31 ` Huangming (Mark)
2018-01-24 13:47 ` Leif Lindholm
2018-01-18 15:01 ` [PATCH edk2-platforms v1 07/14] Hisilicon/Smbios: modify type 4 Ming Huang
2018-01-20 11:01 ` Ard Biesheuvel
2018-01-23 14:15 ` Leif Lindholm
2018-01-18 15:01 ` [PATCH edk2-platforms v1 08/14] Hisilicon/PCIe: Disable PCIe ASPM Ming Huang
2018-01-20 11:04 ` Ard Biesheuvel
2018-01-18 15:01 ` [PATCH edk2-platforms v1 09/14] Hisilicon/D05: Replace SP805Watchdog by WatchdogTimer driver Ming Huang
2018-01-20 11:05 ` Ard Biesheuvel
2018-01-23 14:21 ` Leif Lindholm
2018-01-18 15:01 ` [PATCH edk2-platforms v1 10/14] Hisilicon/D03: " Ming Huang
2018-01-20 11:05 ` Ard Biesheuvel
2018-01-23 14:21 ` Leif Lindholm
2018-01-18 15:01 ` [PATCH edk2-platforms v1 11/14] Hisilicon/D05/ACPI: Add ITS PXM Ming Huang
2018-01-20 11:06 ` Ard Biesheuvel
2018-01-18 15:01 ` [PATCH edk2-platforms v1 12/14] Hisilicon/D05/ACPI: Add Pcie, HNS and SAS PXM Ming Huang
2018-01-20 11:08 ` Ard Biesheuvel
2018-01-18 15:01 ` Ming Huang [this message]
2018-01-20 11:11 ` [PATCH edk2-platforms v1 13/14] Hisilicon/Library: Add OsBootLib Ard Biesheuvel
2018-01-23 10:23 ` Leif Lindholm
2018-01-27 1:47 ` Huangming (Mark)
2018-01-27 10:37 ` Ard Biesheuvel
2018-01-29 8:55 ` Huangming (Mark)
2018-01-29 10:19 ` Ard Biesheuvel
2018-01-29 11:16 ` Leif Lindholm
2018-02-07 21:16 ` Peter Jones
2018-02-11 6:03 ` Huangming (Mark)
2018-02-26 1:12 ` Guo Heyi
2018-01-18 15:01 ` [PATCH edk2-platforms v1 14/14] Hisilicon D03/D05: Update firmware version to 18.02 Ming Huang
2018-01-20 11:11 ` Ard Biesheuvel
2018-01-23 10:18 ` Leif Lindholm
2018-01-24 1:17 ` Huangming (Mark)
2018-01-24 7:54 ` Leif Lindholm
2018-01-22 13:26 ` [PATCH edk2-platforms v1 00/14] Improve D0x platforms and bug fix Leif Lindholm
2018-01-23 14:24 ` Leif Lindholm
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1516287703-35516-14-git-send-email-huangming23@huawei.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox