示例#1
0
文件: Page.c 项目: etiago/vbox
/**
  Frees previous allocated pages.

  @param  Memory                 Base address of memory being freed.
  @param  NumberOfPages          The number of pages to free.

  @retval EFI_NOT_FOUND          Could not find the entry that covers the range.
  @retval EFI_INVALID_PARAMETER  Address not aligned.
  @return EFI_SUCCESS            Pages successfully freed.

**/
EFI_STATUS
EFIAPI
SmmFreePages (
  IN EFI_PHYSICAL_ADDRESS  Memory,
  IN UINTN                 NumberOfPages
  )
{
  LIST_ENTRY      *Node;
  FREE_PAGE_LIST  *Pages;

  if ((Memory & EFI_PAGE_MASK) != 0) {
    return EFI_INVALID_PARAMETER;
  }

  Pages = NULL;
  Node = mSmmMemoryMap.ForwardLink;
  while (Node != &mSmmMemoryMap) {
    Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
    if (Memory < (UINTN)Pages) {
      break;
    }
    Node = Node->ForwardLink;
  }

  if (Node != &mSmmMemoryMap &&
      Memory + EFI_PAGES_TO_SIZE (NumberOfPages) > (UINTN)Pages) {
    return EFI_INVALID_PARAMETER;
  }

  if (Node->BackLink != &mSmmMemoryMap) {
    Pages = BASE_CR (Node->BackLink, FREE_PAGE_LIST, Link);
    if ((UINTN)Pages + EFI_PAGES_TO_SIZE (Pages->NumberOfPages) > Memory) {
      return EFI_INVALID_PARAMETER;
    }
  }

  Pages = (FREE_PAGE_LIST*)(UINTN)Memory;
  Pages->NumberOfPages = NumberOfPages;
  InsertTailList (Node, &Pages->Link);

  if (Pages->Link.BackLink != &mSmmMemoryMap) {
    Pages = InternalMergeNodes (
              BASE_CR (Pages->Link.BackLink, FREE_PAGE_LIST, Link)
              );
  }

  if (Node != &mSmmMemoryMap) {
    InternalMergeNodes (Pages);
  }

  return EFI_SUCCESS;
}
VOID
RemovePagesFromList (
  IN VOID   *Buffer,
  OUT VOID  **Allocation,
  OUT UINTN *Pages
  )
{
  LIST_ENTRY      *Link;
  FREE_PAGE_NODE  *OldNode;

  *Allocation = NULL;
  *Pages = 0;

  for (Link = mPageList.ForwardLink; Link != &mPageList; Link = Link->ForwardLink) {
    OldNode = BASE_CR (Link, FREE_PAGE_NODE, Link);
    if (OldNode->Buffer == Buffer) {
      *Allocation = OldNode->Allocation;
      *Pages = OldNode->Pages;

      RemoveEntryList (&OldNode->Link);
      FreePool (OldNode);
      return;
    }
  }

  return;
}
示例#3
0
/**
  This function find LockBox by GUID.

  @param Guid The guid to indentify the LockBox

  @return LockBoxData
**/
SMM_LOCK_BOX_DATA *
InternalFindLockBoxByGuid (
    IN EFI_GUID   *Guid
)
{
    LIST_ENTRY                    *Link;
    SMM_LOCK_BOX_DATA             *LockBox;
    LIST_ENTRY                    *LockBoxQueue;

    LockBoxQueue = InternalGetLockBoxQueue ();
    ASSERT (LockBoxQueue != NULL);

    for (Link = LockBoxQueue->ForwardLink;
            Link != LockBoxQueue;
            Link = Link->ForwardLink) {
        LockBox = BASE_CR (
                      Link,
                      SMM_LOCK_BOX_DATA,
                      Link
                  );
        if (CompareGuid (&LockBox->Guid, Guid)) {
            return LockBox;
        }
    }
    return NULL;
}
示例#4
0
文件: Pool.c 项目: FishYu1222/edk2
/**
  Internal Function. Allocate a pool by specified PoolIndex.

  @param  PoolIndex             Index which indicate the Pool size.
  @param  FreePoolHdr           The returned Free pool.

  @retval EFI_OUT_OF_RESOURCES   Allocation failed.
  @retval EFI_SUCCESS            Pool successfully allocated.

**/
EFI_STATUS
InternalAllocPoolByIndex (
  IN  UINTN             PoolIndex,
  OUT FREE_POOL_HEADER  **FreePoolHdr
  )
{
  EFI_STATUS            Status;
  FREE_POOL_HEADER      *Hdr;
  EFI_PHYSICAL_ADDRESS  Address;

  ASSERT (PoolIndex <= MAX_POOL_INDEX);
  Status = EFI_SUCCESS;
  if (PoolIndex == MAX_POOL_INDEX) {
    Status = SmmInternalAllocatePages (AllocateAnyPages, EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1), &Address);
    if (EFI_ERROR (Status)) {
      return EFI_OUT_OF_RESOURCES;
    }
    Hdr = (FREE_POOL_HEADER *) (UINTN) Address;
  } else if (!IsListEmpty (&mSmmPoolLists[PoolIndex])) {
    Hdr = BASE_CR (GetFirstNode (&mSmmPoolLists[PoolIndex]), FREE_POOL_HEADER, Link);
    RemoveEntryList (&Hdr->Link);
  } else {
    Status = InternalAllocPoolByIndex (PoolIndex + 1, &Hdr);
    if (!EFI_ERROR (Status)) {
      Hdr->Header.Size >>= 1;
      Hdr->Header.Available = TRUE;
      InsertHeadList (&mSmmPoolLists[PoolIndex], &Hdr->Link);
      Hdr = (FREE_POOL_HEADER*)((UINT8*)Hdr + Hdr->Header.Size);
    }
  }
示例#5
0
文件: Page.c 项目: etiago/vbox
/**
  Internal Function. Allocate n pages from free page list at given address.

  @param  FreePageList           The free page node.
  @param  NumberOfPages          Number of pages to be allocated.
  @param  MaxAddress             Request to allocate memory below this address.

  @return Memory address of allocated pages.

**/
UINTN
InternalAllocAddress (
  IN OUT LIST_ENTRY  *FreePageList,
  IN     UINTN       NumberOfPages,
  IN     UINTN       Address
  )
{
  UINTN           EndAddress;
  LIST_ENTRY      *Node;
  FREE_PAGE_LIST  *Pages;

  if ((Address & EFI_PAGE_MASK) != 0) {
    return ~Address;
  }

  EndAddress = Address + EFI_PAGES_TO_SIZE (NumberOfPages);
  for (Node = FreePageList->BackLink; Node!= FreePageList; Node = Node->BackLink) {
    Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
    if ((UINTN)Pages <= Address) {
      if ((UINTN)Pages + EFI_PAGES_TO_SIZE (Pages->NumberOfPages) < EndAddress) {
        break;
      }
      return InternalAllocPagesOnOneNode (Pages, NumberOfPages, EndAddress);
    }
  }
  return ~Address;
}
示例#6
0
文件: QNCSmmCore.c 项目: b-man/edk2
EFI_STATUS
QNCSmmCoreUnRegister (
  IN QNC_SMM_GENERIC_PROTOCOL                         *This,
  IN EFI_HANDLE                                        DispatchHandle
  )
/*++

Routine Description:

Arguments:

Returns:

--*/
// GC_TODO:    This - add argument and description to function comment
// GC_TODO:    DispatchHandle - add argument and description to function comment
// GC_TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// GC_TODO:    EFI_INVALID_PARAMETER - add return value to function comment
// GC_TODO:    EFI_SUCCESS - add return value to function comment
{
  BOOLEAN         SafeToDisable;
  DATABASE_RECORD *RecordToDelete;
  DATABASE_RECORD *RecordInDb;
  LIST_ENTRY      *LinkInDb;

  if (DispatchHandle == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (BASE_CR (DispatchHandle, DATABASE_RECORD, Link)->Signature != DATABASE_RECORD_SIGNATURE) {
    return EFI_INVALID_PARAMETER;
  }

  RecordToDelete = DATABASE_RECORD_FROM_LINK (DispatchHandle);

  RemoveEntryList (&RecordToDelete->Link);
  RecordToDelete->Signature = 0;

  //
  // See if we can disable the source, reserved for future use since this might
  //  not be the only criteria to disable
  //
  SafeToDisable = TRUE;
  LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
  while(!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
    RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
    if (CompareEnables (&RecordToDelete->SrcDesc, &RecordInDb->SrcDesc)) {
      SafeToDisable = FALSE;
      break;
    }
    LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
  }
  if (SafeToDisable) {
    QNCSmmDisableSource( &RecordToDelete->SrcDesc );
}

  FreePool (RecordToDelete);

  return EFI_SUCCESS;
}
示例#7
0
/**
  Retrieve one record of from free record buffer. This record is removed from
  free record buffer.

  This function retrieves one record from free record buffer.
  If the pool has been exhausted, then new memory would be allocated for it.

  @return  Pointer to the free record.
           NULL means failure to allocate new memeory for free record buffer.

**/
DATA_HUB_STATUS_CODE_DATA_RECORD *
AcquireRecordBuffer (
  VOID
  )
{
  DATAHUB_STATUSCODE_RECORD *Record;
  EFI_TPL                   CurrentTpl;
  LIST_ENTRY                *Node;
  UINT32                    Index;

  CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);

  if (!IsListEmpty (&mRecordsBuffer)) {
    //
    // Strip one entry from free record buffer.
    //
    Node = GetFirstNode (&mRecordsBuffer);
    RemoveEntryList (Node);

    Record = BASE_CR (Node, DATAHUB_STATUSCODE_RECORD, Node);
  } else {
    if (CurrentTpl > TPL_NOTIFY) {
      //
      // Memory management should work at <=TPL_NOTIFY
      // 
      gBS->RestoreTPL (CurrentTpl);
      return NULL;
    }

    //
    // If free record buffer is exhausted, then allocate 16 new records for it.
    //
    gBS->RestoreTPL (CurrentTpl);
    Record   = (DATAHUB_STATUSCODE_RECORD *) AllocateZeroPool (sizeof (DATAHUB_STATUSCODE_RECORD) * 16);
    if (Record == NULL) {
      return NULL;
    }

    CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
    //
    // Here we only insert 15 new records to the free record buffer, for the first record
    // will be returned immediately.
    //
    for (Index = 1; Index < 16; Index++) {
      InsertTailList (&mRecordsBuffer, &Record[Index].Node);
    }
  }

  Record->Signature = DATAHUB_STATUS_CODE_SIGNATURE;
  InsertTailList (&mRecordsFifo, &Record->Node);

  gBS->RestoreTPL (CurrentTpl);

  return (DATA_HUB_STATUS_CODE_DATA_RECORD *) (Record->Data);
}
示例#8
0
/** Console-specific helper function for the fstat() function.

    st_size       Set to number of characters read for stdin and number written for stdout and stderr.
    st_physsize   1 for stdin, 0 if QueryMode error, else max X and Y coordinates for the current mode.
    st_curpos     0 for stdin, current X & Y coordinates for stdout and stderr
    st_blksize    Set to 1 since this is a character device

    All other members of the stat structure are left unchanged.
**/
static
int
EFIAPI
da_ConStat(
  struct __filedes   *filp,
  struct stat        *Buffer,
  void               *Something
  )
{
  ConInstance                        *Stream;
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *Proto;
  XYoffset                            CursorPos;
  INT32                               OutMode;
  UINTN                               ModeCol;
  UINTN                               ModeRow;

// ConGetInfo
  Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
  // Quick check to see if Stream looks reasonable
  if ((Stream->Cookie != CON_COOKIE) ||    // Cookie == 'IoAb'
      (Buffer == NULL))
  {
    EFIerrno = RETURN_INVALID_PARAMETER;
    return -1;
  }
  // All of our parameters are correct, so fill in the information.
  Buffer->st_blksize = 1;

// ConGetPosition
  if(Stream->InstanceNum == STDIN_FILENO) {
    // This is stdin
    Buffer->st_curpos    = 0;
    Buffer->st_size      = (off_t)Stream->NumRead;
    Buffer->st_physsize  = 1;
  }
  else {
    Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)Stream->Dev;
    CursorPos.XYpos.Column  = (UINT32)Proto->Mode->CursorColumn;
    CursorPos.XYpos.Row     = (UINT32)Proto->Mode->CursorRow;
    Buffer->st_curpos       = (off_t)CursorPos.Offset;
    Buffer->st_size         = (off_t)Stream->NumWritten;

    OutMode  = Proto->Mode->Mode;
    EFIerrno = Proto->QueryMode(Proto, (UINTN)OutMode, &ModeCol, &ModeRow);
    if(RETURN_ERROR(EFIerrno)) {
      Buffer->st_physsize = 0;
    }
    else {
      CursorPos.XYpos.Column  = (UINT32)ModeCol;
      CursorPos.XYpos.Row     = (UINT32)ModeRow;
      Buffer->st_physsize     = (off_t)CursorPos.Offset;
    }
  }
  return 0;
}
示例#9
0
文件: EfiFileLib.c 项目: M1cha/edk2
/**
Close a file handle opened by EfiOpen() and free all resources allocated by
EfiOpen().

@param  Stream    Open File Handle

@return EFI_INVALID_PARAMETER  Stream is not an Open File
@return EFI_SUCCESS            Steam closed

**/
EFI_STATUS
EfiClose (
  IN  EFI_OPEN_FILE     *File
  )
{
  EFI_STATUS          Status;
  UINT64              TftpBufferSize;

  if (!FileHandleValid (File)) {
    return EFI_INVALID_PARAMETER;
  }

  //Write the buffer contents to TFTP file.
  if ((File->Type == EfiOpenTftp) && (File->IsDirty)) {

    TftpBufferSize = File->Size;
    Status = EblMtftp (
      EFI_PXE_BASE_CODE_TFTP_WRITE_FILE,
      File->Buffer,
      TRUE,
      &TftpBufferSize,
      NULL,
      &File->ServerIp,
      (UINT8 *)File->FileName,
      NULL,
      FALSE
      );
    if (EFI_ERROR(Status)) {
      AsciiPrint("TFTP error during APPLE_NSP_TFTP_WRITE_FILE: %r\n", Status);
      return Status;
    }
  }

  if ((File->Type == EfiOpenLoadFile) ||
    ((File->Type == EfiOpenTftp) && (File->IsBufferValid == TRUE)) ||
    ((File->Type == EfiOpenFirmwareVolume) && (File->IsBufferValid == TRUE))) {
    EblFreePool(File->Buffer);
  }

  EblFreePool (File->DevicePath);
  EblFreePool (File->DeviceName);
  EblFreePool (File->FsFileInfo);
  EblFreePool (File->FsInfo);

  if (File->FsFileHandle != NULL) {
    File->FsFileHandle->Close (File->FsFileHandle);
  }

  // Need to free File and it's Guard structures
  EblFreePool (BASE_CR (File, EFI_OPEN_FILE_GUARD, File));
  return EFI_SUCCESS;
}
示例#10
0
/** The realloc function changes the size of the object pointed to by Ptr to
    the size specified by NewSize.

    The contents of the object are unchanged up to the lesser of the new and
    old sizes.  If the new size is larger, the value of the newly allocated
    portion of the object is indeterminate.

    If Ptr is a null pointer, the realloc function behaves like the malloc
    function for the specified size.

    If Ptr does not match a pointer earlier returned by the calloc, malloc, or
    realloc function, or if the space has been deallocated by a call to the free
    or realloc function, the behavior is undefined.

    If the space cannot be allocated, the object pointed to by Ptr is unchanged.

    If NewSize is zero and Ptr is not a null pointer, the object it points to
    is freed.

    This implementation uses the UEFI memory allocation boot services to get a
    region of memory that is 8-byte aligned and of the specified size.  The
    region is allocated with type EfiLoaderData.

    The following combinations of Ptr and NewSize can occur:<BR>
      Ptr     NewSize<BR>
    --------  -------------------<BR>
    - NULL        0                 Returns NULL;
    - NULL      > 0                 Same as malloc(NewSize)
    - invalid     X                 Returns NULL;
    - valid   NewSize >= OldSize    Returns malloc(NewSize) with Oldsize bytes copied from Ptr
    - valid   NewSize <  OldSize    Returns new buffer with Oldsize bytes copied from Ptr
    - valid       0                 Return NULL.  Frees Ptr.


    @param  Ptr     Pointer to a previously allocated region of memory to be resized.
    @param  NewSize Size, in bytes, of the new object to allocate space for.

    @return   NULL is returned if the space could not be allocated and errno
              contains the cause.  Otherwise, a pointer to an 8-byte aligned
              region of the requested size is returned.  If NewSize is zero,
              NULL is returned and errno will be unchanged.
**/
void *
realloc(void *Ptr, size_t ReqSize)
{
  void       *RetVal = NULL;
  CPOOL_HEAD *Head    = NULL;
  size_t      OldSize = 0;
  size_t      NewSize;
  size_t      NumCpy;

  // Find out the size of the OLD memory region
  if( Ptr != NULL) {
    Head = BASE_CR (Ptr, CPOOL_HEAD, Data);
    assert(Head != NULL);
    if (Head->Signature != CPOOL_HEAD_SIGNATURE) {
      errno = EFAULT;
      DEBUG((DEBUG_ERROR, "ERROR realloc(0x%p): Signature is 0x%8X, expected 0x%8X\n",
             Ptr, Head->Signature, CPOOL_HEAD_SIGNATURE));
      return NULL;
    }
    OldSize = (size_t)Head->Size;
  }

  // At this point, Ptr is either NULL or a valid pointer to an allocated space
  NewSize = (size_t)(ReqSize + (sizeof(CPOOL_HEAD)));

  if( ReqSize > 0) {
    RetVal = malloc(NewSize); // Get the NEW memory region
    if( Ptr != NULL) {          // If there is an OLD region...
      if( RetVal != NULL) {     // and the NEW region was successfully allocated
        NumCpy = OldSize;
        if( OldSize > NewSize) {
          NumCpy = NewSize;
        }
        (VOID)CopyMem( RetVal, Ptr, NumCpy);  // Copy old data to the new region.
        free( Ptr);                           // and reclaim the old region.
      }
      else {
        errno = ENOMEM;
      }
    }
  }
  else {
      free( Ptr);                           // Reclaim the old region.
    }
  DEBUG((DEBUG_POOL, "0x%p = realloc(%p, %d): Head: %p NewSz: %d\n",
         RetVal, Ptr, ReqSize, Head, NewSize));

  return RetVal;
}
示例#11
0
/**
  Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.

  This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
  It convers pointer to new virtual address.

  @param  Event        Event whose notification function is being invoked.
  @param  Context      Pointer to the notification function's context.

**/
VOID
EFIAPI
VariableClassAddressChangeEvent (
  IN EFI_EVENT                            Event,
  IN VOID                                 *Context
  )
{
  LIST_ENTRY     *Link;
  VARIABLE_ENTRY *Entry;
  EFI_STATUS     Status;

  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetBlockSize);
  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetPhysicalAddress);
  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetAttributes);
  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->SetAttributes);
  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Read);
  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Write);
  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->EraseBlocks);
  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance);
  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);
  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);
  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);
  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
  EfiConvertPointer (0x0, (VOID **) &mHashCtx);
  EfiConvertPointer (0x0, (VOID **) &mSerializationRuntimeBuffer);
  EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);
  EfiConvertPointer (0x0, (VOID **) &mPubKeyStore);
  EfiConvertPointer (0x0, (VOID **) &mCertDbStore);

  //
  // in the list of locked variables, convert the name pointers first
  //
  for ( Link = GetFirstNode (&mLockedVariableList)
      ; !IsNull (&mLockedVariableList, Link)
      ; Link = GetNextNode (&mLockedVariableList, Link)
      ) {
    Entry = BASE_CR (Link, VARIABLE_ENTRY, Link);
    Status = EfiConvertPointer (0x0, (VOID **) &Entry->Name);
    ASSERT_EFI_ERROR (Status);
  }
  //
  // second, convert the list itself using UefiRuntimeLib
  //
  Status = EfiConvertList (0x0, &mLockedVariableList);
  ASSERT_EFI_ERROR (Status);
}
示例#12
0
文件: EfiFileLib.c 项目: M1cha/edk2
/**
Internal worker function to validate a File handle.

@param  File    Open File Handle

@return TRUE    File is valid
@return FALSE   File is not valid


**/
BOOLEAN
FileHandleValid (
  IN EFI_OPEN_FILE  *File
  )
{
  EFI_OPEN_FILE_GUARD  *GuardFile;

  // Look right before and after file structure for the correct signatures
  GuardFile = BASE_CR (File, EFI_OPEN_FILE_GUARD, File);
  if ((GuardFile->Header != EFI_OPEN_FILE_GUARD_HEADER) ||
    (GuardFile->Footer != EFI_OPEN_FILE_GUARD_FOOTER) ) {
      return FALSE;
    }

    return TRUE;
}
示例#13
0
文件: FwVolBlock.c 项目: Cutty/edk2
/**

  Get FVB authentication status

  @param FvbProtocol    FVB protocol.

  @return Authentication status.

**/
UINT32
GetFvbAuthenticationStatus (
  IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *FvbProtocol
  )
{
  EFI_FW_VOL_BLOCK_DEVICE   *FvbDevice;
  UINT32                    AuthenticationStatus;

  AuthenticationStatus = 0;
  FvbDevice = BASE_CR (FvbProtocol, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance);
  if (FvbDevice->Signature == FVB_DEVICE_SIGNATURE) {
    AuthenticationStatus = FvbDevice->AuthenticationStatus;
  }

  return AuthenticationStatus;
}
示例#14
0
/*  Returns a bit mask describing which operations could be completed immediately.

    (POLLIN | POLLRDNORM)   A Unicode character is available to read
    (POLLIN)                A ScanCode is ready.
    (POLLOUT)               The device is ready for output - always set on stdout and stderr.

*/
static
short
EFIAPI
da_ConPoll(
  struct __filedes   *filp,
  short              events
  )
{
  EFI_SIMPLE_TEXT_INPUT_PROTOCOL   *Proto;
  ConInstance                      *Stream;
  EFI_STATUS                        Status = RETURN_SUCCESS;
  short                             RdyMask = 0;

  Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
  // Quick check to see if Stream looks reasonable
  if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'
    EFIerrno = RETURN_INVALID_PARAMETER;
    return POLLNVAL;    // Looks like a bad filp pointer
  }
  if(Stream->InstanceNum == 0) {
    // Only input is supported for this device
    Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;
    if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {
      Status = Proto->ReadKeyStroke(Proto, &Stream->UnGetKey);
      if(Status == RETURN_SUCCESS) {
        RdyMask = POLLIN;
        if(Stream->UnGetKey.UnicodeChar != CHAR_NULL) {
          RdyMask |= POLLRDNORM;
        }
      }
      else {
        Stream->UnGetKey.ScanCode     = SCAN_NULL;
        Stream->UnGetKey.UnicodeChar  = CHAR_NULL;
      }
    }
  }
  else if(Stream->InstanceNum < NUM_SPECIAL) {  // Not 0, is it 1 or 2?
    // Only output is supported for this device
    RdyMask = POLLOUT;
  }
  else {
    RdyMask = POLLERR;    // Not one of the standard streams
  }
  EFIerrno = Status;

  return (RdyMask & (events | POLL_RETONLY));
}
示例#15
0
static
int
EFIAPI
da_ConClose(
  IN      struct __filedes   *filp
)
{
  ConInstance    *Stream;

  Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
  // Quick check to see if Stream looks reasonable
  if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'
    EFIerrno = RETURN_INVALID_PARAMETER;
    return -1;    // Looks like a bad File Descriptor pointer
  }
  gMD->StdIo[Stream->InstanceNum] = NULL;   // Mark the stream as closed
  return RETURN_SUCCESS;
}
示例#16
0
文件: Page.c 项目: etiago/vbox
/**
  Internal Function. Merge two adjacent nodes.

  @param  First             The first of two nodes to merge.

  @return Pointer to node after merge (if success) or pointer to next node (if fail).

**/
FREE_PAGE_LIST *
InternalMergeNodes (
  IN FREE_PAGE_LIST  *First
  )
{
  FREE_PAGE_LIST  *Next;

  Next = BASE_CR (First->Link.ForwardLink, FREE_PAGE_LIST, Link);
  ASSERT (
    TRUNCATE_TO_PAGES ((UINTN)Next - (UINTN)First) >= First->NumberOfPages);

  if (TRUNCATE_TO_PAGES ((UINTN)Next - (UINTN)First) == First->NumberOfPages) {
    First->NumberOfPages += Next->NumberOfPages;
    RemoveEntryList (&Next->Link);
    Next = First;
  }
  return Next;
}
/**
  Internal Function. Allocate a pool by specified PoolIndex.

  @param  PoolType              Type of pool to allocate.
  @param  PoolIndex             Index which indicate the Pool size.
  @param  FreePoolHdr           The returned Free pool.

  @retval EFI_OUT_OF_RESOURCES   Allocation failed.
  @retval EFI_SUCCESS            Pool successfully allocated.

**/
EFI_STATUS
InternalAllocPoolByIndex (
  IN  EFI_MEMORY_TYPE   PoolType,
  IN  UINTN             PoolIndex,
  OUT FREE_POOL_HEADER  **FreePoolHdr
  )
{
  EFI_STATUS            Status;
  FREE_POOL_HEADER      *Hdr;
  POOL_TAIL             *Tail;
  EFI_PHYSICAL_ADDRESS  Address;
  SMM_POOL_TYPE         SmmPoolType;

  Address     = 0;
  SmmPoolType = UefiMemoryTypeToSmmPoolType(PoolType);

  ASSERT (PoolIndex <= MAX_POOL_INDEX);
  Status = EFI_SUCCESS;
  Hdr = NULL;
  if (PoolIndex == MAX_POOL_INDEX) {
    Status = SmmInternalAllocatePages (AllocateAnyPages, PoolType,
                                       EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1),
                                       &Address, FALSE);
    if (EFI_ERROR (Status)) {
      return EFI_OUT_OF_RESOURCES;
    }
    Hdr = (FREE_POOL_HEADER *) (UINTN) Address;
  } else if (!IsListEmpty (&mSmmPoolLists[SmmPoolType][PoolIndex])) {
    Hdr = BASE_CR (GetFirstNode (&mSmmPoolLists[SmmPoolType][PoolIndex]), FREE_POOL_HEADER, Link);
    RemoveEntryList (&Hdr->Link);
  } else {
    Status = InternalAllocPoolByIndex (PoolType, PoolIndex + 1, &Hdr);
    if (!EFI_ERROR (Status)) {
      Hdr->Header.Signature = 0;
      Hdr->Header.Size >>= 1;
      Hdr->Header.Available = TRUE;
      Hdr->Header.Type = 0;
      Tail = HEAD_TO_TAIL(&Hdr->Header);
      Tail->Signature = 0;
      Tail->Size = 0;
      InsertHeadList (&mSmmPoolLists[SmmPoolType][PoolIndex], &Hdr->Link);
      Hdr = (FREE_POOL_HEADER*)((UINT8*)Hdr + Hdr->Header.Size);
    }
  }
示例#18
0
文件: Page.c 项目: etiago/vbox
/**
  Internal Function. Allocate n pages from free page list below MaxAddress.

  @param  FreePageList           The free page node.
  @param  NumberOfPages          Number of pages to be allocated.
  @param  MaxAddress             Request to allocate memory below this address.

  @return Memory address of allocated pages.

**/
UINTN
InternalAllocMaxAddress (
  IN OUT LIST_ENTRY  *FreePageList,
  IN     UINTN       NumberOfPages,
  IN     UINTN       MaxAddress
  )
{
  LIST_ENTRY      *Node;
  FREE_PAGE_LIST  *Pages;

  for (Node = FreePageList->BackLink; Node != FreePageList; Node = Node->BackLink) {
    Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
    if (Pages->NumberOfPages >= NumberOfPages &&
        (UINTN)Pages + EFI_PAGES_TO_SIZE (NumberOfPages) - 1 <= MaxAddress) {
      return InternalAllocPagesOnOneNode (Pages, NumberOfPages, MaxAddress);
    }
  }
  return (UINTN)(-1);
}
示例#19
0
/** The realloc function changes the size of the object pointed to by Ptr to
    the size specified by NewSize.

    The contents of the object are unchanged up to the lesser of the new and
    old sizes.  If the new size is larger, the value of the newly allocated
    portion of the object is indeterminate.

    If Ptr is a null pointer, the realloc function behaves like the malloc
    function for the specified size.

    If Ptr does not match a pointer earlier returned by the calloc, malloc, or
    realloc function, or if the space has been deallocated by a call to the free
    or realloc function, the behavior is undefined.

    If the space cannot be allocated, the object pointed to by Ptr is unchanged.

    If NewSize is zero and Ptr is not a null pointer, the object it points to
    is freed.

    This implementation uses the UEFI memory allocation boot services to get a
    region of memory that is 8-byte aligned and of the specified size.  The
    region is allocated with type EfiLoaderData.

    The following combinations of Ptr and NewSize can occur:<BR>
      Ptr     NewSize<BR>
    --------  -------------------<BR>
    - NULL        0                 Returns NULL;
    - NULL      > 0                 Same as malloc(NewSize)
    - invalid     X                 Returns NULL;
    - valid   NewSize >= OldSize    Returns malloc(NewSize) with Oldsize bytes copied from Ptr
    - valid   NewSize <  OldSize    Returns new buffer with Oldsize bytes copied from Ptr
    - valid       0                 Return NULL.  Frees Ptr.


    @param  Ptr     Pointer to a previously allocated region of memory to be resized.
    @param  NewSize Size, in bytes, of the new object to allocate space for.

    @return   NULL is returned if the space could not be allocated and errno
              contains the cause.  Otherwise, a pointer to an 8-byte aligned
              region of the requested size is returned.  If NewSize is zero,
              NULL is returned and errno will be unchanged.
**/
void *
realloc(void *Ptr, size_t NewSize)
{
  void       *RetVal = NULL;
  POOL_HEAD  *Head;
  UINTN       OldSize = 0;
  UINTN       NumCpy;

  // Find out the size of the OLD memory region
  if( Ptr != NULL) {
    Head = BASE_CR (Ptr, POOL_HEAD, Data);
    assert(Head != NULL);
    if (Head->Signature != POOL_HEAD_SIGNATURE) {
      errno = EFAULT;
      return NULL;
    }
    OldSize = Head->Size;
  }

  // At this point, Ptr is either NULL or a valid pointer to an allocated space

  if( NewSize > 0) {
    RetVal = malloc(NewSize); // Get the NEW memory region
    if( Ptr != NULL) {          // If there is an OLD region...
      if( RetVal != NULL) {     // and the NEW region was successfully allocated
        NumCpy = OldSize;
        if( OldSize > NewSize) {
          NumCpy = NewSize;
        }
        (VOID)CopyMem( RetVal, Ptr, NumCpy);  // Copy old data to the new region.
        free( Ptr);                           // and reclaim the old region.
      }
    }
  }
  else {
    if( Ptr != NULL) {
      free( Ptr);                           // Reclaim the old region.
    }
  }

  return RetVal;
}
示例#20
0
/**
  The clean process of the IfConfig6 application.

  @param[in]   IfList    The pointer of IfList(interface list).

  @retval EFI_SUCCESS    The IfConfig6 clean processed successfully.
  @retval others         The IfConfig6 clean process failed.

**/
EFI_STATUS
IfConfig6ClearInterfaceInfo (
  IN LIST_ENTRY    *IfList
  )
{
  EFI_STATUS                Status;
  LIST_ENTRY                *Entry;
  IFCONFIG6_INTERFACE_CB    *IfCb;
  EFI_IP6_CONFIG_POLICY     Policy;

  Policy = Ip6ConfigPolicyAutomatic;
  Entry  = IfList->ForwardLink;
  Status = EFI_SUCCESS;

  if (IsListEmpty (IfList)) {
    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), mHiiHandle);
  }

  //
  // Go through the interface list.
  //
  while (Entry != IfList) {

    IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);

    Status = IfCb->IfCfg->SetData (
                            IfCb->IfCfg,
                            Ip6ConfigDataTypePolicy,
                            sizeof (EFI_IP6_CONFIG_POLICY),
                            &Policy
                            );

    if (EFI_ERROR (Status)) {
      break;
    }

    Entry  = Entry->ForwardLink;
  }

  return Status;
}
示例#21
0
EFIAPI
IIO_GetDeviceProto (
  int                 fd,
  struct __filedes  **filp
  )
{
  void               *Proto;
  ConInstance        *Stream;
  struct __filedes   *pfil;

  Proto = NULL;
  if(ValidateFD( fd, VALID_OPEN)) {
    pfil = &gMD->fdarray[fd];
    Stream = BASE_CR(pfil->f_ops, ConInstance, Abstraction);
    Proto = (void *)Stream->Dev;
    if(filp != NULL) {
      *filp = pfil;
    }
  }
  return Proto;
}
示例#22
0
static
off_t
EFIAPI
da_ConSeek(
  struct __filedes   *filp,
  off_t               Position,
  int                 whence      ///< Ignored by Console
)
{
  ConInstance                       *Stream;
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *Proto;
  XYoffset                           CursorPos;

  Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
  // Quick check to see if Stream looks reasonable
  if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'
    EFIerrno = RETURN_INVALID_PARAMETER;
    return -1;    // Looks like a bad This pointer
  }
  if(Stream->InstanceNum == STDIN_FILENO) {
    // Seek is not valid for stdin
    EFIerrno = RETURN_UNSUPPORTED;
    return -1;
  }
  // Everything is OK to do the final verification and "seek".
  Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)Stream->Dev;
  CursorPos.Offset = Position;

  EFIerrno = Proto->SetCursorPosition(Proto,
                                      (INTN)CursorPos.XYpos.Column,
                                      (INTN)CursorPos.XYpos.Row);

  if(RETURN_ERROR(EFIerrno)) {
    return -1;
  }
  else {
    return Position;
  }
}
示例#23
0
/** The free function causes the space pointed to by Ptr to be deallocated,
    that is, made available for further allocation.

    If Ptr is a null pointer, no action occurs.  Otherwise, if the argument
    does not match a pointer earlier returned by the calloc, malloc, or realloc
    function, or if the space has been deallocated by a call to free or
    realloc, the behavior is undefined.

    @param  Ptr     Pointer to a previously allocated region of memory to be freed.

**/
void
free(void *Ptr)
{
  CPOOL_HEAD   *Head;

  Head = BASE_CR(Ptr, CPOOL_HEAD, Data);
  assert(Head != NULL);
  DEBUG((DEBUG_POOL, "free(%p): Head: %p\n", Ptr, Head));

  if(Ptr != NULL) {
    if (Head->Signature == CPOOL_HEAD_SIGNATURE) {
      (void) RemoveEntryList((LIST_ENTRY *)Head);   // Remove this node from the malloc pool
      (void) gBS->FreePool (Head);                  // Now free the associated memory
    }
    else {
      errno = EFAULT;
      DEBUG((DEBUG_ERROR, "ERROR free(0x%p): Signature is 0x%8X, expected 0x%8X\n",
             Ptr, Head->Signature, CPOOL_HEAD_SIGNATURE));
  }
  }
  DEBUG((DEBUG_POOL, "free Done\n"));
}
示例#24
0
/**
  The function extracts device information from OpalDeviceList and creat SmmDeviceList used for S3.

  @param[in]       OpalDeviceList   Opal device list created at POST which contains the information of OPAL_DISK_AND_PASSWORD_INFO
  @param[in,out]   SmmDeviceList    Opal Smm device list to be created and used for unlocking devices at S3 resume.

  @retval EFI_SUCCESS            Create SmmDeviceList successfully.
  @retval Others                 Other execution results.
**/
EFI_STATUS
CreateSmmDeviceList (
  IN     LIST_ENTRY                 *OpalDeviceList,
  IN OUT LIST_ENTRY                 *SmmDeviceList
  )
{
  LIST_ENTRY                        *Entry;
  OPAL_DISK_AND_PASSWORD_INFO       *PciDev;
  OPAL_SMM_DEVICE                   *SmmDev;

  for (Entry = OpalDeviceList->ForwardLink; Entry != OpalDeviceList; Entry = Entry->ForwardLink) {
    PciDev = BASE_CR (Entry, OPAL_DISK_AND_PASSWORD_INFO, Link);

    SmmDev = AllocateZeroPool (sizeof (OPAL_SMM_DEVICE));
    if (SmmDev == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    SmmDev->Signature = OPAL_SMM_DEVICE_SIGNATURE;

    ExtractDeviceInfoFromDevicePath(&PciDev->OpalDevicePath, SmmDev);

    SmmDev->PasswordLength = PciDev->PasswordLength;
    CopyMem(&(SmmDev->Password), PciDev->Password, OPAL_PASSWORD_MAX_LENGTH);

    SmmDev->Sscp.ReceiveData = SecurityReceiveData;
    SmmDev->Sscp.SendData = SecuritySendData;

    DEBUG ((DEBUG_INFO, "Opal SMM: Insert device node to SmmDeviceList:\n"));
    DEBUG ((DEBUG_INFO, "DeviceType:%x, Bus:%d, Dev:%d, Fun:%d\n", \
      SmmDev->DeviceType, SmmDev->BusNum, SmmDev->DevNum, SmmDev->FuncNum));
    DEBUG ((DEBUG_INFO, "SataPort:%x, MultiplierPort:%x, NvmeNamespaceId:%x\n", \
      SmmDev->SataPort, SmmDev->SataPortMultiplierPort, SmmDev->NvmeNamespaceId));

    InsertHeadList (SmmDeviceList, &SmmDev->Link);
  }

  return EFI_SUCCESS;
}
示例#25
0
/**
  This function find LockBox by GUID from SMRAM.

  @param LockBoxQueue The LockBox queue in SMRAM
  @param Guid         The guid to indentify the LockBox

  @return LockBoxData
**/
SMM_LOCK_BOX_DATA *
InternalFindLockBoxByGuidFromSmram (
  IN LIST_ENTRY *LockBoxQueue,
  IN EFI_GUID   *Guid
  )
{
  LIST_ENTRY                    *Link;
  SMM_LOCK_BOX_DATA             *LockBox;

  for (Link = InternalInitLinkDxe (LockBoxQueue);
       Link != LockBoxQueue;
       Link = InternalNextLinkDxe (Link)) {
    LockBox = BASE_CR (
                Link,
                SMM_LOCK_BOX_DATA,
                Link
                );
    if (CompareGuid (&LockBox->Guid, Guid)) {
      return LockBox;
    }
  }
  return NULL;
}
示例#26
0
/**
  ExitBootServices Callback function for memory protection.
**/
VOID
MemoryProtectionExitBootServicesCallback (
  VOID
  )
{
  EFI_RUNTIME_IMAGE_ENTRY       *RuntimeImage;
  LIST_ENTRY                    *Link;

  //
  // We need remove the RT protection, because RT relocation need write code segment
  // at SetVirtualAddressMap(). We cannot assume OS/Loader has taken over page table at that time.
  //
  // Firmware does not own page tables after ExitBootServices(), so the OS would
  // have to relax protection of RT code pages across SetVirtualAddressMap(), or
  // delay setting protections on RT code pages until after SetVirtualAddressMap().
  // OS may set protection on RT based upon EFI_MEMORY_ATTRIBUTES_TABLE later.
  //
  if (mImageProtectionPolicy != 0) {
    for (Link = gRuntime->ImageHead.ForwardLink; Link != &gRuntime->ImageHead; Link = Link->ForwardLink) {
      RuntimeImage = BASE_CR (Link, EFI_RUNTIME_IMAGE_ENTRY, Link);
      SetUefiImageMemoryAttributes ((UINT64)(UINTN)RuntimeImage->ImageBase, ALIGN_VALUE(RuntimeImage->ImageSize, EFI_PAGE_SIZE), 0);
    }
  }
}
示例#27
0
文件: FwVol.c 项目: phshentu/UDK2014
/**
  This notification function is invoked when an instance of the
  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL is produced.  It layers an instance of the
  EFI_FIRMWARE_VOLUME2_PROTOCOL on the same handle.  This is the function where
  the actual initialization of the EFI_FIRMWARE_VOLUME2_PROTOCOL is done.

  @param  Event                 The event that occured
  @param  Context               For EFI compatiblity.  Not used.

**/
VOID
EFIAPI
NotifyFwVolBlock (
  IN  EFI_EVENT Event,
  IN  VOID      *Context
  )
{
  EFI_HANDLE                            Handle;
  EFI_STATUS                            Status;
  UINTN                                 BufferSize;
  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *Fvb;
  EFI_FIRMWARE_VOLUME2_PROTOCOL         *Fv;
  FV_DEVICE                             *FvDevice;
  EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader;
  //
  // Examine all new handles
  //
  for (;;) {
    //
    // Get the next handle
    //
    BufferSize = sizeof (Handle);
    Status = CoreLocateHandle (
              ByRegisterNotify,
              NULL,
              gEfiFwVolBlockNotifyReg,
              &BufferSize,
              &Handle
              );

    //
    // If not found, we're done
    //
    if (EFI_NOT_FOUND == Status) {
      break;
    }

    if (EFI_ERROR (Status)) {
      continue;
    }

    //
    // Get the FirmwareVolumeBlock protocol on that handle
    //
    Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
    ASSERT_EFI_ERROR (Status);
    ASSERT (Fvb != NULL);

    //
    // Make sure the Fv Header is O.K.
    //
    Status = GetFwVolHeader (Fvb, &FwVolHeader);
    if (EFI_ERROR (Status)) {
      return;
    }
    ASSERT (FwVolHeader != NULL);

    if (!VerifyFvHeaderChecksum (FwVolHeader)) {
      CoreFreePool (FwVolHeader);
      continue;
    }


    //
    // Check to see that the file system is indeed formatted in a way we can
    // understand it...
    //
    if ((!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) &&
        (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) {
      continue;
    }

    //
    // Check if there is an FV protocol already installed in that handle
    //
    Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
    if (!EFI_ERROR (Status)) {
      //
      // Update Fv to use a new Fvb
      //
      FvDevice = BASE_CR (Fv, FV_DEVICE, Fv);
      if (FvDevice->Signature == FV2_DEVICE_SIGNATURE) {
        //
        // Only write into our device structure if it's our device structure
        //
        FvDevice->Fvb = Fvb;
      }

    } else {
      //
      // No FwVol protocol on the handle so create a new one
      //
      FvDevice = AllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice);
      if (FvDevice == NULL) {
        return;
      }

      FvDevice->Fvb             = Fvb;
      FvDevice->Handle          = Handle;
      FvDevice->FwVolHeader     = FwVolHeader;
      FvDevice->IsFfs3Fv        = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);
      FvDevice->Fv.ParentHandle = Fvb->ParentHandle;

      if (Fvb->ParentHandle != NULL) {
        //
        // Inherit the authentication status from FVB.
        //
        FvDevice->AuthenticationStatus = GetFvbAuthenticationStatus (Fvb);
      }
      
      if (!EFI_ERROR (FvCheck (FvDevice))) {
        //
        // Install an New FV protocol on the existing handle
        //
        Status = CoreInstallProtocolInterface (
                    &Handle,
                    &gEfiFirmwareVolume2ProtocolGuid,
                    EFI_NATIVE_INTERFACE,
                    &FvDevice->Fv
                    );
        ASSERT_EFI_ERROR (Status);
      } else {
        //
        // Free FvDevice Buffer for the corrupt FV image.
        //
        CoreFreePool (FvDevice);
      }
    }
  }

  return;
}
示例#28
0
文件: Runtime.c 项目: jeppeter/vbox
/**

  Changes the runtime addressing mode of EFI firmware from physical to virtual.


  @param MemoryMapSize   The size in bytes of VirtualMap.
  @param DescriptorSize  The size in bytes of an entry in the VirtualMap.
  @param DescriptorVersion The version of the structure entries in VirtualMap.
  @param VirtualMap      An array of memory descriptors which contain new virtual
                         address mapping information for all runtime ranges.

  @retval  EFI_SUCCESS            The virtual address map has been applied.
  @retval  EFI_UNSUPPORTED        EFI firmware is not at runtime, or the EFI firmware is already in
                                  virtual address mapped mode.
  @retval  EFI_INVALID_PARAMETER  DescriptorSize or DescriptorVersion is invalid.
  @retval  EFI_NO_MAPPING         A virtual address was not supplied for a range in the memory
                                  map that requires a mapping.
  @retval  EFI_NOT_FOUND          A virtual address was supplied for an address that is not found
                                  in the memory map.

**/
EFI_STATUS
EFIAPI
RuntimeDriverSetVirtualAddressMap (
    IN UINTN                  MemoryMapSize,
    IN UINTN                  DescriptorSize,
    IN UINT32                 DescriptorVersion,
    IN EFI_MEMORY_DESCRIPTOR  *VirtualMap
)
{
    EFI_STATUS                    Status;
    EFI_RUNTIME_EVENT_ENTRY       *RuntimeEvent;
    EFI_RUNTIME_IMAGE_ENTRY       *RuntimeImage;
    LIST_ENTRY                    *Link;
    EFI_PHYSICAL_ADDRESS          VirtImageBase;

    //
    // Can only switch to virtual addresses once the memory map is locked down,
    // and can only set it once
    //
    if (!mRuntime.AtRuntime || mRuntime.VirtualMode) {
        return EFI_UNSUPPORTED;
    }
    //
    // Only understand the original descriptor format
    //
    if (DescriptorVersion != EFI_MEMORY_DESCRIPTOR_VERSION || DescriptorSize < sizeof (EFI_MEMORY_DESCRIPTOR)) {
        return EFI_INVALID_PARAMETER;
    }
    //
    // We are now committed to go to virtual mode, so lets get to it!
    //
    mRuntime.VirtualMode = TRUE;

    //
    // ConvertPointer() needs this mVirtualMap to do the conversion. So set up
    // globals we need to parse the virtual address map.
    //
    mVirtualMapDescriptorSize = DescriptorSize;
    mVirtualMapMaxIndex       = MemoryMapSize / DescriptorSize;
    mVirtualMap               = VirtualMap;

    //
    // ReporstStatusCodeLib will check and make sure this service can be called in runtime mode.
    //
    REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_EFI_RUNTIME_SERVICE | EFI_SW_RS_PC_SET_VIRTUAL_ADDRESS_MAP));

    //
    // Signal all the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE events.
    // All runtime events are stored in a list in Runtime AP.
    //
    for (Link = mRuntime.EventHead.ForwardLink; Link != &mRuntime.EventHead; Link = Link->ForwardLink) {
        RuntimeEvent = BASE_CR (Link, EFI_RUNTIME_EVENT_ENTRY, Link);
        if ((RuntimeEvent->Type & EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {
            RuntimeEvent->NotifyFunction (
                RuntimeEvent->Event,
                RuntimeEvent->NotifyContext
            );
        }
    }

    //
    // Relocate runtime images. All runtime images are stored in a list in Runtime AP.
    //
    for (Link = mRuntime.ImageHead.ForwardLink; Link != &mRuntime.ImageHead; Link = Link->ForwardLink) {
        RuntimeImage = BASE_CR (Link, EFI_RUNTIME_IMAGE_ENTRY, Link);
        //
        // We don't want to relocate our selves, as we only run in physical mode.
        //
        if (mMyImageBase != RuntimeImage->ImageBase) {

            VirtImageBase = (EFI_PHYSICAL_ADDRESS) (UINTN) RuntimeImage->ImageBase;
            Status  = RuntimeDriverConvertPointer (0, (VOID **) &VirtImageBase);
            ASSERT_EFI_ERROR (Status);

            PeCoffLoaderRelocateImageForRuntime (
                (EFI_PHYSICAL_ADDRESS) (UINTN) RuntimeImage->ImageBase,
                VirtImageBase,
                (UINTN) RuntimeImage->ImageSize,
                RuntimeImage->RelocationData
            );

            InvalidateInstructionCacheRange (RuntimeImage->ImageBase, (UINTN) RuntimeImage->ImageSize);
        }
    }

    //
    // Convert all the Runtime Services except ConvertPointer() and SetVirtualAddressMap()
    // and recompute the CRC-32
    //
    RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetTime);
    RuntimeDriverConvertInternalPointer ((VOID **) &gRT->SetTime);
    RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetWakeupTime);
    RuntimeDriverConvertInternalPointer ((VOID **) &gRT->SetWakeupTime);
    RuntimeDriverConvertInternalPointer ((VOID **) &gRT->ResetSystem);
    RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetNextHighMonotonicCount);
    RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetVariable);
    RuntimeDriverConvertInternalPointer ((VOID **) &gRT->SetVariable);
    RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetNextVariableName);
    RuntimeDriverConvertInternalPointer ((VOID **) &gRT->QueryVariableInfo);
    RuntimeDriverConvertInternalPointer ((VOID **) &gRT->UpdateCapsule);
    RuntimeDriverConvertInternalPointer ((VOID **) &gRT->QueryCapsuleCapabilities);
    RuntimeDriverCalculateEfiHdrCrc (&gRT->Hdr);

    //
    // UEFI don't require System Configuration Tables Conversion.
    //

    //
    // Convert the runtime fields of the EFI System Table and recompute the CRC-32
    //
    RuntimeDriverConvertInternalPointer ((VOID **) &gST->FirmwareVendor);
    RuntimeDriverConvertInternalPointer ((VOID **) &gST->ConfigurationTable);
    RuntimeDriverConvertInternalPointer ((VOID **) &gST->RuntimeServices);
    RuntimeDriverCalculateEfiHdrCrc (&gST->Hdr);

    //
    // At this point, gRT and gST are physical pointers, but the contents of these tables
    // have been converted to runtime.
    //
    //
    // mVirtualMap is only valid during SetVirtualAddressMap() call
    //
    mVirtualMap = NULL;

    return EFI_SUCCESS;
}
/**
  Helper function of memory allocation with Guard pages.

  @param  FreePageList           The free page node.
  @param  NumberOfPages          Number of pages to be allocated.
  @param  MaxAddress             Request to allocate memory below this address.
  @param  MemoryType             Type of memory requested.

  @return Memory address of allocated pages.
**/
UINTN
InternalAllocMaxAddressWithGuard (
  IN OUT LIST_ENTRY           *FreePageList,
  IN     UINTN                NumberOfPages,
  IN     UINTN                MaxAddress,
  IN     EFI_MEMORY_TYPE      MemoryType

  )
{
  LIST_ENTRY      *Node;
  FREE_PAGE_LIST  *Pages;
  UINTN           PagesToAlloc;
  UINTN           HeadGuard;
  UINTN           TailGuard;
  UINTN           Address;

  for (Node = FreePageList->BackLink; Node != FreePageList;
        Node = Node->BackLink) {
    Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
    if (Pages->NumberOfPages >= NumberOfPages &&
        (UINTN)Pages + EFI_PAGES_TO_SIZE (NumberOfPages) - 1 <= MaxAddress) {

      //
      // We may need 1 or 2 more pages for Guard. Check it out.
      //
      PagesToAlloc = NumberOfPages;
      TailGuard = (UINTN)Pages + EFI_PAGES_TO_SIZE (Pages->NumberOfPages);
      if (!IsGuardPage (TailGuard)) {
        //
        // Add one if no Guard at the end of current free memory block.
        //
        PagesToAlloc += 1;
        TailGuard     = 0;
      }

      HeadGuard = (UINTN)Pages +
                  EFI_PAGES_TO_SIZE (Pages->NumberOfPages - PagesToAlloc) -
                  EFI_PAGE_SIZE;
      if (!IsGuardPage (HeadGuard)) {
        //
        // Add one if no Guard at the page before the address to allocate
        //
        PagesToAlloc += 1;
        HeadGuard     = 0;
      }

      if (Pages->NumberOfPages < PagesToAlloc) {
        // Not enough space to allocate memory with Guards? Try next block.
        continue;
      }

      Address = InternalAllocPagesOnOneNode (Pages, PagesToAlloc, MaxAddress);
      ConvertSmmMemoryMapEntry(MemoryType, Address, PagesToAlloc, FALSE);
      CoreFreeMemoryMapStack();
      if (HeadGuard == 0) {
        // Don't pass the Guard page to user.
        Address += EFI_PAGE_SIZE;
      }
      SetGuardForMemory (Address, NumberOfPages);
      return Address;
    }
  }

  return (UINTN)(-1);
}
示例#30
0
/**
  Dispatch function for a Software SMI handler.

  @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
  @param[in]     RegisterContext Points to an optional handler context which was specified when the
                                 handler was registered.
  @param[in, out] CommBuffer     A pointer to a collection of Data in memory that will
                                 be conveyed from a non-SMM environment into an SMM environment.
  @param[in, out] CommBufferSize The Size of the CommBuffer.

  @retval EFI_SUCCESS            The interrupt was handled and quiesced. No other handlers
                                 should still be called.
  @retval Others                 Other execution results.
**/
EFI_STATUS
EFIAPI
SmmUnlockOpalPassword (
  IN     EFI_HANDLE              DispatchHandle,
  IN     CONST VOID              *RegisterContext,
  IN OUT VOID                    *CommBuffer,
  IN OUT UINTN                   *CommBufferSize
  )
{
  EFI_STATUS                     Status;
  OPAL_SMM_DEVICE                *OpalDev;
  LIST_ENTRY                     *Entry;
  UINT8                          BaseClassCode;
  UINT8                          SubClassCode;
  UINT8                          ProgInt;
  TCG_RESULT                     Result;
  UINT8                          SataCmdSt;
  UINT8                          *StorePcieConfDataList[16];
  UINTN                          RpBase;
  UINTN                          MemoryBase;
  UINTN                          MemoryLength;
  OPAL_SESSION                   Session;
  BOOLEAN                        BlockSidSupport;

  ZeroMem (StorePcieConfDataList, sizeof (StorePcieConfDataList));
  Status = EFI_DEVICE_ERROR;

  //
  // try to unlock all locked hdd disks.
  //
  for (Entry = mSmmDeviceList.ForwardLink; Entry != &mSmmDeviceList; Entry = Entry->ForwardLink) {
    OpalDev = BASE_CR(Entry, OPAL_SMM_DEVICE, Link);

    RpBase    = 0;
    SataCmdSt = 0;

    ///
    /// Configure RootPort for PCIe AHCI/NVME devices.
    ///
    if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
      ///
      /// Save original RootPort configuration space to heap
      ///
      RpBase = SaveRestoreRootportConfSpace (
                  OpalDev,
                  TRUE,
                  StorePcieConfDataList
                  );
      MemoryBase = mNvmeContext.Nbar;
      MemoryLength = 0;
      ConfigureRootPortForPcieNand (RpBase, OpalDev->BusNum, (UINT32) MemoryBase, (UINT32) MemoryLength);

      ///
      /// Enable PCIE decode for RootPort
      ///
      SataCmdSt = PciRead8 (RpBase + NVME_PCIE_PCICMD);
      PciWrite8  (RpBase + NVME_PCIE_PCICMD,  0x6);
    } else {
      SataCmdSt = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD));
      PciWrite8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD), 0x6);
    }

    BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0B));
    SubClassCode  = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0A));
    ProgInt       = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x09));
    if (BaseClassCode != PCI_CLASS_MASS_STORAGE) {
      Status = EFI_INVALID_PARAMETER;
      break;
    }

    Status = EFI_DEVICE_ERROR;
    if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_SATA) {
      if ((SubClassCode == PCI_CLASS_MASS_STORAGE_AHCI) || (SubClassCode == PCI_CLASS_MASS_STORAGE_RAID)) {
        Status = GetAhciBaseAddress (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum);
        if (EFI_ERROR (Status)) {
          DEBUG ((DEBUG_ERROR, "GetAhciBaseAddress error, Status: %r\n", Status));
          goto done;
        }
        Status = AhciModeInitialize ((UINT8)OpalDev->SataPort);
        ASSERT_EFI_ERROR (Status);
        if (EFI_ERROR (Status)) {
          DEBUG ((DEBUG_ERROR, "AhciModeInitialize error, Status: %r\n", Status));
          goto done;
        }
      } else {
        DEBUG ((DEBUG_ERROR, "SubClassCode not support for SATA device\n"));
      }
    } else if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
      if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVM) {
        if (ProgInt != PCI_IF_NVMHCI) {
          DEBUG ((DEBUG_ERROR, "PI not support, skipped\n"));
          Status = EFI_NOT_FOUND;
          goto done;
        }

        mNvmeContext.PciBase = PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0);
        mNvmeContext.NvmeInitWaitTime = 0;
        mNvmeContext.Nsid = OpalDev->NvmeNamespaceId;
        Status = NvmeControllerInit (&mNvmeContext);
      } else {
        DEBUG ((DEBUG_ERROR, "SubClassCode not support for NVME device\n"));
      }
    } else {
      DEBUG ((DEBUG_ERROR, "Invalid Devicetype\n"));
      goto done;
    }

    Status = EFI_DEVICE_ERROR;
    BlockSidSupport = FALSE;
    if (IsOpalDeviceLocked (OpalDev, &BlockSidSupport)) {
      ZeroMem(&Session, sizeof(Session));
      Session.Sscp = &OpalDev->Sscp;
      Session.MediaId = 0;
      Session.OpalBaseComId = OpalDev->OpalBaseComId;

      Result = OpalSupportUnlock (&Session, OpalDev->Password, OpalDev->PasswordLength, NULL);
      if (Result == TcgResultSuccess) {
        Status = EFI_SUCCESS;
      }
    }

    if (mSendBlockSID && BlockSidSupport) {
      Result = OpalBlockSid (&Session, TRUE);
      if (Result != TcgResultSuccess) {
        break;
      }
    }

    if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
      if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVM) {
        Status = NvmeControllerExit (&mNvmeContext);
      }
    }

done:
    if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
      ASSERT (RpBase != 0);
      PciWrite8  (RpBase + NVME_PCIE_PCICMD, 0);
      RpBase = SaveRestoreRootportConfSpace (
                  OpalDev,
                  FALSE,  // restore
                  StorePcieConfDataList
                  );
      PciWrite8  (RpBase + NVME_PCIE_PCICMD, SataCmdSt);
    } else {
      PciWrite8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD), SataCmdSt);
    }

    if (EFI_ERROR (Status)) {
      break;
    }
  }

  return Status;
}