From: "Wang, Jian J" <jian.j.wang@intel.com>
To: "Chen, Chen A" <chen.a.chen@intel.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Wu, Hao A" <hao.a.wu@intel.com>,
"Zhang, Chao B" <chao.b.zhang@intel.com>
Subject: Re: [PATCH v3 3/4] MdeModulePkg/CapsuleApp: Add functions to support Capsule-on-Disk
Date: Tue, 29 Jan 2019 14:02:07 +0000 [thread overview]
Message-ID: <D827630B58408649ACB04F44C5100036258A8653@SHSMSX107.ccr.corp.intel.com> (raw)
In-Reply-To: <20190129074341.7032-4-chen.a.chen@intel.com>
Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
> -----Original Message-----
> From: Chen, Chen A
> Sent: Tuesday, January 29, 2019 3:44 PM
> To: edk2-devel@lists.01.org
> Cc: Chen, Chen A <chen.a.chen@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>
> Subject: [PATCH v3 3/4] MdeModulePkg/CapsuleApp: Add functions to support
> Capsule-on-Disk
>
> BZ:https://bugzilla.tianocore.org/show_bug.cgi?id=1482
>
> This file provide some basic function to support Capsule-on-Disk.
>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao Wu <hao.a.wu@intel.com>
> Cc: Zhang Chao B <chao.b.zhang@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Chen A Chen <chen.a.chen@intel.com>
> ---
> .../Application/CapsuleApp/CapsuleOnDisk.c | 806
> +++++++++++++++++++++
> 1 file changed, 806 insertions(+)
> create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c
>
> diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c
> b/MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c
> new file mode 100644
> index 0000000000..16ce9519b2
> --- /dev/null
> +++ b/MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c
> @@ -0,0 +1,806 @@
> +/** @file
> + Process Capsule On Disk.
> +
> + Copyright (c) 2019, 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.
> +
> +**/
> +#include <Uefi.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/FileHandleLib.h>
> +#include <Library/UefiBootManagerLib.h>
> +#include <Protocol/SimpleFileSystem.h>
> +#include <Protocol/Shell.h>
> +#include <Guid/FileInfo.h>
> +#include <Guid/GlobalVariable.h>
> +#include <Guid/Gpt.h>
> +
> +EFI_GUID mCapsuleOnDiskBootOptionGuid = { 0x4CC29BB7, 0x2413, 0x40A2,
> { 0xB0, 0x6D, 0x25, 0x3E, 0x37, 0x10, 0xF5, 0x32 } };
> +
> +/**
> + Get shell protocol.
> +
> + @return Pointer to shell protocol.
> +
> +**/
> +EFI_SHELL_PROTOCOL *
> +GetShellProtocol (
> + VOID
> + );
> +
> +/**
> + Get file name from file path.
> +
> + @param FilePath File path.
> +
> + @return Pointer to file name.
> +
> +**/
> +CHAR16 *
> +GetFileNameFromPath (
> + CHAR16 *FilePath
> + )
> +{
> + EFI_STATUS Status;
> + EFI_SHELL_PROTOCOL *ShellProtocol;
> + SHELL_FILE_HANDLE Handle;
> + EFI_FILE_INFO *FileInfo;
> +
> + ShellProtocol = GetShellProtocol ();
> + if (ShellProtocol == NULL) {
> + return NULL;
> + }
> +
> + //
> + // Open file by FileName.
> + //
> + Status = ShellProtocol->OpenFileByName (
> + FilePath,
> + &Handle,
> + EFI_FILE_MODE_READ
> + );
> + if (EFI_ERROR (Status)) {
> + return NULL;
> + }
> +
> + //
> + // Get file name from EFI_FILE_INFO.
> + //
> + FileInfo = ShellProtocol->GetFileInfo (Handle);
> + ShellProtocol->CloseFile (Handle);
> + if (FileInfo == NULL) {
> + return NULL;
> + }
> +
> + return FileInfo->FileName;
> +}
> +
> +/**
> + Check if the device path is EFI system Partition.
> +
> + @param DevicePath The ESP device path.
> +
> + @retval TRUE DevicePath is a device path for ESP.
> + @retval FALSE DevicePath is not a device path for ESP.
> +
> +**/
> +BOOLEAN
> +IsEfiSysPartitionDevicePath (
> + EFI_DEVICE_PATH_PROTOCOL *DevicePath
> + )
> +{
> + EFI_STATUS Status;
> + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
> + HARDDRIVE_DEVICE_PATH *Hd;
> + EFI_HANDLE Handle;
> +
> + //
> + // Check if the device path contains GPT node
> + //
> + TempDevicePath = DevicePath;
> +
> + while (!IsDevicePathEnd (TempDevicePath)) {
> + if ((DevicePathType (TempDevicePath) == MEDIA_DEVICE_PATH) &&
> + (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP)) {
> + Hd = (HARDDRIVE_DEVICE_PATH *)TempDevicePath;
> + if (Hd->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) {
> + break;
> + }
> + }
> + TempDevicePath = NextDevicePathNode (TempDevicePath);
> + }
> +
> + if (!IsDevicePathEnd (TempDevicePath)) {
> + //
> + // Search for EFI system partition protocol on full device path in Boot Option
> + //
> + Status = gBS->LocateDevicePath (&gEfiPartTypeSystemPartGuid,
> &DevicePath, &Handle);
> + return EFI_ERROR (Status) ? FALSE : TRUE;
> + } else {
> + return FALSE;
> + }
> +}
> +
> +/**
> + Dump all EFI System Partition.
> +
> +**/
> +VOID
> +DumpAllEfiSysPartition (
> + VOID
> + )
> +{
> + EFI_HANDLE *SimpleFileSystemHandles;
> + UINTN NumberSimpleFileSystemHandles;
> + UINTN Index;
> + EFI_DEVICE_PATH_PROTOCOL *DevicePath;
> + UINTN NumberEfiSystemPartitions;
> + EFI_SHELL_PROTOCOL *ShellProtocol;
> +
> + ShellProtocol = GetShellProtocol ();
> + NumberEfiSystemPartitions = 0;
> +
> + Print (L"EFI System Partition list:\n");
> +
> + gBS->LocateHandleBuffer (
> + ByProtocol,
> + &gEfiSimpleFileSystemProtocolGuid,
> + NULL,
> + &NumberSimpleFileSystemHandles,
> + &SimpleFileSystemHandles
> + );
> +
> + for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {
> + DevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);
> + if (IsEfiSysPartitionDevicePath (DevicePath)) {
> + NumberEfiSystemPartitions++;
> + Print(L" %s\n %s\n", ShellProtocol->GetMapFromDevicePath
> (&DevicePath), ConvertDevicePathToText (DevicePath, TRUE, TRUE));
> + }
> + }
> +
> + if (NumberEfiSystemPartitions == 0) {
> + Print(L" No ESP found.\n");
> + }
> +}
> +
> +/**
> + Check if capsule is provisioned.
> +
> + @retval TRUE Capsule is provisioned previously.
> + @retval FALSE No capsule is provisioned.
> +
> +**/
> +BOOLEAN
> +IsCapsuleProvisioned (
> + VOID
> + )
> +{
> + EFI_STATUS Status;
> + UINT64 OsIndication;
> + UINTN DataSize;
> +
> + OsIndication = 0;
> + DataSize = sizeof(UINT64);
> + Status = gRT->GetVariable (
> + L"OsIndications",
> + &gEfiGlobalVariableGuid,
> + NULL,
> + &DataSize,
> + &OsIndication
> + );
> + if (!EFI_ERROR (Status) &&
> + (OsIndication &
> EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) != 0) {
> + return TRUE;
> + }
> +
> + return FALSE;
> +}
> +
> +/**
> + Get one active Efi System Partition
> +
> + @param[out] FsDevicePath The device path of Fs
> + @param[out] Fs The file system within EfiSysPartition
> +
> + @retval EFI_SUCCESS Get file system successfully
> + @retval EFI_NOT_FOUND No valid file system found
> +
> +**/
> +EFI_STATUS
> +GetEfiSysPartition (
> + OUT EFI_DEVICE_PATH_PROTOCOL **FsDevicePath,
> + OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> + )
> +{
> + EFI_HANDLE *SimpleFileSystemHandles;
> + UINTN NumberSimpleFileSystemHandles;
> + UINTN Index;
> + EFI_DEVICE_PATH_PROTOCOL *DevicePath;
> + EFI_STATUS Status;
> +
> + Status = gBS->LocateHandleBuffer (
> + ByProtocol,
> + &gEfiSimpleFileSystemProtocolGuid,
> + NULL,
> + &NumberSimpleFileSystemHandles,
> + &SimpleFileSystemHandles
> + );
> +
> + if (EFI_ERROR (Status)) {
> + return EFI_NOT_FOUND;
> + }
> +
> + for (Index = 0; Index < NumberSimpleFileSystemHandles; Index++) {
> + DevicePath = DevicePathFromHandle (SimpleFileSystemHandles[Index]);
> + if (IsEfiSysPartitionDevicePath (DevicePath)) {
> + Status = gBS->HandleProtocol (SimpleFileSystemHandles[Index],
> &gEfiSimpleFileSystemProtocolGuid, Fs);
> + if (!EFI_ERROR (Status)) {
> + *FsDevicePath = DevicePath;
> + return EFI_SUCCESS;
> + }
> + }
> + }
> +
> + return EFI_NOT_FOUND;
> +}
> +
> +/**
> + Check if Active Efi System Partition within GPT is in the device path
> +
> + @param[in] DevicePath The device path
> + @param[out] FullPath The device path of Fs
> + @param[out] Fs The file system within EfiSysPartition
> +
> + @retval EFI_SUCCESS Get file system successfully
> + @retval EFI_NOT_FOUND No valid file system found
> + @retval others Get file system failed
> +
> +**/
> +EFI_STATUS
> +GetEfiSysPartitionFromDevPath (
> + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
> + OUT EFI_DEVICE_PATH_PROTOCOL **FsDevicePath,
> + OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> + )
> +{
> + EFI_STATUS Status;
> + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
> + HARDDRIVE_DEVICE_PATH *Hd;
> + EFI_HANDLE Handle;
> +
> + //
> + // Check if the device path contains GPT node
> + //
> + TempDevicePath = DevicePath;
> + while (!IsDevicePathEnd (TempDevicePath)) {
> + if ((DevicePathType (TempDevicePath) == MEDIA_DEVICE_PATH) &&
> + (DevicePathSubType (TempDevicePath) == MEDIA_HARDDRIVE_DP)) {
> + Hd = (HARDDRIVE_DEVICE_PATH *)TempDevicePath;
> + if (Hd->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER) {
> + break;
> + }
> + }
> + TempDevicePath = NextDevicePathNode (TempDevicePath);
> + }
> +
> + if (!IsDevicePathEnd (TempDevicePath)) {
> + //
> + // Search for EFI system partition protocol on full device path in Boot Option
> + //
> + Status = gBS->LocateDevicePath (&gEfiPartTypeSystemPartGuid,
> &DevicePath, &Handle);
> +
> + //
> + // Search for simple file system on this handler
> + //
> + if (!EFI_ERROR (Status)) {
> + Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid,
> Fs);
> + if (!EFI_ERROR (Status)) {
> + *FsDevicePath = DevicePathFromHandle (Handle);
> + return EFI_SUCCESS;
> + }
> + }
> + }
> +
> + return EFI_NOT_FOUND;
> +}
> +
> +/**
> + Get SimpleFileSystem from boot option file path
> +
> + @param[in] DevicePath The file path of boot option
> + @param[out] FullPath The full device path of boot device
> + @param[out] Fs The file system within EfiSysPartition
> +
> + @retval EFI_SUCCESS Get file system successfully
> + @retval EFI_NOT_FOUND No valid file system found
> + @retval others Get file system failed
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetEfiSysPartitionFromBootOptionFilePath (
> + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
> + OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
> + OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs
> + )
> +{
> + EFI_STATUS Status;
> + EFI_DEVICE_PATH_PROTOCOL *CurFullPath;
> + EFI_DEVICE_PATH_PROTOCOL *PreFullPath;
> + EFI_DEVICE_PATH_PROTOCOL *FsFullPath;
> +
> + CurFullPath = NULL;
> + FsFullPath = NULL;
> + //
> + // Try every full device Path generated from bootoption
> + //
> + do {
> + PreFullPath = CurFullPath;
> + CurFullPath = EfiBootManagerGetNextFullDevicePath (DevicePath,
> CurFullPath);
> +
> + if (PreFullPath != NULL) {
> + FreePool (PreFullPath);
> + }
> +
> + if (CurFullPath == NULL) {
> + //
> + // No Active EFI system partition is found in BootOption device path
> + //
> + Status = EFI_NOT_FOUND;
> + break;
> + }
> +
> + DEBUG_CODE (
> + CHAR16 *DevicePathStr;
> +
> + DevicePathStr = ConvertDevicePathToText (CurFullPath, TRUE, TRUE);
> + if (DevicePathStr != NULL){
> + DEBUG ((DEBUG_INFO, "Full device path %s\n", DevicePathStr));
> + FreePool (DevicePathStr);
> + }
> + );
> +
> + Status = GetEfiSysPartitionFromDevPath (CurFullPath, &FsFullPath, Fs);
> + } while (EFI_ERROR (Status));
> +
> + if (*Fs != NULL) {
> + *FullPath = FsFullPath;
> + return EFI_SUCCESS;
> + } else {
> + return EFI_NOT_FOUND;
> + }
> +}
> +
> +/**
> + Get a valid SimpleFileSystem within EFI system partition
> +
> + @param[In] Map The FS mapping capsule write to
> + @param[out] BootNext The value of BootNext Variable
> + @param[out] Handle The file system handle
> + @param[out] UpdateBootNext The flag to indicate whether update
> BootNext Variable
> +
> + @retval EFI_SUCCESS Get FS successfully
> + @retval EFI_NOT_FOUND No valid FS found
> + @retval others Get FS failed
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetUpdateFileSystem (
> + IN CHAR16 *Map,
> + OUT UINT16 *BootNext,
> + OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **Fs,
> + OUT BOOLEAN *UpdateBootNext
> +)
> +{
> + EFI_STATUS Status;
> + CHAR16 BootOptionName[20];
> + UINTN Index;
> + CONST EFI_DEVICE_PATH_PROTOCOL *MappedDevicePath;
> + EFI_DEVICE_PATH_PROTOCOL *DevicePath;
> + EFI_DEVICE_PATH_PROTOCOL *FullPath;
> + UINT16 *BootNextData;
> + EFI_BOOT_MANAGER_LOAD_OPTION BootNextOption;
> + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptionBuffer;
> + UINTN BootOptionCount;
> + EFI_SHELL_PROTOCOL *ShellProtocol;
> + EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
> +
> + MappedDevicePath = NULL;
> + ShellProtocol = GetShellProtocol ();
> +
> + //
> + // 1. If Fs is not assigned and there are capsule provisioned before,
> + // Get EFI system partition from BootNext.
> + //
> + if (IsCapsuleProvisioned () && Map == NULL) {
> + Status = GetVariable2 (
> + L"BootNext",
> + &gEfiGlobalVariableGuid,
> + &BootNextData,
> + NULL
> + );
> + if (!EFI_ERROR (Status)) {
> + UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x",
> *BootNextData);
> + Status = EfiBootManagerVariableToLoadOption (BootOptionName,
> &BootNextOption);
> + if (!EFI_ERROR (Status)) {
> + DevicePath = BootNextOption.FilePath;
> + Status = GetEfiSysPartitionFromBootOptionFilePath (DevicePath, &FullPath,
> Fs);
> + if (!EFI_ERROR (Status)) {
> + *UpdateBootNext = FALSE;
> + Print(L"Get EFI system partition from BootNext : %s\n",
> BootNextOption.Description);
> + Print(L"%s %s\n", ShellProtocol->GetMapFromDevicePath (&FullPath),
> ConvertDevicePathToText (FullPath, TRUE, TRUE));
> + return EFI_SUCCESS;
> + }
> + }
> + }
> + }
> +
> + //
> + // Check if Map is valid.
> + //
> + if (Map != NULL) {
> + MappedDevicePath = ShellProtocol->GetDevicePathFromMap (Map);
> + if (MappedDevicePath == NULL) {
> + Print(L"'%s' is not a valid mapping.\n", Map);
> + return EFI_INVALID_PARAMETER;
> + } else if (!IsEfiSysPartitionDevicePath (DuplicateDevicePath
> (MappedDevicePath))) {
> + Print(L"'%s' is not a EFI System Partition.\n", Map);
> + return EFI_INVALID_PARAMETER;
> + }
> + }
> +
> + //
> + // 2. Get EFI system partition form boot options.
> + //
> + BootOptionBuffer = EfiBootManagerGetLoadOptions (&BootOptionCount,
> LoadOptionTypeBoot);
> + if (BootOptionCount == 0 && Map == NULL) {
> + return EFI_NOT_FOUND;
> + }
> +
> + for (Index = 0; Index < BootOptionCount; Index++) {
> + //
> + // Get the boot option from the link list
> + //
> + DevicePath = BootOptionBuffer[Index].FilePath;
> +
> + //
> + // Skip inactive or legacy boot options
> + //
> + if ((BootOptionBuffer[Index].Attributes & LOAD_OPTION_ACTIVE) == 0 ||
> + DevicePathType (DevicePath) == BBS_DEVICE_PATH) {
> + continue;
> + }
> +
> + DEBUG_CODE (
> + CHAR16 *DevicePathStr;
> +
> + DevicePathStr = ConvertDevicePathToText (DevicePath, TRUE, TRUE);
> + if (DevicePathStr != NULL){
> + DEBUG ((DEBUG_INFO, "Try BootOption %s\n", DevicePathStr));
> + FreePool (DevicePathStr);
> + } else {
> + DEBUG ((DEBUG_INFO, "DevicePathToStr failed\n"));
> + }
> + );
> +
> + Status = GetEfiSysPartitionFromBootOptionFilePath (DevicePath, &FullPath,
> Fs);
> + if (!EFI_ERROR (Status)) {
> + if (Map == NULL) {
> + *BootNext = (UINT16) BootOptionBuffer[Index].OptionNumber;
> + *UpdateBootNext = TRUE;
> + Print (L"Found EFI system partition on Boot%04x: %s\n", *BootNext,
> BootOptionBuffer[Index].Description);
> + Print (L"%s %s\n", ShellProtocol->GetMapFromDevicePath (&FullPath),
> ConvertDevicePathToText (FullPath, TRUE, TRUE));
> + return EFI_SUCCESS;
> + }
> +
> + if (StrnCmp (Map, ShellProtocol->GetMapFromDevicePath (&FullPath),
> StrLen (Map)) == 0) {
> + *BootNext = (UINT16) BootOptionBuffer[Index].OptionNumber;
> + *UpdateBootNext = TRUE;
> + Print (L"Found Boot Option on %s : %s\n", Map,
> BootOptionBuffer[Index].Description);
> + return EFI_SUCCESS;
> + }
> + }
> + }
> +
> + //
> + // 3. If no ESP is found on boot option, try to find a ESP and create boot
> option for it.
> + //
> + if (Map != NULL) {
> + //
> + // If map is assigned, try to get ESP from mapped Fs.
> + //
> + DevicePath = DuplicateDevicePath (MappedDevicePath);
> + Status = GetEfiSysPartitionFromDevPath (DevicePath, &FullPath, Fs);
> + if (EFI_ERROR (Status)) {
> + Print (L"Error: Cannot get EFI system partiion from '%s' - %r\n", Map,
> Status);
> + return EFI_NOT_FOUND;
> + }
> + Print (L"Warning: Cannot find Boot Option on '%s'!\n", Map);
> + } else {
> + Status = GetEfiSysPartition (&DevicePath, Fs);
> + if (EFI_ERROR (Status)) {
> + Print (L"Error: Cannot find a EFI system partition!\n");
> + return EFI_NOT_FOUND;
> + }
> + }
> +
> + Print (L"Create Boot option for capsule on disk:\n");
> + Status = EfiBootManagerInitializeLoadOption (
> + &NewOption,
> + LoadOptionNumberUnassigned,
> + LoadOptionTypeBoot,
> + LOAD_OPTION_ACTIVE,
> + L"UEFI Capsule On Disk",
> + DevicePath,
> + (UINT8 *) &mCapsuleOnDiskBootOptionGuid,
> + sizeof(EFI_GUID)
> + );
> + if (!EFI_ERROR (Status)) {
> + Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN) -1);
> {
> + if (!EFI_ERROR (Status)) {
> + *UpdateBootNext = TRUE;
> + *BootNext = (UINT16) NewOption.OptionNumber;
> + Print (L" Boot%04x: %s\n", *BootNext,
> ConvertDevicePathToText(DevicePath, TRUE, TRUE));
> + return EFI_SUCCESS;
> + }
> + }
> + }
> +
> + Print (L"ERROR: Cannot create boot option! - %r\n", Status);
> +
> + return EFI_NOT_FOUND;
> +}
> +
> +/**
> + Write files to a given SimpleFileSystem.
> +
> + @param[in] Buffer The buffer array
> + @param[in] BufferSize The buffer size array
> + @param[in] FileName The file name array
> + @param[in] BufferNum The buffer number
> + @param[in] Fs The SimpleFileSystem handle to be written
> +
> + @retval EFI_SUCCESS Write file successfully
> + @retval EFI_NOT_FOUND SFS protocol not found
> + @retval others Write file failed
> +
> +**/
> +EFI_STATUS
> +WriteUpdateFile (
> + IN VOID **Buffer,
> + IN UINTN *BufferSize,
> + IN CHAR16 **FileName,
> + IN UINTN BufferNum,
> + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs
> +)
> +{
> + EFI_STATUS Status;
> + EFI_FILE *Root;
> + CHAR16 *mDirName = L"\\EFI\\UpdateCapsule";
> + CHAR16 *mDirName1 = L"\\EFI";
> + EFI_FILE_PROTOCOL *DirHandle = NULL;
> + EFI_FILE *FileHandle = NULL;
> + UINT64 FileInfo;
> + UINTN Index = 0;
> + VOID *Filebuffer;
> + UINTN FileSize;
> +
> + //
> + // Open Root from SFS
> + //
> + Status = Fs->OpenVolume (Fs, &Root);
> + if (EFI_ERROR (Status)) {
> + Print (L"Cannot open volume. Status = %r\n", Status);
> + return EFI_NOT_FOUND;
> + }
> +
> + //
> + // Ensure that efi and updatecapsule directories exist
> + //
> + Status = Root->Open (Root, &DirHandle, mDirName1, EFI_FILE_MODE_READ
> | EFI_FILE_MODE_WRITE, 0);
> + if (EFI_ERROR (Status)) {
> + Status = Root->Open (Root, &DirHandle, mDirName1, EFI_FILE_MODE_READ
> | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, EFI_FILE_DIRECTORY);
> + if (EFI_ERROR (Status)) {
> + Print(L"Unable to create %s directory\n", mDirName1);
> + return EFI_NOT_FOUND;
> + }
> + }
> + Status = Root->Open (Root, &DirHandle, mDirName, EFI_FILE_MODE_READ |
> EFI_FILE_MODE_WRITE , 0);
> + if (EFI_ERROR (Status)) {
> + Status = Root->Open (Root, &DirHandle, mDirName, EFI_FILE_MODE_READ
> | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, EFI_FILE_DIRECTORY);
> + if (EFI_ERROR (Status)) {
> + Print(L"Unable to create %s directory\n", mDirName);
> + return EFI_NOT_FOUND;
> + }
> + }
> +
> + for (Index = 0; Index < BufferNum; Index++) {
> + FileHandle = NULL;
> +
> + //
> + // Open UpdateCapsule file
> + //
> + Status = DirHandle->Open (DirHandle, &FileHandle, FileName[Index],
> EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0);
> + if (EFI_ERROR (Status)) {
> + Print (L"Unable to create %s file\n", FileName[Index]);
> + return EFI_NOT_FOUND;
> + }
> +
> + //
> + // Empty the file contents
> + //
> + Status = FileHandleGetSize (FileHandle, &FileInfo);
> + if (EFI_ERROR (Status)) {
> + FileHandleClose (FileHandle);
> + Print (L"Error Reading %s\n", FileName[Index]);
> + return EFI_DEVICE_ERROR;
> + }
> +
> + //
> + // If the file size is already 0, then it has been empty.
> + //
> + if (FileInfo != 0) {
> + //
> + // Set the file size to 0.
> + //
> + FileInfo = 0;
> + Status = FileHandleSetSize (FileHandle, FileInfo);
> + if (EFI_ERROR (Status)) {
> + Print (L"Error Deleting %s\n", FileName[Index]);
> + FileHandleClose (FileHandle);
> + return Status;
> + }
> + }
> +
> + //
> + // Write Filebuffer to file
> + //
> + Filebuffer = Buffer[Index];
> + FileSize = BufferSize[Index];
> + Status = FileHandleWrite (FileHandle, &FileSize, Filebuffer);
> + if (EFI_ERROR (Status)) {
> + Print (L"Unable to write Capsule Update to %s, Status = %r\n",
> FileName[Index], Status);
> + return EFI_NOT_FOUND;
> + }
> +
> + Print (L"Succeed to write %s\n", FileName[Index]);
> + FileHandleClose (FileHandle);
> + }
> +
> + return EFI_SUCCESS;
> +}
> +
> +/**
> + Set capsule status variable.
> +
> + @param[in] SetCap Set or clear the capsule flag.
> +
> + @retval EFI_SUCCESS Succeed to set SetCap variable.
> + @retval others Fail to set the variable.
> +
> +**/
> +EFI_STATUS
> +SetCapsuleStatusVariable (
> + BOOLEAN SetCap
> + )
> +{
> + EFI_STATUS Status;
> + UINT64 OsIndication;
> + UINTN DataSize;
> +
> + OsIndication = 0;
> + DataSize = sizeof(UINT64);
> + Status = gRT->GetVariable (
> + L"OsIndications",
> + &gEfiGlobalVariableGuid,
> + NULL,
> + &DataSize,
> + &OsIndication
> + );
> + if (EFI_ERROR (Status)) {
> + OsIndication = 0;
> + }
> + if (SetCap) {
> + OsIndication |=
> ((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED);
> + }
> + else {
> + OsIndication &=
> ~((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED);
> + }
> + Status = gRT->SetVariable (
> + L"OsIndications",
> + &gEfiGlobalVariableGuid,
> + EFI_VARIABLE_BOOTSERVICE_ACCESS |
> EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
> + sizeof(UINT64),
> + &OsIndication
> + );
> +
> + return Status;
> +}
> +
> +/**
> + Process Capsule On Disk.
> +
> + @param[in] CapsuleBuffer An array of pointer to capsule images
> + @param[in] FileSize An array of UINTN to capsule images size
> + @param[in] FilePath An array of capsule images file path
> + @param[in] NewFileName An array of new capsule images name
> + @param[in] CapsuleNum The count of capsule images
> +
> + @retval EFI_SUCCESS Capsule on disk success.
> + @retval others Capsule on disk fail.
> +
> +**/
> +EFI_STATUS
> +ProcessCapsuleOnDisk (
> + IN VOID **CapsuleBuffer,
> + IN UINTN *CapsuleBufferSize,
> + IN CHAR16 **FilePath,
> + IN CHAR16 *Map,
> + IN UINTN CapsuleNum
> + )
> +{
> + EFI_STATUS Status;
> + UINT16 BootNext;
> + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
> + BOOLEAN UpdateBootNext;
> +
> + //
> + // Get a valid file system from boot path
> + //
> + Fs = NULL;
> +
> + Status = GetUpdateFileSystem (Map, &BootNext, &Fs, &UpdateBootNext);
> + if (EFI_ERROR (Status)) {
> + Print (L"CapsuleApp: cannot find a valid file system on boot devies. Status
> = %r\n", Status);
> + return Status;
> + }
> +
> + //
> + // Copy capsule image to '\efi\UpdateCapsule\'
> + //
> + Status = WriteUpdateFile (CapsuleBuffer, CapsuleBufferSize, FilePath,
> CapsuleNum, Fs);
> + if (EFI_ERROR (Status)) {
> + Print (L"CapsuleApp: capsule image could not be copied for update.\n");
> + return Status;
> + }
> +
> + //
> + // Set variable then reset
> + //
> + Status = SetCapsuleStatusVariable (TRUE);
> + if (EFI_ERROR (Status)) {
> + Print (L"CapsuleApp: unable to set OSIndication variable.\n");
> + return Status;
> + }
> +
> + if (UpdateBootNext) {
> + Status = gRT->SetVariable (
> + L"BootNext",
> + &gEfiGlobalVariableGuid,
> + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
> | EFI_VARIABLE_NON_VOLATILE,
> + sizeof(UINT16),
> + &BootNext
> + );
> + if (EFI_ERROR (Status)){
> + Print (L"CapsuleApp: unable to set BootNext variable.\n");
> + return Status;
> + }
> + }
> +
> + return EFI_SUCCESS;
> +}
> --
> 2.16.2.windows.1
next prev parent reply other threads:[~2019-01-29 14:02 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-29 7:43 [PATCH v3 0/4] Introduce CapsuleApp patch v3 Chen A Chen
2019-01-29 7:43 ` [PATCH v3 1/4] MdePkg/UefiSpec.h: Add definition to support Capsule-on-Disk feature Chen A Chen
2019-01-29 9:00 ` Ni, Ray
2019-01-29 7:43 ` [PATCH v3 2/4] MdeModulePkg/CapsuleApp: Add a function used to get next DevicePath Chen A Chen
2019-01-29 14:02 ` Wang, Jian J
2019-01-29 7:43 ` [PATCH v3 3/4] MdeModulePkg/CapsuleApp: Add functions to support Capsule-on-Disk Chen A Chen
2019-01-29 14:02 ` Wang, Jian J [this message]
2019-01-29 7:43 ` [PATCH v3 4/4] MdeModulePkg/CapsuleApp: Enhance CapsuleApp " Chen A Chen
2019-01-29 14:01 ` Wang, Jian J
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=D827630B58408649ACB04F44C5100036258A8653@SHSMSX107.ccr.corp.intel.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