Esempio n. 1
0
EFIAPI
EFI_STATUS
BootMonFsDelete (
  IN EFI_FILE_PROTOCOL *This
  )
{
  EFI_STATUS               Status;
  BOOTMON_FS_FILE         *File;
  LIST_ENTRY              *RegionToFlushLink;
  BOOTMON_FS_FILE_REGION  *Region;
  HW_IMAGE_DESCRIPTION    *Description;
  EFI_BLOCK_IO_PROTOCOL   *BlockIo;
  UINT8                   *EmptyBuffer;

  File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
  if (File == NULL) {
    return EFI_DEVICE_ERROR;
  }

  Status = EFI_SUCCESS;

  if (BootMonFsFileNeedFlush (File)) {
    // Free the entries from the Buffer List
    RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink);
    do {
      Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;

      // Get Next entry
      RegionToFlushLink = RemoveEntryList (RegionToFlushLink);

      // Free the buffers
      FreePool (Region->Buffer);
      FreePool (Region);
    } while (!IsListEmpty (&File->RegionToFlushLink));
  }

  // If (RegionCount is greater than 0) then the file already exists
  if (File->HwDescription.RegionCount > 0) {
    Description = &File->HwDescription;
    BlockIo = File->Instance->BlockIo;

    // Create an empty buffer
    EmptyBuffer = AllocateZeroPool (BlockIo->Media->BlockSize);
    if (EmptyBuffer == NULL) {
      FreePool (File);
      return EFI_OUT_OF_RESOURCES;
    }

    // Invalidate the last Block
    Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, Description->BlockEnd, BlockIo->Media->BlockSize, EmptyBuffer);
    ASSERT_EFI_ERROR (Status);

    FreePool (EmptyBuffer);
  }

  // Remove the entry from the list
  RemoveEntryList (&File->Link);
  FreePool (File);
  return Status;
}
Esempio n. 2
0
EFI_STATUS
CheckStore (
  IN  EFI_HANDLE                 SimpleFileSystemHandle,
  IN  UINT32                     VolumeId,
  OUT EFI_DEVICE_PATH_PROTOCOL   **Device
  )
{
#define BLOCK_SIZE              0x200
#define FAT16_VOLUME_ID_OFFSET  39
#define FAT32_VOLUME_ID_OFFSET  67
  EFI_STATUS                      Status;
  EFI_BLOCK_IO_PROTOCOL           *BlkIo;
  UINT8                           BootSector[BLOCK_SIZE];

  *Device = NULL;
  Status  = gBS->HandleProtocol (
                   SimpleFileSystemHandle,
                   &gEfiBlockIoProtocolGuid, // BlockIo should be supported if it supports SimpleFileSystem
                   (VOID*)&BlkIo
                   );

  if (EFI_ERROR (Status)) {
    goto ErrHandle;
  }
  if (!BlkIo->Media->MediaPresent) {
    DEBUG ((EFI_D_ERROR, "FwhMappedFile: Media not present!\n"));
    Status = EFI_NO_MEDIA;
    goto ErrHandle;
  }
  if (BlkIo->Media->ReadOnly) {
    DEBUG ((EFI_D_ERROR, "FwhMappedFile: Media is read-only!\n"));
    Status = EFI_ACCESS_DENIED;
    goto ErrHandle;
  }

  Status = BlkIo->ReadBlocks(
                    BlkIo,
                    BlkIo->Media->MediaId,
                    0,
                    BLOCK_SIZE,
                    BootSector
                    );
  ASSERT_EFI_ERROR (Status);
  if ((*(UINT32 *) &BootSector[FAT16_VOLUME_ID_OFFSET] != VolumeId) &&
      (*(UINT32 *) &BootSector[FAT32_VOLUME_ID_OFFSET] != VolumeId)
      ) {
    Status = EFI_NOT_FOUND;
    goto ErrHandle;
  }

  *Device = DuplicateDevicePath (DevicePathFromHandle (SimpleFileSystemHandle));
  ASSERT (*Device != NULL);

ErrHandle:
  return Status;
}
Esempio n. 3
0
EFI_STATUS
BootMonFsDiscoverNextImage (
  IN BOOTMON_FS_INSTANCE      *Instance,
  IN EFI_LBA                  *LbaStart,
  OUT HW_IMAGE_DESCRIPTION    *Image
  )
{
  EFI_BLOCK_IO_PROTOCOL *Blocks;
  EFI_LBA                CurrentLba;
  VOID                  *Out;

  Blocks = Instance->BlockIo;

  // Allocate an output buffer
  Out = AllocatePool (Instance->Media->BlockSize);
  if (Out == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  Blocks->Reset (Blocks, FALSE);
  CurrentLba = *LbaStart;

  // Look for images in the rest of this block
  while (CurrentLba <= Instance->Media->LastBlock) {
    // Read in the next block
    Blocks->ReadBlocks (Blocks, Instance->Media->MediaId, CurrentLba, Instance->Media->BlockSize, Out);
    // Check for an image in the current block
    if (BootMonFsImageInThisBlock (Out, Instance->Media->BlockSize, (CurrentLba - Instance->Media->LowestAlignedLba), Image)) {
      DEBUG ((EFI_D_ERROR, "Found image: %a in block %d.\n", &(Image->Footer.Filename), (UINTN)(CurrentLba - Instance->Media->LowestAlignedLba)));
      FreePool (Out);
      *LbaStart = Image->BlockEnd + 1;
      return EFI_SUCCESS;
    } else {
      CurrentLba++;
    }
  }

  *LbaStart = CurrentLba;
  FreePool (Out);
  return EFI_NOT_FOUND;
}
Esempio n. 4
0
/**
  Read a disk from disk into HBufferImage.

  @param[in] DeviceName   filename to read.
  @param[in] Offset       The offset.
  @param[in] Size         The size.
  @param[in] Recover      if is for recover, no information print.

  @retval EFI_SUCCESS           The operation was successful.
  @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
  @retval EFI_LOAD_ERROR        A load error occured.
  @retval EFI_INVALID_PARAMETER A parameter was invalid.  
**/
EFI_STATUS
HDiskImageRead (
  IN CONST CHAR16   *DeviceName,
  IN UINTN    Offset,
  IN UINTN    Size,
  IN BOOLEAN  Recover
  )
{
  CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
  EFI_DEVICE_PATH_PROTOCOL        *DupDevicePath;
  EFI_DEVICE_PATH_PROTOCOL        *DupDevicePathForFree;
  EFI_HANDLE                      Handle;
  EFI_BLOCK_IO_PROTOCOL           *BlkIo;
  EFI_STATUS                      Status;

  VOID                            *Buffer;
  CHAR16                          *Str;
  UINTN                           Bytes;

  HEFI_EDITOR_LINE                *Line;
  UINT64                          ByteOffset;

  EDIT_FILE_TYPE                  BufferTypeBackup;

  BufferTypeBackup        = HBufferImage.BufferType;
  HBufferImage.BufferType = FileTypeDiskBuffer;

  DevicePath              = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
  if (DevicePath == NULL) {
    StatusBarSetStatusString (L"Cannot Find Device");
    return EFI_INVALID_PARAMETER;
  }
  DupDevicePath = DuplicateDevicePath(DevicePath);
  DupDevicePathForFree = DupDevicePath;
  //
  // get blkio interface
  //
  Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
  FreePool(DupDevicePathForFree);
  if (EFI_ERROR (Status)) {
    StatusBarSetStatusString (L"Read Disk Failed");
    return Status;
  }
  Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
  if (EFI_ERROR (Status)) {
    StatusBarSetStatusString (L"Read Disk Failed");
    return Status;
  }
  //
  // if Offset exceeds LastBlock,
  //   return error
  //
  if (Offset > BlkIo->Media->LastBlock || Offset + Size > BlkIo->Media->LastBlock) {
    StatusBarSetStatusString (L"Invalid Offset + Size");
    return EFI_LOAD_ERROR;
  }

  Bytes   = BlkIo->Media->BlockSize * Size;
  Buffer  = AllocateZeroPool (Bytes);

  if (Buffer == NULL) {
    StatusBarSetStatusString (L"Read Disk Failed");
    return EFI_OUT_OF_RESOURCES;
  }

  ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize);

  //
  // read from disk
  //
  Status = BlkIo->ReadBlocks (
                    BlkIo,
                    BlkIo->Media->MediaId,
                    Offset,
                    Bytes,
                    Buffer
                    );

  if (EFI_ERROR (Status)) {
    FreePool (Buffer);
    StatusBarSetStatusString (L"Read Disk Failed");
    return EFI_LOAD_ERROR;
  }

  HBufferImageFree ();

  //
  // convert buffer to line list
  //
  Status = HBufferImageBufferToList (Buffer, Bytes);
  FreePool (Buffer);

  if (EFI_ERROR (Status)) {
    StatusBarSetStatusString (L"Read Disk Failed");
    return Status;
  }

  Status = HDiskImageSetDiskNameOffsetSize (DeviceName, Offset, Size);
  if (EFI_ERROR (Status)) {
    StatusBarSetStatusString (L"Read Disk Failed");
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // initialize some variables
  //
  HDiskImage.BlockSize                = BlkIo->Media->BlockSize;

  HBufferImage.DisplayPosition.Row    = 2;
  HBufferImage.DisplayPosition.Column = 10;

  HBufferImage.MousePosition.Row      = 2;
  HBufferImage.MousePosition.Column   = 10;

  HBufferImage.LowVisibleRow          = 1;
  HBufferImage.HighBits               = TRUE;

  HBufferImage.BufferPosition.Row     = 1;
  HBufferImage.BufferPosition.Column  = 1;

  if (!Recover) {
    Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
    if (Str == NULL) {
      StatusBarSetStatusString (L"Read Disk Failed");
      return EFI_OUT_OF_RESOURCES;
    }

    StatusBarSetStatusString (Str);
    SHELL_FREE_NON_NULL (Str);

    HMainEditor.SelectStart = 0;
    HMainEditor.SelectEnd   = 0;

  }

  //
  // has line
  //
  if (HBufferImage.Lines != NULL) {
    HBufferImage.CurrentLine = CR (
                                HBufferImage.ListHead->ForwardLink,
                                HEFI_EDITOR_LINE,
                                Link,
                                EFI_EDITOR_LINE_LIST
                                );
  } else {
    //
    // create a dummy line
    //
    Line = HBufferImageCreateLine ();
    if (Line == NULL) {
      StatusBarSetStatusString (L"Read Disk Failed");
      return EFI_OUT_OF_RESOURCES;
    }

    HBufferImage.CurrentLine = Line;
  }

  HBufferImage.Modified           = FALSE;
  HBufferImageNeedRefresh         = TRUE;
  HBufferImageOnlyLineNeedRefresh = FALSE;
  HBufferImageMouseNeedRefresh    = TRUE;

  return EFI_SUCCESS;
}
Esempio n. 5
0
/**
  Read data as fast as possible from a block I/O device

  The ShellCEntryLib library instance wrappers the actual UEFI application
  entry point and calls this ShellAppMain function.

  @param  ImageHandle  The image handle of the UEFI Application.
  @param  SystemTable  A pointer to the EFI System Table.

  @retval  0               The application exited normally.
  @retval  Other           An error occurred.

**/
INTN
EFIAPI 
ShellAppMain (
  IN UINTN Argc, 
  IN CHAR16 **Argv
  )
{
  BOOLEAN bBlockIo2;
  UINT32 BlockIoCount;
  UINT32 BlockIo2Count;
  UINT32 BlocksPerRead;
  UINT32 BlockSize;
  BOOLEAN bReadComplete;
  UINT32 BytesPerSecond;
  UINT32 BytesToRead;
  UINT64 DataRead;
  EFI_LBA Lba;
  EFI_LBA LbaMax;
  EFI_HANDLE Handle;
  UINTN HandleCount;
  UINTN Index;
  UINT64 MaxMBytes;
  UINT64 MaxReads;
  UINT64 MediaBytes;
  UINT32 MediaId;
  EFI_BLOCK_IO_PROTOCOL * pBlockIo;
  EFI_BLOCK_IO2_PROTOCOL * pBlockIo2;
  EFI_HANDLE * pBlockIoArray;
  EFI_HANDLE * pBlockIo2Array;
  EFI_HANDLE * pHandle;
  EFI_HANDLE * pHandleEnd;
  EFI_BLOCK_IO_MEDIA * pMedia;
  EFI_BLOCK_IO2_TOKEN * pToken;
  EFI_BLOCK_IO2_TOKEN * pTokenEnd;
  CHAR8 * pUnits;
  UINT32 Seconds;
  EFI_STATUS Status;
  UINT64 Timeout;
  EFI_EVENT TimeoutEvent;
  UINT32 TestCount;
  UINT32 WarmUpBlocks;

  //
  //  Display the help text
  //
  if ( 1 == Argc ) {
    Print ( L"%s   [/2]   <handle>\r\n", Argv[ 0 ]);
    Print ( L"\r\n" );
    Print ( L"/2 - Use Block I/O 2 protocol\r\n" );

    //
    //  Determine which handles have the block I/O protocol on them
    //
    Print ( L"Block I/O Handles\r\n" );
    Status = gBS->LocateHandleBuffer ( ByProtocol,
                                       &gEfiBlockIoProtocolGuid,
                                       NULL,
                                       &HandleCount,
                                       &pBlockIoArray );
    if ( !EFI_ERROR ( Status )) {
      pHandle = pBlockIoArray;
      BlockIoCount = (UINT32)HandleCount;
      pHandleEnd = &pHandle[ BlockIoCount ];
      while ( pHandleEnd > pHandle ) {
        Handle = *pHandle++;
        Status = gBS->OpenProtocol ( Handle,
                                     &gEfiBlockIoProtocolGuid,
                                     (VOID **)&pBlockIo,
                                     NULL,
                                     NULL,
                                     EFI_OPEN_PROTOCOL_GET_PROTOCOL );
        if ( !EFI_ERROR ( Status )) {
          if (( NULL != pBlockIo )
            && ( NULL != pBlockIo->Media )
            && ( pBlockIo->Media->MediaPresent )) {
            //
            //  Display the handle and device size
            //
            pUnits = "Bytes";
            MediaBytes = MultU64x32 ( pBlockIo->Media->LastBlock + 1,
                                      pBlockIo->Media->BlockSize );
            if ( KIBYTE <= MediaBytes ) {
              pUnits = "KiBytes";
              if ( MIBYTE <= MediaBytes ) {
                pUnits = "MiBytes";
                MediaBytes = DivU64x32 ( MediaBytes, 1024 );
                if ( MIBYTE <= MediaBytes ) {
                  pUnits = "GiBytes";
                  MediaBytes = DivU64x32 ( MediaBytes, 1024 );
                  if ( MIBYTE <= MediaBytes ) {
                    pUnits = "TiBytes";
                    MediaBytes = DivU64x32 ( MediaBytes, 1024 );
                    if ( MIBYTE <= MediaBytes ) {
                      pUnits = "PiBytes";
                      MediaBytes = DivU64x32 ( MediaBytes, 1024 );
                    }
                  }
                }
              }
              BytesToRead = (UINT32)MediaBytes;
              Print ( L"    0x%016Lx: %d.%03d %a\r\n",
                      (UINT64)(UINTN)Handle,
                      BytesToRead / 1024,
                      ( BytesToRead % 1024 ) * 1000 / 1024,
                      pUnits );
            }
            else {
              BytesToRead = (UINT32)MediaBytes;
              Print ( L"    0x%016Lx: %d %a\r\n",
                      (UINT64)(UINTN)Handle,
                      BytesToRead,
                      pUnits );
            }
          }
        }
      }

      //
      //  Free the handle buffer
      //
      gBS->FreePool ( pBlockIoArray );
    }
    else {
      Print ( L"    No block I/O handles found!\r\n" );
    }

    //
    //  Determine which handles have the block I/O 2 protocol on them
    //
    Print ( L"Block I/O 2 Handles\r\n" );
    Status = gBS->LocateHandleBuffer ( ByProtocol,
                                       &gEfiBlockIo2ProtocolGuid,
                                       NULL,
                                       &HandleCount,
                                       &pBlockIo2Array );
    if ( !EFI_ERROR ( Status )) {
      pHandle = pBlockIo2Array;
      BlockIo2Count = (UINT32)HandleCount;
      pHandleEnd = &pHandle[ BlockIo2Count ];
      while ( pHandleEnd > pHandle ) {
        Handle = *pHandle++;
        Status = gBS->OpenProtocol ( Handle,
                                     &gEfiBlockIoProtocolGuid,
                                     (VOID **)&pBlockIo,
                                     NULL,
                                     NULL,
                                     EFI_OPEN_PROTOCOL_GET_PROTOCOL );
        if ( !EFI_ERROR ( Status )) {
          if (( NULL != pBlockIo )
            && ( NULL != pBlockIo->Media )
            && ( pBlockIo->Media->MediaPresent )) {
            //
            //  Display the handle and device size
            //
            pUnits = "Bytes";
            MediaBytes = MultU64x32 ( pBlockIo->Media->LastBlock + 1,
                                      pBlockIo->Media->BlockSize );
            if ( KIBYTE <= MediaBytes ) {
              pUnits = "KiBytes";
              if ( MIBYTE <= MediaBytes ) {
                pUnits = "MiBytes";
                MediaBytes = DivU64x32 ( MediaBytes, 1024 );
                if ( MIBYTE <= MediaBytes ) {
                  pUnits = "GiBytes";
                  MediaBytes = DivU64x32 ( MediaBytes, 1024 );
                  if ( MIBYTE <= MediaBytes ) {
                    pUnits = "TiBytes";
                    MediaBytes = DivU64x32 ( MediaBytes, 1024 );
                    if ( MIBYTE <= MediaBytes ) {
                      pUnits = "PiBytes";
                      MediaBytes = DivU64x32 ( MediaBytes, 1024 );
                    }
                  }
                }
              }
              BytesToRead = (UINT32)MediaBytes;
              Print ( L"    0x%016Lx: %d.%03d %a\r\n",
                      (UINT64)(UINTN)Handle,
                      BytesToRead / 1024,
                      ( BytesToRead % 1024 ) * 1000 / 1024,
                      pUnits );
            }
            else {
              BytesToRead = (UINT32)MediaBytes;
              Print ( L"    0x%016Lx: %d %a\r\n",
                      (UINT64)(UINTN)Handle,
                      BytesToRead,
                      pUnits );
            }
          }
        }
      }

      //
      //  Free the handle buffer
      //
      gBS->FreePool ( pBlockIo2Array );
    }
    else {
      Print ( L"    No block I/O 2 handles found!\r\n" );
    }

    Print ( L"The test reads %d KiByte buffers as fast as it can for a total\r\n",
            BUFFER_LENGTH_IN_BYTES / 1024 );
    Print ( L"of %d seconds.  At the end of the time, the performance is computed\r\n",
            TEST_TIME_IN_SECONDS );
    Print ( L"by dividing the number of bytes received prior to the timer expiring\r\n" );
    Print ( L"by the test duration.  The test reads at most %d MiBytes from the\r\n",
            MAX_MBYTES );
    Print ( L"beginning of the media before wrapping around to the beginning again.\r\n" );
    Print ( L"As a warm-up, two buffers worth of data are read from the end of the\r\n" );
    Print ( L"%d MiByte region.\r\n",
            MAX_MBYTES );
    return EFI_NOT_STARTED;
  }

  //
  //  Determine if the block I/O 2 protocol should be used
  //
  bBlockIo2 = FALSE;
  pToken = &mTokens[ 0 ];
  pTokenEnd = &pToken[ DIM ( mTokens )];
  if ( 0 == StrCmp ( L"/2", Argv[ 1 ])) {
    bBlockIo2 = TRUE;
  }

  //
  //  Get the handle address
  //
  HandleCount = bBlockIo2 ? 2 : 1;
  Handle = (EFI_HANDLE)StrHexToUintn ( Argv[ HandleCount ]);
  if ( NULL == Handle ) {
    Print ( L"ERROR - Invalid handle value\r\n" );
    return EFI_INVALID_PARAMETER;
  }

  //
  //  Validate the handle
  //
  pBlockIo = NULL;
  pBlockIo2 = NULL;
  Status = gBS->OpenProtocol ( Handle,
                               bBlockIo2
                               ? &gEfiBlockIo2ProtocolGuid
                               : &gEfiBlockIoProtocolGuid,
                               bBlockIo2
                               ? (VOID *)&pBlockIo2
                               : (VOID *)&pBlockIo,
                               NULL,
                               NULL,
                               EFI_OPEN_PROTOCOL_GET_PROTOCOL );
  if ( EFI_ERROR ( Status )) {
    Print ( L"ERROR - %r\r\n", Status );
    return (( Status & MAX_BIT ) ? 0x80000000 : 0 )
            | ( Status & 0x7fffffff );
  }

  //
  //  Create the necessary events
  //
  Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,
                              TPL_NOTIFY,
                              TestComplete,
                              NULL,
                              &TimeoutEvent );
  if ( EFI_ERROR ( Status )) {
    Print ( L"ERROR - Failed to create event, Status: %r\r\n",
             Status );
    return (( Status & MAX_BIT ) ? 0x80000000 : 0 )
            | ( Status & 0x7fffffff );
  }

  while ( pTokenEnd > pToken ) {
    Status = gBS->CreateEvent ( 0,
                                TPL_NOTIFY,
                                NULL,
                                NULL,
                                &pToken->Event );
    if ( EFI_ERROR ( Status )) {
      Print ( L"ERROR - Failed to create token event, Status: %r\r\n",
               Status );
      break;
    }
    pToken += 1;
  }
  if ( !EFI_ERROR ( Status )) {
    //
    //  Display the media parameters
    //
    pMedia = bBlockIo2 ? pBlockIo2->Media : pBlockIo->Media;
    Print ( L"\r\nMedia Parameters:\r\n" );
    Print ( L"  BlockSize: %d bytes\r\n", pMedia->BlockSize );
    Print ( L"  IoAlign: %d bytes\r\n", pMedia->IoAlign );
    Print ( L"  LastBlock: 0x%Lx\r\n", pMedia->LastBlock );
    Print ( L"  LogicalBlocksPerPhysicalBlock: %d\r\n", pMedia->LogicalBlocksPerPhysicalBlock );
    Print ( L"  LogicalPartition: %a\r\n", pMedia->LogicalPartition ? "TRUE" : "FALSE" );
    Print ( L"  LowestAlignedLba: 0x%Lx\r\n", pMedia->LowestAlignedLba );
    Print ( L"  MediaId: 0x%08x\r\n", pMedia->MediaId );
    Print ( L"  MediaPresent: %a\r\n", pMedia->MediaPresent ? "TRUE" : "FALSE" );
#ifdef  EFI_BLOCK_IO_PROTOCOL_REVISION3
    Print ( L"  OptimalTransferLengthGranularity: %d blocks\r\n", pMedia->OptimalTransferLengthGranularity );
#endif  //  EFI_BLOCK_IO_PROTOCOL_REVISION3
    Print ( L"  ReadOnly: %a\r\n", pMedia->ReadOnly ? "TRUE" : "FALSE" );
    Print ( L"  RemovableMedia: %a\r\n", pMedia->RemovableMedia ? "TRUE" : "FALSE" );
    Print ( L"  WriteCaching: %a\r\n", pMedia->WriteCaching ? "TRUE" : "FALSE" );
    Print ( L"\r\n" );

    //
    //  Locate the end of the media
    //
    BlockSize = pMedia->BlockSize;
    MediaBytes = pMedia->LastBlock + 1;
    MediaBytes = MultU64x32 ( MediaBytes, BlockSize );
    BlocksPerRead = sizeof ( mBuffer ) / BlockSize;
    BytesToRead = BlocksPerRead * BlockSize;
    ASSERT ( 0 < BlocksPerRead );
    LbaMax = MAX_MBYTES * 1024L * 1024L;
    LbaMax = DivU64x32 ( LbaMax, BlocksPerRead );
    LbaMax = MultU64x32 ( LbaMax, BlocksPerRead );
    LbaMax = DivU64x32 ( LbaMax, BlockSize );
    if ( LbaMax > pMedia->LastBlock ) {
      LbaMax = MultU64x32 ( DivU64x32 ( pMedia->LastBlock + 1,
                                        BlocksPerRead ),
                            BlocksPerRead );
    }
    MaxReads = DivU64x32 ( LbaMax, BlocksPerRead );
    MaxMBytes = DivU64x32 ( MultU64x32 ( MaxReads,
                                         BlocksPerRead * BlockSize ),
                            1024 * 1024 );
    WarmUpBlocks = WARM_UP_READS * BlocksPerRead;
    if ( LbaMax < WarmUpBlocks ) {
      WarmUpBlocks = ((UINT32)DivU64x32 ( LbaMax, BlocksPerRead )) * BlocksPerRead;
    }

    //
    //  Get the test duration
    //
    Seconds = TEST_TIME_IN_SECONDS;

    //
    //  Display the test parameters
    //
    Print ( L"Test Parameters:\r\n" );
    Print ( L"  Using: BlockIo%sProtocol\r\n", bBlockIo2 ? "2" : "" );
    Print ( L"  BlockSize: %d bytes\r\n", BlockSize );
    Print ( L"  Blocks/Read: %d\r\n", BlocksPerRead );
    Print ( L"  Duration: %d seconds\r\n", Seconds );
    Print ( L"  LBA max: %Ld\r\n", LbaMax );
    Print ( L"  Max data: %Ld MiBytes\r\n", MaxMBytes );
    Print ( L"  Max reads: %Ld\r\n", MaxReads );
    if (( 1000 * 1000 * 1000 ) <= MediaBytes ) {
      UINT32 Remainder;
      UINT64 GByte;
      GByte = DivU64x32Remainder ( MediaBytes,
                                   1000 * 1000 * 1000,
                                   &Remainder );
      Print ( L"  Media Size: %d.%03d GiBytes (%d.%03d GBytes)\r\n",
              (UINT32)( MediaBytes / GIBYTE ),
              ((UINT32)(( MediaBytes % GIBYTE ) / MIBYTE ) * 1000 ) / KIBYTE,
              (UINT32)GByte,
              Remainder / ( 1000 * 1000 ));
    }
    else {
      UINT32 Remainder;
      UINT64 MByte;
      MByte = DivU64x32Remainder ( MediaBytes,
                                   1000 * 1000,
                                   &Remainder );
      Print ( L"  Media Size: %d.%03d MiBytes (%d.%03d MBytes)\r\n",
              (UINT32)DivU64x32 ( MediaBytes, MIBYTE ),
              ((UINT32)(( MediaBytes % MIBYTE ) / KIBYTE ) * 1000 ) / KIBYTE,
              (UINT32)MByte,
              Remainder / 1000 );
    }
    Print ( L"  Test Count: %d runs\r\n", TEST_COUNT );
    Print ( L"  Warm-up reads: %d\r\n", WarmUpBlocks / BlocksPerRead );
    Print ( L"\r\n" );

    //
    //  Compute the timeout
    //
    Timeout = Seconds;
    Timeout *= 1000L * 1000L * 10L;

    //
    //  Get the media ID value
    //
    MediaId = pMedia->MediaId;

    //
    //  Warm-up the data path
    //
    Lba = LbaMax - WarmUpBlocks;
    while ( LbaMax > Lba ) {
      if ( bBlockIo2 ) {
        Status = pBlockIo2->ReadBlocksEx ( pBlockIo2,
                                           MediaId,
                                           Lba,
                                           NULL,
                                           BytesToRead,
                                           &mBuffer[ 0 ]);
      }
      else {
        Status = pBlockIo->ReadBlocks ( pBlockIo,
                                        MediaId,
                                        Lba,
                                        BytesToRead,
                                        &mBuffer[ 0 ]);
      }
      if ( EFI_ERROR ( Status )) {
        Print ( L"ERROR - Read failure during warm-up, Lba: 0x%016Lx, Status: %r\r\n",
                Lba,
                Status );
        break;
      }
      Lba += BlocksPerRead;
    }
    if ( !EFI_ERROR ( Status )) {
      //
      //  Perform each of the tests
      //
      for ( TestCount = 1; TEST_COUNT >= TestCount; TestCount++ ) {
        //
        //  Initialize the tokens
        //
        pToken = &mTokens[ 0 ];
        while ( pTokenEnd > pToken ) {
          gBS->SignalEvent ( pToken->Event );
          pToken->TransactionStatus = EFI_SUCCESS;
          pToken += 1;
        }
        pToken = &mTokens[ 0 ];

        //
        //  Start the timer
        //
        bTestRunning = TRUE;
        ReadCount = 0;
        bReadComplete = TRUE;
        gBS->CheckEvent ( TimeoutEvent );
        Status = gBS->SetTimer ( TimeoutEvent,
                                 TimerRelative,
                                 Timeout );
        ASSERT ( EFI_SUCCESS == Status );
        if ( bBlockIo2 ) {
          //
          //  Run the test using Block I/O 2 protocol
          //
          do {
            Lba = 0;
            while ( bTestRunning && ( LbaMax > Lba )) {
              //
              //  Wrap the token list if necessary
              //
              if ( pTokenEnd <= pToken ) {
                pToken = &mTokens[ 0 ];
              }

              //
              //  Wait for the next token
              //
              gBS->WaitForEvent ( 1, &pToken->Event, &Index );

              //
              //  Verify the read status
              //
              Status = pToken->TransactionStatus;
              if ( EFI_ERROR ( Status )) {
                break;
              }

              //
              //  Start the next read
              //
              Status = pBlockIo2->ReadBlocksEx ( pBlockIo2,
                                                 MediaId,
                                                 Lba,
                                                 pToken,
                                                 BytesToRead,
                                                 &mBuffer[ 0 ]);
              if ( EFI_ERROR ( Status )) {
                bReadComplete = FALSE;
                break;
              }

              //
              //  Account for this read
              //
              ReadCount += 1;
              Lba += BlocksPerRead;
              pToken += 1;
            }
          }while ( bTestRunning );

          //
          //  Wait for the rest of the reads to complete
          //
          pToken = &mTokens[ 0 ];
          while ( pTokenEnd > pToken ) {
            gBS->WaitForEvent ( 1,
                                &pToken->Event,
                                &Index );
            pToken += 1;
          }

          //
          //  Display any errors
          //
          if ( EFI_ERROR ( Status )) {
            Print ( L"ERROR - Read %afailure, Lba: 0x%016Lx, Status: %r\r\n",
                    bReadComplete ? "" : "queue ",
                    bReadComplete ? Lba - ( DIM ( mTokens ) * BlocksPerRead ) : Lba,
                    Status );
            break;
          }
        }
        else {
          //
          //  Run the test using Block I/O protocol
          //
          do {
            Lba = 0;
            while ( bTestRunning && ( LbaMax > Lba )) {
              Status = pBlockIo->ReadBlocks ( pBlockIo,
                                              MediaId,
                                              Lba,
                                              BytesToRead,
                                              &mBuffer[ 0 ]);
              if ( EFI_ERROR ( Status )) {
                Print ( L"ERROR - Read failure, Lba: 0x%016Lx, Status: %r\r\n",
                        Lba,
                        Status );
                return (( Status & MAX_BIT ) ? 0x80000000 : 0 )
                        | ( Status & 0x7fffffff );
              }
              ReadCount += 1;
              Lba += BlocksPerRead;
            }
          } while ( bTestRunning );
        }

        //
        //  Adjust the read count for the tokens
        //
        if ( bBlockIo2 ) {
          FinalReadCount = ( DIM ( mTokens ) >= FinalReadCount )
                         ? 0
                         : FinalReadCount - DIM ( mTokens );
        }

        //
        //  Compute the results
        //
        TotalReadCount += FinalReadCount;
        DataRead = FinalReadCount;
        DataRead = MultU64x32 ( DataRead, BytesToRead );
        BytesPerSecond = (UINT32)DivU64x32 ( DataRead, Seconds );

        //
        //  Display the test results
        //
        Print ( L"\r\nTest %d Results:\r\n", TestCount );
        Print ( L"  Reads: %d\r\n", FinalReadCount );
        Print ( L"  %d.%03d MiBytes/Second (%d.%03d Mbit/Second)\r\n",
                  BytesPerSecond / ( 1024 * 1024 ),
                  ((( BytesPerSecond % ( 1024 * 1024 )) / 1024 ) * 1000 ) / 1024,
                  ( BytesPerSecond * 8 ) / ( 1000 * 1000 ),
                  (( BytesPerSecond * 8 ) % ( 1000 * 1000 )) / 1000 );
      }

      //
      //  Compute the results
      //
      DataRead = TotalReadCount;
      DataRead = MultU64x32 ( DataRead, BytesToRead );
      DataRead = DivU64x32 ( DataRead, TEST_COUNT );
      BytesPerSecond = (UINT32)DivU64x32 ( DataRead, Seconds );

      //
      //  Display the test results
      //
      Print ( L"\r\nAverage Test Results:\r\n" );
      Print ( L"  Total Reads: %d\r\n", TotalReadCount );
      Print ( L"  %d.%03d MiBytes/Second (%d.%03d Mbit/Second)\r\n",
                BytesPerSecond / ( 1024 * 1024 ),
                ((( BytesPerSecond % ( 1024 * 1024 )) / 1024 ) * 1000 ) / 1024,
                ( BytesPerSecond * 8 ) / ( 1000 * 1000 ),
                (( BytesPerSecond * 8 ) % ( 1000 * 1000 )) / 1000 );
    }
  }

  //
  //  Done with the events
  //
  gBS->CloseEvent ( TimeoutEvent );
  pToken = &mTokens[ 0 ];
  while ( pTokenEnd > pToken ) {
    if ( NULL != pToken->Event ) {
      gBS->CloseEvent ( pToken->Event );
    }
    pToken += 1;
  }

  //
  //  Return the test status
  //
  return (( Status & MAX_BIT ) ? 0x80000000 : 0 )
          | ( Status & 0x7fffffff );
}
Esempio n. 6
0
EFI_STATUS
HDiskImageSave (
  IN CHAR16 *DeviceName,
  IN UINTN  Offset,
  IN UINTN  Size
  )
/*++

Routine Description: 

  Save lines in HBufferImage to disk
  NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!!

Arguments:  

  DeviceName - The device name
  Offset     - The offset
  Size       - The size

Returns:  

  EFI_SUCCESS
  EFI_LOAD_ERROR
  EFI_OUT_OF_RESOURCES
  EFI_INVALID_PARAMETER

--*/
{

  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
  EFI_BLOCK_IO_PROTOCOL           *BlkIo;
  EFI_STATUS                      Status;

  VOID                            *Buffer;
  UINTN                           Bytes;

  UINT64                          ByteOffset;

  HEFI_EDITOR_ACTIVE_BUFFER_TYPE  BufferTypeBackup;

  //
  // if not modified, directly return
  //
  if (HBufferImage.Modified == FALSE) {
    return EFI_SUCCESS;
  }

  BufferTypeBackup        = HBufferImage.BufferType;
  HBufferImage.BufferType = DISK_BUFFER;

  DevicePath              = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (DeviceName);
  if (DevicePath == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Status = LibDevicePathToInterface (
            &gEfiBlockIoProtocolGuid,
            DevicePath,
            &BlkIo
            );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Bytes   = BlkIo->Media->BlockSize * Size;
  Buffer  = AllocatePool (Bytes);

  if (Buffer == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // concatenate the line list to a buffer
  //
  Status = HBufferImageListToBuffer (Buffer, Bytes);
  if (EFI_ERROR (Status)) {
    FreePool (Buffer);
    return Status;
  }

  ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize);

  //
  // write the buffer to disk
  //
  Status = BlkIo->WriteBlocks (
                    BlkIo,
                    BlkIo->Media->MediaId,
                    Offset,
                    Bytes,
                    Buffer
                    );

  FreePool (Buffer);

  if (EFI_ERROR (Status)) {
    return EFI_LOAD_ERROR;
  }
  //
  // now not modified
  //
  HBufferImage.Modified = FALSE;

  return EFI_SUCCESS;
}
Esempio n. 7
0
EFI_STATUS
HDiskImageRead (
  IN CHAR16   *DeviceName,
  IN UINTN    Offset,
  IN UINTN    Size,
  IN BOOLEAN  Recover
  )
/*++

Routine Description: 

  Read a disk from disk into HBufferImage

Arguments:  

  DeviceName - filename to read
  Offset     - The offset
  Size       - The size
  Recover    - if is for recover, no information print

Returns:  

  EFI_SUCCESS
  EFI_LOAD_ERROR
  EFI_OUT_OF_RESOURCES
  EFI_INVALID_PARAMETER 
  
--*/
{
  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
  EFI_BLOCK_IO_PROTOCOL           *BlkIo;
  EFI_STATUS                      Status;

  VOID                            *Buffer;
  CHAR16                          *Str;
  UINTN                           Bytes;

  HEFI_EDITOR_LINE                *Line;
  UINT64                          ByteOffset;

  HEFI_EDITOR_ACTIVE_BUFFER_TYPE  BufferTypeBackup;

  BufferTypeBackup        = HBufferImage.BufferType;
  HBufferImage.BufferType = DISK_BUFFER;

  DevicePath              = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (DeviceName);
  if (DevicePath == NULL) {
    HMainStatusBarSetStatusString (L"Cannot Find Device");
    return EFI_INVALID_PARAMETER;
  }
  //
  // get blkio interface
  //
  Status = LibDevicePathToInterface (
            &gEfiBlockIoProtocolGuid,
            DevicePath,
            &BlkIo
            );
  if (EFI_ERROR (Status)) {
    HMainStatusBarSetStatusString (L"Read Disk Failed");
    return Status;
  }
  //
  // if Offset exceeds LastBlock,
  //   return error
  //
  if (Offset > BlkIo->Media->LastBlock || Offset + Size > BlkIo->Media->LastBlock) {
    HMainStatusBarSetStatusString (L"Invalid Offset + Size");
    return EFI_LOAD_ERROR;
  }

  Bytes   = BlkIo->Media->BlockSize * Size;
  Buffer  = AllocatePool (Bytes);

  if (Buffer == NULL) {
    HMainStatusBarSetStatusString (L"Read Disk Failed");
    return EFI_OUT_OF_RESOURCES;
  }

  ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize);

  //
  // read from disk
  //
  Status = BlkIo->ReadBlocks (
                    BlkIo,
                    BlkIo->Media->MediaId,
                    Offset,
                    Bytes,
                    Buffer
                    );

  if (EFI_ERROR (Status)) {
    FreePool (Buffer);
    HMainStatusBarSetStatusString (L"Read Disk Failed");
    return EFI_LOAD_ERROR;
  }

  HBufferImageFree ();

  //
  // convert buffer to line list
  //
  Status = HBufferImageBufferToList (Buffer, Bytes);
  FreePool (Buffer);

  if (EFI_ERROR (Status)) {
    HMainStatusBarSetStatusString (L"Read Disk Failed");
    return Status;
  }

  Status = HDiskImageSetDiskNameOffsetSize (DeviceName, Offset, Size);
  if (EFI_ERROR (Status)) {
    HMainStatusBarSetStatusString (L"Read Disk Failed");
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // initialize some variables
  //
  HDiskImage.BlockSize                = BlkIo->Media->BlockSize;

  HBufferImage.DisplayPosition.Row    = TEXT_START_ROW;
  HBufferImage.DisplayPosition.Column = HEX_POSITION;

  HBufferImage.MousePosition.Row      = TEXT_START_ROW;
  HBufferImage.MousePosition.Column   = HEX_POSITION;

  HBufferImage.LowVisibleRow          = 1;
  HBufferImage.HighBits               = TRUE;

  HBufferImage.BufferPosition.Row     = 1;
  HBufferImage.BufferPosition.Column  = 1;

  if (!Recover) {
    Str = PoolPrint (L"%d Lines Read", HBufferImage.NumLines);
    if (Str == NULL) {
      HMainStatusBarSetStatusString (L"Read Disk Failed");
      return EFI_OUT_OF_RESOURCES;
    }

    HMainStatusBarSetStatusString (Str);
    HEditorFreePool (Str);

    HMainEditor.SelectStart = 0;
    HMainEditor.SelectEnd   = 0;

  }

  //
  // has line
  //
  if (HBufferImage.Lines != NULL) {
    HBufferImage.CurrentLine = CR (
                                HBufferImage.ListHead->Flink,
                                HEFI_EDITOR_LINE,
                                Link,
                                EFI_EDITOR_LINE_LIST
                                );
  } else {
    //
    // create a dummy line
    //
    Line = HBufferImageCreateLine ();
    if (Line == NULL) {
      HMainStatusBarSetStatusString (L"Read Disk Failed");
      return EFI_OUT_OF_RESOURCES;
    }

    HBufferImage.CurrentLine = Line;
  }

  HBufferImage.Modified           = FALSE;
  HBufferImageNeedRefresh         = TRUE;
  HBufferImageOnlyLineNeedRefresh = FALSE;
  HBufferImageMouseNeedRefresh    = TRUE;

  return EFI_SUCCESS;
}
Esempio n. 8
0
EFI_STATUS
ArmFastbootPlatformFlashPartition (
  IN CHAR8  *PartitionName,
  IN UINTN   Size,
  IN VOID   *Image
  )
{
  EFI_STATUS               Status;
  EFI_BLOCK_IO_PROTOCOL   *BlockIo;
  EFI_DISK_IO_PROTOCOL    *DiskIo;
  UINT32                   MediaId;
  UINTN                    PartitionSize;
  FASTBOOT_PARTITION_LIST *Entry;
  CHAR16                   PartitionNameUnicode[60];
  BOOLEAN                  PartitionFound;

  AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode);

  PartitionFound = FALSE;
  Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead));
  while (!IsNull (&mPartitionListHead, &Entry->Link)) {
    // Search the partition list for the partition named by PartitionName
    if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) {
      PartitionFound = TRUE;
      break;
    }

   Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link);
  }
  if (!PartitionFound) {
    return EFI_NOT_FOUND;
  }

  Status = gBS->OpenProtocol (
                  Entry->PartitionHandle,
                  &gEfiBlockIoProtocolGuid,
                  (VOID **) &BlockIo,
                  gImageHandle,
                  NULL,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status));
    return EFI_NOT_FOUND;
  }

  // Check image will fit on device
  PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize;
  if (PartitionSize < Size) {
    DEBUG ((EFI_D_ERROR, "Partition not big enough.\n"));
    DEBUG ((EFI_D_ERROR, "Partition Size:\t%d\nImage Size:\t%d\n", PartitionSize, Size));

    return EFI_VOLUME_FULL;
  }

  MediaId = BlockIo->Media->MediaId;

  Status = gBS->OpenProtocol (
                  Entry->PartitionHandle,
                  &gEfiDiskIoProtocolGuid,
                  (VOID **) &DiskIo,
                  gImageHandle,
                  NULL,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );
  ASSERT_EFI_ERROR (Status);

  Status = DiskIo->WriteDisk (DiskIo, MediaId, 0, Size, Image);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  BlockIo->FlushBlocks(BlockIo);

  return Status;
}
Esempio n. 9
0
//
// TDS 5.1
//
EFI_STATUS
BBTestResetFunctionAutoTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL   *StandardLib;
  EFI_STATUS                           Status;
  EFI_BLOCK_IO_PROTOCOL                *BlockIo;
  EFI_TEST_ASSERTION                   AssertionType;

  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                   SupportHandle,
                   &gEfiStandardTestLibraryGuid,
                   &StandardLib
                   );

  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.HandleProtocol - Handle standard test library",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                 );
    return Status;
  }

  BlockIo = (EFI_BLOCK_IO_PROTOCOL *)ClientInterface;

  //
  // Assertion Point 5.1.2.1
  // Reset must succeed to reset the block device hardware with extended verification
  //
  Status = BlockIo->Reset (BlockIo, TRUE);
  if (EFI_ERROR(Status)) {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_PASSED;
  }

  //
  // Sometimes the file system will be destroied from this point. Just add a
  // stall to avoid it. (Need investigation, I don't know it is useful or not!)
  //
  Print (L"Wait 5 seconds for the block device resetting...");
  gtBS->Stall (5000000);

  StandardLib->RecordAssertion (
                 StandardLib,
                 AssertionType,
                 gBlockIoFunctionTestAssertionGuid001,
                 L"EFI_BLOCK_IO_PROTOCOL.Reset - Reset the block device with extended verification",
                 L"%a:%d:Status=%r",
                 __FILE__,
                 __LINE__,
                 Status
                 );

  //
  // Assertion Point 5.1.2.2
  // Reset must succeed to reset the block device hardware without extended verification
  //
  Status = BlockIo->Reset (BlockIo, FALSE);
  if (EFI_ERROR(Status)) {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_PASSED;
  }

  //
  // Sometimes the file system will be destroied from this point. Just add a
  // stall to avoid it. (Need investigation, I don't know it is useful or not!)
  //
  Print (L"Wait 5 seconds for the block device resetting...");
  gtBS->Stall (5000000);

  StandardLib->RecordAssertion (
                 StandardLib,
                 AssertionType,
                 gBlockIoFunctionTestAssertionGuid002,
                 L"EFI_BLOCK_IO_PROTOCOL.Reset - Reset the block device without extended verification",
                 L"%a:%d:Status=%r",
                 __FILE__,
                 __LINE__,
                 Status
                 );

  return EFI_SUCCESS;
}
Esempio n. 10
0
//
// TDS 5.2
//
EFI_STATUS
BBTestReadBlocksFunctionAutoTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL   *StandardLib;
  EFI_STATUS                           Status;
  EFI_BLOCK_IO_PROTOCOL                *BlockIo;
  EFI_TEST_ASSERTION                   AssertionType;
  UINT32                               MediaId;
  BOOLEAN                              RemovableMedia;
  BOOLEAN                              MediaPresent;
  BOOLEAN                              LogicalPartition;
  BOOLEAN                              ReadOnly;
  BOOLEAN                              WriteCaching;
  UINT32                               BlockSize;
  UINT32                               IoAlign;
  EFI_LBA                              LastBlock;

  UINTN                                BufferSize;
  UINT8                                *Buffer;

  UINT32                               BlockNumber;

  UINTN                                IndexI, IndexJ;
  UINTN                                NewBufferSize;
  EFI_LBA                              NewLba;

  UINTN                                Remainder;

  EFI_DEVICE_PATH_PROTOCOL             *DevicePath;

  CHAR16                               *DevicePathStr;


  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                   SupportHandle,
                   &gEfiStandardTestLibraryGuid,
                   &StandardLib
                   );

  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.HandleProtocol - Handle standard test library",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                   );
    return Status;
  }

  BlockIo = (EFI_BLOCK_IO_PROTOCOL *)ClientInterface;

  //
  // Locate & record DevicePath for further investigation
  //

  LocateDevicePathFromBlockIo (BlockIo, &DevicePath, StandardLib);

  DevicePathStr = DevicePathToStr (DevicePath);
  if (DevicePathStr != NULL) {
    StandardLib->RecordMessage (
                   StandardLib,
                   EFI_VERBOSE_LEVEL_DEFAULT,
                   L"Current Device: %s",
                   DevicePathStr
                 );

    Status = gtBS->FreePool (DevicePathStr);
    if (EFI_ERROR(Status)) {
      StandardLib->RecordAssertion (
                     StandardLib,
                     EFI_TEST_ASSERTION_FAILED,
                     gTestGenericFailureGuid,
                     L"BS.FreePool - Free device path string",
                     L"%a:%d:Status - %r",
                     __FILE__,
                     __LINE__,
                     Status
                     );
      return Status;
    }

    DevicePathStr = NULL;
  }

  //
  // Initialize variable
  //
  MediaId           = BlockIo->Media->MediaId;
  RemovableMedia    = BlockIo->Media->RemovableMedia;
  MediaPresent      = BlockIo->Media->MediaPresent;
  LogicalPartition  = BlockIo->Media->LogicalPartition;
  ReadOnly          = BlockIo->Media->ReadOnly;
  WriteCaching      = BlockIo->Media->WriteCaching;
  BlockSize         = BlockIo->Media->BlockSize;
  IoAlign           = BlockIo->Media->IoAlign;
  LastBlock         = BlockIo->Media->LastBlock;

  BlockNumber       = (UINT32) MINIMUM(LastBlock, MAX_NUMBER_OF_READ_BLOCK_BUFFER);
  BufferSize        = BlockNumber * BlockSize;

  if (BufferSize == 0) {
    BufferSize = 512;
  }

  //
  // allocate buffer
  //
  Status = gtBS->AllocatePool (EfiBootServicesData, BufferSize, &Buffer);
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.AllocatePool - Allocate buffer for testing",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                   );
    return Status;
  }

  //
  // Assertion Point 5.2.2.1
  // ReadBlocks must succeed to read proper data from device with valid parameter
  //
  if (MediaPresent == TRUE) {
    for (IndexI = 1; IndexI < MAX_DIFFERENT_BUFFERSIZE_FOR_TEST; IndexI++) {
      //
      // prepare test data
      // BufferSize will range from BlockSize to MAX_DIFFERENT_BUFFERSIZE_FOR_TEST*BlockSize
      //
      NewBufferSize = IndexI * BlockSize;

      //
      //parameter verification on NewBufferSize
      //
      if (NewBufferSize > BufferSize) {
        break;
      }

      for (IndexJ = 0; IndexJ < 3 * MAX_DIFFERENT_LBA_FOR_TEST; IndexJ++) {
        //
        // prepare test data
        //
        if (IndexJ < MAX_DIFFERENT_LBA_FOR_TEST) {
          // from 1 to MAX_DIFFERENT_LBA_FOR_TEST
          NewLba = IndexJ;
        } else if (IndexJ < 2 * MAX_DIFFERENT_LBA_FOR_TEST) {
          // from (LastBlock - MAX_DIFFERENT_LBA_FOR_TEST - MAX_DIFFERENT_BUFFERSIZE_FOR_TEST)  to (LastBlock - MAX_DIFFERENT_BUFFERSIZE_FOR_TEST)
          NewLba = IndexJ + LastBlock - 2 * MAX_DIFFERENT_LBA_FOR_TEST - MAX_DIFFERENT_BUFFERSIZE_FOR_TEST;
        } else {
          // from (LastBlock/2 - MAX_DIFFERENT_LBA_FOR_TEST/2) to (LastBlock/2 + MAX_DIFFERENT_LBA_FOR_TEST/2)
          NewLba = IndexJ - 2 * MAX_DIFFERENT_LBA_FOR_TEST + (DivU64x32 (LastBlock, 2, &Remainder) - MAX_DIFFERENT_LBA_FOR_TEST / 2);
        }

        //
        //parameter verification on NewLba
        //
        if (NewLba + NewBufferSize / BlockSize > LastBlock + 1) {
          continue;
        }

        //
        // Call ReadBlocks with the specified LBA and BufferSize
        //
        Status = BlockIo->ReadBlocks (
                            BlockIo,
                            MediaId,
                            NewLba,
                            NewBufferSize,
                            (VOID*)Buffer
                            );
        if (EFI_ERROR(Status)) {
          AssertionType = EFI_TEST_ASSERTION_FAILED;
        } else {
          AssertionType = EFI_TEST_ASSERTION_PASSED;
        }

        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionType,
                       gBlockIoFunctionTestAssertionGuid003,
                       L"EFI_BLOCK_IO_PROTOCOL.ReadBlocks - Read Block with proper parameter from valid media",
                       L"%a:%d:BufferSize=%d, Lba=0x%lx, Status=%r",
                       __FILE__,
                       __LINE__,
                       NewBufferSize,
                       NewLba,
                       Status
                       );
        if (EFI_ERROR(Status)) {
          continue;
        }
      }//end of loop of Lba - IndexJ
    }//end of loop of BufferSize - IndexI
  }


  //
  // Free resources
  //
  Status = gtBS->FreePool (Buffer);
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.FreePool - Free buffer for testing",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                   );
    return Status;
  }

  return EFI_SUCCESS;
}
Esempio n. 11
0
/**
  Stop this driver on ControllerHandle. Support stopping any child handles
  created by this driver.

  @param  This              Protocol instance pointer.
  @param  ControllerHandle  Handle of device to stop driver on
  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
                            children is zero stop the entire bus driver.
  @param  ChildHandleBuffer List of Child Handles to Stop.

  @retval EFI_SUCCESS       This driver is removed ControllerHandle
  @retval other             This driver was not removed from this device

**/
EFI_STATUS
EFIAPI
PartitionDriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
  IN  EFI_HANDLE                    ControllerHandle,
  IN  UINTN                         NumberOfChildren,
  IN  EFI_HANDLE                    *ChildHandleBuffer
  )
{
  EFI_STATUS              Status;
  UINTN                   Index;
  EFI_BLOCK_IO_PROTOCOL   *BlockIo;
  EFI_BLOCK_IO2_PROTOCOL  *BlockIo2;
  BOOLEAN                 AllChildrenStopped;
  PARTITION_PRIVATE_DATA  *Private;
  EFI_DISK_IO_PROTOCOL    *DiskIo;
  EFI_GUID                *TypeGuid;

  BlockIo  = NULL;
  BlockIo2 = NULL;
  Private = NULL;

  if (NumberOfChildren == 0) {
    //
    // In the case of re-entry of the PartitionDriverBindingStop, the
    // NumberOfChildren may not reflect the actual number of children on the
    // bus driver. Hence, additional check is needed here.
    //
    if (HasChildren (ControllerHandle)) {
      DEBUG((EFI_D_ERROR, "PartitionDriverBindingStop: Still has child.\n"));
      return EFI_DEVICE_ERROR;
    }

    //
    // Close the bus driver
    //
    gBS->CloseProtocol (
          ControllerHandle,
          &gEfiDiskIoProtocolGuid,
          This->DriverBindingHandle,
          ControllerHandle
          );
    //
    // Close Parent BlockIO2 if has.
    //
    gBS->CloseProtocol (
           ControllerHandle,
           &gEfiDiskIo2ProtocolGuid,
           This->DriverBindingHandle,
           ControllerHandle
           );

    gBS->CloseProtocol (
          ControllerHandle,
          &gEfiDevicePathProtocolGuid,
          This->DriverBindingHandle,
          ControllerHandle
          );
    return EFI_SUCCESS;
  }

  AllChildrenStopped = TRUE;
  for (Index = 0; Index < NumberOfChildren; Index++) {
    gBS->OpenProtocol (
           ChildHandleBuffer[Index],
           &gEfiBlockIoProtocolGuid,
           (VOID **) &BlockIo,
           This->DriverBindingHandle,
           ControllerHandle,
           EFI_OPEN_PROTOCOL_GET_PROTOCOL
           );
    //
    // Try to locate BlockIo2.
    //
    gBS->OpenProtocol (
           ChildHandleBuffer[Index],
           &gEfiBlockIo2ProtocolGuid,
           (VOID **) &BlockIo2,
           This->DriverBindingHandle,
           ControllerHandle,
           EFI_OPEN_PROTOCOL_GET_PROTOCOL
           );


    Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);
    if (Private->InStop) {
      //
      // If the child handle is going to be stopped again during the re-entry
      // of DriverBindingStop, just do nothing.
      //
      break;
    }
    Private->InStop = TRUE;

    BlockIo->FlushBlocks (BlockIo);

    if (BlockIo2 != NULL) {
      Status = BlockIo2->FlushBlocksEx (BlockIo2, NULL);
      DEBUG((EFI_D_ERROR, "PartitionDriverBindingStop: FlushBlocksEx returned with %r\n", Status));
    } else {
      Status = EFI_SUCCESS;
    }

    gBS->CloseProtocol (
           ControllerHandle,
           &gEfiDiskIoProtocolGuid,
           This->DriverBindingHandle,
           ChildHandleBuffer[Index]
           );

    if (IsZeroGuid (&Private->TypeGuid)) {
      TypeGuid = NULL;
    } else {
      TypeGuid = &Private->TypeGuid;
    }

    //
    // All Software protocols have be freed from the handle so remove it.
    // Remove the BlockIo Protocol if has.
    // Remove the BlockIo2 Protocol if has.
    //
    if (BlockIo2 != NULL) {
      //
      // Some device drivers might re-install the BlockIO(2) protocols for a
      // media change condition. Therefore, if the FlushBlocksEx returned with
      // EFI_MEDIA_CHANGED, just let the BindingStop fail to avoid potential
      // reference of already stopped child handle.
      //
      if (Status != EFI_MEDIA_CHANGED) {
        Status = gBS->UninstallMultipleProtocolInterfaces (
                         ChildHandleBuffer[Index],
                         &gEfiDevicePathProtocolGuid,
                         Private->DevicePath,
                         &gEfiBlockIoProtocolGuid,
                         &Private->BlockIo,
                         &gEfiBlockIo2ProtocolGuid,
                         &Private->BlockIo2,
                         &gEfiPartitionInfoProtocolGuid,
                         &Private->PartitionInfo,
                         TypeGuid,
                         NULL,
                         NULL
                         );
      }
    } else {
      Status = gBS->UninstallMultipleProtocolInterfaces (
                       ChildHandleBuffer[Index],
                       &gEfiDevicePathProtocolGuid,
                       Private->DevicePath,
                       &gEfiBlockIoProtocolGuid,
                       &Private->BlockIo,
                       &gEfiPartitionInfoProtocolGuid,
                       &Private->PartitionInfo,
                       TypeGuid,
                       NULL,
                       NULL
                       );
    }

    if (EFI_ERROR (Status)) {
      Private->InStop = FALSE;
      gBS->OpenProtocol (
             ControllerHandle,
             &gEfiDiskIoProtocolGuid,
             (VOID **) &DiskIo,
             This->DriverBindingHandle,
             ChildHandleBuffer[Index],
             EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
             );
    } else {
      FreePool (Private->DevicePath);
      FreePool (Private);
    }

    if (EFI_ERROR (Status)) {
      AllChildrenStopped = FALSE;
      if (Status == EFI_MEDIA_CHANGED) {
        break;
      }
    }
  }

  if (!AllChildrenStopped) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}
Esempio n. 12
0
VOID
EFIAPI
SEnvBlkIo (
  IN EFI_HANDLE   h,
  IN VOID         *Interface
  )
/*++

Routine Description:

Arguments:

  h         - An EFI handle
  Interface - The interface

Returns:

--*/
{
  EFI_BLOCK_IO_PROTOCOL *BlkIo;
  EFI_BLOCK_IO_MEDIA    *BlkMedia;
  VOID                  *Buffer;

  BlkIo     = Interface;
  BlkMedia  = BlkIo->Media;

  //
  // Issue a dummy read to the device to check for media change
  //
  Buffer = AllocatePool (BlkMedia->BlockSize);
  if (Buffer) {
    BlkIo->ReadBlocks (
            BlkIo,
            BlkMedia->MediaId,
            0,
            BlkMedia->BlockSize,
            Buffer
            );
    FreePool (Buffer);
  }
  //
  // Dump BlkIo Info
  //
  PrintToken (
    STRING_TOKEN (STR_SHELLENV_DPROT_MID),
    HiiEnvHandle,
    BlkMedia->RemovableMedia ? L"Removable " : L"Fixed ",
    BlkMedia->MediaPresent ? L"" : L"not-present ",
    BlkMedia->MediaId
    );

  PrintToken (
    STRING_TOKEN (STR_SHELLENV_DPROT_BSIZE_LBLOCK),
    HiiEnvHandle,
    BlkMedia->BlockSize,
    BlkMedia->LastBlock,
    MultU64x32 (BlkMedia->LastBlock + 1, BlkMedia->BlockSize),
    BlkMedia->LogicalPartition ? L"partition" : L"raw",
    BlkMedia->ReadOnly ? L"ro" : L"rw",
    BlkMedia->WriteCaching ? L"cached" : L"!cached"
    );
}
Esempio n. 13
0
EFI_STATUS
BOpt_FindFileSystem (
  IN BMM_CALLBACK_DATA          *CallbackData
  )
/*++

Routine Description
  Find file systems for current Extensible Firmware
  Including Handles that support Simple File System
  protocol, Load File protocol.

  Building up the FileSystem Menu for user selection
  All file system will be stored in FsOptionMenu
  for future use.

Arguments:
  CallbackData           -   BMM context data

Returns:
  EFI_SUCCESS            -   Success find the file system
  EFI_OUT_OF_RESOURCES   -   Can not create menu entry

--*/
{
  UINTN                     NoBlkIoHandles;
  UINTN                     NoSimpleFsHandles;
  UINTN                     NoLoadFileHandles;
  EFI_HANDLE                *BlkIoHandle;
  EFI_HANDLE                *SimpleFsHandle;
  EFI_HANDLE                *LoadFileHandle;
  UINT16                    *VolumeLabel;
  EFI_BLOCK_IO_PROTOCOL     *BlkIo;
  UINTN                     Index;
  EFI_STATUS                Status;
  BM_MENU_ENTRY             *MenuEntry;
  BM_FILE_CONTEXT           *FileContext;
  UINT16                    *TempStr;
  UINTN                     OptionNumber;
  VOID                      *Buffer;
  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
  UINT16                    DeviceType;
  BBS_BBS_DEVICE_PATH       BbsDevicePathNode;
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
  BOOLEAN                   RemovableMedia;


  NoSimpleFsHandles = 0;
  NoLoadFileHandles = 0;
  OptionNumber      = 0;
  InitializeListHead (&FsOptionMenu.Head);

  //
  // Locate Handles that support BlockIo protocol
  //
  Status = gBS->LocateHandleBuffer (
                  ByProtocol,
                  &gEfiBlockIoProtocolGuid,
                  NULL,
                  &NoBlkIoHandles,
                  &BlkIoHandle
                  );
  if (!EFI_ERROR (Status)) {

    for (Index = 0; Index < NoBlkIoHandles; Index++) {
      Status = gBS->HandleProtocol (
                      BlkIoHandle[Index],
                      &gEfiBlockIoProtocolGuid,
                      &BlkIo
                      );

      if (EFI_ERROR (Status)) {
        continue;
      }

      //
      // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media
      //
      if (BlkIo->Media->RemovableMedia) {
        Buffer = EfiAllocateZeroPool (BlkIo->Media->BlockSize);
        if (NULL == Buffer) {
          SafeFreePool (BlkIoHandle);
          return EFI_OUT_OF_RESOURCES;
        }

        BlkIo->ReadBlocks (
                BlkIo,
                BlkIo->Media->MediaId,
                0,
                BlkIo->Media->BlockSize,
                Buffer
                );
        SafeFreePool (Buffer);
      }
    }
    SafeFreePool (BlkIoHandle);
  }

  //
  // Locate Handles that support Simple File System protocol
  //
  Status = gBS->LocateHandleBuffer (
                  ByProtocol,
                  &gEfiSimpleFileSystemProtocolGuid,
                  NULL,
                  &NoSimpleFsHandles,
                  &SimpleFsHandle
                  );
  if (!EFI_ERROR (Status)) {
    //
    // Find all the instances of the File System prototocol
    //
    for (Index = 0; Index < NoSimpleFsHandles; Index++) {
      Status = gBS->HandleProtocol (
                      SimpleFsHandle[Index],
                      &gEfiBlockIoProtocolGuid,
                      &BlkIo
                      );
      if (EFI_ERROR (Status)) {
        //
        // If no block IO exists assume it's NOT a removable media
        //
        RemovableMedia = FALSE;
      } else {
        //
        // If block IO exists check to see if it's remobable media
        //
        RemovableMedia = BlkIo->Media->RemovableMedia;
      }

      //
      // Allocate pool for this load option
      //
      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
      if (NULL == MenuEntry) {
        SafeFreePool (SimpleFsHandle);
        return EFI_OUT_OF_RESOURCES;
      }

      FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;

      FileContext->Handle     = SimpleFsHandle[Index];
      MenuEntry->OptionNumber = Index;
      FileContext->FHandle    = EfiLibOpenRoot (FileContext->Handle);
      if (!FileContext->FHandle) {
        BOpt_DestroyMenuEntry (MenuEntry);
        continue;
      }

      MenuEntry->HelpString = DevicePathToStr (EfiDevicePathFromHandle (FileContext->Handle));
      FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle);
      FileContext->FileName = EfiStrDuplicate (L"\\");
      FileContext->DevicePath = EfiFileDevicePath (
                                  FileContext->Handle,
                                  FileContext->FileName
                                  );
      FileContext->IsDir            = TRUE;
      FileContext->IsRoot           = TRUE;
      FileContext->IsRemovableMedia = FALSE;
      FileContext->IsLoadFile       = FALSE;

      //
      // Get current file system's Volume Label
      //
      if (FileContext->Info == NULL) {
        VolumeLabel = L"NO FILE SYSTEM INFO";
      } else {
        if (FileContext->Info->VolumeLabel == NULL) {
          VolumeLabel = L"NULL VOLUME LABEL";
        } else {
          VolumeLabel = FileContext->Info->VolumeLabel;
          if (*VolumeLabel == 0x0000) {
            VolumeLabel = L"NO VOLUME LABEL";
          }
        }
      }

      TempStr                   = MenuEntry->HelpString;
      MenuEntry->DisplayString  = EfiAllocateZeroPool (MAX_CHAR);
      ASSERT (MenuEntry->DisplayString != NULL);
      SPrint (
        MenuEntry->DisplayString,
        MAX_CHAR,
        L"%s, [%s]",
        VolumeLabel,
        TempStr
        );
      OptionNumber++;
      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
    }
  }

  if (NoSimpleFsHandles != 0) {
    SafeFreePool (SimpleFsHandle);
  }
  //
  // Searching for handles that support Load File protocol
  //
  Status = gBS->LocateHandleBuffer (
                  ByProtocol,
                  &gEfiLoadFileProtocolGuid,
                  NULL,
                  &NoLoadFileHandles,
                  &LoadFileHandle
                  );

  if (!EFI_ERROR (Status)) {
    for (Index = 0; Index < NoLoadFileHandles; Index++) {
      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
      if (NULL == MenuEntry) {
        SafeFreePool (LoadFileHandle);
        return EFI_OUT_OF_RESOURCES;
      }

      FileContext                   = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
      FileContext->IsRemovableMedia = FALSE;
      FileContext->IsLoadFile       = TRUE;
      FileContext->Handle           = LoadFileHandle[Index];
      FileContext->IsRoot           = TRUE;

      FileContext->DevicePath = EfiDevicePathFromHandle (FileContext->Handle);

      MenuEntry->HelpString     = DevicePathToStr (FileContext->DevicePath);

      TempStr                   = MenuEntry->HelpString;
      MenuEntry->DisplayString  = EfiAllocateZeroPool (MAX_CHAR);
      ASSERT (MenuEntry->DisplayString != NULL);
      SPrint (
        MenuEntry->DisplayString,
        MAX_CHAR,
        L"Load File [%s]",
        TempStr
        );

      MenuEntry->OptionNumber = OptionNumber;
      OptionNumber++;
      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
    }
  }

  if (NoLoadFileHandles != 0) {
    SafeFreePool (LoadFileHandle);
  }

  //
  // Add Legacy Boot Option Support Here
  //
  Status = gBS->LocateProtocol (
                  &gEfiLegacyBiosProtocolGuid,
                  NULL,
                  &LegacyBios
                  );
  if (!EFI_ERROR (Status)) {

    for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) {
      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
      if (NULL == MenuEntry) {
        return EFI_OUT_OF_RESOURCES;
      }

      FileContext                       = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;

      FileContext->IsRemovableMedia     = FALSE;
      FileContext->IsLoadFile           = TRUE;
      FileContext->IsBootLegacy         = TRUE;
      DeviceType                        = (UINT16) Index;
      BbsDevicePathNode.Header.Type     = BBS_DEVICE_PATH;
      BbsDevicePathNode.Header.SubType  = BBS_BBS_DP;
      SetDevicePathNodeLength (
        &BbsDevicePathNode.Header,
        sizeof (BBS_BBS_DEVICE_PATH)
        );
      BbsDevicePathNode.DeviceType  = DeviceType;
      BbsDevicePathNode.StatusFlag  = 0;
      BbsDevicePathNode.String[0]   = 0;
      DevicePath = EfiAppendDevicePathNode (
                    EndDevicePath,
                    (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode
                    );

      FileContext->DevicePath   = DevicePath;
      MenuEntry->HelpString     = DevicePathToStr (FileContext->DevicePath);

      TempStr                   = MenuEntry->HelpString;
      MenuEntry->DisplayString  = EfiAllocateZeroPool (MAX_CHAR);
      ASSERT (MenuEntry->DisplayString != NULL);
      SPrint (
        MenuEntry->DisplayString,
        MAX_CHAR,
        L"Boot Legacy [%s]",
        TempStr
        );
      MenuEntry->OptionNumber = OptionNumber;
      OptionNumber++;
      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
    }
  }
  //
  // Remember how many file system options are here
  //
  FsOptionMenu.MenuNumber = OptionNumber;
  return EFI_SUCCESS;
}
/**
  This function builds the FsOptionMenu list which records all
  available file system in the system. They include all instances
  of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM
  and all type of legacy boot device.

  @retval  EFI_SUCCESS             Success find the file system
  @retval  EFI_OUT_OF_RESOURCES    Can not create menu entry

**/
EFI_STATUS
FindFileSystem (
  VOID
  )
{
  UINTN                     NoBlkIoHandles;
  UINTN                     NoSimpleFsHandles;
  EFI_HANDLE                *BlkIoHandle;
  EFI_HANDLE                *SimpleFsHandle;
  UINT16                    *VolumeLabel;
  EFI_BLOCK_IO_PROTOCOL     *BlkIo;
  UINTN                     Index;
  EFI_STATUS                Status;
  SECUREBOOT_MENU_ENTRY     *MenuEntry;
  SECUREBOOT_FILE_CONTEXT   *FileContext;
  UINT16                    *TempStr;
  UINTN                     OptionNumber;
  VOID                      *Buffer;

  BOOLEAN                   RemovableMedia;


  NoSimpleFsHandles = 0;
  OptionNumber      = 0;
  InitializeListHead (&FsOptionMenu.Head);

  //
  // Locate Handles that support BlockIo protocol
  //
  Status = gBS->LocateHandleBuffer (
                  ByProtocol,
                  &gEfiBlockIoProtocolGuid,
                  NULL,
                  &NoBlkIoHandles,
                  &BlkIoHandle
                  );
  if (!EFI_ERROR (Status)) {

    for (Index = 0; Index < NoBlkIoHandles; Index++) {
      Status = gBS->HandleProtocol (
                      BlkIoHandle[Index],
                      &gEfiBlockIoProtocolGuid,
                      (VOID **) &BlkIo
                      );

      if (EFI_ERROR (Status)) {
        continue;
      }

      //
      // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media
      //
      if (BlkIo->Media->RemovableMedia) {
        Buffer = AllocateZeroPool (BlkIo->Media->BlockSize);
        if (NULL == Buffer) {
          FreePool (BlkIoHandle);
          return EFI_OUT_OF_RESOURCES;
        }

        BlkIo->ReadBlocks (
                BlkIo,
                BlkIo->Media->MediaId,
                0,
                BlkIo->Media->BlockSize,
                Buffer
                );
        FreePool (Buffer);
      }
    }
    FreePool (BlkIoHandle);
  }

  //
  // Locate Handles that support Simple File System protocol
  //
  Status = gBS->LocateHandleBuffer (
                  ByProtocol,
                  &gEfiSimpleFileSystemProtocolGuid,
                  NULL,
                  &NoSimpleFsHandles,
                  &SimpleFsHandle
                  );
  if (!EFI_ERROR (Status)) {
    //
    // Find all the instances of the File System prototocol
    //
    for (Index = 0; Index < NoSimpleFsHandles; Index++) {
      Status = gBS->HandleProtocol (
                      SimpleFsHandle[Index],
                      &gEfiBlockIoProtocolGuid,
                      (VOID **) &BlkIo
                      );
      if (EFI_ERROR (Status)) {
        //
        // If no block IO exists assume it's NOT a removable media
        //
        RemovableMedia = FALSE;
      } else {
        //
        // If block IO exists check to see if it's remobable media
        //
        RemovableMedia = BlkIo->Media->RemovableMedia;
      }

      //
      // Allocate pool for this instance.
      //
      MenuEntry = CreateMenuEntry ();
      if (NULL == MenuEntry) {
        FreePool (SimpleFsHandle);
        return EFI_OUT_OF_RESOURCES;
      }

      FileContext = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext;

      FileContext->Handle     = SimpleFsHandle[Index];
      MenuEntry->OptionNumber = Index;
      FileContext->FHandle    = OpenRoot (FileContext->Handle);
      if (FileContext->FHandle == NULL) {
        DestroyMenuEntry (MenuEntry);
        continue;
      }

      MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));
      FileContext->Info = FileSystemVolumeLabelInfo (FileContext->FHandle);
      FileContext->FileName = StrDuplicate (L"\\");
      FileContext->DevicePath = FileDevicePath (
                                  FileContext->Handle,
                                  FileContext->FileName
                                  );
      FileContext->IsDir            = TRUE;
      FileContext->IsRoot           = TRUE;
      FileContext->IsRemovableMedia = RemovableMedia;
      FileContext->IsLoadFile       = FALSE;

      //
      // Get current file system's Volume Label
      //
      if (FileContext->Info == NULL) {
        VolumeLabel = L"NO FILE SYSTEM INFO";
      } else {
        if (FileContext->Info->VolumeLabel == NULL) {
          VolumeLabel = L"NULL VOLUME LABEL";
        } else {
          VolumeLabel = FileContext->Info->VolumeLabel;
          if (*VolumeLabel == 0x0000) {
            VolumeLabel = L"NO VOLUME LABEL";
          }
        }
      }

      TempStr                   = MenuEntry->HelpString;
      MenuEntry->DisplayString  = AllocateZeroPool (MAX_CHAR);
      ASSERT (MenuEntry->DisplayString != NULL);
      UnicodeSPrint (
        MenuEntry->DisplayString,
        MAX_CHAR,
        L"%s, [%s]",
        VolumeLabel,
        TempStr
        );
      OptionNumber++;
      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
    }
  }

  if (NoSimpleFsHandles != 0) {
    FreePool (SimpleFsHandle);
  }

  //
  // Remember how many file system options are here
  //
  FsOptionMenu.MenuNumber = OptionNumber;
  return EFI_SUCCESS;
}
Esempio n. 15
0
/**
  Save lines in HBufferImage to disk.
  NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!!

  @param[in] DeviceName   The device name.
  @param[in] Offset       The offset.
  @param[in] Size         The size.

  @retval EFI_SUCCESS           The operation was successful.
  @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
  @retval EFI_LOAD_ERROR        A load error occured.
  @retval EFI_INVALID_PARAMETER A parameter was invalid.  
**/
EFI_STATUS
HDiskImageSave (
  IN CHAR16 *DeviceName,
  IN UINTN  Offset,
  IN UINTN  Size
  )
{

  CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
  EFI_DEVICE_PATH_PROTOCOL        *DupDevicePath;
  EFI_BLOCK_IO_PROTOCOL           *BlkIo;
  EFI_STATUS                      Status;
  EFI_HANDLE                      Handle;
  VOID                            *Buffer;
  UINTN                           Bytes;

  UINT64                          ByteOffset;

  EDIT_FILE_TYPE                  BufferTypeBackup;

  //
  // if not modified, directly return
  //
  if (HBufferImage.Modified == FALSE) {
    return EFI_SUCCESS;
  }

  BufferTypeBackup        = HBufferImage.BufferType;
  HBufferImage.BufferType = FileTypeDiskBuffer;

  DevicePath              = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
  if (DevicePath == NULL) {
//    StatusBarSetStatusString (L"Cannot Find Device");
    return EFI_INVALID_PARAMETER;
  }
  DupDevicePath = DuplicateDevicePath(DevicePath);

  //
  // get blkio interface
  //
  Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
  FreePool(DupDevicePath);
  if (EFI_ERROR (Status)) {
//    StatusBarSetStatusString (L"Read Disk Failed");
    return Status;
  }
  Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
  if (EFI_ERROR (Status)) {
//    StatusBarSetStatusString (L"Read Disk Failed");
    return Status;
  }

  Bytes   = BlkIo->Media->BlockSize * Size;
  Buffer  = AllocateZeroPool (Bytes);

  if (Buffer == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // concatenate the line list to a buffer
  //
  Status = HBufferImageListToBuffer (Buffer, Bytes);
  if (EFI_ERROR (Status)) {
    FreePool (Buffer);
    return Status;
  }

  ByteOffset = MultU64x32 (Offset, BlkIo->Media->BlockSize);

  //
  // write the buffer to disk
  //
  Status = BlkIo->WriteBlocks (
                    BlkIo,
                    BlkIo->Media->MediaId,
                    Offset,
                    Bytes,
                    Buffer
                    );

  FreePool (Buffer);

  if (EFI_ERROR (Status)) {
    return EFI_LOAD_ERROR;
  }
  //
  // now not modified
  //
  HBufferImage.Modified = FALSE;

  return EFI_SUCCESS;
}
Esempio n. 16
0
//
// TDS 5.3
//
EFI_STATUS
BBTestWriteBlocksFunctionAutoTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL   *StandardLib;
  EFI_STATUS                           Status;
  EFI_BLOCK_IO_PROTOCOL                *BlockIo;
  UINT32                               MediaId;
  BOOLEAN                              RemovableMedia;
  BOOLEAN                              MediaPresent;
  BOOLEAN                              LogicalPartition;
  BOOLEAN                              ReadOnly;
  BOOLEAN                              WriteCaching;
  UINT32                               BlockSize;
  UINT32                               IoAlign;
  EFI_LBA                              LastBlock;

  UINTN                                BufferSize;
  UINT8                                *Buffer;
  UINT8                                *Buffer2;
  UINT8                                *Buffer3;

  UINT32                               BlockNumber;

  UINTN                                IndexI, IndexJ;
  UINTN                                NewBufferSize;
  EFI_LBA                              NewLba;

  UINTN                                Remainder;

  EFI_DEVICE_PATH_PROTOCOL             *DevicePath;
  CHAR16                               *DevicePathStr;

  EFI_TEST_ASSERTION                   AssertionTypeRead1;
  EFI_TEST_ASSERTION                   AssertionTypeRead2;
  EFI_TEST_ASSERTION                   AssertionTypeRead3;
  EFI_TEST_ASSERTION                   AssertionTypeWrite1;
  EFI_TEST_ASSERTION                   AssertionTypeWrite2;
  EFI_TEST_ASSERTION                   AssertionTypeComp1;
  EFI_TEST_ASSERTION                   AssertionTypeComp2;

  EFI_STATUS                           StatusRead1;
  EFI_STATUS                           StatusRead2;
  EFI_STATUS                           StatusRead3;
  EFI_STATUS                           StatusWrite1;
  EFI_STATUS                           StatusWrite2;

  UINTN                                CountComp1;
  UINTN                                CountComp2;


  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                   SupportHandle,
                   &gEfiStandardTestLibraryGuid,
                   &StandardLib
                   );

  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.HandleProtocol - Handle standard test library",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                 );
    return Status;
  }

  BlockIo = (EFI_BLOCK_IO_PROTOCOL *)ClientInterface;

  //
  // Locate & record DevicePath for further investigation
  //
  LocateDevicePathFromBlockIo (BlockIo, &DevicePath, StandardLib);

  DevicePathStr = DevicePathToStr (DevicePath);
  if (DevicePathStr != NULL) {
    StandardLib->RecordMessage (
                   StandardLib,
                   EFI_VERBOSE_LEVEL_DEFAULT,
                   L"Current Device: %s",
                   DevicePathStr
                   );

    Status = gtBS->FreePool (DevicePathStr);
    if (EFI_ERROR(Status)) {
      StandardLib->RecordAssertion (
                     StandardLib,
                     EFI_TEST_ASSERTION_FAILED,
                     gTestGenericFailureGuid,
                     L"BS.FreePool - Free device path string",
                     L"%a:%d:Status - %r",
                     __FILE__,
                     __LINE__,
                     Status
                     );
      return Status;
    }

    DevicePathStr = NULL;
  }


  //
  // Initialize variable
  //
  MediaId           = BlockIo->Media->MediaId;
  RemovableMedia    = BlockIo->Media->RemovableMedia;
  MediaPresent      = BlockIo->Media->MediaPresent;
  LogicalPartition  = BlockIo->Media->LogicalPartition;
  ReadOnly          = BlockIo->Media->ReadOnly;
  WriteCaching      = BlockIo->Media->WriteCaching;
  BlockSize         = BlockIo->Media->BlockSize;
  IoAlign           = BlockIo->Media->IoAlign;
  LastBlock         = BlockIo->Media->LastBlock;

  BlockNumber       = (UINT32) MINIMUM(LastBlock, MAX_NUMBER_OF_READ_BLOCK_BUFFER);
  BufferSize        = BlockNumber * BlockSize;

  if (BufferSize == 0) {
    BufferSize = 512;
  }

  //
  // allocate buffer
  //
  Status = gtBS->AllocatePool (EfiBootServicesData, BufferSize, &Buffer);
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.AllocatePool - Allocate buffer for testing",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                   );
    return Status;
  }

  Status = gtBS->AllocatePool (EfiBootServicesData, BufferSize, &Buffer2);
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.AllocatePool - Allocate buffer for testing",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                   );
    gtBS->FreePool (Buffer);
    return Status;
  }

  Status = gtBS->AllocatePool (EfiBootServicesData, BufferSize, &Buffer3);
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.AllocatePool - Allocate buffer for testing",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                   );
    gtBS->FreePool (Buffer);
    gtBS->FreePool (Buffer2);
    return Status;
  }

  //
  // Assertion Point 5.3.2.1
  // ReadBlocks must succeed to read proper data from device with valid parameter
  //
  if ((MediaPresent == TRUE) && (ReadOnly == FALSE)) {
    for (IndexI = 1; IndexI < MAX_DIFFERENT_BUFFERSIZE_FOR_TEST; IndexI++) {
      //
      // prepare test data
      // BufferSize will range from BlockSize to MAX_DIFFERENT_BUFFERSIZE_FOR_TEST*BlockSize
      //
      NewBufferSize = IndexI * BlockSize;

      //
      //parameter verification on NewBufferSize
      //
      if (NewBufferSize > BufferSize) {
        break;
      }

      for (IndexJ = 0; IndexJ < 3 * MAX_DIFFERENT_LBA_FOR_TEST; IndexJ++) {
        //
        // prepare test data
        //
        if (IndexJ < MAX_DIFFERENT_LBA_FOR_TEST) {
          // from 1 to MAX_DIFFERENT_LBA_FOR_TEST
          NewLba = IndexJ;
        } else if (IndexJ < 2 * MAX_DIFFERENT_LBA_FOR_TEST) {
          // from (LastBlock - MAX_DIFFERENT_LBA_FOR_TEST - MAX_DIFFERENT_BUFFERSIZE_FOR_TEST)  to (LastBlock - MAX_DIFFERENT_BUFFERSIZE_FOR_TEST)
          NewLba = IndexJ + LastBlock - 2 * MAX_DIFFERENT_LBA_FOR_TEST - MAX_DIFFERENT_BUFFERSIZE_FOR_TEST;
        } else {
          // from (LastBlock/2 - MAX_DIFFERENT_LBA_FOR_TEST/2) to (LastBlock/2 + MAX_DIFFERENT_LBA_FOR_TEST/2)
          NewLba = IndexJ - 2 * MAX_DIFFERENT_LBA_FOR_TEST + (DivU64x32 (LastBlock, 2, &Remainder) - MAX_DIFFERENT_LBA_FOR_TEST / 2);
        }

        //
        //parameter verification on NewLba
        //
        if (NewLba + NewBufferSize / BlockSize > LastBlock + 1) {
          continue;
        }

        //
        // To avoid the LOG information is destroied, the LOG information will
        // be recorded after the original data is written again.
        //

        //
        // Call ReadBlocks with the specified LBA and BufferSize
        //
        StatusRead1 = BlockIo->ReadBlocks (
                                 BlockIo,
                                 MediaId,
                                 NewLba,
                                 NewBufferSize,
                                 (VOID*)Buffer
                                 );
        if (EFI_ERROR(StatusRead1)) {
          AssertionTypeRead1 = EFI_TEST_ASSERTION_FAILED;
        } else {
          AssertionTypeRead1 = EFI_TEST_ASSERTION_PASSED;
        }

        //
        // Write specified buffer2 differ from buffer to the device
        //
        StatusWrite1 = BlockIo->WriteBlocks (
                                  BlockIo,
                                  MediaId,
                                  NewLba,
                                  NewBufferSize,
                                  (VOID*)Buffer2
                                  );
        if (EFI_ERROR(StatusWrite1)) {
          AssertionTypeWrite1 = EFI_TEST_ASSERTION_FAILED;
        } else {
          AssertionTypeWrite1 = EFI_TEST_ASSERTION_PASSED;
        }

        //
        // if write-cached, then flush the data to physical device
        //
        if (WriteCaching) {
          BlockIo->FlushBlocks (BlockIo);
        }

        //
        // Read Block with same LBA and BufferSize again and save data into Buffer3
        //
        StatusRead2 = BlockIo->ReadBlocks (
                                 BlockIo,
                                 MediaId,
                                 NewLba,
                                 NewBufferSize,
                                 (VOID*)Buffer3
                                 );
        if (EFI_ERROR(StatusRead2)) {
          AssertionTypeRead2 = EFI_TEST_ASSERTION_FAILED;
        } else {
          AssertionTypeRead2 = EFI_TEST_ASSERTION_PASSED;
        }

        //
        // verification on Write and Read blocks on valid media
        //
        CountComp1 = VerifyBuffer (Buffer2, Buffer3, NewBufferSize);
        if (CountComp1 > 0) {
          AssertionTypeComp1 = EFI_TEST_ASSERTION_FAILED;
        } else {
          AssertionTypeComp1 = EFI_TEST_ASSERTION_PASSED;
        }

        //
        // Write buffer read in the first call of ReadBlocks back to the device
        //
        StatusWrite2 = BlockIo->WriteBlocks (
                                  BlockIo,
                                  MediaId,
                                  NewLba,
                                  NewBufferSize,
                                  (VOID*)Buffer
                                  );
        if (EFI_ERROR(StatusWrite2)) {
          AssertionTypeWrite2 = EFI_TEST_ASSERTION_FAILED;
        } else {
          AssertionTypeWrite2 = EFI_TEST_ASSERTION_PASSED;
        }

        //
        // if write-cached, then flush the data to physical device
        //
        if (WriteCaching) {
          BlockIo->FlushBlocks (BlockIo);
        }

        //
        // Read Block with same LBA and BufferSize again and save data into Buffer3
        //
        StatusRead3 = BlockIo->ReadBlocks (
                                 BlockIo,
                                 MediaId,
                                 NewLba,
                                 NewBufferSize,
                                 (VOID*)Buffer3
                                 );
        if (EFI_ERROR(StatusRead3)) {
          AssertionTypeRead3 = EFI_TEST_ASSERTION_FAILED;
        } else {
          AssertionTypeRead3 = EFI_TEST_ASSERTION_PASSED;
        }

        //
        // verification on first and last call of ReadBlocks
        //
        CountComp2 = VerifyBuffer (Buffer, Buffer3, NewBufferSize);
        if (CountComp2 > 0) {
          AssertionTypeComp2 = EFI_TEST_ASSERTION_FAILED;
        } else {
          AssertionTypeComp2 = EFI_TEST_ASSERTION_PASSED;
        }

        //
        // Record test results
        //
        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionTypeRead1,
                       gTestGenericFailureGuid,
                       L"EFI_BLOCK_IO_PROTOCOL.ReadBlocks - Read Block with proper parameter from valid media",
                       L"%a:%d:BufferSize=%d, Lba=0x%lx, Status=%r",
                       __FILE__,
                       __LINE__,
                       NewBufferSize,
                       NewLba,
                       StatusRead1
                       );

        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionTypeWrite1,
                       gBlockIoFunctionTestAssertionGuid009,
                       L"EFI_BLOCK_IO_PROTOCOL.WriteBlocks - Write Block with proper parameter from valid media",
                       L"%a:%d:BufferSize=%d, Lba=0x%lx, Status=%r",
                       __FILE__,
                       __LINE__,
                       NewBufferSize,
                       NewLba,
                       StatusWrite1
                       );

        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionTypeRead2,
                       gTestGenericFailureGuid,
                       L"EFI_BLOCK_IO_PROTOCOL.ReadBlocks - Read Block with proper parameter from valid media",
                       L"%a:%d:BufferSize=%d, Lba=0x%lx, Status=%r",
                       __FILE__,
                       __LINE__,
                       NewBufferSize,
                       NewLba,
                       StatusRead2
                       );

        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionTypeComp1,
                       gBlockIoFunctionTestAssertionGuid012,
                       L"EFI_BLOCK_IO_PROTOCOL.WriteBlocks - Verification on Write and Read blocks on valid media",
                       L"%a:%d:BufferSize=%d, Lba=0x%lx, DiffCount=%d",
                       __FILE__,
                       __LINE__,
                       NewBufferSize,
                       NewLba,
                       CountComp1
                       );

        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionTypeWrite2,
                       gBlockIoFunctionTestAssertionGuid013,
                       L"EFI_BLOCK_IO_PROTOCOL.WriteBlocks - Write Block with proper parameter back to valid media ",
                       L"%a:%d:BufferSize=%d, Lba=0x%lx, Status=%r",
                       __FILE__,
                       __LINE__,
                       NewBufferSize,
                       NewLba,
                       StatusWrite2
                       );

        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionTypeRead3,
                       gTestGenericFailureGuid,
                       L"EFI_BLOCK_IO_PROTOCOL.ReadBlocks - Read Block with proper parameter from valid media",
                       L"%a:%d:BufferSize=%d, Lba=0x%lx, Status=%r",
                       __FILE__,
                       __LINE__,
                       NewBufferSize,
                       NewLba,
                       StatusRead3
                       );

        StandardLib->RecordAssertion (
                       StandardLib,
                       AssertionTypeComp2,
                       gBlockIoFunctionTestAssertionGuid016,
                       L"EFI_BLOCK_IO_PROTOCOL.WriteBlocks - Verification on Write and Read blocks on valid media",
                       L"%a:%d:BufferSize=%d, Lba=0x%lx,  DiffCount=%d",
                      __FILE__,
                      __LINE__,
                      NewBufferSize,
                      NewLba,
                      CountComp2
                      );
      }//end of loop of Lba - IndexJ
    }//end of loop of BufferSize - IndexI
  }

  //
  // Free resources
  //
  Status = gtBS->FreePool (Buffer3);
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.FreePool - Free buffer for testing",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                   );
    return Status;
  }

  Status = gtBS->FreePool (Buffer2);
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.FreePool - Free buffer for testing",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                   );
    return Status;
  }

  Status = gtBS->FreePool (Buffer);
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.FreePool - Free buffer for testing",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                   );
    return Status;
  }

  return EFI_SUCCESS;
}
Esempio n. 17
0
/**
  Display blocks to the screen.

  @param[in] DevPath      The device path to get the blocks from.
  @param[in] Lba          The Lba number to start from.
  @param[in] BlockCount   How many blocks to display.

  @retval SHELL_SUCCESS   The display was successful.
**/
SHELL_STATUS
EFIAPI
DisplayTheBlocks(
  IN CONST EFI_DEVICE_PATH_PROTOCOL *DevPath,
  IN CONST UINT64                   Lba,
  IN CONST UINT8                    BlockCount
  )
{
  EFI_BLOCK_IO_PROTOCOL     *BlockIo;
  EFI_HANDLE                BlockIoHandle;
  EFI_STATUS                Status;
  SHELL_STATUS              ShellStatus;
  UINT8                     *Buffer;
  UINTN                     BufferSize;

  ShellStatus = SHELL_SUCCESS;

  Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid, (EFI_DEVICE_PATH_PROTOCOL **)&DevPath, &BlockIoHandle);
  if (EFI_ERROR(Status)) {
    return (SHELL_NOT_FOUND);
  }

  Status = gBS->OpenProtocol(BlockIoHandle, &gEfiBlockIoProtocolGuid, (VOID**)&BlockIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
  if (EFI_ERROR(Status)) {
    return (SHELL_NOT_FOUND);
  }

  BufferSize = BlockIo->Media->BlockSize * BlockCount;
  if (BufferSize > 0) {
    Buffer     = AllocateZeroPool(BufferSize);
  } else {
    ShellPrintEx(-1,-1,L"  BlockSize: 0x%08x, BlockCount: 0x%08x\r\n", BlockIo->Media->BlockSize, BlockCount);
    Buffer    = NULL;
  }

  Status = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, Lba, BufferSize, Buffer);
  if (!EFI_ERROR(Status) && Buffer != NULL) {
    ShellPrintHiiEx(
      -1, 
      -1, 
      NULL, 
      STRING_TOKEN (STR_DBLK_HEADER), 
      gShellDebug1HiiHandle, 
      Lba,
      BufferSize,
      BlockIo
      );

    DumpHex(2,0,BufferSize,Buffer);
  } else {
    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_READ_FAIL), gShellDebug1HiiHandle, L"BlockIo", Status);
    ShellStatus = SHELL_DEVICE_ERROR;
  }

  if (Buffer != NULL) {
    FreePool(Buffer);
  }

  gBS->CloseProtocol(BlockIoHandle, &gEfiBlockIoProtocolGuid, gImageHandle, NULL);
  return (ShellStatus);
}
Esempio n. 18
0
//
// TDS 5.5
//
EFI_STATUS
BBTestMediaIntegrityManualTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL   *StandardLib;
  EFI_STATUS                           Status;
  EFI_BLOCK_IO_PROTOCOL                *BlockIo;
  EFI_TEST_ASSERTION                   AssertionType;
  UINT32                               MediaId;
  BOOLEAN                              RemovableMedia;
  BOOLEAN                              MediaPresent;
  BOOLEAN                              LogicalPartition;
  BOOLEAN                              ReadOnly;
  BOOLEAN                              WriteCaching;
  UINT32                               BlockSize;
  UINT32                               IoAlign;
  EFI_LBA                              LastBlock;

  UINTN                                BufferSize;
  UINT8                                *Buffer;

  UINT32                               BlockNumber;
  UINTN                                Index;

  EFI_DEVICE_PATH_PROTOCOL             *DevicePath;
  CHAR16                               *DevicePathStr;

  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                   SupportHandle,
                   &gEfiStandardTestLibraryGuid,
                   &StandardLib
                   );

  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.HandleProtocol - Handle standard test library",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                   );
    return Status;
  }

  BlockIo = (EFI_BLOCK_IO_PROTOCOL *)ClientInterface;

  //
  // Initialize variable
  //
  MediaId           = BlockIo->Media->MediaId;
  RemovableMedia    = BlockIo->Media->RemovableMedia;
  MediaPresent      = BlockIo->Media->MediaPresent;
  LogicalPartition  = BlockIo->Media->LogicalPartition;
  ReadOnly          = BlockIo->Media->ReadOnly;
  WriteCaching      = BlockIo->Media->WriteCaching;
  BlockSize         = BlockIo->Media->BlockSize;
  IoAlign           = BlockIo->Media->IoAlign;
  LastBlock         = BlockIo->Media->LastBlock;

  BlockNumber       = (UINT32) MINIMUM(LastBlock, MAX_NUMBER_OF_READ_BLOCK_BUFFER);
  BufferSize        = BlockNumber * BlockSize;

  if (BufferSize == 0) {
    BufferSize = 512;
  }

  //
  // allocate buffer
  //
  Status = gtBS->AllocatePool (EfiBootServicesData, BufferSize, &Buffer);
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.AllocatePool - Allocate buffer for testing",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                   );
    return Status;
  }

  //
  // Locate the Handle that the BlockIo interface is bound to
  //
  LocateDevicePathFromBlockIo (BlockIo, &DevicePath, StandardLib);

  DevicePathStr = DevicePathToStr (DevicePath);
  if (DevicePathStr != NULL) {
    StandardLib->RecordMessage (
                   StandardLib,
                   EFI_VERBOSE_LEVEL_DEFAULT,
                   L"Current Device: %s",
                   DevicePathStr
                   );

    Status = gtBS->FreePool (DevicePathStr);
    if (EFI_ERROR(Status)) {
      StandardLib->RecordAssertion (
                     StandardLib,
                     EFI_TEST_ASSERTION_FAILED,
                     gTestGenericFailureGuid,
                     L"BS.FreePool - Free device path string",
                     L"%a:%d:Status - %r",
                     __FILE__,
                     __LINE__,
                     Status
                     );
      goto FreeBuffer;
    }

    DevicePathStr = NULL;
  }

  //
  // Assertion Point 5.5.2.1
  // Media remove of insert of device must affect the MediaPresent field
  //
  if (RemovableMedia == TRUE) {

    //
    // Insert -> Remove -> Insert or Remove -> Insert -> Remove
    //
    for (Index = 0; Index < 2; Index++) {
      if (MediaPresent == TRUE) {
        Print (L"Remove media in device ");
      } else {
        Print (L"Insert media into device ");
      }

      DevicePathStr = DevicePathToStr (DevicePath);
      if (DevicePathStr != NULL) {
        Print (DevicePathStr);

        Status = gtBS->FreePool (DevicePathStr);
        if (EFI_ERROR(Status)) {
          StandardLib->RecordAssertion (
                         StandardLib,
                         EFI_TEST_ASSERTION_FAILED,
                         gTestGenericFailureGuid,
                         L"BS.FreePool - Free device path string",
                         L"%a:%d:Status - %r",
                         __FILE__,
                         __LINE__,
                         Status
                         );
          goto FreeBuffer;
        }

        DevicePathStr = NULL;
      }

      if (AutoJudge (50, FALSE, L"\r\nReady?\r\n") != TRUE) {
        goto AssertionPoint2;
      }

      //
      // Call ReadBlocks to force re-install device
      //
      Status = BlockIo->ReadBlocks (
                          BlockIo,
                          MediaId,
                          0,
                          BlockSize,
                          (VOID*)Buffer
                          );
      if (EFI_ERROR(Status)) {
        //
        // No Status check here.
        //
      }

      //
      // Begin to re-locate the BlockIo interface according to the DevicePath
      //
      LocateBlockIoFromDevicePath (&BlockIo, DevicePath, StandardLib);

      if (MediaPresent == BlockIo->Media->MediaPresent) {
        AssertionType = EFI_TEST_ASSERTION_FAILED;
      } else {
        AssertionType = EFI_TEST_ASSERTION_PASSED;
      }

      StandardLib->RecordAssertion (
                     StandardLib,
                     AssertionType,
                     gBlockIoFunctionTestAssertionGuid017,
                     L"EFI_BLOCK_IO_PROTOCOL.Media->MediaPresent,Media remove or insert of device must affect the MediaPresent field",
                     L"%a:%d:Previous MediaPresent=%d, After MediaPresent=%d",
                     __FILE__,
                     __LINE__,
                     MediaPresent,
                     BlockIo->Media->MediaPresent
                     );

      //
      // Restore the envionment
      //
      MediaPresent = BlockIo->Media->MediaPresent;
    }

    //
    // Initialize variable
    //
    MediaId           = BlockIo->Media->MediaId;
    RemovableMedia    = BlockIo->Media->RemovableMedia;
    MediaPresent      = BlockIo->Media->MediaPresent;
    LogicalPartition  = BlockIo->Media->LogicalPartition;
    ReadOnly          = BlockIo->Media->ReadOnly;
    WriteCaching      = BlockIo->Media->WriteCaching;
    BlockSize         = BlockIo->Media->BlockSize;
    IoAlign           = BlockIo->Media->IoAlign;
    LastBlock         = BlockIo->Media->LastBlock;
  }

  //
  // Assertion Point 5.5.2.2
  // Media change of device must affect the MediaId field and
  // may affect the BlockSize and ReadOnly and Logical Partition field.
  //
AssertionPoint2:
  if (RemovableMedia == TRUE) {

    if (MediaPresent == TRUE) {
      Print (L"Change media  in device ");
    } else {
      Print (L"Insert media into device ");
    }

    DevicePathStr = DevicePathToStr (DevicePath);
    if (DevicePathStr != NULL) {
      Print (DevicePathStr);

      Status = gtBS->FreePool (DevicePathStr);
      if (EFI_ERROR(Status)) {
        StandardLib->RecordAssertion (
                       StandardLib,
                       EFI_TEST_ASSERTION_FAILED,
                       gTestGenericFailureGuid,
                       L"BS.FreePool - Free device path string",
                       L"%a:%d:Status - %r",
                       __FILE__,
                       __LINE__,
                       Status
                       );
        goto FreeBuffer;
      }

      DevicePathStr = NULL;
    }

    if (AutoJudge (50, FALSE, L"\r\nReady?\r\n") != TRUE) {
      goto FreeBuffer;
    }

    //
    // Call ReadBlocks to force re-install device
    //
    Status = BlockIo->ReadBlocks (
                        BlockIo,
                        MediaId,
                        0,
                        BlockSize,
                        (VOID*)Buffer
                        );
    if (EFI_ERROR(Status)) {
      //
      // No Status check here.
      //
    }

    //
    // Begin to re-locate the BlockIo interface according to the DevicePath
    //
    LocateBlockIoFromDevicePath (&BlockIo, DevicePath, StandardLib);

    //
    // MediaID verificatoin
    //
    if (MediaId == BlockIo->Media->MediaId) {
      AssertionType = EFI_TEST_ASSERTION_FAILED;
    } else {
      AssertionType = EFI_TEST_ASSERTION_PASSED;
    }

    StandardLib->RecordAssertion (
                   StandardLib,
                   AssertionType,
                   gBlockIoFunctionTestAssertionGuid019,
                   L"EFI_BLOCK_IO_PROTOCOL.Media->MediaId,Media remove or insert of device must affect the MediaId field",
                   L"%a:%d:Previous MediaId=%d, After MediaId=%d",
                   __FILE__,
                   __LINE__,
                   MediaId,
                   BlockIo->Media->MediaId
                   );

    //
    // User's view about the current attribute of the media
    //
    MediaId           = BlockIo->Media->MediaId;
    RemovableMedia    = BlockIo->Media->RemovableMedia;
    MediaPresent      = BlockIo->Media->MediaPresent;
    LogicalPartition  = BlockIo->Media->LogicalPartition;
    ReadOnly          = BlockIo->Media->ReadOnly;
    WriteCaching      = BlockIo->Media->WriteCaching;
    BlockSize         = BlockIo->Media->BlockSize;
    IoAlign           = BlockIo->Media->IoAlign;
    LastBlock         = BlockIo->Media->LastBlock;

    StandardLib->RecordMessage (
                   StandardLib,
                   EFI_VERBOSE_LEVEL_DEFAULT,
                   L"Current Media data field:\n"
                   L"MediaId         =%d\n"
                   L"RemovableMedia  =%d\n"
                   L"MediaPresent    =%d\n"
                   L"LogicalPartition=%d\n"
                   L"ReadOnly        =%d\n"
                   L"WriteCaching    =%d\n"
                   L"BlockSize       =%d\n"
                   L"IoAlign         =%d\n"
                   L"LastBlock       =%lx\n",
                   MediaId,
                   RemovableMedia,
                   MediaPresent,
                   LogicalPartition,
                   ReadOnly,
                   WriteCaching,
                   BlockSize,
                   IoAlign,
                   LastBlock
                   );

    //
    // Output current media data structure
    //

    if (AutoJudge (99, TRUE, L"\r\nCorrect?\r\n") != TRUE) {
      AssertionType = EFI_TEST_ASSERTION_FAILED;
    } else {
      AssertionType = EFI_TEST_ASSERTION_PASSED;
    }

    StandardLib->RecordAssertion (
                   StandardLib,
                   AssertionType,
                   gBlockIoFunctionTestAssertionGuid020,
                   L"EFI_BLOCK_IO_PROTOCOL.Media,Media remove or insert of device must affect the MediaId field",
                   L"%a:%d:As user's select",
                   __FILE__,
                   __LINE__
                   );

    //
    // Restore environment
    //
    if (MediaPresent == TRUE) {
      Print (L"Change media back in device ");
    } else {
      Print (L"Remove media from device ");
    }

    DevicePathStr = DevicePathToStr (DevicePath);
    if (DevicePathStr != NULL) {
      Print (DevicePathStr);

      Status = gtBS->FreePool (DevicePathStr);
      if (EFI_ERROR(Status)) {
        StandardLib->RecordAssertion (
                       StandardLib,
                       EFI_TEST_ASSERTION_FAILED,
                       gTestGenericFailureGuid,
                       L"BS.FreePool - Free device path string",
                       L"%a:%d:Status - %r",
                       __FILE__,
                       __LINE__,
                       Status
                       );
        goto FreeBuffer;
      }

      DevicePathStr = NULL;
    }

    if (AutoJudge (50, FALSE, L"\r\nReady?\r\n") != TRUE) {
      goto FreeBuffer;
    }

    //
    // Call ReadBlocks to force re-install device
    //
    Status = BlockIo->ReadBlocks (
                        BlockIo,
                        MediaId,
                        0,
                        BlockSize,
                        (VOID*)Buffer
                        );
    if (EFI_ERROR(Status)) {
      //
      // No Status check here.
      //
    }
  }

FreeBuffer:
  //
  // Free resources
  //
  Status = gtBS->FreePool (Buffer);
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"BS.FreePool - Free buffer for testing",
                   L"%a:%d:Status - %r",
                   __FILE__,
                   __LINE__,
                   Status
                   );
    return Status;
  }

  return EFI_SUCCESS;
}
Esempio n. 19
0
/**
  Stop this driver on ControllerHandle. Support stopping any child handles
  created by this driver.

  @param  This              Protocol instance pointer.
  @param  ControllerHandle  Handle of device to stop driver on
  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
                            children is zero stop the entire bus driver.
  @param  ChildHandleBuffer List of Child Handles to Stop.

  @retval EFI_SUCCESS       This driver is removed ControllerHandle
  @retval other             This driver was not removed from this device

**/
EFI_STATUS
EFIAPI
PartitionDriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
  IN  EFI_HANDLE                    ControllerHandle,
  IN  UINTN                         NumberOfChildren,
  IN  EFI_HANDLE                    *ChildHandleBuffer
  )
{
  EFI_STATUS              Status;
  UINTN                   Index;
  EFI_BLOCK_IO_PROTOCOL   *BlockIo;
  EFI_BLOCK_IO2_PROTOCOL  *BlockIo2;
  BOOLEAN                 AllChildrenStopped;
  PARTITION_PRIVATE_DATA  *Private;
  EFI_DISK_IO_PROTOCOL    *DiskIo;

  BlockIo  = NULL;
  BlockIo2 = NULL;
  Private = NULL;

  if (NumberOfChildren == 0) {
    //
    // Close the bus driver
    //
    gBS->CloseProtocol (
          ControllerHandle,
          &gEfiDiskIoProtocolGuid,
          This->DriverBindingHandle,
          ControllerHandle
          );
    //
    // Close Parent BlockIO2 if has.
    //    
    gBS->CloseProtocol (
           ControllerHandle,
           &gEfiDiskIo2ProtocolGuid,
           This->DriverBindingHandle,
           ControllerHandle
           );

    gBS->CloseProtocol (
          ControllerHandle,
          &gEfiDevicePathProtocolGuid,
          This->DriverBindingHandle,
          ControllerHandle
          );
    return EFI_SUCCESS;
  }

  AllChildrenStopped = TRUE;
  for (Index = 0; Index < NumberOfChildren; Index++) {
    gBS->OpenProtocol (
           ChildHandleBuffer[Index],
           &gEfiBlockIoProtocolGuid,
           (VOID **) &BlockIo,
           This->DriverBindingHandle,
           ControllerHandle,
           EFI_OPEN_PROTOCOL_GET_PROTOCOL
           );
    //
    // Try to locate BlockIo2.
    //
    gBS->OpenProtocol (
           ChildHandleBuffer[Index],
           &gEfiBlockIo2ProtocolGuid,
           (VOID **) &BlockIo2,
           This->DriverBindingHandle,
           ControllerHandle,
           EFI_OPEN_PROTOCOL_GET_PROTOCOL
           ); 


    Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo);

    Status = gBS->CloseProtocol (
                    ControllerHandle,
                    &gEfiDiskIoProtocolGuid,
                    This->DriverBindingHandle,
                    ChildHandleBuffer[Index]
                    );
    //
    // All Software protocols have be freed from the handle so remove it.
    // Remove the BlockIo Protocol if has.
    // Remove the BlockIo2 Protocol if has.
    //
    if (BlockIo2 != NULL) {
      BlockIo->FlushBlocks (BlockIo);
      BlockIo2->FlushBlocksEx (BlockIo2, NULL);
      Status = gBS->UninstallMultipleProtocolInterfaces (
                       ChildHandleBuffer[Index],
                       &gEfiDevicePathProtocolGuid,
                       Private->DevicePath,
                       &gEfiBlockIoProtocolGuid,
                       &Private->BlockIo,
                       &gEfiBlockIo2ProtocolGuid,
                       &Private->BlockIo2,
                       Private->EspGuid,
                       NULL,
                       NULL
                       );
    } else {
      BlockIo->FlushBlocks (BlockIo);
      Status = gBS->UninstallMultipleProtocolInterfaces (
                       ChildHandleBuffer[Index],
                       &gEfiDevicePathProtocolGuid,
                       Private->DevicePath,
                       &gEfiBlockIoProtocolGuid,
                       &Private->BlockIo,
                       Private->EspGuid,
                       NULL,
                       NULL
                       );
    }

    if (EFI_ERROR (Status)) {
      gBS->OpenProtocol (
             ControllerHandle,
             &gEfiDiskIoProtocolGuid,
             (VOID **) &DiskIo,
             This->DriverBindingHandle,
             ChildHandleBuffer[Index],
             EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
             );
    } else {
      FreePool (Private->DevicePath);
      FreePool (Private);
    }

    if (EFI_ERROR (Status)) {
      AllChildrenStopped = FALSE;
    }
  }

  if (!AllChildrenStopped) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}
Esempio n. 20
0
EFIAPI
EFI_STATUS
BootMonFsFlushFile (
  IN EFI_FILE_PROTOCOL  *This
  )
{
  EFI_STATUS               Status;
  BOOTMON_FS_INSTANCE     *Instance;
  LIST_ENTRY              *RegionToFlushLink;
  BOOTMON_FS_FILE         *File;
  BOOTMON_FS_FILE         *NextFile;
  BOOTMON_FS_FILE_REGION  *Region;
  LIST_ENTRY              *FileLink;
  UINTN                    CurrentPhysicalSize;
  UINTN                    BlockSize;
  UINT64                   FileStart;
  UINT64                   FileEnd;
  UINT64                   RegionStart;
  UINT64                   RegionEnd;
  UINT64                   NewFileSize;
  UINT64                   EndOfAppendSpace;
  BOOLEAN                  HasSpace;
  EFI_DISK_IO_PROTOCOL    *DiskIo;
  EFI_BLOCK_IO_PROTOCOL   *BlockIo;

  Status      = EFI_SUCCESS;
  FileStart   = 0;

  File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
  if (File == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  // Check if the file needs to be flushed
  if (!BootMonFsFileNeedFlush (File)) {
    return Status;
  }

  Instance = File->Instance;
  BlockIo = Instance->BlockIo;
  DiskIo = Instance->DiskIo;
  BlockSize = BlockIo->Media->BlockSize;

  // If the file doesn't exist then find a space for it
  if (File->HwDescription.RegionCount == 0) {
    Status = BootMonFsFindSpaceForNewFile (File, &FileStart);
    // FileStart has changed so we need to recompute RegionEnd
    if (EFI_ERROR (Status)) {
      return Status;
    }
  } else {
    FileStart = File->HwDescription.BlockStart * BlockSize;
  }

  // FileEnd is the NOR address of the end of the file's data
  FileEnd = FileStart + BootMonFsGetImageLength (File);

  for (RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink);
       !IsNull (&File->RegionToFlushLink, RegionToFlushLink);
       RegionToFlushLink = GetNextNode (&File->RegionToFlushLink, RegionToFlushLink)
       )
  {
    Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;

    // RegionStart and RegionEnd are the the intended NOR address of the
    // start and end of the region
    RegionStart = FileStart + Region->Offset;
    RegionEnd = RegionStart + Region->Size;

    if (RegionEnd < FileEnd) {
      // Handle regions representing edits to existing portions of the file
      // Write the region data straight into the file
      Status = DiskIo->WriteDisk (DiskIo,
                        BlockIo->Media->MediaId,
                        RegionStart,
                        Region->Size,
                        Region->Buffer
                        );
      if (EFI_ERROR (Status)) {
        return Status;
      }
    } else {
      // Handle regions representing appends to the file
      //
      // Note: Since seeking past the end of the file with SetPosition() is
      //  valid, it's possible there will be a gap between the current end of
      //  the file and the beginning of the new region. Since the UEFI spec
      //  says nothing about this case (except "a subsequent write would grow
      //  the file"), we just leave garbage in the gap.

      // Check if there is space to append the new region
      HasSpace = FALSE;
      NewFileSize = (RegionEnd - FileStart) + sizeof (HW_IMAGE_DESCRIPTION);
      CurrentPhysicalSize = BootMonFsGetPhysicalSize (File);
      if (NewFileSize <= CurrentPhysicalSize) {
        HasSpace = TRUE;
      } else {
        // Get the File Description for the next file
        FileLink = GetNextNode (&Instance->RootFile->Link, &File->Link);
        if (!IsNull (&Instance->RootFile->Link, FileLink)) {
          NextFile = BOOTMON_FS_FILE_FROM_LINK_THIS (FileLink);

          // If there is space between the beginning of the current file and the
          // beginning of the next file then use it
          EndOfAppendSpace = NextFile->HwDescription.BlockStart * BlockSize;
        } else {
          // We are flushing the last file.
          EndOfAppendSpace = (BlockIo->Media->LastBlock + 1) * BlockSize;
        }
        if (EndOfAppendSpace - FileStart >= NewFileSize) {
          HasSpace = TRUE;
        }
      }

      if (HasSpace == TRUE) {
        Status = FlushAppendRegion (File, Region, NewFileSize, FileStart);
        if (EFI_ERROR (Status)) {
          return Status;
        }
      } else {
        // There isn't a space for the file.
        // Options here are to move the file or fragment it. However as files
        // may represent boot images at fixed positions, these options will
        // break booting if the bootloader doesn't use BootMonFs to find the
        // image.

        return EFI_VOLUME_FULL;
      }
    }
  }

  FreeFileRegions (File);

  // Flush DiskIo Buffers (see UEFI Spec 12.7 - DiskIo buffers are flushed by
  // calling FlushBlocks on the same device's BlockIo).
  BlockIo->FlushBlocks (BlockIo);

  return Status;
}