Beispiel #1
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;
}
Beispiel #2
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;
}
Beispiel #3
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);
}
Beispiel #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;
}
Beispiel #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 );
}
Beispiel #6
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;
}
//
// 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;
}
//
// 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;
}
//
// 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;
}
Beispiel #10
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"
    );
}
Beispiel #11
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;
}