Esempio n. 1
0
void dataset_convert(dataset_t* data, stream_t* out)
{
    void* m;
    int i;

    printf("Allocating %d bytes.\n", ACTUAL_MEMORY_SIZE(out));
    m = malloc(ACTUAL_MEMORY_SIZE(out));
    if(m == NULL)
    {
        printf("Cannot allocate memory.\n");
        return;
    }
    memset(m, 0, ACTUAL_MEMORY_SIZE(out));

    for(i = 0; i < data->n_records / MEMORY_RECORDS(out); i++)
    {
        memcpy(m, data->records + (i * MEMORY_RECORDS(out) * RECORD_SIZE(out)), MEMORY_RECORDS(out) * RECORD_SIZE(out));
        memory_write(out, m, MEMORY_RECORDS(out));
        stats_print();
    }
    if(data->n_records % MEMORY_RECORDS(out))
    {
        memcpy(m, data->records + (i * MEMORY_RECORDS(out) * RECORD_SIZE(out)), (data->n_records % MEMORY_RECORDS(out)) * RECORD_SIZE(out));
        memory_write(out, m, data->n_records % MEMORY_RECORDS(out));
        stats_print();
    }
    free(m);
}
Esempio n. 2
0
/**
  To check if FtwRecord is the first record of FtwHeader.

  @param FtwHeader  Pointer to the write record header
  @param FtwRecord  Pointer to retrieve the previous write record

  @retval EFI_ACCESS_DENIED  Input record is the first record, no previous record is return.
  @retval EFI_SUCCESS        The previous write record is found.

**/
EFI_STATUS
GetPreviousRecordOfWrites (
  IN     EFI_FAULT_TOLERANT_WRITE_HEADER    *FtwHeader,
  IN OUT EFI_FAULT_TOLERANT_WRITE_RECORD    **FtwRecord
  )
{
  UINT8 *Ptr;

  if (IsFirstRecordOfWrites (FtwHeader, *FtwRecord)) {
    *FtwRecord = NULL;
    return EFI_ACCESS_DENIED;
  }

  Ptr = (UINT8 *) (*FtwRecord);
  Ptr -= RECORD_SIZE (FtwHeader->PrivateDataSize);
  *FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) Ptr;
  return EFI_SUCCESS;
}
Esempio n. 3
0
/**
  Get the last Write Record pointer. The last write Record is the Record
  whose DestinationCompleted state hasn't been set. After all, this Record
  may be a EMPTY record entry for next write.


  @param FtwWriteHeader  Pointer to the write record header
  @param FtwWriteRecord  Pointer to retrieve the last write record

  @retval EFI_SUCCESS        Get the last write record successfully
  @retval EFI_ABORTED        The FTW work space is damaged

**/
EFI_STATUS
FtwGetLastWriteRecord (
  IN EFI_FAULT_TOLERANT_WRITE_HEADER          *FtwWriteHeader,
  OUT EFI_FAULT_TOLERANT_WRITE_RECORD         **FtwWriteRecord
  )
{
  UINTN                           Index;
  EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord;

  *FtwWriteRecord = NULL;
  FtwRecord       = (EFI_FAULT_TOLERANT_WRITE_RECORD *) (FtwWriteHeader + 1);

  //
  // Try to find the last write record "that has not completed"
  //
  for (Index = 0; Index < FtwWriteHeader->NumberOfWrites; Index += 1) {
    if (FtwRecord->DestinationComplete != FTW_VALID_STATE) {
      //
      // The last write record is found
      //
      *FtwWriteRecord = FtwRecord;
      return EFI_SUCCESS;
    }

    FtwRecord++;

    if (FtwWriteHeader->PrivateDataSize != 0) {
      FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord + FtwWriteHeader->PrivateDataSize);
    }
  }
  //
  //  if Index == NumberOfWrites, then
  //  the last record has been written successfully,
  //  but the Header->Complete Flag has not been set.
  //  also return the last record.
  //
  if (Index == FtwWriteHeader->NumberOfWrites) {
    *FtwWriteRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord - RECORD_SIZE (FtwWriteHeader->PrivateDataSize));
    return EFI_SUCCESS;
  }

  return EFI_ABORTED;
}
Esempio n. 4
0
/**
  Starts a target block update. This function will record data about write
  in fault tolerant storage and will complete the write in a recoverable
  manner, ensuring at all times that either the original contents or
  the modified contents are available.

  @param This            The pointer to this protocol instance. 
  @param Lba             The logical block address of the target block.
  @param Offset          The offset within the target block to place the data.
  @param Length          The number of bytes to write to the target block.
  @param PrivateData     A pointer to private data that the caller requires to
                         complete any pending writes in the event of a fault.
  @param FvBlockHandle   The handle of FVB protocol that provides services for
                         reading, writing, and erasing the target block.
  @param Buffer          The data to write.

  @retval EFI_SUCCESS          The function completed successfully 
  @retval EFI_ABORTED          The function could not complete successfully. 
  @retval EFI_BAD_BUFFER_SIZE  The input data can't fit within the spare block. 
                               Offset + *NumBytes > SpareAreaLength.
  @retval EFI_ACCESS_DENIED    No writes have been allocated. 
  @retval EFI_OUT_OF_RESOURCES Cannot allocate enough memory resource.
  @retval EFI_NOT_FOUND        Cannot find FVB protocol by handle.

**/
EFI_STATUS
EFIAPI
FtwWrite (
  IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL     *This,
  IN EFI_LBA                               Lba,
  IN UINTN                                 Offset,
  IN UINTN                                 Length,
  IN VOID                                  *PrivateData,
  IN EFI_HANDLE                            FvBlockHandle,
  IN VOID                                  *Buffer
  )
{
  EFI_STATUS                          Status;
  EFI_FTW_DEVICE                      *FtwDevice;
  EFI_FAULT_TOLERANT_WRITE_HEADER     *Header;
  EFI_FAULT_TOLERANT_WRITE_RECORD     *Record;
  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;
  UINTN                               MyLength;
  UINTN                               MyOffset;
  UINTN                               MyBufferSize;
  UINT8                               *MyBuffer;
  UINTN                               SpareBufferSize;
  UINT8                               *SpareBuffer;
  UINTN                               Index;
  UINT8                               *Ptr;
  EFI_PHYSICAL_ADDRESS                FvbPhysicalAddress;

  FtwDevice = FTW_CONTEXT_FROM_THIS (This);

  Status    = WorkSpaceRefresh (FtwDevice);
  if (EFI_ERROR (Status)) {
    return EFI_ABORTED;
  }

  Header  = FtwDevice->FtwLastWriteHeader;
  Record  = FtwDevice->FtwLastWriteRecord;
  
  if (IsErasedFlashBuffer ((UINT8 *) Header, sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER))) {
    if (PrivateData == NULL) {
      //
      // Ftw Write Header is not allocated.
      // No additional private data, the private data size is zero. Number of record can be set to 1.
      //
      Status = FtwAllocate (This, &gEfiCallerIdGuid, 0, 1);
      if (EFI_ERROR (Status)) {
        return Status;
      }
    } else {
      //
      // Ftw Write Header is not allocated
      // Additional private data is not NULL, the private data size can't be determined.
      //
      DEBUG ((EFI_D_ERROR, "Ftw: no allocates space for write record!\n"));
      DEBUG ((EFI_D_ERROR, "Ftw: Allocate service should be called before Write service!\n"));
      return EFI_NOT_READY;
    }
  }

  //
  // If Record is out of the range of Header, return access denied.
  //
  if (((UINTN)((UINT8 *) Record - (UINT8 *) Header)) > WRITE_TOTAL_SIZE (Header->NumberOfWrites - 1, Header->PrivateDataSize)) {
    return EFI_ACCESS_DENIED;
  }

  //
  // Check the COMPLETE flag of last write header
  //
  if (Header->Complete == FTW_VALID_STATE) {
    return EFI_ACCESS_DENIED;
  }

  if (Record->DestinationComplete == FTW_VALID_STATE) {
    return EFI_ACCESS_DENIED;
  }

  if ((Record->SpareComplete == FTW_VALID_STATE) && (Record->DestinationComplete != FTW_VALID_STATE)) {
    return EFI_NOT_READY;
  }
  //
  // Check if the input data can fit within the target block
  //
  if ((Offset + Length) > FtwDevice->SpareAreaLength) {
    return EFI_BAD_BUFFER_SIZE;
  }
  //
  // Get the FVB protocol by handle
  //
  Status = FtwGetFvbByHandle (FvBlockHandle, &Fvb);
  if (EFI_ERROR (Status)) {
    return EFI_NOT_FOUND;
  }

  Status = Fvb->GetPhysicalAddress (Fvb, &FvbPhysicalAddress);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "FtwLite: Get FVB physical address - %r\n", Status));
    return EFI_ABORTED;
  }

  //
  // Set BootBlockUpdate FLAG if it's updating boot block.
  //
  if (IsBootBlock (FtwDevice, Fvb, Lba)) {
    Record->BootBlockUpdate = FTW_VALID_STATE;
  }
  //
  // Write the record to the work space.
  //
  Record->Lba     = Lba;
  Record->Offset  = Offset;
  Record->Length  = Length;
  Record->FvBaseAddress = FvbPhysicalAddress;
  if (PrivateData != NULL) {
    CopyMem ((Record + 1), PrivateData, Header->PrivateDataSize);
  }

  MyOffset  = (UINT8 *) Record - FtwDevice->FtwWorkSpace;
  MyLength  = RECORD_SIZE (Header->PrivateDataSize);

  Status = FtwDevice->FtwFvBlock->Write (
                                    FtwDevice->FtwFvBlock,
                                    FtwDevice->FtwWorkSpaceLba,
                                    FtwDevice->FtwWorkSpaceBase + MyOffset,
                                    &MyLength,
                                    (UINT8 *) Record
                                    );
  if (EFI_ERROR (Status)) {
    return EFI_ABORTED;
  }
  //
  // Record has written to working block, then do the data.
  //
  //
  // Allocate a memory buffer
  //
  MyBufferSize  = FtwDevice->SpareAreaLength;
  MyBuffer      = AllocatePool (MyBufferSize);
  if (MyBuffer == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // Read all original data from target block to memory buffer
  //
  Ptr = MyBuffer;
  for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
    MyLength  = FtwDevice->BlockSize;
    Status    = Fvb->Read (Fvb, Lba + Index, 0, &MyLength, Ptr);
    if (EFI_ERROR (Status)) {
      FreePool (MyBuffer);
      return EFI_ABORTED;
    }

    Ptr += MyLength;
  }
  //
  // Overwrite the updating range data with
  // the input buffer content
  //
  CopyMem (MyBuffer + Offset, Buffer, Length);

  //
  // Try to keep the content of spare block
  // Save spare block into a spare backup memory buffer (Sparebuffer)
  //
  SpareBufferSize = FtwDevice->SpareAreaLength;
  SpareBuffer     = AllocatePool (SpareBufferSize);
  if (SpareBuffer == NULL) {
    FreePool (MyBuffer);
    return EFI_OUT_OF_RESOURCES;
  }

  Ptr = SpareBuffer;
  for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
    MyLength = FtwDevice->BlockSize;
    Status = FtwDevice->FtwBackupFvb->Read (
                                        FtwDevice->FtwBackupFvb,
                                        FtwDevice->FtwSpareLba + Index,
                                        0,
                                        &MyLength,
                                        Ptr
                                        );
    if (EFI_ERROR (Status)) {
      FreePool (MyBuffer);
      FreePool (SpareBuffer);
      return EFI_ABORTED;
    }

    Ptr += MyLength;
  }
  //
  // Write the memory buffer to spare block
  //
  Status  = FtwEraseSpareBlock (FtwDevice);
  Ptr     = MyBuffer;
  for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
    MyLength = FtwDevice->BlockSize;
    Status = FtwDevice->FtwBackupFvb->Write (
                                        FtwDevice->FtwBackupFvb,
                                        FtwDevice->FtwSpareLba + Index,
                                        0,
                                        &MyLength,
                                        Ptr
                                        );
    if (EFI_ERROR (Status)) {
      FreePool (MyBuffer);
      FreePool (SpareBuffer);
      return EFI_ABORTED;
    }

    Ptr += MyLength;
  }
  //
  // Free MyBuffer
  //
  FreePool (MyBuffer);

  //
  // Set the SpareComplete in the FTW record,
  //
  MyOffset = (UINT8 *) Record - FtwDevice->FtwWorkSpace;
  Status = FtwUpdateFvState (
            FtwDevice->FtwFvBlock,
            FtwDevice->FtwWorkSpaceLba,
            FtwDevice->FtwWorkSpaceBase + MyOffset,
            SPARE_COMPLETED
            );
  if (EFI_ERROR (Status)) {
    FreePool (SpareBuffer);
    return EFI_ABORTED;
  }

  Record->SpareComplete = FTW_VALID_STATE;

  //
  //  Since the content has already backuped in spare block, the write is
  //  guaranteed to be completed with fault tolerant manner.
  //
  Status = FtwWriteRecord (This, Fvb);
  if (EFI_ERROR (Status)) {
    FreePool (SpareBuffer);
    return EFI_ABORTED;
  }
  //
  // Restore spare backup buffer into spare block , if no failure happened during FtwWrite.
  //
  Status  = FtwEraseSpareBlock (FtwDevice);
  Ptr     = SpareBuffer;
  for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
    MyLength = FtwDevice->BlockSize;
    Status = FtwDevice->FtwBackupFvb->Write (
                                        FtwDevice->FtwBackupFvb,
                                        FtwDevice->FtwSpareLba + Index,
                                        0,
                                        &MyLength,
                                        Ptr
                                        );
    if (EFI_ERROR (Status)) {
      FreePool (SpareBuffer);
      return EFI_ABORTED;
    }

    Ptr += MyLength;
  }
  //
  // All success.
  //
  FreePool (SpareBuffer);

  DEBUG (
    (EFI_D_ERROR,
    "Ftw: Write() success, (Lba:Offset)=(%lx:0x%x), Length: 0x%x\n",
    Lba,
    Offset,
    Length)
    );

  return EFI_SUCCESS;
}