123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818 |
- /** @file
- Process Capsule On Disk.
- Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #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;
- NumberEfiSystemPartitions = 0;
- ShellProtocol = GetShellProtocol ();
- if (ShellProtocol == NULL) {
- Print (L"Get Shell Protocol Fail\n");;
- return ;
- }
- 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, (VOID **)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] 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
- @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, (VOID **)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 = EfiBootManagerGetNextLoadOptionDevicePath (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] Fs The file system within EfiSysPartition
- @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;
- BootOptionBuffer = NULL;
- ShellProtocol = GetShellProtocol ();
- if (ShellProtocol == NULL) {
- Print (L"Get Shell Protocol Fail\n");;
- return EFI_NOT_FOUND;
- }
- //
- // 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,
- (VOID **)&BootNextData,
- NULL
- );
- if (EFI_ERROR (Status) || BootNextData == NULL) {
- Print (L"Get Boot Next Data Fail. Status = %r\n", Status);
- return EFI_NOT_FOUND;
- } else {
- 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 ( (BootOptionBuffer == NULL) ||
- (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;
- EFI_FILE *FileHandle;
- EFI_FILE_PROTOCOL *DirHandle;
- UINT64 FileInfo;
- VOID *Filebuffer;
- UINTN FileSize;
- UINTN Index;
- DirHandle = NULL;
- FileHandle = NULL;
- Index = 0;
- //
- // 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, L"\\EFI", EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
- if (EFI_ERROR (Status)) {
- Status = Root->Open (Root, &DirHandle, L"\\EFI", 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", L"\\EFI");
- return EFI_NOT_FOUND;
- }
- }
- Status = Root->Open (Root, &DirHandle, EFI_CAPSULE_FILE_DIRECTORY, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE , 0);
- if (EFI_ERROR (Status)) {
- Status = Root->Open (Root, &DirHandle, EFI_CAPSULE_FILE_DIRECTORY, 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", EFI_CAPSULE_FILE_DIRECTORY);
- 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] CapsuleBufferSize An array of UINTN to capsule images size
- @param[in] FilePath An array of capsule images file path
- @param[in] Map File system mapping string
- @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;
- }
|