194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin/** @file 294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin* 394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin* Copyright (c) 2012-2014, ARM Limited. All rights reserved. 494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin* 594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin* This program and the accompanying materials 694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin* are licensed and made available under the terms and conditions of the BSD License 794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin* which accompanies this distribution. The full text of the license may be found at 894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin* http://opensource.org/licenses/bsd-license.php 994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin* 1094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 1194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 1294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin* 1394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin**/ 1494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 1594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin#include "BootMonFsInternal.h" 1694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 1794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFIAPI 1894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFI_STATUS 1994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinOpenBootMonFsOpenVolume ( 2094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, 2194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin OUT EFI_FILE_PROTOCOL **Root 2294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 2394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 2494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin BOOTMON_FS_INSTANCE *Instance; 2594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 2694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Instance = BOOTMON_FS_FROM_FS_THIS (This); 2794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (Instance == NULL) { 2894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_DEVICE_ERROR; 2994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 3094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 3195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Instance->RootFile->Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY; 3295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 3394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin *Root = &Instance->RootFile->File; 3494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 3594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_SUCCESS; 3694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 3794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 3894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinUINT32 3994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinBootMonFsGetImageLength ( 4094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN BOOTMON_FS_FILE *File 4194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 4294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 4394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin UINT32 Index; 4494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin UINT32 FileSize; 4594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin LIST_ENTRY *RegionToFlushLink; 4694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin BOOTMON_FS_FILE_REGION *Region; 4794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 4894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin FileSize = 0; 4994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 5094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // Look at all Flash areas to determine file size 5194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin for (Index = 0; Index < HW_IMAGE_DESCRIPTION_REGION_MAX; Index++) { 5294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin FileSize += File->HwDescription.Region[Index].Size; 5394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 5494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 5594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // Add the regions that have not been flushed yet 5694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin for (RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink); 5794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin !IsNull (&File->RegionToFlushLink, RegionToFlushLink); 5894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin RegionToFlushLink = GetNextNode (&File->RegionToFlushLink, RegionToFlushLink) 5994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 6094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin { 6194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink; 6294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (Region->Offset + Region->Size > FileSize) { 6394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin FileSize += Region->Offset + Region->Size; 6494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 6594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 6694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 6794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return FileSize; 6894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 6994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 7094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinUINTN 7194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinBootMonFsGetPhysicalSize ( 7294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN BOOTMON_FS_FILE* File 7394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 7494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 7594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // Return 0 for files that haven't yet been flushed to media 7694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (File->HwDescription.RegionCount == 0) { 7794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return 0; 7894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 7994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 8094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return ((File->HwDescription.BlockEnd - File->HwDescription.BlockStart) + 1 ) 8194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin * File->Instance->Media->BlockSize; 8294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 8394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 8494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFIAPI 8594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFI_STATUS 8694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinBootMonFsSetDirPosition ( 8794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN EFI_FILE_PROTOCOL *This, 8894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN UINT64 Position 8994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 9094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 9194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin BOOTMON_FS_FILE *File; 9294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 9394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); 9494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (File == NULL) { 9594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_INVALID_PARAMETER; 9694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 9794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 9894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // UEFI Spec section 12.5: 9994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // "The seek request for nonzero is not valid on open directories." 10094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (Position != 0) { 10194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_UNSUPPORTED; 10294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 10394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin File->Position = Position; 10494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 10594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_SUCCESS; 10694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 10794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 10894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFI_STATUS 10994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinBootMonFsOpenDirectory ( 11094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin OUT EFI_FILE_PROTOCOL **NewHandle, 11194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN CHAR16 *FileName, 11294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN BOOTMON_FS_INSTANCE *Volume 11394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 11494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 11594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ASSERT(0); 11694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 11794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_UNSUPPORTED; 11894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 11995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 12095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald CronSTATIC 12194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFI_STATUS 12294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinGetFileSystemVolumeLabelInfo ( 12394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN BOOTMON_FS_INSTANCE *Instance, 12494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN OUT UINTN *BufferSize, 12594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin OUT VOID *Buffer 12694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 12794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 12894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin UINTN Size; 12994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin EFI_FILE_SYSTEM_VOLUME_LABEL *Label; 13094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin EFI_STATUS Status; 13194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 13294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Label = Buffer; 13394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 13494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // Value returned by StrSize includes null terminator. 13594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Size = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL 13694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin + StrSize (Instance->FsInfo.VolumeLabel); 13794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 13894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (*BufferSize >= Size) { 13994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin CopyMem (&Label->VolumeLabel, &Instance->FsInfo.VolumeLabel, Size); 14094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Status = EFI_SUCCESS; 14194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } else { 14294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Status = EFI_BUFFER_TOO_SMALL; 14394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 14494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin *BufferSize = Size; 14594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return Status; 14694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 14794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 14894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin// Helper function that calculates a rough "free space" by: 14994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin// - Taking the media size 15094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin// - Subtracting the sum of all file sizes 15194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin// - Subtracting the block size times the number of files 15294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin// (To account for the blocks containing the HW_IMAGE_INFO 15394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinSTATIC 15494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinUINT64 15594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinComputeFreeSpace ( 15694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN BOOTMON_FS_INSTANCE *Instance 15794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 15894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 15994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin LIST_ENTRY *FileLink; 16094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin UINT64 FileSizeSum; 16194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin UINT64 MediaSize; 16294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin UINTN NumFiles; 16394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin EFI_BLOCK_IO_MEDIA *Media; 16494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin BOOTMON_FS_FILE *File; 16594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 16694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Media = Instance->BlockIo->Media; 16794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin MediaSize = Media->BlockSize * (Media->LastBlock + 1); 16894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 16994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin NumFiles = 0; 17094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin FileSizeSum = 0; 17194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin for (FileLink = GetFirstNode (&Instance->RootFile->Link); 17294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin !IsNull (&Instance->RootFile->Link, FileLink); 17394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin FileLink = GetNextNode (&Instance->RootFile->Link, FileLink) 17494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 17594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin { 17694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin File = BOOTMON_FS_FILE_FROM_LINK_THIS (FileLink); 17794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin FileSizeSum += BootMonFsGetImageLength (File); 17894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 17994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin NumFiles++; 18094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 18194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 18294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return MediaSize - (FileSizeSum + (Media->BlockSize + NumFiles)); 18394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 18494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 18595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald CronSTATIC 18694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFI_STATUS 18794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinGetFilesystemInfo ( 18894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN BOOTMON_FS_INSTANCE *Instance, 18994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN OUT UINTN *BufferSize, 19094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin OUT VOID *Buffer 19194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 19294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 19394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin EFI_STATUS Status; 19494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 19594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (*BufferSize >= Instance->FsInfo.Size) { 19694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Instance->FsInfo.FreeSpace = ComputeFreeSpace (Instance); 19794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin CopyMem (Buffer, &Instance->FsInfo, Instance->FsInfo.Size); 19894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Status = EFI_SUCCESS; 19994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } else { 20094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Status = EFI_BUFFER_TOO_SMALL; 20194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 20294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 20394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin *BufferSize = Instance->FsInfo.Size; 20494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return Status; 20594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 20694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 20795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald CronSTATIC 20894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFI_STATUS 20994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinGetFileInfo ( 21095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron IN BOOTMON_FS_INSTANCE *Instance, 21195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron IN BOOTMON_FS_FILE *File, 21295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron IN OUT UINTN *BufferSize, 21395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron OUT VOID *Buffer 21494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 21594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 21695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron EFI_FILE_INFO *Info; 21795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron UINTN ResultSize; 21894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 21995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron ResultSize = SIZE_OF_EFI_FILE_INFO + StrSize (File->Info->FileName); 22094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 22194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (*BufferSize < ResultSize) { 22294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin *BufferSize = ResultSize; 22394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_BUFFER_TOO_SMALL; 22494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 22594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 22694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Info = Buffer; 22794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 22895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron CopyMem (Info, File->Info, ResultSize); 22995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // Size of the information 23094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Info->Size = ResultSize; 23194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 23294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin *BufferSize = ResultSize; 23394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 23494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_SUCCESS; 23594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 23694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 23794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinSTATIC 23894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFI_STATUS 239da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry LiebelGetBootMonFsFileInfo ( 240da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel IN BOOTMON_FS_INSTANCE *Instance, 241da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel IN BOOTMON_FS_FILE *File, 242da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel IN OUT UINTN *BufferSize, 243da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel OUT VOID *Buffer 244da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel ) 245da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel{ 246da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel EFI_STATUS Status; 247da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel BOOTMON_FS_FILE_INFO *Info; 248da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel UINTN ResultSize; 249da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel UINTN Index; 250da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel 251da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel if (File == Instance->RootFile) { 252da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel Status = EFI_UNSUPPORTED; 253da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel } else { 254da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel ResultSize = SIZE_OF_BOOTMON_FS_FILE_INFO; 255da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel 256da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel if (*BufferSize < ResultSize) { 257da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel *BufferSize = ResultSize; 258da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel Status = EFI_BUFFER_TOO_SMALL; 259da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel } else { 260da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel Info = Buffer; 261da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel 262da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel // Zero out the structure 263da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel ZeroMem (Info, ResultSize); 264da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel 265da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel // Fill in the structure 266da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel Info->Size = ResultSize; 267da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel 268da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel Info->EntryPoint = File->HwDescription.EntryPoint; 269da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel Info->RegionCount = File->HwDescription.RegionCount; 270da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel for (Index = 0; Index < File->HwDescription.RegionCount; Index++) { 271da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel Info->Region[Index].LoadAddress = File->HwDescription.Region[Index].LoadAddress; 272da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel Info->Region[Index].Size = File->HwDescription.Region[Index].Size; 273da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel Info->Region[Index].Offset = File->HwDescription.Region[Index].Offset; 274da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel Info->Region[Index].Checksum = File->HwDescription.Region[Index].Checksum; 275da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel } 276da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel *BufferSize = ResultSize; 277da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel Status = EFI_SUCCESS; 278da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel } 279da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel } 280da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel 281da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel return Status; 282da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel} 283da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel 28495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron/** 28595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Set the name of a file. 28695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 28795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron This is a helper function for SetFileInfo(). 28895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 28995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @param[in] Instance A pointer to the description of the volume 29095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron the file belongs to. 29195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @param[in] File A pointer to the description of the file. 29295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @param[in] FileName A pointer to the new name of the file. 29395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 29495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_SUCCESS The name was set. 29595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file 29695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron to a file that is already present. 29795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 29895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron**/ 299da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry LiebelSTATIC 300da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry LiebelEFI_STATUS 30194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinSetFileName ( 30295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron IN BOOTMON_FS_INSTANCE *Instance, 30395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron IN BOOTMON_FS_FILE *File, 30495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron IN CONST CHAR16 *FileName 30594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 30694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 30795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron CHAR16 TruncFileName[MAX_NAME_LENGTH]; 30895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron CHAR8 AsciiFileName[MAX_NAME_LENGTH]; 30995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron BOOTMON_FS_FILE *SameFile; 31095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 31195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // If the file path start with a \ strip it. The EFI Shell may 31295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // insert a \ in front of the file name. 31395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (FileName[0] == L'\\') { 31495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron FileName++; 31594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 31694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 31795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron StrnCpy (TruncFileName, FileName, MAX_NAME_LENGTH - 1); 31895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron TruncFileName[MAX_NAME_LENGTH - 1] = 0; 31995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron UnicodeStrToAsciiStr (TruncFileName, AsciiFileName); 32095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 32195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (BootMonGetFileFromAsciiFileName ( 32295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron File->Instance, 32395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron AsciiFileName, 32495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron &SameFile 32595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron ) != EFI_NOT_FOUND) { 32635d3b52ddd168318892f8598611e6544b3f5a545Brendan Jackman // A file with that name already exists. 32795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_ACCESS_DENIED; 32894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } else { 32935d3b52ddd168318892f8598611e6544b3f5a545Brendan Jackman // OK, change the filename. 33095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron AsciiStrToUnicodeStr (AsciiFileName, File->Info->FileName); 33195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_SUCCESS; 33294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 33394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 33494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 33595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron/** 33695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Set the size of a file. 33795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 33895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron This is a helper function for SetFileInfo(). 33995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 34095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @param[in] Instance A pointer to the description of the volume 34195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron the file belongs to. 34295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @param[in] File A pointer to the description of the file. 34395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @param[in] NewSize The requested new size for the file. 34495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 34595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_SUCCESS The size was set. 34695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_OUT_OF_RESOURCES An allocation needed to process the request failed. 34795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 34895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron**/ 34994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinSTATIC 35094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFI_STATUS 35194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinSetFileSize ( 35295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron IN BOOTMON_FS_INSTANCE *Instance, 35395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron IN BOOTMON_FS_FILE *BootMonFsFile, 35495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron IN UINTN NewSize 35594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 35694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 35795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron EFI_STATUS Status; 35895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron UINT32 OldSize; 35995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron LIST_ENTRY *RegionToFlushLink; 36095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron LIST_ENTRY *NextRegionToFlushLink; 36195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron BOOTMON_FS_FILE_REGION *Region; 36295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron EFI_FILE_PROTOCOL *File; 36395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron CHAR8 *Buffer; 36495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron UINTN BufferSize; 36595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron UINT64 StoredPosition; 36694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 36795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron OldSize = BootMonFsFile->Info->FileSize; 36894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 36995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // 37095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // In case of file truncation, force the regions waiting for writing to 37195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // not overflow the new size of the file. 37295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // 37395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (NewSize < OldSize) { 37495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron for (RegionToFlushLink = GetFirstNode (&BootMonFsFile->RegionToFlushLink); 37595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron !IsNull (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink); 37695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron ) 37795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron { 37895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron NextRegionToFlushLink = GetNextNode (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink); 37995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink; 38095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (Region->Offset > NewSize) { 38195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron RemoveEntryList (RegionToFlushLink); 38295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron FreePool (Region->Buffer); 38395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron FreePool (Region); 38495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } else { 38595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Region->Size = MIN (Region->Size, NewSize - Region->Offset); 38695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 38795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron RegionToFlushLink = NextRegionToFlushLink; 38895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 38994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 39095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } else if (NewSize > OldSize) { 39194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // Increasing a file's size is potentially complicated as it may require 39294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // moving the image description on media. The simplest way to do it is to 39394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // seek past the end of the file (which is valid in UEFI) and perform a 39494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // Write. 39595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron File = &BootMonFsFile->File; 39694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 39794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // Save position 39894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Status = File->GetPosition (File, &StoredPosition); 39994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (EFI_ERROR (Status)) { 40094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return Status; 40194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 40295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // Set position at the end of the file 40395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Status = File->SetPosition (File, OldSize); 40494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (EFI_ERROR (Status)) { 40594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return Status; 40694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 40795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 40895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron BufferSize = NewSize - OldSize; 40995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Buffer = AllocateZeroPool (BufferSize); 41095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (Buffer == NULL) { 41195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_OUT_OF_RESOURCES; 41294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 41394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 41495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Status = File->Write (File, &BufferSize, Buffer); 41595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron FreePool (Buffer); 41694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (EFI_ERROR (Status)) { 41794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return Status; 41894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 41994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 42095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // Restore saved position 42195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Status = File->SetPosition (File, StoredPosition); 42294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (EFI_ERROR (Status)) { 42394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return Status; 42494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 42594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 42695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 42795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron BootMonFsFile->Info->FileSize = NewSize; 42895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 42994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_SUCCESS; 43094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 43194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 43295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron/** 43395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Set information about a file. 43495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 43595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @param[in] Instance A pointer to the description of the volume 43695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron the file belongs to. 43795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @param[in] File A pointer to the description of the file. 43895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @param[in] Info A pointer to the file information to write. 43995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 44095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_SUCCESS The information was set. 44195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_ACCESS_DENIED An attempt is being made to change the 44295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron EFI_FILE_DIRECTORY Attribute. 44395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_ACCESS_DENIED The file was opened in read-only mode and an 44495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron attempt is being made to modify a field other 44595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron than Attribute. 44695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file 44795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron to a file that is already present. 44895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only 44995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron attribute. 45095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_OUT_OF_RESOURCES An allocation needed to process the request 45195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron failed. 45295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 45395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron**/ 45495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald CronSTATIC 45594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFI_STATUS 45694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinSetFileInfo ( 45795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron IN BOOTMON_FS_INSTANCE *Instance, 45895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron IN BOOTMON_FS_FILE *File, 45995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron IN EFI_FILE_INFO *Info 46094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 46194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 46295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron EFI_STATUS Status; 46395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron BOOLEAN FileSizeIsDifferent; 46495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron BOOLEAN FileNameIsDifferent; 46595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron BOOLEAN TimeIsDifferent; 46694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 46795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // 46895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // A directory can not be changed to a file and a file can 46995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // not be changed to a directory. 47095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // 47195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if ((Info->Attribute & EFI_FILE_DIRECTORY) != 47295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron (File->Info->Attribute & EFI_FILE_DIRECTORY) ) { 47395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_ACCESS_DENIED; 47495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 47594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 47695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron FileSizeIsDifferent = (Info->FileSize != File->Info->FileSize); 47795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron FileNameIsDifferent = (StrnCmp ( 47895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Info->FileName, 47995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron File->Info->FileName, 48095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron MAX_NAME_LENGTH - 1 48195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron ) != 0); 48295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // 48395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // Check if the CreateTime, LastAccess or ModificationTime 48495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // have been changed. The file system does not support file 48595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // timestamps thus the three times in "File->Info" are 48695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // always equal to zero. The following comparison actually 48795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // checks if all three times are still equal to 0 or not. 48895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // 48995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron TimeIsDifferent = CompareMem ( 49095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron &Info->CreateTime, 49195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron &File->Info->CreateTime, 49295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 3 * sizeof (EFI_TIME) 49395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron ) != 0; 49494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 49595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // 49695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // For a file opened in read-only mode, only the Attribute field can be 49795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // modified. The root directory open mode is forced to read-only at opening 49895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // thus the following test protects the root directory to be somehow modified. 49995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // 50095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (File->OpenMode == EFI_FILE_MODE_READ) { 50195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (FileSizeIsDifferent || FileNameIsDifferent || TimeIsDifferent) { 50294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_ACCESS_DENIED; 50394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 50495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 50595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 50695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (TimeIsDifferent) { 50795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_WRITE_PROTECTED; 50895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 50994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 51095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (FileSizeIsDifferent) { 51195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Status = SetFileSize (Instance, File, Info->FileSize); 51294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (EFI_ERROR (Status)) { 51394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return Status; 51494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 51595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 51694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 51795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // 51895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // Note down in RAM the Attribute field but we can not 51995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // ask to store it in flash for the time being. 52095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // 52195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron File->Info->Attribute = Info->Attribute; 52295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 52395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (FileNameIsDifferent) { 52495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Status = SetFileName (Instance, File, Info->FileName); 52594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (EFI_ERROR (Status)) { 52694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return Status; 52794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 52894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 52995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 53095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_SUCCESS; 53194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 53294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 53394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFIAPI 53494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFI_STATUS 53594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinBootMonFsGetInfo ( 53694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN EFI_FILE_PROTOCOL *This, 53794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN EFI_GUID *InformationType, 53894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN OUT UINTN *BufferSize, 53994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin OUT VOID *Buffer 54094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 54194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 54294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin EFI_STATUS Status; 54394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin BOOTMON_FS_FILE *File; 54494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin BOOTMON_FS_INSTANCE *Instance; 54594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 54695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if ((This == NULL) || 54795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron (InformationType == NULL) || 54895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron (BufferSize == NULL) || 54995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron ((Buffer == NULL) && (*BufferSize > 0)) ) { 55095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_INVALID_PARAMETER; 55194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 55294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 55395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); 55495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (File->Info == NULL) { 55595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_INVALID_PARAMETER; 55695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 55794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Instance = File->Instance; 55894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 55994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // If the instance has not been initialized yet then do it ... 56094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (!Instance->Initialized) { 56194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Status = BootMonFsInitialize (Instance); 56294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } else { 56394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Status = EFI_SUCCESS; 56494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 56594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 56694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (!EFI_ERROR (Status)) { 56794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid) 56894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin != 0) { 56994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Status = GetFileSystemVolumeLabelInfo (Instance, BufferSize, Buffer); 57094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) { 57194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Status = GetFilesystemInfo (Instance, BufferSize, Buffer); 57294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) { 57394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Status = GetFileInfo (Instance, File, BufferSize, Buffer); 574da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel } else if (CompareGuid (InformationType, &gArmBootMonFsFileInfoGuid) != 0) { 575da5daf369fd4c130e0dbf43c292cc57ee8eabcdfHarry Liebel Status = GetBootMonFsFileInfo (Instance, File, BufferSize, Buffer); 57694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } else { 57794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Status = EFI_UNSUPPORTED; 57894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 57994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 58094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 58194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return Status; 58294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 58394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 58495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron/** 58595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Set information about a file or a volume. 58695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 58795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that 58895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron is the file handle the information is for. 58995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @param[in] InformationType The type identifier for the information being set : 59095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or 59195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron EFI_FILE_SYSTEM_VOLUME_LABEL_ID 59295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @param[in] BufferSize The size, in bytes, of Buffer. 59395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @param[in] Buffer A pointer to the data buffer to write. The type of the 59495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron data inside the buffer is indicated by InformationType. 59595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 59695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_SUCCESS The information was set. 59795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_UNSUPPORTED The InformationType is not known. 59895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed. 59995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file 60095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron to a file that is already present. 60195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_ACCESS_DENIED An attempt is being made to change the 60295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron EFI_FILE_DIRECTORY Attribute. 60395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and 60495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron the file was opened in read-only mode and an 60595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron attempt is being made to modify a field other 60695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron than Attribute. 60795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only 60895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron attribute. 60995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_BAD_BUFFER_SIZE The size of the buffer is lower than that indicated by 61095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron the data inside the buffer. 61195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_OUT_OF_RESOURCES A allocation needed to process the request failed. 61295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. 61395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 61495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron**/ 61594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFIAPI 61694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFI_STATUS 61794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinBootMonFsSetInfo ( 61894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN EFI_FILE_PROTOCOL *This, 61994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN EFI_GUID *InformationType, 62094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN UINTN BufferSize, 62194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN VOID *Buffer 62294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 62394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 62495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron BOOTMON_FS_FILE *File; 62595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron EFI_FILE_INFO *Info; 62695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron EFI_FILE_SYSTEM_INFO *SystemInfo; 62795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 62895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if ((This == NULL) || 62995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron (InformationType == NULL) || 63095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron (Buffer == NULL) ) { 63195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_INVALID_PARAMETER; 63295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 63394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 63494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); 63595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (File->Info == NULL) { 63695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_INVALID_PARAMETER; 63794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 63894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 63995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { 64095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron Info = Buffer; 64195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (Info->Size < (SIZE_OF_EFI_FILE_INFO + StrSize (Info->FileName))) { 64295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_INVALID_PARAMETER; 64395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 64495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (BufferSize < Info->Size) { 64595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_BAD_BUFFER_SIZE; 64695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 64795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return (SetFileInfo (File->Instance, File, Info)); 64895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 64994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 65095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // 65195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // The only writable field in the other two information types 65295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // (i.e. EFI_FILE_SYSTEM_INFO and EFI_FILE_SYSTEM_VOLUME_LABEL) is the 65395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // filesystem volume label. This can be retrieved with GetInfo, but it is 65495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // hard-coded into this driver, not stored on media. 65595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron // 65695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 65795204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) { 65895204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron SystemInfo = Buffer; 65995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (SystemInfo->Size < 66095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron (SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (SystemInfo->VolumeLabel))) { 66195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_INVALID_PARAMETER; 66295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 66395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (BufferSize < SystemInfo->Size) { 66495204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_BAD_BUFFER_SIZE; 66595204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 66695204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_WRITE_PROTECTED; 66794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 66894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 66995204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) { 67095204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_WRITE_PROTECTED; 67195204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron } 67295204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron 67395204533ad8ef83e0f5128ce03831eb5bcbac6cfRonald Cron return EFI_UNSUPPORTED; 67494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 67594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 67694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFIAPI 67794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFI_STATUS 67894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinBootMonFsReadDirectory ( 67994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN EFI_FILE_PROTOCOL *This, 68094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN OUT UINTN *BufferSize, 68194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin OUT VOID *Buffer 68294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 68394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 68494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin BOOTMON_FS_INSTANCE *Instance; 68594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin BOOTMON_FS_FILE *RootFile; 68694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin BOOTMON_FS_FILE *File; 68794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin EFI_FILE_INFO *Info; 68894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin UINTN NameSize; 68994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin UINTN ResultSize; 69094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin EFI_STATUS Status; 69194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin UINTN Index; 69294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 69394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin RootFile = BOOTMON_FS_FILE_FROM_FILE_THIS (This); 69494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (RootFile == NULL) { 69594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_INVALID_PARAMETER; 69694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 69794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 69894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Instance = RootFile->Instance; 69994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Status = BootMonGetFileFromPosition (Instance, RootFile->Position, &File); 70094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (EFI_ERROR (Status)) { 70194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // No more file 70294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin *BufferSize = 0; 70394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_SUCCESS; 70494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 70594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 70694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin NameSize = AsciiStrLen (File->HwDescription.Footer.Filename) + 1; 70794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ResultSize = SIZE_OF_EFI_FILE_INFO + (NameSize * sizeof (CHAR16)); 70894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (*BufferSize < ResultSize) { 70994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin *BufferSize = ResultSize; 71094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_BUFFER_TOO_SMALL; 71194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 71294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 71394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // Zero out the structure 71494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Info = Buffer; 71594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ZeroMem (Info, ResultSize); 71694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 71794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // Fill in the structure 71894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Info->Size = ResultSize; 71994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Info->FileSize = BootMonFsGetImageLength (File); 72094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Info->PhysicalSize = BootMonFsGetPhysicalSize (File); 72194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin for (Index = 0; Index < NameSize; Index++) { 72294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Info->FileName[Index] = File->HwDescription.Footer.Filename[Index]; 72394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 72494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 72594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin *BufferSize = ResultSize; 72694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin RootFile->Position++; 72794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 72894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_SUCCESS; 72994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 73094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 73194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFIAPI 73294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinEFI_STATUS 73394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier MartinBootMonFsFlushDirectory ( 73494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin IN EFI_FILE_PROTOCOL *This 73594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 73694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin{ 73794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin BOOTMON_FS_FILE *RootFile; 73894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin LIST_ENTRY *ListFiles; 73994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin LIST_ENTRY *Link; 74094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin BOOTMON_FS_FILE *File; 74194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 74294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin RootFile = BOOTMON_FS_FILE_FROM_FILE_THIS (This); 74394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (RootFile == NULL) { 74494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_INVALID_PARAMETER; 74594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 74694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 74794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ListFiles = &RootFile->Link; 74894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 74994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin if (IsListEmpty (ListFiles)) { 75094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_SUCCESS; 75194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 75294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 75394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // 75494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // Flush all the files that need to be flushed 75594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // 75694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 75794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin // Go through all the list of files to flush them 75894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin for (Link = GetFirstNode (ListFiles); 75994e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin !IsNull (ListFiles, Link); 76094e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin Link = GetNextNode (ListFiles, Link) 76194e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin ) 76294e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin { 76394e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin File = BOOTMON_FS_FILE_FROM_LINK_THIS (Link); 76494e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin File->File.Flush (&File->File); 76594e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin } 76694e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin 76794e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin return EFI_SUCCESS; 76894e0955d3e8a3d949e3f00fe69b2827a637058c3Olivier Martin} 769