Example #1
0
/**
  Remove the block number from the block range list.

  @param[in]  Head                   The block range list to remove from.
  @param[in]  Num                    The block number to remove.
  @param[in]  Completed              Whether Num is the last block number
  @param[out] TotalBlock             The continuous block number in all

  @retval EFI_NOT_FOUND          The block number isn't in the block range list.
  @retval EFI_SUCCESS            The block number has been removed from the list.
  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.

**/
EFI_STATUS
Mtftp6RemoveBlockNum (
  IN LIST_ENTRY             *Head,
  IN UINT16                 Num,
  IN BOOLEAN                Completed,
  OUT UINT64                *TotalBlock
  )
{
  MTFTP6_BLOCK_RANGE        *Range;
  MTFTP6_BLOCK_RANGE        *NewRange;
  LIST_ENTRY                *Entry;

  NET_LIST_FOR_EACH (Entry, Head) {

    //
    // Each block represents a hole [Start, End] in the file,
    // skip to the first range with End >= Num
    //
    Range = NET_LIST_USER_STRUCT (Entry, MTFTP6_BLOCK_RANGE, Link);

    if (Range->End < Num) {
      continue;
    }

    //
    // There are three different cases for Start
    // 1. (Start > Num) && (End >= Num):
    //    because all the holes before this one has the condition of
    //    End < Num, so this block number has been removed.
    //
    // 2. (Start == Num) && (End >= Num):
    //    Need to increase the Start by one, and if End == Num, this
    //    hole has been removed completely, remove it.
    //
    // 3. (Start < Num) && (End >= Num):
    //    if End == Num, only need to decrease the End by one because
    //    we have (Start < Num) && (Num == End), so (Start <= End - 1).
    //    if (End > Num), the hold is splited into two holes, with
    //    [Start, Num - 1] and [Num + 1, End].
    //
    if (Range->Start > Num) {
      return EFI_NOT_FOUND;

    } else if (Range->Start == Num) {
      Range->Start++;

      //
      // Note that: RFC 1350 does not mention block counter roll-over,
      // but several TFTP hosts implement the roll-over be able to accept
      // transfers of unlimited size. There is no consensus, however, whether
      // the counter should wrap around to zero or to one. Many implementations
      // wrap to zero, because this is the simplest to implement. Here we choose
      // this solution.
      //
      *TotalBlock  = Num;

      if (Range->Round > 0) {
        *TotalBlock += Range->Bound +  MultU64x32 (Range->Round - 1, (UINT32)(Range->Bound + 1)) + 1;
      }

      if (Range->Start > Range->Bound) {
        Range->Start = 0;
        Range->Round ++;
      }

      if ((Range->Start > Range->End) || Completed) {
        RemoveEntryList (&Range->Link);
        FreePool (Range);
      }

      return EFI_SUCCESS;

    } else {
      if (Range->End == Num) {
        Range->End--;
      } else {
        NewRange = Mtftp6AllocateRange ((UINT16) (Num + 1), (UINT16) Range->End);

        if (NewRange == NULL) {
          return EFI_OUT_OF_RESOURCES;
        }

        Range->End = Num - 1;
        NetListInsertAfter (&Range->Link, &NewRange->Link);
      }

      return EFI_SUCCESS;
    }
  }
Example #2
0
EFI_STATUS
Mtftp4RemoveBlockNum (
  IN NET_LIST_ENTRY         *Head,
  IN UINT16                 Num
  )
/*++

Routine Description:

  Remove the block number from the block range list.

Arguments:

  Head  - The block range list to remove from
  Num   - The block number to remove

Returns:

  EFI_NOT_FOUND        - The block number isn't in the block range list
  EFI_SUCCESS          - The block number has been removed from the list
  EFI_OUT_OF_RESOURCES - Failed to allocate resource

--*/
{
  MTFTP4_BLOCK_RANGE        *Range;
  MTFTP4_BLOCK_RANGE        *NewRange;
  NET_LIST_ENTRY            *Entry;

  NET_LIST_FOR_EACH (Entry, Head) {
    
    //
    // Each block represents a hole [Start, End] in the file,
    // skip to the first range with End >= Num
    //
    Range = NET_LIST_USER_STRUCT (Entry, MTFTP4_BLOCK_RANGE, Link);
    
    if (Range->End < Num) {
      continue;
    }
    
    //
    // There are three different cases for Start
    // 1. (Start > Num) && (End >= Num):
    //    because all the holes before this one has the condition of
    //    End < Num, so this block number has been removed.
    //
    // 2. (Start == Num) && (End >= Num):
    //    Need to increase the Start by one, and if End == Num, this
    //    hole has been removed completely, remove it.
    //
    // 3. (Start < Num) && (End >= Num):
    //    if End == Num, only need to decrease the End by one because
    //    we have (Start < Num) && (Num == End), so (Start <= End - 1).
    //    if (End > Num), the hold is splited into two holes, with
    //    [Start, Num - 1] and [Num + 1, End].
    //
    if (Range->Start > Num) {
      return EFI_NOT_FOUND;

    } else if (Range->Start == Num) {
      Range->Start++;

      if (Range->Start > Range->End) {
        NetListRemoveEntry (&Range->Link);
        NetFreePool (Range);
      }

      return EFI_SUCCESS;

    } else {
      if (Range->End == Num) {
        Range->End--;
      } else {
        NewRange = Mtftp4AllocateRange (Num + 1, (UINT16) Range->End);

        if (NewRange == NULL) {
          return EFI_OUT_OF_RESOURCES;
        }

        Range->End = Num - 1;
        NetListInsertAfter (&Range->Link, &NewRange->Link);
      }

      return EFI_SUCCESS;
    }
  }