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