ehcimem.c

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

C
775
字号
      // reset associated bits in bit arry
      //
      for (Index = StartBytePos, Index2 = StartBitPos, Count = 0; Count < (RealAllocSize / MEM_UNIT_SIZE); Count++) {
        ASSERT ((TempHeaderPtr->BitArrayPtr[Index] & bit (Index2) )== bit (Index2));

        TempHeaderPtr->BitArrayPtr[Index] ^= (UINT8) (bit (Index2));
        Index2++;
        if (Index2 == 8) {
          Index += 1;
          Index2 = 0;
        }
      }
      //
      // break the loop
      //
      break;
    }
  }

  //
  // Release emptied memory blocks (only if the memory block is not
  // the first one in the memory header list
  //
  for (TempHeaderPtr = MemoryHeader->Next; TempHeaderPtr != NULL;) {

    ASSERT (MemoryHeader->Next != NULL);

    if (IsMemoryBlockEmptied (TempHeaderPtr)) {

      DelinkMemoryBlock (MemoryHeader, TempHeaderPtr);
      //
      // when the TempHeaderPtr is freed in FreeMemoryHeader(),
      // the TempHeaderPtr is pointing to nonsense content.
      //
      gBS->RestoreTPL (OldTpl);
      FreeMemoryHeader (HcDev, TempHeaderPtr);
      OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY + 1);
      //
      // reset the TempHeaderPtr, continue search for
      // another empty memory block.
      //
      TempHeaderPtr = MemoryHeader->Next;
      continue;
    }

    TempHeaderPtr = TempHeaderPtr->Next;
  }

  gBS->RestoreTPL (OldTpl);
}

VOID
InsertMemoryHeaderToList (
  IN MEMORY_MANAGE_HEADER     *MemoryHeader,
  IN MEMORY_MANAGE_HEADER     *NewMemoryHeader
  )
/*++

Routine Description:

  Insert Memory Header To List

Arguments:

  MemoryHeader    - MEMORY_MANAGE_HEADER
  NewMemoryHeader - MEMORY_MANAGE_HEADER

Returns:

  VOID

--*/
{
  MEMORY_MANAGE_HEADER  *TempHeaderPtr;

  for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {
    if (TempHeaderPtr->Next == NULL) {
      TempHeaderPtr->Next = NewMemoryHeader;
      break;
    }
  }
}

EFI_STATUS
AllocMemInMemoryBlock (
  IN  MEMORY_MANAGE_HEADER     *MemoryHeader,
  OUT VOID                     **Pool,
  IN  UINTN                    NumberOfMemoryUnit
  )
/*++

Routine Description:

  Alloc Memory In MemoryBlock

Arguments:

  MemoryHeader        - MEMORY_MANAGE_HEADER
  Pool                - Place to store pointer to memory
  NumberOfMemoryUnit  - Number Of Memory Unit

Returns:

  EFI_SUCCESS    Success
  EFI_NOT_FOUND  Can't find the free memory

--*/
{
  UINTN TempBytePos;
  UINTN FoundBytePos;
  UINT8 Index;
  UINT8 FoundBitPos;
  UINT8 ByteValue;
  UINT8 BitValue;
  UINTN NumberOfZeros;
  UINTN Count;

  FoundBytePos  = 0;
  FoundBitPos   = 0;
  ByteValue     = MemoryHeader->BitArrayPtr[0];
  NumberOfZeros = 0;
  Index         = 0;

  for (TempBytePos = 0; TempBytePos < MemoryHeader->BitArraySizeInBytes;) {

    //
    // Pop out BitValue from a byte in TempBytePos.
    //
    BitValue = (UINT8) (ByteValue & 0x1);

    //
    // right shift the byte
    //
    ByteValue = ByteValue >> 1;

    if (BitValue == 0) {
      //
      // Found a free bit, the NumberOfZeros only record the number
      // of those consecutive zeros
      //
      NumberOfZeros++;
      //
      // Found enough consecutive free space, break the loop
      //
      if (NumberOfZeros >= NumberOfMemoryUnit) {
        break;
      }
    } else {
      //
      // Encountering a '1', meant the bit is ocupied.
      //
      if (NumberOfZeros >= NumberOfMemoryUnit) {
        //
        // Found enough consecutive free space,break the loop
        //
        break;
      } else {
        //
        // the NumberOfZeros only record the number of those consecutive zeros,
        // so reset the NumberOfZeros to 0 when encountering '1' before finding
        // enough consecutive '0's
        //
        NumberOfZeros = 0;
        //
        // reset the (FoundBytePos,FoundBitPos) to the position of '1'
        //
        FoundBytePos  = TempBytePos;
        FoundBitPos   = Index;
      }
    }

    //
    // step forward a bit
    //
    Index++;
    if (Index == 8) {
      //
      // step forward a byte, getting the byte value,
      // and reset the bit pos.
      //
      TempBytePos += 1;
      ByteValue = MemoryHeader->BitArrayPtr[TempBytePos];
      Index     = 0;
    }
  }

  if (NumberOfZeros < NumberOfMemoryUnit) {
    return EFI_NOT_FOUND;
  }

  //
  // Found enough free space.
  //

  //
  // The values recorded in (FoundBytePos,FoundBitPos) have two conditions:
  //  1)(FoundBytePos,FoundBitPos) record the position
  //    of the last '1' before the consecutive '0's, it must
  //    be adjusted to the start position of the consecutive '0's.
  //  2)the start address of the consecutive '0's is just the start of
  //    the bitarray. so no need to adjust the values of
  //    (FoundBytePos,FoundBitPos).
  //
  if ((MemoryHeader->BitArrayPtr[FoundBytePos] & bit (FoundBitPos)) != 0) {
    FoundBitPos += 1;
  }

  //
  // Have the (FoundBytePos,FoundBitPos) make sense.
  //
  if (FoundBitPos > 7) {
    FoundBytePos += 1;
    FoundBitPos -= 8;
  }

  //
  // Set the memory as allocated
  //
  for (TempBytePos = FoundBytePos, Index = FoundBitPos, Count = 0; Count < NumberOfMemoryUnit; Count++) {

    ASSERT ((MemoryHeader->BitArrayPtr[TempBytePos] & bit (Index) )== 0);
    MemoryHeader->BitArrayPtr[TempBytePos] |= bit (Index);
    Index++;
    if (Index == 8) {
      TempBytePos += 1;
      Index = 0;
    }
  }

  *Pool = MemoryHeader->MemoryBlockPtr + (FoundBytePos * 8 + FoundBitPos) * MEM_UNIT_SIZE;

  return EFI_SUCCESS;
}

BOOLEAN
IsMemoryBlockEmptied (
  IN MEMORY_MANAGE_HEADER     *MemoryHeaderPtr
  )
/*++

Routine Description:

  Is Memory Block Emptied

Arguments:

  MemoryHeaderPtr - MEMORY_MANAGE_HEADER

Returns:

  TRUE    Empty
  FALSE   Not Empty

--*/
{
  UINTN Index;

  for (Index = 0; Index < MemoryHeaderPtr->BitArraySizeInBytes; Index++) {
    if (MemoryHeaderPtr->BitArrayPtr[Index] != 0) {
      return FALSE;
    }
  }

  return TRUE;
}

VOID
DelinkMemoryBlock (
  IN MEMORY_MANAGE_HEADER     *FirstMemoryHeader,
  IN MEMORY_MANAGE_HEADER     *NeedFreeMemoryHeader
  )
/*++

Routine Description:

  Delink Memory Block

Arguments:

  FirstMemoryHeader     - MEMORY_MANAGE_HEADER
  NeedFreeMemoryHeader  - MEMORY_MANAGE_HEADER

Returns:

  VOID

--*/
{
  MEMORY_MANAGE_HEADER  *TempHeaderPtr;

  if ((FirstMemoryHeader == NULL) || (NeedFreeMemoryHeader == NULL)) {
    return ;
  }

  for (TempHeaderPtr = FirstMemoryHeader; TempHeaderPtr != NULL; TempHeaderPtr = TempHeaderPtr->Next) {

    if (TempHeaderPtr->Next == NeedFreeMemoryHeader) {
      //
      // Link the before and after
      //
      TempHeaderPtr->Next = NeedFreeMemoryHeader->Next;
      NeedFreeMemoryHeader->Next = NULL;
      break;
    }
  }
}

EFI_STATUS
InitialMemoryManagement (
  IN USB2_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Initialize Memory Management

Arguments:

  HcDev  - USB2_HC_DEV

Returns:

  EFI_SUCCESS        Success
  EFI_DEVICE_ERROR   Fail

--*/
{
  EFI_STATUS            Status;
  MEMORY_MANAGE_HEADER  *MemoryHeader;
  UINTN                 MemPages;

  MemPages  = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;
  Status    = CreateMemoryBlock (HcDev, &MemoryHeader, MemPages);
  if (EFI_ERROR (Status)) {
    Status = EFI_OUT_OF_RESOURCES;
    goto exit;
  }

  HcDev->MemoryHeader = MemoryHeader;

exit:
  return Status;
}

EFI_STATUS
DeinitialMemoryManagement (
  IN USB2_HC_DEV     *HcDev
  )
/*++

Routine Description:

  Deinitialize Memory Management

Arguments:

  HcDev   - USB2_HC_DEV

Returns:

  EFI_SUCCESS        Success
  EFI_DEVICE_ERROR   Fail

--*/
{
  MEMORY_MANAGE_HEADER  *TempHeaderPtr;

  for (TempHeaderPtr = HcDev->MemoryHeader->Next; TempHeaderPtr != NULL;) {

    DelinkMemoryBlock (HcDev->MemoryHeader, TempHeaderPtr);
    //
    // when the TempHeaderPtr is freed in FreeMemoryHeader(),
    // the TempHeaderPtr is pointing to nonsense content.
    //
    FreeMemoryHeader (HcDev, TempHeaderPtr);
    //
    // reset the TempHeaderPtr,continue free another memory block.
    //
    TempHeaderPtr = HcDev->MemoryHeader->Next;
  }

  FreeMemoryHeader (HcDev, HcDev->MemoryHeader);

  return EFI_SUCCESS;
}

⌨️ 快捷键说明

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