Beispiel #1
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;
}
Beispiel #2
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;
}
Beispiel #3
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;
}
//
// 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;
}
Beispiel #5
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;
}