fwblockservice.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,943 行 · 第 1/4 页

C
1,943
字号
  //
  Dest  = (UINT8 *) WriteAddress;
  Src   = Buffer;

  for (Count = 0; Count < *NumBytes; Count++, Dest++, Src++) {

    HubCommand = FWH_WRITE_SETUP_COMMAND;
    FvbMemWrite8 ((UINT64) ((UINTN) Dest), HubCommand);
    FvbMemWrite8 ((UINT64) ((UINTN) Dest), *Src);

    //
    // Device error if time out occurs
    //
    RetryTimes = 0;
    while (RetryTimes < FVB_MAX_RETRY_TIMES) {
      HubCommand = FWH_READ_STATUS_COMMAND;
      FvbMemWrite8 ((UINT64) ((UINTN) Dest), HubCommand);
      EfiMemRead (EfiCpuIoWidthUint8, (UINT64) ((UINTN) Dest), 0x1, &HubData);
      if (HubData & FWH_WRITE_STATE_STATUS) {
        break;
      }

      RetryTimes++;
    }

    if (RetryTimes >= FVB_MAX_RETRY_TIMES) {
      *NumBytes = Count;
      Status    = EFI_DEVICE_ERROR;
      break;
    }
  }
  //
  // Clear status register
  //
  HubCommand = FWH_CLEAR_STATUS_COMMAND;
  FvbMemWrite8 ((UINT64) ((UINTN) WriteAddress), HubCommand);

  //
  // Issue read array command to return the FWH state machine to the
  // normal operational state
  //
  HubCommand = FWH_READ_ARRAY_COMMAND;
  FvbMemWrite8 ((UINT64) ((UINTN) WriteAddress), HubCommand);
  //
  // Flush the changed area to make the cache consistent
  //
  EfiCpuFlushCache (WriteAddress, *NumBytes);

  //
  // End of critical code section, release lock.
  //
  //  EfiReleaseLock(&(FwhInstance->FvbDevLock));
  //
  EnableFvbWrites (FALSE);

  return Status;
}

EFI_STATUS
FlashFdErase (
  IN UINTN                                WriteAddress,
  IN UINTN                                Address,
  IN UINTN                                LbaLength
  )
/*++

Routine Description:
  Erase a certain block from address LbaWriteAddress

Arguments:

Returns: 

--*/
{
  EFI_STATUS  Status;
  UINT8       HubCommand;
  UINT8       HubData;
  UINTN       RetryTimes;

  Status = EFI_SUCCESS;

  EnableFvbWrites (TRUE);

  //
  // Grab the lock before entering critical code section
  //
  //  EfiAcquireLock(&(FwhInstance->FvbDevLock));
  //
  // Send erase commands to FWH
  //
  HubCommand = FWH_BLOCK_ERASE_SETUP_COMMAND;
  FvbMemWrite8 ((UINT64) WriteAddress, HubCommand);
  HubCommand = FWH_BLOCK_ERASE_CONFIRM_COMMAND;
  FvbMemWrite8 ((UINT64) WriteAddress, HubCommand);

  //
  // Wait for completion. Indicated by FWH_WRITE_STATE_STATUS bit becoming 0
  // Device error if time out occurs
  //
  RetryTimes = 0;
  while (RetryTimes < FVB_MAX_RETRY_TIMES) {
    HubCommand = FWH_READ_STATUS_COMMAND;
    FvbMemWrite8 ((UINT64) WriteAddress, HubCommand);
    EfiMemRead (EfiCpuIoWidthUint8, (UINT64) WriteAddress, 0x1, &HubData);
    if (HubData & FWH_WRITE_STATE_STATUS) {
      break;
    }

    RetryTimes++;
  }

  if (RetryTimes >= FVB_MAX_RETRY_TIMES) {
    Status = EFI_DEVICE_ERROR;
  }
  //
  // Clear status register
  //
  HubCommand = FWH_CLEAR_STATUS_COMMAND;
  FvbMemWrite8 ((UINT64) WriteAddress, HubCommand);

  //
  // Issue read array command to return the FWH state machine to the normal op state
  //
  HubCommand = FWH_READ_ARRAY_COMMAND;
  FvbMemWrite8 ((UINT64) ((UINTN) WriteAddress), HubCommand);

  EfiCpuFlushCache (Address, LbaLength);

  //
  // End of critical code section, release lock.
  //
  //  EfiReleaseLock(&(FwhInstance->FvbDevLock));
  //
  EnableFvbWrites (FALSE);

  return Status;
}

EFI_STATUS
FvbWriteBlock (
  IN UINTN                                Instance,
  IN EFI_LBA                              Lba,
  IN UINTN                                BlockOffset,
  IN OUT UINTN                            *NumBytes,
  IN UINT8                                *Buffer,
  IN ESAL_FWB_GLOBAL                      *Global,
  IN BOOLEAN                              Virtual
  )
/*++

Routine Description:
  Writes specified number of bytes from the input buffer to the block

Arguments:
  Instance              - The FV instance to be written to
  Lba                   - The starting logical block index to write to
  BlockOffset           - Offset into the block at which to begin writing
  NumBytes              - Pointer that on input contains the total size of
                          the buffer. On output, it contains the total number
                          of bytes actually written
  Buffer                - Pointer to a caller allocated buffer that contains
                          the source for the write
  Global                - Pointer to ESAL_FWB_GLOBAL that contains all
                          instance data
  Virtual               - Whether CPU is in virtual or physical mode

Returns: 
  EFI_SUCCESS           - The firmware volume was written successfully
  EFI_BAD_BUFFER_SIZE   - Write attempted across a LBA boundary. On output,
                          NumBytes contains the total number of bytes
                          actually written
  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state
  EFI_DEVICE_ERROR      - The block device is not functioning correctly and 
                          could not be written
  EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL

--*/
{
  EFI_FVB_ATTRIBUTES  Attributes;
  UINTN               LbaAddress;
  UINTN               LbaWriteAddress;
  UINTN               LbaLength;
  EFI_FW_VOL_INSTANCE *FwhInstance;
  EFI_STATUS          Status;
  EFI_STATUS          ReturnStatus;

  //
  // Find the right instance of the FVB private data
  //
  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
  ASSERT_EFI_ERROR (Status);

  //
  // Writes are enabled in the init routine itself
  //
  if (!FwhInstance->WriteEnabled) {
    return EFI_ACCESS_DENIED;
  }
  //
  // Check for invalid conditions
  //
  if ((NumBytes == NULL) || (Buffer == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  if (*NumBytes == 0) {
    return EFI_INVALID_PARAMETER;
  }

  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Check if the FV is write enabled
  //
  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);

  if ((Attributes & EFI_FVB_WRITE_STATUS) == 0) {
    return EFI_ACCESS_DENIED;
  }
  //
  // Perform boundary checks and adjust NumBytes
  //
  if (BlockOffset > LbaLength) {
    return EFI_INVALID_PARAMETER;
  }

  if (LbaLength < (*NumBytes + BlockOffset)) {
    *NumBytes = (UINT32) (LbaLength - BlockOffset);
    Status    = EFI_BAD_BUFFER_SIZE;
  }

  ReturnStatus = FlashFdWrite (
                  LbaWriteAddress + BlockOffset,
                  LbaAddress,
                  NumBytes,
                  Buffer,
                  LbaLength
                  );
  if (EFI_ERROR (ReturnStatus)) {
    return ReturnStatus;
  }

  return Status;
}

EFI_STATUS
FvbEraseBlock (
  IN UINTN                                Instance,
  IN EFI_LBA                              Lba,
  IN ESAL_FWB_GLOBAL                      *Global,
  IN BOOLEAN                              Virtual
  )
/*++

Routine Description:
  Erases and initializes a firmware volume block

Arguments:
  Instance              - The FV instance to be erased
  Lba                   - The logical block index to be erased
  Global                - Pointer to ESAL_FWB_GLOBAL that contains all
                          instance data
  Virtual               - Whether CPU is in virtual or physical mode

Returns: 
  EFI_SUCCESS           - The erase request was successfully completed
  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state
  EFI_DEVICE_ERROR      - The block device is not functioning correctly and 
                          could not be written. Firmware device may have been
                          partially erased
  EFI_INVALID_PARAMETER - Instance not found

--*/
{

  EFI_FVB_ATTRIBUTES  Attributes;
  UINTN               LbaAddress;
  UINTN               LbaWriteAddress;
  EFI_FW_VOL_INSTANCE *FwhInstance;
  UINTN               LbaLength;
  EFI_STATUS          Status;

  //
  // Find the right instance of the FVB private data
  //
  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
  ASSERT_EFI_ERROR (Status);

  //
  // Writes are enabled in the init routine itself
  //
  if (!FwhInstance->WriteEnabled) {
    return EFI_ACCESS_DENIED;
  }
  //
  // Check if the FV is write enabled
  //
  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);

  if ((Attributes & EFI_FVB_WRITE_STATUS) == 0) {
    return EFI_ACCESS_DENIED;
  }
  //
  // Get the starting address of the block for erase. For debug reasons,
  // LbaWriteAddress may not be the same as LbaAddress.
  //
  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  return FlashFdErase (
          LbaWriteAddress,
          LbaAddress,
          LbaLength
          );
}

EFI_STATUS
FvbEraseCustomBlockRange (
  IN UINTN                                Instance,
  IN EFI_LBA                              StartLba,
  IN UINTN                                OffsetStartLba,
  IN EFI_LBA                              LastLba,
  IN UINTN                                OffsetLastLba,
  IN ESAL_FWB_GLOBAL                      *Global,
  IN BOOLEAN                              Virtual
  )
/*++

Routine Description:
  Erases and initializes a specified range of a firmware volume

Arguments:
  Instance              - The FV instance to be erased
  StartLba              - The starting logical block index to be erased
  OffsetStartLba        - Offset into the starting block at which to 
                          begin erasing
  LastLba               - The last logical block index to be erased
  OffsetStartLba        - Offset into the last block at which to end erasing
  Global                - Pointer to ESAL_FWB_GLOBAL that contains all
                          instance data
  Virtual               - Whether CPU is in virtual or physical mode

Returns: 
  EFI_SUCCESS           - The firmware volume was erased successfully
  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state
  EFI_DEVICE_ERROR      - The block device is not functioning correctly and 
                          could not be written. Firmware device may have been
                          partially erased
  EFI_INVALID_PARAMETER - Instance not found

--*/
{
  EFI_LBA Index;
  UINTN   LbaSize;
  UINTN   ScratchLbaSizeData;

  //
  // First LBA.
  //
  FvbGetLbaAddress (Instance, StartLba, NULL, NULL, &LbaSize, NULL, Global, Virtual);

  //
  // Use the scratch space as the intermediate buffer to transfer data
  // Back up the first LBA in scratch space.
  //
  FvbReadBlock (Instance, StartLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual);

  //
  // erase now
  //
  FvbEraseBlock (Instance, StartLba, Global, Virtual);
  ScratchLbaSizeData = OffsetStartLba;

  //
  // write the data back to the first block
  //
  if (ScratchLbaSizeData > 0) {
    FvbWriteBlock (Instance, StartLba, 0, &ScratchLbaSizeData, Global->FvbScratchSpace[Virtual], Global, Virtual);
  }
  //
  // Middle LBAs
  //
  if (LastLba > (StartLba + 1)) {
    for (Index = (StartLba + 1); Index <= (LastLba - 1); Index++) {
      FvbEraseBlock (Instance, Index, Global, Virtual);
    }
  }
  //
  // Last LBAs, the same as first LBAs
  //
  if (LastLba > StartLba) {
    FvbGetLbaAddress (Instance, LastLba, NULL, NULL, &LbaSize, NULL, Global, Virtual);
    FvbReadBlock (Instance, LastLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual);
    FvbEraseBlock (Instance, LastLba, Global, Virtual);
  }

  ScratchLbaSizeData = LbaSize - (OffsetStartLba + 1);

  return FvbWriteBlock (
          Instance,
          LastLba,
          (OffsetLastLba + 1),
          &ScratchLbaSizeData,
          Global->FvbScratchSpace[Virtual],
          Global,
          Virtual
          );
}

EFI_STATUS
FvbSetVolumeAttributes (
  IN UINTN                                Instance,
  IN OUT EFI_FVB_ATTRIBUTES               *Attributes,
  IN ESAL_FWB_GLOBAL                      *Global,
  IN BOOLEAN                              Virtual
  )
/*++

Routine Description:
  Modifies the current settings of the firmware volume according to the 
  input parameter, and returns the new setting of the volume

Arguments:
  Instance              - The FV instance whose attributes is going to be 
                          modified
  Attributes            - On input, it is a pointer to EFI_FVB_ATTRIBUTES 
                          containing the desired firmware volume settings.
                          On successful return, it contains the new settings
                          of the firmware volume
  Global                - Pointer to ESAL_FWB_GLOBAL that contains all
                          instance data
  Virtual               - Whether CPU is in virtual or physical mode

Returns: 
  EFI_SUCCESS           - Successfully returns
  EFI_ACCESS_DENIED     - The volume setting is locked and cannot be modified
  EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are
                          in conflict with the capabilities as declared in the
                          firmware volume header

--*/
{
  EFI_FW_VOL_INSTANCE *FwhInstance;
  EFI_FVB_ATTRIBUTES  OldAttributes;
  EFI_FVB_ATTRIBUTES  *AttribPtr;
  UINT32              Capabilities;
  UINT32              OldStatus;
  UINT32              NewStatus;
  EFI_STATUS          Status;

  //
  // Find the right instance of the FVB private data
  //
  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
  ASSERT_EFI_ERROR (Status);

  AttribPtr     = (EFI_FVB_ATTRIBUTES *) &(FwhInstance->VolumeHeader.Attributes);
  OldAttributes = *AttribPtr;
  Capabilities  = OldAttributes & EFI_FVB_CAPABILITIES;
  OldStatus     = OldAttributes & EFI_FVB_STATUS;
  NewStatus     = *Attributes & EFI_FVB_STATUS;

  //
  // If firmware volume is locked, no status bit can be updated
  //
  if (OldAttributes & EFI_FVB_LOCK_STATUS) {
    if (OldStatus ^ NewStatus) {
      return EFI_ACCESS_DENIED;
    }
  }
  //
  // Test read disable
  //
  if ((Capabilities & EFI_FVB_READ_DISABLED_CAP) == 0) {
    if ((NewStatus & EFI_FVB_READ_STATUS) == 0) {
      return EFI_INVALID_PARAMETER;
    }
  }
  //
  // Test read enable
  //

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?