consplitter.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 2,473 行 · 第 1/5 页

C
2,473
字号
         );
  gBS->CloseProtocol (
         ControllerHandle, 
         DeviceGuid,
         This->DriverBindingHandle,
         ControllerHandle
         );

  return EFI_SUCCESS;
}

STATIC
EFI_STATUS
EFIAPI
ConSplitterConInDriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
  IN  EFI_HANDLE                      ControllerHandle,
  IN  UINTN                           NumberOfChildren,
  IN  EFI_HANDLE                      *ChildHandleBuffer
  )
/*++

Routine Description:

Arguments:
  (Standard DriverBinding Protocol Stop() function)

Returns:

  None

--*/
{
  EFI_STATUS                          Status;
  EFI_SIMPLE_TEXT_IN_PROTOCOL         *TextIn; 

  if (NumberOfChildren == 0) {
    return EFI_SUCCESS;
  }

  Status = ConSplitterStop (
             This,
             ControllerHandle,
             mConIn.VirtualHandle,
             &gEfiConsoleInDeviceGuid,
             &gEfiSimpleTextInProtocolGuid,
             (VOID **)&TextIn
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  
  //
  // Delete this console input device's data structures.
  //
  return ConSplitterTextInDeleteDevice (&mConIn, TextIn);
}

STATIC
EFI_STATUS
EFIAPI
ConSplitterSimplePointerDriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
  IN  EFI_HANDLE                      ControllerHandle,
  IN  UINTN                           NumberOfChildren,
  IN  EFI_HANDLE                      *ChildHandleBuffer
  )
/*++

Routine Description:

Arguments:
  (Standard DriverBinding Protocol Stop() function)

Returns:

  None

--*/
{
  EFI_STATUS                          Status;
  EFI_SIMPLE_POINTER_PROTOCOL         *SimplePointer; 

  if (NumberOfChildren == 0) {
    return EFI_SUCCESS;
  }

  Status = ConSplitterStop (
             This,
             ControllerHandle,
             mConIn.VirtualHandle,
             &gEfiSimplePointerProtocolGuid,
             &gEfiSimplePointerProtocolGuid,
             (VOID **)&SimplePointer
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  
  //
  // Delete this console input device's data structures.
  //
  return ConSplitterSimplePointerDeleteDevice (&mConIn, SimplePointer);
}

STATIC
EFI_STATUS
EFIAPI
ConSplitterConOutDriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
  IN  EFI_HANDLE                      ControllerHandle,
  IN  UINTN                           NumberOfChildren,
  IN  EFI_HANDLE                      *ChildHandleBuffer
  )
/*++

Routine Description:

Arguments:
  (Standard DriverBinding Protocol Stop() function)

Returns:

  None

--*/
{
  EFI_STATUS                          Status;
  EFI_SIMPLE_TEXT_OUT_PROTOCOL        *TextOut;
  EFI_UGA_DRAW_PROTOCOL               *UgaDraw;

  if (NumberOfChildren == 0) {
    return EFI_SUCCESS;
  }

  Status = ConSplitterStop (
             This,
             ControllerHandle,
             mConOut.VirtualHandle,
             &gEfiConsoleOutDeviceGuid,
             &gEfiSimpleTextOutProtocolGuid,
             (VOID **)&TextOut
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Remove any UGA devices
  //
  Status = gBS->OpenProtocol (
                ControllerHandle,
                &gEfiUgaDrawProtocolGuid,
                &UgaDraw,
                This->DriverBindingHandle,   
                mConOut.VirtualHandle, 
                EFI_OPEN_PROTOCOL_GET_PROTOCOL
                );

  //
  // Delete this console output device's data structures.
  //
  return ConSplitterTextOutDeleteDevice (&mConOut, TextOut);
}

STATIC
EFI_STATUS
EFIAPI
ConSplitterStdErrDriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
  IN  EFI_HANDLE                      ControllerHandle,
  IN  UINTN                           NumberOfChildren,
  IN  EFI_HANDLE                      *ChildHandleBuffer
  )
/*++

Routine Description:

Arguments:
  (Standard DriverBinding Protocol Stop() function)

Returns:

  None

--*/
{
  EFI_STATUS                          Status;
  EFI_SIMPLE_TEXT_OUT_PROTOCOL        *TextOut;

  if (NumberOfChildren == 0) {
    return EFI_SUCCESS;
  }

  Status = ConSplitterStop (
             This,
             ControllerHandle,
             mStdErr.VirtualHandle,
             &gEfiStandardErrorDeviceGuid,
             &gEfiSimpleTextOutProtocolGuid,
             (VOID **)&TextOut
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Delete this console error out device's data structures.
  //
  Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if (mStdErr.CurrentNumberOfConsoles == 0) {
    gST->StandardErrorHandle = NULL;
    gST->StdErr = NULL;
    //
    // Update the CRC32 in the EFI System Table header
    //
    gST->Hdr.CRC32 = 0;
    gBS->CalculateCrc32 ((UINT8 *)&gST->Hdr, 
                          gST->Hdr.HeaderSize, 
                          &gST->Hdr.CRC32
                          );
  }

  return Status;
}

EFI_STATUS
ConSplitterGrowBuffer (
  IN  UINTN                           SizeOfCount,
  IN  UINTN                           *Count,
  IN OUT  VOID                        **Buffer
  )
/*++

Routine Description:
  Take the passed in Buffer of size SizeOfCount and grow the buffer
  by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount
  bytes. Copy the current data in Buffer to the new version of Buffer
  and free the old version of buffer.


Arguments:
  SizeOfCount - Size of element in array
  Count       - Current number of elements in array
  Buffer      - Bigger version of passed in Buffer with all the data

Returns:
  EFI_SUCCESS - Buffer size has grown
  EFI_OUT_OF_RESOURCES - Could not grow the buffer size

  None

--*/
{
  UINTN                               NewSize;
  UINTN                               OldSize;
  VOID                                *Ptr;
  
  //
  // grow the buffer to new buffer size,
  // copy the old buffer's content to the new-size buffer,
  // then free the old buffer.
  //
  OldSize = *Count * SizeOfCount;
  *Count += CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT;
  NewSize = *Count * SizeOfCount;

  Ptr = EfiLibAllocateZeroPool (NewSize);
  if ( Ptr == NULL ) {
    return EFI_OUT_OF_RESOURCES;
  }

  EfiCopyMem (Ptr, *Buffer, OldSize); 
  
  if (*Buffer != NULL) {
    gBS->FreePool (*Buffer);
  }
  
  *Buffer = Ptr;    

  return EFI_SUCCESS;
}    

EFI_STATUS
ConSplitterTextInAddDevice (
  IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,
  IN  EFI_SIMPLE_TEXT_IN_PROTOCOL     *TextIn 
  )
/*++

Routine Description:

Arguments:

Returns:

  None

--*/
{
  EFI_STATUS                          Status;
  
  //
  // If the Text In List is full, enlarge it by calling growbuffer().
  //
  if ( Private->CurrentNumberOfConsoles >= Private->TextInListCount ) {    
    Status = ConSplitterGrowBuffer (
                sizeof (EFI_SIMPLE_TEXT_IN_PROTOCOL *),
                &Private->TextInListCount,
                (VOID **)&Private->TextInList
                );
    if (EFI_ERROR (Status)) {
      return EFI_OUT_OF_RESOURCES;
    }    
  }
  
  //
  // Add the new text-in device data structure into the Text In List.
  //
  Private->TextInList[Private->CurrentNumberOfConsoles] = TextIn;
  Private->CurrentNumberOfConsoles++;

  return EFI_SUCCESS;
}

EFI_STATUS
ConSplitterTextInDeleteDevice (
  IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,
  IN  EFI_SIMPLE_TEXT_IN_PROTOCOL     *TextIn
  )
/*++

Routine Description:

Arguments:

Returns:

  None

--*/
{
  UINTN                               Index;
  //
  // Remove the specified text-in device data structure from the Text In List,
  // and rearrange the remaining data structures in the Text In List.
  //
  for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
    if (Private->TextInList[Index] == TextIn) {
      for (Index = Index; Index < Private->CurrentNumberOfConsoles - 1; 
            Index++) {
        Private->TextInList[Index] = Private->TextInList[Index + 1];
      }
      Private->CurrentNumberOfConsoles--;
      return EFI_SUCCESS;
    }
  }   
  return EFI_NOT_FOUND;
}

EFI_STATUS
ConSplitterSimplePointerAddDevice (
  IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,
  IN  EFI_SIMPLE_POINTER_PROTOCOL     *SimplePointer 
  )
/*++

Routine Description:

Arguments:

Returns:

  None

--*/
{
  EFI_STATUS                          Status;
  
  //
  // If the Text In List is full, enlarge it by calling growbuffer().
  //
  if (Private->CurrentNumberOfPointers >= Private->PointerListCount) {    
    Status = ConSplitterGrowBuffer (
                sizeof (EFI_SIMPLE_POINTER_PROTOCOL *),
                &Private->PointerListCount,
                (VOID **)&Private->PointerList
                );
    if (EFI_ERROR (Status)) {
      return EFI_OUT_OF_RESOURCES;
    }    
  }
  
  //
  // Add the new text-in device data structure into the Text In List.
  //
  Private->PointerList[Private->CurrentNumberOfPointers] = SimplePointer;
  Private->CurrentNumberOfPointers++;
  return EFI_SUCCESS;
}

EFI_STATUS
ConSplitterSimplePointerDeleteDevice (
  IN  TEXT_IN_SPLITTER_PRIVATE_DATA   *Private,
  IN  EFI_SIMPLE_POINTER_PROTOCOL     *SimplePointer
  )
/*++

Routine Description:

Arguments:

Returns:

  None

--*/
{
  UINTN                               Index;
  //
  // Remove the specified text-in device data structure from the Text In List,
  // and rearrange the remaining data structures in the Text In List.
  //
  for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {
    if (Private->PointerList[Index] == SimplePointer) {
      for (Index = Index; Index < Private->CurrentNumberOfPointers - 1; 
            Index++) {
        Private->PointerList[Index] = Private->PointerList[Index + 1];
      }
      Private->CurrentNumberOfPointers--;
      return EFI_SUCCESS;
    }
  }   
  return EFI_NOT_FOUND;
}

EFI_STATUS
ConSplitterGrowMapTable (
  IN  TEXT_OUT_SPLITTER_PRIVATE_DATA  *Private
  )
/*++

Routine Description:

Arguments:

Returns:

  None

--*/
{
  UINTN                               Size, NewSize, TotalSize;
  INT32                               *TextOutModeMap, *OldTextOutModeMap;
  INT32                               *SrcAddress;
  INT32                               Index;

  NewSize           = Private->TextOutListCount * sizeof (INT32);
  OldTextOutModeMap = Private->TextOutModeMap;
  TotalSize         = NewSize * Private->TextOutQueryDataCount;

  TextOutModeMap    = EfiLibAllocateZeroPool (TotalSize);
  if ( TextOutModeMap == NULL ) {
    return EFI_OUT_OF_RESOURCES;
  }
  EfiSetMem (TextOutModeMap, TotalSize, 0xFF);
  Private->TextOutModeMap = TextOutModeMap;

  //
  // If TextOutList has been enlarged, need to realloc the mode map table
  // The mode map table is regarded as a two dimension array. 
  //
  //                         Old                    New
  //  0   ---------> TextOutListCount ----> TextOutListCount
  //  |   -------------------------------------------
  //  |  |                    |                      |
  //  |  |                    |                      |
  //  |  |                    |                      |
  //  |  |                    |                      |
  //  |  |                    |                      |
  // \/  |                    |                      |
  //      -------------------------------------------
  // QueryDataCount
  //
  if ( OldTextOutModeMap ) {

    Size            = Private->CurrentNumberOfConsoles * sizeof (INT32);
    Index           = 0;
    SrcAddress      = OldTextOutModeMap;

    //
    // Copy the old data to the new one

⌨️ 快捷键说明

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