From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.115; helo=mga14.intel.com; envelope-from=jian.j.wang@intel.com; receiver=edk2-devel@lists.01.org Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id C9CAC211B696B for ; Tue, 29 Jan 2019 06:02:10 -0800 (PST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 29 Jan 2019 06:02:10 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,537,1539673200"; d="scan'208";a="120386059" Received: from fmsmsx106.amr.corp.intel.com ([10.18.124.204]) by fmsmga008.fm.intel.com with ESMTP; 29 Jan 2019 06:02:10 -0800 Received: from fmsmsx157.amr.corp.intel.com (10.18.116.73) by FMSMSX106.amr.corp.intel.com (10.18.124.204) with Microsoft SMTP Server (TLS) id 14.3.408.0; Tue, 29 Jan 2019 06:02:10 -0800 Received: from shsmsx102.ccr.corp.intel.com (10.239.4.154) by FMSMSX157.amr.corp.intel.com (10.18.116.73) with Microsoft SMTP Server (TLS) id 14.3.408.0; Tue, 29 Jan 2019 06:02:09 -0800 Received: from shsmsx107.ccr.corp.intel.com ([169.254.9.162]) by shsmsx102.ccr.corp.intel.com ([169.254.2.207]) with mapi id 14.03.0415.000; Tue, 29 Jan 2019 22:02:07 +0800 From: "Wang, Jian J" To: "Chen, Chen A" , "edk2-devel@lists.01.org" CC: "Wu, Hao A" , "Zhang, Chao B" Thread-Topic: [PATCH v3 3/4] MdeModulePkg/CapsuleApp: Add functions to support Capsule-on-Disk Thread-Index: AQHUt6ZnDJBYi/3FgkiY2wsjk0+EzqXGRxfw Date: Tue, 29 Jan 2019 14:02:07 +0000 Message-ID: References: <20190129074341.7032-1-chen.a.chen@intel.com> <20190129074341.7032-4-chen.a.chen@intel.com> In-Reply-To: <20190129074341.7032-4-chen.a.chen@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiOWUzYTAwNWItZThmYi00NzExLWI4YzItYzk4ZTlhZWEzOThlIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiNWJtMjdhblQ5MXRiSzk3YVVGS3huOHhHd3dDNkJpUmJMckFrREQ4MFRRd3V2bStBMVlFRDBmVk1NNGxib0doMSJ9 x-ctpclassification: CTP_NT dlp-product: dlpe-windows dlp-version: 11.0.400.15 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH v3 3/4] MdeModulePkg/CapsuleApp: Add functions to support Capsule-on-Disk X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 29 Jan 2019 14:02:11 -0000 X-List-Received-Date: Tue, 29 Jan 2019 14:02:11 -0000 X-List-Received-Date: Tue, 29 Jan 2019 14:02:11 -0000 X-List-Received-Date: Tue, 29 Jan 2019 14:02:11 -0000 X-List-Received-Date: Tue, 29 Jan 2019 14:02:11 -0000 X-List-Received-Date: Tue, 29 Jan 2019 14:02:11 -0000 X-List-Received-Date: Tue, 29 Jan 2019 14:02:11 -0000 X-List-Received-Date: Tue, 29 Jan 2019 14:02:11 -0000 X-List-Received-Date: Tue, 29 Jan 2019 14:02:11 -0000 X-List-Received-Date: Tue, 29 Jan 2019 14:02:11 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Jian J Wang > -----Original Message----- > From: Chen, Chen A > Sent: Tuesday, January 29, 2019 3:44 PM > To: edk2-devel@lists.01.org > Cc: Chen, Chen A ; Wang, Jian J > ; Wu, Hao A ; Zhang, Chao B > > Subject: [PATCH v3 3/4] MdeModulePkg/CapsuleApp: Add functions to support > Capsule-on-Disk >=20 > BZ:https://bugzilla.tianocore.org/show_bug.cgi?id=3D1482 >=20 > This file provide some basic function to support Capsule-on-Disk. >=20 > Cc: Jian J Wang > Cc: Hao Wu > Cc: Zhang Chao B > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Chen A Chen > --- > .../Application/CapsuleApp/CapsuleOnDisk.c | 806 > +++++++++++++++++++++ > 1 file changed, 806 insertions(+) > create mode 100644 MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c >=20 > 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.
> + 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 > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +EFI_GUID mCapsuleOnDiskBootOptionGuid =3D { 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 =3D GetShellProtocol (); > + if (ShellProtocol =3D=3D NULL) { > + return NULL; > + } > + > + // > + // Open file by FileName. > + // > + Status =3D ShellProtocol->OpenFileByName ( > + FilePath, > + &Handle, > + EFI_FILE_MODE_READ > + ); > + if (EFI_ERROR (Status)) { > + return NULL; > + } > + > + // > + // Get file name from EFI_FILE_INFO. > + // > + FileInfo =3D ShellProtocol->GetFileInfo (Handle); > + ShellProtocol->CloseFile (Handle); > + if (FileInfo =3D=3D 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 =3D DevicePath; > + > + while (!IsDevicePathEnd (TempDevicePath)) { > + if ((DevicePathType (TempDevicePath) =3D=3D MEDIA_DEVICE_PATH) && > + (DevicePathSubType (TempDevicePath) =3D=3D MEDIA_HARDDRIVE_DP)) { > + Hd =3D (HARDDRIVE_DEVICE_PATH *)TempDevicePath; > + if (Hd->MBRType =3D=3D MBR_TYPE_EFI_PARTITION_TABLE_HEADER) { > + break; > + } > + } > + TempDevicePath =3D NextDevicePathNode (TempDevicePath); > + } > + > + if (!IsDevicePathEnd (TempDevicePath)) { > + // > + // Search for EFI system partition protocol on full device path in B= oot Option > + // > + Status =3D 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 =3D GetShellProtocol (); > + NumberEfiSystemPartitions =3D 0; > + > + Print (L"EFI System Partition list:\n"); > + > + gBS->LocateHandleBuffer ( > + ByProtocol, > + &gEfiSimpleFileSystemProtocolGuid, > + NULL, > + &NumberSimpleFileSystemHandles, > + &SimpleFileSystemHandles > + ); > + > + for (Index =3D 0; Index < NumberSimpleFileSystemHandles; Index++) { > + DevicePath =3D DevicePathFromHandle (SimpleFileSystemHandles[Index])= ; > + if (IsEfiSysPartitionDevicePath (DevicePath)) { > + NumberEfiSystemPartitions++; > + Print(L" %s\n %s\n", ShellProtocol->GetMapFromDevicePath > (&DevicePath), ConvertDevicePathToText (DevicePath, TRUE, TRUE)); > + } > + } > + > + if (NumberEfiSystemPartitions =3D=3D 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 =3D 0; > + DataSize =3D sizeof(UINT64); > + Status =3D gRT->GetVariable ( > + L"OsIndications", > + &gEfiGlobalVariableGuid, > + NULL, > + &DataSize, > + &OsIndication > + ); > + if (!EFI_ERROR (Status) && > + (OsIndication & > EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) !=3D 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 =3D gBS->LocateHandleBuffer ( > + ByProtocol, > + &gEfiSimpleFileSystemProtocolGuid, > + NULL, > + &NumberSimpleFileSystemHandles, > + &SimpleFileSystemHandles > + ); > + > + if (EFI_ERROR (Status)) { > + return EFI_NOT_FOUND; > + } > + > + for (Index =3D 0; Index < NumberSimpleFileSystemHandles; Index++) { > + DevicePath =3D DevicePathFromHandle (SimpleFileSystemHandles[Index])= ; > + if (IsEfiSysPartitionDevicePath (DevicePath)) { > + Status =3D gBS->HandleProtocol (SimpleFileSystemHandles[Index], > &gEfiSimpleFileSystemProtocolGuid, Fs); > + if (!EFI_ERROR (Status)) { > + *FsDevicePath =3D 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 =3D DevicePath; > + while (!IsDevicePathEnd (TempDevicePath)) { > + if ((DevicePathType (TempDevicePath) =3D=3D MEDIA_DEVICE_PATH) && > + (DevicePathSubType (TempDevicePath) =3D=3D MEDIA_HARDDRIVE_DP)) { > + Hd =3D (HARDDRIVE_DEVICE_PATH *)TempDevicePath; > + if (Hd->MBRType =3D=3D MBR_TYPE_EFI_PARTITION_TABLE_HEADER) { > + break; > + } > + } > + TempDevicePath =3D NextDevicePathNode (TempDevicePath); > + } > + > + if (!IsDevicePathEnd (TempDevicePath)) { > + // > + // Search for EFI system partition protocol on full device path in B= oot Option > + // > + Status =3D gBS->LocateDevicePath (&gEfiPartTypeSystemPartGuid, > &DevicePath, &Handle); > + > + // > + // Search for simple file system on this handler > + // > + if (!EFI_ERROR (Status)) { > + Status =3D gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProto= colGuid, > Fs); > + if (!EFI_ERROR (Status)) { > + *FsDevicePath =3D 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 =3D NULL; > + FsFullPath =3D NULL; > + // > + // Try every full device Path generated from bootoption > + // > + do { > + PreFullPath =3D CurFullPath; > + CurFullPath =3D EfiBootManagerGetNextFullDevicePath (DevicePath, > CurFullPath); > + > + if (PreFullPath !=3D NULL) { > + FreePool (PreFullPath); > + } > + > + if (CurFullPath =3D=3D NULL) { > + // > + // No Active EFI system partition is found in BootOption device pa= th > + // > + Status =3D EFI_NOT_FOUND; > + break; > + } > + > + DEBUG_CODE ( > + CHAR16 *DevicePathStr; > + > + DevicePathStr =3D ConvertDevicePathToText (CurFullPath, TRUE, TRUE= ); > + if (DevicePathStr !=3D NULL){ > + DEBUG ((DEBUG_INFO, "Full device path %s\n", DevicePathStr)); > + FreePool (DevicePathStr); > + } > + ); > + > + Status =3D GetEfiSysPartitionFromDevPath (CurFullPath, &FsFullPath, = Fs); > + } while (EFI_ERROR (Status)); > + > + if (*Fs !=3D NULL) { > + *FullPath =3D 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 =3D NULL; > + ShellProtocol =3D GetShellProtocol (); > + > + // > + // 1. If Fs is not assigned and there are capsule provisioned before, > + // Get EFI system partition from BootNext. > + // > + if (IsCapsuleProvisioned () && Map =3D=3D NULL) { > + Status =3D GetVariable2 ( > + L"BootNext", > + &gEfiGlobalVariableGuid, > + &BootNextData, > + NULL > + ); > + if (!EFI_ERROR (Status)) { > + UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x= ", > *BootNextData); > + Status =3D EfiBootManagerVariableToLoadOption (BootOptionName, > &BootNextOption); > + if (!EFI_ERROR (Status)) { > + DevicePath =3D BootNextOption.FilePath; > + Status =3D GetEfiSysPartitionFromBootOptionFilePath (DevicePath,= &FullPath, > Fs); > + if (!EFI_ERROR (Status)) { > + *UpdateBootNext =3D FALSE; > + Print(L"Get EFI system partition from BootNext : %s\n", > BootNextOption.Description); > + Print(L"%s %s\n", ShellProtocol->GetMapFromDevicePath (&FullPa= th), > ConvertDevicePathToText (FullPath, TRUE, TRUE)); > + return EFI_SUCCESS; > + } > + } > + } > + } > + > + // > + // Check if Map is valid. > + // > + if (Map !=3D NULL) { > + MappedDevicePath =3D ShellProtocol->GetDevicePathFromMap (Map); > + if (MappedDevicePath =3D=3D 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 =3D EfiBootManagerGetLoadOptions (&BootOptionCount, > LoadOptionTypeBoot); > + if (BootOptionCount =3D=3D 0 && Map =3D=3D NULL) { > + return EFI_NOT_FOUND; > + } > + > + for (Index =3D 0; Index < BootOptionCount; Index++) { > + // > + // Get the boot option from the link list > + // > + DevicePath =3D BootOptionBuffer[Index].FilePath; > + > + // > + // Skip inactive or legacy boot options > + // > + if ((BootOptionBuffer[Index].Attributes & LOAD_OPTION_ACTIVE) =3D=3D= 0 || > + DevicePathType (DevicePath) =3D=3D BBS_DEVICE_PATH) { > + continue; > + } > + > + DEBUG_CODE ( > + CHAR16 *DevicePathStr; > + > + DevicePathStr =3D ConvertDevicePathToText (DevicePath, TRUE, TRUE)= ; > + if (DevicePathStr !=3D NULL){ > + DEBUG ((DEBUG_INFO, "Try BootOption %s\n", DevicePathStr)); > + FreePool (DevicePathStr); > + } else { > + DEBUG ((DEBUG_INFO, "DevicePathToStr failed\n")); > + } > + ); > + > + Status =3D GetEfiSysPartitionFromBootOptionFilePath (DevicePath, &Fu= llPath, > Fs); > + if (!EFI_ERROR (Status)) { > + if (Map =3D=3D NULL) { > + *BootNext =3D (UINT16) BootOptionBuffer[Index].OptionNumber; > + *UpdateBootNext =3D TRUE; > + Print (L"Found EFI system partition on Boot%04x: %s\n", *BootNex= t, > BootOptionBuffer[Index].Description); > + Print (L"%s %s\n", ShellProtocol->GetMapFromDevicePath (&FullPat= h), > ConvertDevicePathToText (FullPath, TRUE, TRUE)); > + return EFI_SUCCESS; > + } > + > + if (StrnCmp (Map, ShellProtocol->GetMapFromDevicePath (&FullPath), > StrLen (Map)) =3D=3D 0) { > + *BootNext =3D (UINT16) BootOptionBuffer[Index].OptionNumber; > + *UpdateBootNext =3D 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 !=3D NULL) { > + // > + // If map is assigned, try to get ESP from mapped Fs. > + // > + DevicePath =3D DuplicateDevicePath (MappedDevicePath); > + Status =3D 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 =3D 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 =3D EfiBootManagerInitializeLoadOption ( > + &NewOption, > + LoadOptionNumberUnassigned, > + LoadOptionTypeBoot, > + LOAD_OPTION_ACTIVE, > + L"UEFI Capsule On Disk", > + DevicePath, > + (UINT8 *) &mCapsuleOnDiskBootOptionGuid, > + sizeof(EFI_GUID) > + ); > + if (!EFI_ERROR (Status)) { > + Status =3D EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN) = -1); > { > + if (!EFI_ERROR (Status)) { > + *UpdateBootNext =3D TRUE; > + *BootNext =3D (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 =3D L"\\EFI\\UpdateCapsu= le"; > + CHAR16 *mDirName1 =3D L"\\EFI"; > + EFI_FILE_PROTOCOL *DirHandle =3D NULL; > + EFI_FILE *FileHandle =3D NULL; > + UINT64 FileInfo; > + UINTN Index =3D 0; > + VOID *Filebuffer; > + UINTN FileSize; > + > + // > + // Open Root from SFS > + // > + Status =3D Fs->OpenVolume (Fs, &Root); > + if (EFI_ERROR (Status)) { > + Print (L"Cannot open volume. Status =3D %r\n", Status); > + return EFI_NOT_FOUND; > + } > + > + // > + // Ensure that efi and updatecapsule directories exist > + // > + Status =3D Root->Open (Root, &DirHandle, mDirName1, EFI_FILE_MODE_READ > | EFI_FILE_MODE_WRITE, 0); > + if (EFI_ERROR (Status)) { > + Status =3D Root->Open (Root, &DirHandle, mDirName1, EFI_FILE_MODE_RE= AD > | 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 =3D Root->Open (Root, &DirHandle, mDirName, EFI_FILE_MODE_READ = | > EFI_FILE_MODE_WRITE , 0); > + if (EFI_ERROR (Status)) { > + Status =3D Root->Open (Root, &DirHandle, mDirName, EFI_FILE_MODE_REA= D > | 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 =3D 0; Index < BufferNum; Index++) { > + FileHandle =3D NULL; > + > + // > + // Open UpdateCapsule file > + // > + Status =3D 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 =3D 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 !=3D 0) { > + // > + // Set the file size to 0. > + // > + FileInfo =3D 0; > + Status =3D FileHandleSetSize (FileHandle, FileInfo); > + if (EFI_ERROR (Status)) { > + Print (L"Error Deleting %s\n", FileName[Index]); > + FileHandleClose (FileHandle); > + return Status; > + } > + } > + > + // > + // Write Filebuffer to file > + // > + Filebuffer =3D Buffer[Index]; > + FileSize =3D BufferSize[Index]; > + Status =3D FileHandleWrite (FileHandle, &FileSize, Filebuffer); > + if (EFI_ERROR (Status)) { > + Print (L"Unable to write Capsule Update to %s, Status =3D %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 =3D 0; > + DataSize =3D sizeof(UINT64); > + Status =3D gRT->GetVariable ( > + L"OsIndications", > + &gEfiGlobalVariableGuid, > + NULL, > + &DataSize, > + &OsIndication > + ); > + if (EFI_ERROR (Status)) { > + OsIndication =3D 0; > + } > + if (SetCap) { > + OsIndication |=3D > ((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED); > + } > + else { > + OsIndication &=3D > ~((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED); > + } > + Status =3D 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 =3D NULL; > + > + Status =3D GetUpdateFileSystem (Map, &BootNext, &Fs, &UpdateBootNext); > + if (EFI_ERROR (Status)) { > + Print (L"CapsuleApp: cannot find a valid file system on boot devies.= Status > =3D %r\n", Status); > + return Status; > + } > + > + // > + // Copy capsule image to '\efi\UpdateCapsule\' > + // > + Status =3D 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 =3D SetCapsuleStatusVariable (TRUE); > + if (EFI_ERROR (Status)) { > + Print (L"CapsuleApp: unable to set OSIndication variable.\n"); > + return Status; > + } > + > + if (UpdateBootNext) { > + Status =3D 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